[更新:]我现在正在生成多个进程并且它运行得相当好,尽管基本的线程问题仍然存在。 [/]
我正在尝试编写一个编译一堆opencl内核的c ++(g ++ 4.6.1)程序。大部分时间都花在clBuildProgram中。 (这是遗传编程,实际运行代码和评估适应性要快得多。)我正在尝试编译这些内核的编译,到目前为止没有任何运气。此时,线程之间没有共享数据(除了拥有相同的平台和设备引用),但它一次只能运行一个线程。我可以将这个代码作为几个进程运行(只需在linux中的不同终端窗口中启动它们),然后它将使用多个内核但不在一个进程内。我可以使用具有相同基本线程代码(std :: thread)的多个核心,只需要基本数学,所以我认为这与opencl编译或我忘记的一些静态数据有关。 :) 有任何想法吗?我已经尽力使这个线程安全,所以我很难过。
我正在使用AMD的SDK(opencl 1.1,大约6/13/2010)和5830或5850来运行它。 SDK和g ++并不像它们那样是最新的。我最后一次安装一个较新的Linux发行版以获得更新的g ++,我的代码以半速运行(至少是opencl编译),所以我回去了。 (刚刚检查了该安装上的代码,它仍以半速运行,没有线程差异。)另外,当我说它一次只运行一个线程时,它将启动所有这些线程,然后在两个线程之间交替,直到它们完成,然后执行接下来的两个等等。看起来所有的线程都在运行,直到代码构建程序。我没有在clBuildProgram中使用回调函数。我意识到这里可能会出现很多错误,如果没有代码,很难说。 :)
我很确定这个问题发生在clBuildProgram的内部或调用中。我正在打印这里的时间,推迟的线程会在第一次编译时返回很长的编译时间。这些clBuildProgram调用之间唯一的共享数据是设备ID,因为每个线程的cl_device_id具有相同的值。
这就是我发布线程的方式:
for (a = 0; a < num_threads; a++) {
threads[a] = std::thread(std::ref(programs[a]));
threads[a].detach();
sleep(1); // giving the opencl init f()s time to complete
}
这是它陷入困境的地方(这些都是传递的局部变量,但设备ID将是相同的):
clBuildProgram(program, 1, & device, options, NULL, NULL);
每个线程是否具有唯一上下文或command_queue似乎没有区别。我真的怀疑这是问题,这就是为什么我提到它。 :)
更新:使用fork()生成子进程将适用于此。
答案 0 :(得分:2)
您可能想在AMD的支持论坛上发布一些相关信息。考虑到规范要求的许多关于线程一致性的OpenGL实现失败,我认为OpenCL驱动程序在这种意义上仍然不是最理想的。他们可以在内部使用进程ID来代替数据,谁知道呢。
如果你有一个多工作的生成代,那么我建议你保留它,并使用IPC传达结果。要么你可以使用boost :: ipc,它有使用序列化的有趣方法(例如用boost :: spirit来反映数据结构)。或者您可以使用posix管道或共享内存,或者只是将编译结果转储到文件并使用boost :: filesystem和目录迭代器从父进程轮询目录...
分叉进程可以继承一些句柄;所以有一些方法可以使用未命名的管道,我相信,这可以帮助您避免创建一个管道服务器来实例化客户端管道,这可能导致广泛的协议编码。