mirror of https://github.com/BOINC/boinc.git
client: fix matching of ATI/AMD CAL and OpenCL GPU enumeration for (most) cases where CAL supports some older GPUs but OpenCL does not.
This commit is contained in:
parent
0eaaca174a
commit
c8e1b51e40
|
@ -89,6 +89,15 @@ cl_int (*__clGetDeviceInfo)(
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool is_AMD(char *vendor) {
|
||||||
|
if ((strstr(vendor, GPU_TYPE_ATI)) ||
|
||||||
|
(strstr(vendor, "AMD")) ||
|
||||||
|
(strstr(vendor, "Advanced Micro Devices, Inc."))
|
||||||
|
) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// If "loose", tolerate small diff
|
// If "loose", tolerate small diff
|
||||||
//
|
//
|
||||||
int opencl_compare(OPENCL_DEVICE_PROP& c1, OPENCL_DEVICE_PROP& c2, bool loose) {
|
int opencl_compare(OPENCL_DEVICE_PROP& c1, OPENCL_DEVICE_PROP& c2, bool loose) {
|
||||||
|
@ -120,10 +129,14 @@ void COPROCS::get_opencl(
|
||||||
cl_uint num_platforms, platform_index, num_devices, device_index;
|
cl_uint num_platforms, platform_index, num_devices, device_index;
|
||||||
cl_device_id devices[MAX_COPROC_INSTANCES];
|
cl_device_id devices[MAX_COPROC_INSTANCES];
|
||||||
char platform_version[256];
|
char platform_version[256];
|
||||||
|
char platform_vendor[256];
|
||||||
OPENCL_DEVICE_PROP prop;
|
OPENCL_DEVICE_PROP prop;
|
||||||
COPROC_NVIDIA nvidia_temp;
|
COPROC_NVIDIA nvidia_temp;
|
||||||
COPROC_ATI ati_temp;
|
COPROC_ATI ati_temp;
|
||||||
int current_CUDA_index;
|
int current_CUDA_index;
|
||||||
|
int current_CAL_index;
|
||||||
|
int min_CAL_target;
|
||||||
|
int num_CAL_devices = (int)ati_gpus.size();
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
opencl_lib = LoadLibrary("OpenCL.dll");
|
opencl_lib = LoadLibrary("OpenCL.dll");
|
||||||
|
@ -188,12 +201,23 @@ void COPROCS::get_opencl(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ciErrNum = (*__clGetPlatformInfo)(
|
||||||
|
platforms[platform_index], CL_PLATFORM_VENDOR,
|
||||||
|
sizeof(platform_vendor), &platform_vendor, NULL
|
||||||
|
);
|
||||||
|
if (ciErrNum != CL_SUCCESS) {
|
||||||
|
msg_printf(0, MSG_INFO,
|
||||||
|
"Couldn't get PLATFORM_VENDOR for platform #%d; error %d", platform_index, ciErrNum
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
ciErrNum = (*__clGetDeviceIDs)(
|
ciErrNum = (*__clGetDeviceIDs)(
|
||||||
platforms[platform_index], CL_DEVICE_TYPE_GPU,
|
platforms[platform_index], CL_DEVICE_TYPE_GPU,
|
||||||
MAX_COPROC_INSTANCES, devices, &num_devices
|
MAX_COPROC_INSTANCES, devices, &num_devices
|
||||||
);
|
);
|
||||||
|
|
||||||
if (ciErrNum == CL_DEVICE_NOT_FOUND) continue; // No devices
|
if (ciErrNum == CL_DEVICE_NOT_FOUND) continue; // No devices
|
||||||
|
if (num_devices == 0) continue; // No devices
|
||||||
|
|
||||||
if (ciErrNum != CL_SUCCESS) {
|
if (ciErrNum != CL_SUCCESS) {
|
||||||
msg_printf(0, MSG_INFO,
|
msg_printf(0, MSG_INFO,
|
||||||
|
@ -203,9 +227,51 @@ void COPROCS::get_opencl(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mac OpenCL does not recognize all NVIDIA GPUs returned by CUDA
|
// Mac OpenCL does not recognize all NVIDIA GPUs returned by CUDA
|
||||||
|
// Fortunately, CUDA and OpenCL return the same GPU model name on
|
||||||
|
// the Mac, so we can use this to match OpenCL devices with CUDA.
|
||||||
//
|
//
|
||||||
current_CUDA_index = 0;
|
current_CUDA_index = 0;
|
||||||
|
|
||||||
|
// ATI/AMD OpenCL does not always recognize all GPUs returned by CAL.
|
||||||
|
// This is complicated for several reasons:
|
||||||
|
// * CAL returns only an enum (CALtargetEnum) for the GPU's family,
|
||||||
|
// not specific model information.
|
||||||
|
// * OpenCL return only the GPU family name
|
||||||
|
// * Which GPUs support OpenCL varies with different versions of the
|
||||||
|
// AMD Catalyst drivers.
|
||||||
|
//
|
||||||
|
// To deal with this, we make some (probably imperfect) assumptions:
|
||||||
|
// * AMD drivers eliminate OpenCL support for older GPU families first.
|
||||||
|
// * Lower values of CALtargetEnum represent older GPU families.
|
||||||
|
// * All ATI/AMD GPUs reported by CUDA are also reported by CAL (on
|
||||||
|
// systems where CAL is available) though the converse may not be true.
|
||||||
|
//
|
||||||
|
current_CAL_index = 0;
|
||||||
|
min_CAL_target = 0;
|
||||||
|
if (is_AMD(platform_vendor) && (num_CAL_devices > 0)) {
|
||||||
|
while (1) {
|
||||||
|
int numToMatch = 0;
|
||||||
|
for (int i=0; i<num_CAL_devices; ++i) {
|
||||||
|
if ((int)ati_gpus[i].attribs.target >= min_CAL_target) {
|
||||||
|
++numToMatch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (numToMatch == (int)num_devices) break;
|
||||||
|
if (numToMatch < (int)num_devices) {
|
||||||
|
msg_printf(0, MSG_INTERNAL_ERROR,
|
||||||
|
"Could not match ATI OpenCL and CAL GPUs: ignoring CAL."
|
||||||
|
);
|
||||||
|
// If we can't match ATI OpenCL and CAL GPUs, ignore CAL
|
||||||
|
// and keep OpenCL because AMD has deprecated CAL.
|
||||||
|
ati_gpus.clear();
|
||||||
|
ati.have_cal = false;
|
||||||
|
num_CAL_devices = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++min_CAL_target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (device_index=0; device_index<num_devices; ++device_index) {
|
for (device_index=0; device_index<num_devices; ++device_index) {
|
||||||
memset(&prop, 0, sizeof(prop));
|
memset(&prop, 0, sizeof(prop));
|
||||||
prop.device_id = devices[device_index];
|
prop.device_id = devices[device_index];
|
||||||
|
@ -274,20 +340,38 @@ void COPROCS::get_opencl(
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////// AMD / ATI //////////////
|
//////////// AMD / ATI //////////////
|
||||||
if ((strstr(prop.vendor, GPU_TYPE_ATI)) ||
|
if (is_AMD(prop.vendor)) {
|
||||||
(strstr(prop.vendor, "AMD")) ||
|
|
||||||
(strstr(prop.vendor, "Advanced Micro Devices, Inc."))
|
|
||||||
) {
|
|
||||||
prop.device_num = (int)(ati_opencls.size());
|
|
||||||
prop.opencl_device_index = device_index;
|
prop.opencl_device_index = device_index;
|
||||||
|
|
||||||
if (ati.have_cal) {
|
if (ati.have_cal) {
|
||||||
if (prop.device_num < (int)(ati_gpus.size())) {
|
// AMD OpenCL does not recognize all AMD GPUs returned by
|
||||||
// Always use GPU model name from CAL if available
|
// CAL but we assume that OpenCL and CAL return devices in
|
||||||
// for ATI / AMD GPUs because
|
// the same order. See additional comments earlier in
|
||||||
|
// this source file for more details.
|
||||||
|
//
|
||||||
|
while (1) {
|
||||||
|
if (current_CAL_index >= num_CAL_devices) {
|
||||||
|
if (log_flags.coproc_debug) {
|
||||||
|
msg_printf(0, MSG_INFO,
|
||||||
|
"[coproc] OpenCL ATI device #%d does not match any CAL device",
|
||||||
|
device_index
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return; // Should never happen
|
||||||
|
}
|
||||||
|
if ((int)ati_gpus[current_CAL_index].attribs.target >= min_CAL_target) {
|
||||||
|
break; // We have a match
|
||||||
|
}
|
||||||
|
// This CAL GPU is not recognized by OpenCL,
|
||||||
|
// so try the next
|
||||||
|
//
|
||||||
|
++current_CAL_index;
|
||||||
|
}
|
||||||
|
prop.device_num = current_CAL_index;
|
||||||
|
|
||||||
|
// Always use GPU model name from CAL if
|
||||||
|
// available for ATI / AMD GPUs because
|
||||||
// (we believe) it is more user-friendly.
|
// (we believe) it is more user-friendly.
|
||||||
// Assumes OpenCL and CAL return the devices
|
|
||||||
// in the same order
|
|
||||||
//
|
//
|
||||||
strcpy(prop.name, ati_gpus[prop.device_num].name);
|
strcpy(prop.name, ati_gpus[prop.device_num].name);
|
||||||
|
|
||||||
|
@ -298,15 +382,8 @@ void COPROCS::get_opencl(
|
||||||
//
|
//
|
||||||
prop.global_mem_size = ati_gpus[prop.device_num].attribs.localRAM * MEGA;
|
prop.global_mem_size = ati_gpus[prop.device_num].attribs.localRAM * MEGA;
|
||||||
prop.peak_flops = ati_gpus[prop.device_num].peak_flops;
|
prop.peak_flops = ati_gpus[prop.device_num].peak_flops;
|
||||||
} else {
|
|
||||||
if (log_flags.coproc_debug) {
|
|
||||||
msg_printf(0, MSG_INFO,
|
|
||||||
"[coproc] OpenCL ATI device #%d does not match any CAL device",
|
|
||||||
device_index
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { // ! ati.have_cal
|
} else { // ! ati.have_cal
|
||||||
|
prop.device_num = (int)(ati_opencls.size());
|
||||||
COPROC_ATI c;
|
COPROC_ATI c;
|
||||||
c.opencl_prop = prop;
|
c.opencl_prop = prop;
|
||||||
c.set_peak_flops();
|
c.set_peak_flops();
|
||||||
|
@ -314,7 +391,6 @@ void COPROCS::get_opencl(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ati_gpus.size()) {
|
if (ati_gpus.size()) {
|
||||||
// Assumes OpenCL and CAL return the same device with the same index
|
|
||||||
prop.opencl_available_ram = ati_gpus[prop.device_num].available_ram;
|
prop.opencl_available_ram = ati_gpus[prop.device_num].available_ram;
|
||||||
} else {
|
} else {
|
||||||
prop.opencl_available_ram = prop.global_mem_size;
|
prop.opencl_available_ram = prop.global_mem_size;
|
||||||
|
@ -751,11 +827,7 @@ void COPROCS::opencl_get_ati_mem_size_from_opengl() {
|
||||||
if (cglContext) {
|
if (cglContext) {
|
||||||
// get vendor string from renderer
|
// get vendor string from renderer
|
||||||
const GLubyte * strVend = glGetString (GL_VENDOR);
|
const GLubyte * strVend = glGetString (GL_VENDOR);
|
||||||
if (strVend &&
|
if (is_AMD((char *)strVend)) {
|
||||||
((strstr((char *)strVend, GPU_TYPE_ATI)) ||
|
|
||||||
(strstr((char *)strVend, "AMD")) ||
|
|
||||||
(strstr((char *)strVend, "Advanced Micro Devices, Inc.")))
|
|
||||||
) {
|
|
||||||
ati_opencls[ati_gpu_index].global_mem_size = deviceVRAM;
|
ati_opencls[ati_gpu_index].global_mem_size = deviceVRAM;
|
||||||
ati_opencls[ati_gpu_index].opencl_available_ram = deviceVRAM;
|
ati_opencls[ati_gpu_index].opencl_available_ram = deviceVRAM;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue