在创建 OpenCL 上下文之前设置线程亲和性会导致段错误
Setting thread affinity before creating OpenCL context leads to Segfault
我将主线程的亲和力设置为核心 0,但 OpenCl 上下文创建以段错误结束。 (我加入了一个代码片段来重现这个问题,我删除了矢量大小检查以使其尽可能简洁)。
如果我在我的 cpuset 中定义了一个以上的核心,一切都正常。
我有直觉知道哪里出了问题。但我更喜欢具体的解释。
然后错误可能比原始段错误更好。
打开 CL 信息:
- 设备版本 英特尔 OpenCL 1.2(内部版本 475)
- 驱动程序版本 1.2.0.475
#include <vector>
#include <CL/cl.hpp>
int main(int argc, char** argv)
{
// Set affinity to core 0
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(0, &cpuset);
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
// Retrieve first platform
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
cl::Platform platform = platforms[0];
// Retrieve first CPU device
std::vector<cl::Device> devices;
platform.getDevices(CL_DEVICE_TYPE_CPU, &devices);
cl::Device device = devices[0];
// Create context
cl::Context ctx(device);
return 0;
}
编辑:添加 OpenCL 版本
我刚刚使用两个英特尔 OpenCL SDK 尝试了您的示例,但手头没有您的确切版本。两者运行都没有错误,所以:无法重现。
这个似乎比你的老一点(按内部版本号):
CL_DEVICE_VERSION: OpenCL 1.2 (Build 43)
CL_DRIVER_VERSION: 1.2.0.43
CL_DEVICE_OPENCL_C_VERSION: OpenCL C 1.2
我认为第二个是最新的 Intel CPU 驱动程序:
CL_DEVICE_VERSION: OpenCL 2.1 (Build 0)
CL_DRIVER_VERSION: 18.1.0.0920
CL_DEVICE_OPENCL_C_VERSION: OpenCL C 2.0
我在 Ubuntu 18.4.
上使用 GCC 7.4.0
根据我的经验为 CPUs 设置与英特尔 OpenCL 运行时的亲和力不是问题。
我在超级计算机上将它与 MPI 一起使用,在那里你会有多个,例如4,每个计算节点的 MPI 进程,然后 运行time 将每个 process' CPU 掩码设置为可用内核的分离子集。然后,每个进程内的英特尔 OpenCL 运行时(在引擎盖下使用英特尔线程构建模块)将为每个分配的内核生成一个线程,即如预期的那样遵守主机进程的 CPU 掩码。如果您设置第一个线程的亲和力,结果可能会有所不同,并且还取决于您在程序中设置的位置(相对于 OpenCL 运行 时间生成线程的位置)。
因为您似乎已经 运行 调试器中的代码并将范围缩小到 clcreatecontext
。 我建议您尝试使用更新的 OpenCL 驱动程序。
我将主线程的亲和力设置为核心 0,但 OpenCl 上下文创建以段错误结束。 (我加入了一个代码片段来重现这个问题,我删除了矢量大小检查以使其尽可能简洁)。
如果我在我的 cpuset 中定义了一个以上的核心,一切都正常。
我有直觉知道哪里出了问题。但我更喜欢具体的解释。
然后错误可能比原始段错误更好。
打开 CL 信息:
- 设备版本 英特尔 OpenCL 1.2(内部版本 475)
- 驱动程序版本 1.2.0.475
#include <vector>
#include <CL/cl.hpp>
int main(int argc, char** argv)
{
// Set affinity to core 0
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(0, &cpuset);
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
// Retrieve first platform
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
cl::Platform platform = platforms[0];
// Retrieve first CPU device
std::vector<cl::Device> devices;
platform.getDevices(CL_DEVICE_TYPE_CPU, &devices);
cl::Device device = devices[0];
// Create context
cl::Context ctx(device);
return 0;
}
编辑:添加 OpenCL 版本
我刚刚使用两个英特尔 OpenCL SDK 尝试了您的示例,但手头没有您的确切版本。两者运行都没有错误,所以:无法重现。
这个似乎比你的老一点(按内部版本号):
CL_DEVICE_VERSION: OpenCL 1.2 (Build 43)
CL_DRIVER_VERSION: 1.2.0.43
CL_DEVICE_OPENCL_C_VERSION: OpenCL C 1.2
我认为第二个是最新的 Intel CPU 驱动程序:
CL_DEVICE_VERSION: OpenCL 2.1 (Build 0)
CL_DRIVER_VERSION: 18.1.0.0920
CL_DEVICE_OPENCL_C_VERSION: OpenCL C 2.0
我在 Ubuntu 18.4.
上使用 GCC 7.4.0根据我的经验为 CPUs 设置与英特尔 OpenCL 运行时的亲和力不是问题。
我在超级计算机上将它与 MPI 一起使用,在那里你会有多个,例如4,每个计算节点的 MPI 进程,然后 运行time 将每个 process' CPU 掩码设置为可用内核的分离子集。然后,每个进程内的英特尔 OpenCL 运行时(在引擎盖下使用英特尔线程构建模块)将为每个分配的内核生成一个线程,即如预期的那样遵守主机进程的 CPU 掩码。如果您设置第一个线程的亲和力,结果可能会有所不同,并且还取决于您在程序中设置的位置(相对于 OpenCL 运行 时间生成线程的位置)。
因为您似乎已经 运行 调试器中的代码并将范围缩小到 clcreatecontext
。 我建议您尝试使用更新的 OpenCL 驱动程序。