2

I'm working in an c# windows application where it will show Discrete card related info like GPU activity, GPU fan and temperature parameters etc. For NVIDIA , AMD, we have NVAPI and ATL. But for Intel, I'm not aware.

For Intel arc card, I could get parameters like memory size, GPU fan, temperature from Intel IGCL . But for GPU activity and memory activity, OpenCL usageI could not find suitable method/struct in it.

Is there any other c++ API available that provides these details? or any low level APIs?

if anybody knows about this!

Previously for integrated graphics, there is a struct named D3DKMT_ESCAPE where it would return parameter values for video usage, open CL usage, GPU activity etc. Since Intel stopped supporting D3DKMT_ESCAPE and Intel Arc card being new, I could not find them.

What I try to get is, g->PStateUtil_GPU = pDynamicPStatesInfo.utilization[0].percentage; --> returns GPU activity percent for NVIDIA card. I want to get similar value for Intel

2
  • Your gonna need to contact Intel for this and be sure to read through a lot of hard C++ code
    – user16612111
    Commented Oct 6, 2023 at 16:44
  • I posted this same in Intel Community and didn't get any response!!
    – Sindhu N
    Commented Oct 9, 2023 at 3:06

1 Answer 1

1

You can also get GPU/memory activity from the IGCL C++ API.

Download the files igcl_api.h and cApiWrapper.cpp to your source code. Below is a quick-and-dirty minimal example on how to get GPU/VRAM usage, VRAM bandwidth usage, clock speed, temperature and fan speed. For a more detailed example, look here.

string gpu_name; // GPU name
uint gpu_usage; // GPU usage in %
uint gpu_memory, gpu_memory_used, gpu_memory_max; // VRAM usage in % and MB
uint gpu_memory_bandwidth, gpu_memory_bandwidth_used, gpu_memory_bandwidth_max; // in % and MB/s
uint gpu_temp, gpu_fan; // in °C and RPM
uint gpu_clock_core; // GPU core clock in MHz

#include "cApiWrapper.cpp"

ctl_device_adapter_handle_t igcl_device;
uint64_t igcl_timestamp_last_activeTime = 0ull;
uint64_t igcl_timestamp_last_timestamp = 0ull;
uint64_t igcl_read_write_counter = 0ull;
uint64_t igcl_timestamp_last_bandwidth = 0ull;

void initialize_gpu_data() {
    ctl_device_adapter_handle_t* igcl_devices = nullptr;
    uint igcl_device_number = 0;
    ctl_init_args_t init_args;
    ctl_api_handle_t api_handle;
    init_args.AppVersion = CTL_MAKE_VERSION(CTL_IMPL_MAJOR_VERSION, CTL_IMPL_MINOR_VERSION);
    init_args.flags = CTL_INIT_FLAG_USE_LEVEL_ZERO;
    init_args.Size = sizeof(init_args);
    init_args.Version = 0;
    ZeroMemory(&init_args.ApplicationUID, sizeof(ctl_application_id_t));
    do {
        ctl_result_t igcl_device_exists = ctlInit(&init_args, &api_handle);
        if(igcl_device_exists==CTL_RESULT_SUCCESS) {
            igcl_device_exists = ctlEnumerateDevices(api_handle, &igcl_device_number, igcl_devices);
            if(igcl_device_exists==CTL_RESULT_SUCCESS) {
                igcl_devices = (ctl_device_adapter_handle_t*)malloc(sizeof(ctl_device_adapter_handle_t) * igcl_device_number);
                igcl_device_exists = ctlEnumerateDevices(api_handle, &igcl_device_number, igcl_devices);
            }
        }
    } while(igcl_device_number<1u);
    igcl_device = igcl_devices[0];
    {
        ctl_device_adapter_properties_t deviceadapterproperties = { 0 };
        deviceadapterproperties.Size = sizeof(ctl_device_adapter_properties_t);
        deviceadapterproperties.pDeviceID = malloc(sizeof(LUID));
        deviceadapterproperties.device_id_size = sizeof(LUID);
        deviceadapterproperties.Version = 2;
        ctlGetDeviceProperties(igcl_device, &deviceadapterproperties);
        gpu_name = deviceadapterproperties.name;
    }
}

