有没有办法让OpenCL为我提供所有可用OpenCL实现的独特物理设备的列表?我知道如何遍历平台/设备列表但是,例如,在我的情况下,我有一个英特尔提供的平台,它为我的CPU提供了高效的设备实现,以及为我的GPU提供快速实现的APP平台但是我的CPU实施得很糟糕。
有没有办法解决这两个CPU设备实际上是同一个物理设备,因此我可以选择最有效的设备并使用它,而不是同时使用它们并使它们相互竞争计算单个物理设备上的时间?
我查看了CL_DEVICE_VENDOR_ID
和CL_DEVICE_NAME
但是他们没有解决我的问题,CL_DEVICE_NAME
对于同一型号的两个独立的物理设备是相同的(双GPU' s和CL_DEVICE_VENDOR_ID
根据平台为我的CPU提供了不同的ID。
理想的解决方案是某种独特的物理设备ID,但我很乐意手动更改OpenCL配置以自行重新排列设备(如果可能的话)。
答案 0 :(得分:5)
就我现在可以调查的问题而言,没有可靠的解决方案。如果您的所有工作都在一个过程中完成,您可以使用clGetDeviceIDs
或cl_device
值本身返回的条目顺序(基本上它们是指针),但如果您尝试共享,情况会变得更糟进程之间的那些标识符。
请参阅that guy's blog post,说:
问题是,如果您有两个相同的GPU,则无法区分它们。如果你调用
clGetDeviceIDs
,它们的返回顺序实际上是未指定的,所以如果第一个进程选择第一个设备而第二个进程选择第二个设备,它们可能会结束超额订阅相同的GPU并离开另一个一个人闲着。
但是,他指出nVidia和AMD提供自定义扩展程序cl_amd_device_topology
和cl_nv_device_attribute_query
。您可以检查设备是否支持这些扩展,然后将它们用作以下内容(原作者的代码):
// This cl_ext is provided as part of the AMD APP SDK
#include <CL/cl_ext.h>
cl_device_topology_amd topology;
status = clGetDeviceInfo (devices[i], CL_DEVICE_TOPOLOGY_AMD,
sizeof(cl_device_topology_amd), &topology, NULL);
if(status != CL_SUCCESS) {
// Handle error
}
if (topology.raw.type == CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD) {
std::cout << "INFO: Topology: " << "PCI[ B#" << (int)topology.pcie.bus
<< ", D#" << (int)topology.pcie.device << ", F#"
<< (int)topology.pcie.function << " ]" << std::endl;
}
或(我的代码,改编自上面的链接帖子):
#define CL_DEVICE_PCI_BUS_ID_NV 0x4008
#define CL_DEVICE_PCI_SLOT_ID_NV 0x4009
cl_int bus_id;
cl_int slot_id;
status = clGetDeviceInfo (devices[i], CL_DEVICE_PCI_BUS_ID_NV,
sizeof(cl_int), &bus_id, NULL);
if (status != CL_SUCCESS) {
// Handle error.
}
status = clGetDeviceInfo (devices[i], CL_DEVICE_PCI_BUS_ID_NV,
sizeof(cl_int), &slot_id, NULL);
if (status != CL_SUCCESS) {
// Handle error.
}
std::cout << "Topology = [" << bus_id <<
":"<< slot_id << "]" << std::endl;
答案 1 :(得分:3)
如果您有两个属于某个平台的完全相同类型的设备,您可以通过clGetDeviceIDs返回相关联的cl_device_ids来区分它们。
如果您的设备可以由两个不同的平台使用,则可以通过比较CL_DEVICE_NAME中的设备名称来消除第二个平台的条目。
如果要查找设备的目标平台,请分别比较clGetPlatformInfo()和clGetDeviceInfo中的CL_PLATFORM_VENDOR和CL_DEVICE_VENDOR字符串。
您可以将所有平台及其所有相关设备读入单独的平台特定列表,然后通过比较单独列表中的设备名称来消除双打。这应该确保您不会为不同的平台获得相同的设备。
最后,您可以通过命令行参数或配置文件为应用程序提供参数,以便将特定类型的设备(CPU,GPU,加速器)与特定平台相关联(如果存在可供选择的不同平台)设备类型。希望这能回答你的问题。
答案 2 :(得分:0)
无论如何,让我们假设您正在尝试为所有设备提取唯一ID,实际上您只需使用clGetDeviceIDs进行查询:
cl_int clGetDeviceIDs(cl_platform_id platform,
cl_device_type device_type,
cl_uint num_entries,
cl_device_id *devices,
cl_uint *num_devices)
然后你的设备列表将被插入* devices数组,然后你可以执行clGetDeviceInfo()来找出你想要使用的设备。
答案 3 :(得分:0)
结合以上答案,我的解决方案是:
long bus = 0; // leave it 0 for Intel
// update bus for NVIDIA/AMD ...
// ...
long uid = (bus << 5) | device_type;
变量bus
是根据NVIDIA / AMD设备特定的信息查询计算的,如firegurafiku所述,变量device_type
是clGetDeviceInfo(clDevice, CL_DEVICE_TYPE, sizeof(cl_device_type), &device_type, nullptr)
API调用的结果,如{{3 }}。
这种方法解决了具有集成GPU的Intel CPU具有相同唯一ID的问题。现在,两个设备都有唯一的标识符,这要感谢不同的CL_DEVICE_TYPE
。
令人惊讶的是,在Steinin模拟的设备Oclgrind simulator
设备上运行代码的情况下,也获得了唯一的标识符15
,与我的系统上的其他标识符都没有区别。
建议的方法失败的唯一情况是-一块主板上有多个相同型号的CPU。