void query_gpu_data() {
    {
        uint engine_count = 0u;
        ctlEnumEngineGroups(igcl_device, &engine_count, nullptr);
        ctl_engine_handle_t* engines = new ctl_engine_handle_t[engine_count];
        ctlEnumEngineGroups(igcl_device, &engine_count, engines);
        for(uint i=0u; i<engine_count; i++) {
            ctl_engine_properties_t engine_properties = { 0 };
            engine_properties.Size = sizeof(ctl_engine_properties_t);
            ctlEngineGetProperties(engines[i], &engine_properties);
            if(engine_properties.type==CTL_ENGINE_GROUP_RENDER) { // CTL_ENGINE_GROUP_MEDIA
                ctl_engine_stats_t engine_stats = { 0 };
                engine_stats.Size = sizeof(ctl_engine_stats_t);
                ctlEngineGetActivity(engines[i], &engine_stats);
                gpu_usage = to_uint(100.0f*(float)(engine_stats.activeTime-igcl_timestamp_last_activeTime)/(float)(engine_stats.timestamp-igcl_timestamp_last_timestamp));
                igcl_timestamp_last_activeTime = engine_stats.activeTime;
                igcl_timestamp_last_timestamp = engine_stats.timestamp;
            }
        }
        delete[] engines;
    } {
        uint memory_count = 0u;
        ctlEnumMemoryModules(igcl_device, &memory_count, nullptr);
        ctl_mem_handle_t* memory_handle = new ctl_mem_handle_t[memory_count];
        ctlEnumMemoryModules(igcl_device, &memory_count, memory_handle);
        for(uint i=0u; i<min(memory_count, 1u); i++) {
            ctl_mem_state_t state = { 0 };
            state.Size = sizeof(ctl_mem_state_t);
            ctlMemoryGetState(memory_handle[i], &state);
            gpu_memory_used = (uint)((state.size-state.free)/1048576ull);
            gpu_memory_max = (uint)(state.free/1048576ull);
            gpu_memory = to_uint(100.0f*(float)(state.size-state.free)/(float)state.size);
            ctl_mem_bandwidth_t bandwidth = { 0 };
            bandwidth.Version = 1;
            bandwidth.Size = sizeof(ctl_mem_bandwidth_t);
            ctlMemoryGetBandwidth(memory_handle[i], &bandwidth);
            gpu_memory_bandwidth_used = (uint)(((bandwidth.readCounter+bandwidth.writeCounter-igcl_read_write_counter))/(bandwidth.timestamp-igcl_timestamp_last_bandwidth)); // does not work
            gpu_memory_bandwidth_max =(uint)(bandwidth.maxBandwidth/1000000ull);
            gpu_memory_bandwidth = to_uint(100.0f*(float)gpu_memory_bandwidth_used/(float)gpu_memory_bandwidth_max);
            igcl_read_write_counter = bandwidth.readCounter+bandwidth.writeCounter;
            igcl_timestamp_last_bandwidth = bandwidth.timestamp;
        }
        delete[] memory_handle;
    } {
        ctl_power_telemetry_t power_telemetry = { 0 };
        power_telemetry.Size = sizeof(ctl_power_telemetry_t);
        ctlPowerTelemetryGet(igcl_device, &power_telemetry);
        gpu_temp = to_uint(power_telemetry.gpuCurrentTemperature.value.datadouble);
        gpu_fan = to_uint(power_telemetry.fanSpeed[0].value.datadouble);
        gpu_clock_core = to_uint(power_telemetry.gpuCurrentClockFrequency.value.datadouble);
    }
}
2
  • 1
    Thank you @ProjectPhysX. I tried getting the temperature and Fan parameters using this SampleTelemetryApp only!. But unsure of whether to take CTL_ENGINE_GROUP_MEDIA or CTL_ENGINE_GROUP_RENDER to get GPU activity!. I tried with CTL_ENGINE_GROUP_MEDIA, but the engine_stats.activeTime was same all the time and the gpu_usage values keeps decreasing due to timestamp difference. Will check this approach!!
    – Sindhu N
    Commented Oct 18, 2023 at 9:06
  • @Sinshu N use the _RENDER variant, that is GPU render/compute activity, or what you typically would consider as GPU load. The _MEDIA variant is for the video encoder/decoder. And don't forget to keep track of the last timestamp, to always divide by the time interval (= difference between new and last timestamp); see in my sample code! Commented Oct 18, 2023 at 17:39

Not the answer you're looking for? Browse other questions tagged or ask your own question.