8

[更新:] 我现在正在生成多个进程并且它工作得相当好,尽管基本的线程问题仍然存在。[/]

我正在尝试编写一个编译一堆 opencl 内核的 c++ (g++ 4.6.1) 程序。大部分时间都花在 clBuildProgram 中。(这是基因编程,实际上运行代码和评估适应性要快得多。)我正在尝试线程化这些内核的编译,但到目前为止没有任何运气。此时,线程之间没有共享数据(除了具有相同的平台和设备引用),但它一次只能运行一个线程。我可以将此代码作为多个进程运行(只是在 linux 的不同终端窗口中启动它们),然后它将用完多个内核,但不在一个进程中。我可以使用具有相同基本线程代码(std::thread)的多个内核,只需要基本数学,所以我认为它' 与 opencl 编译或我忘记的一些静态数据有关。:) 有任何想法吗?我已经尽力使这个线程安全,所以我很难过。

我正在使用 AMD 的 SDK(opencl 1.1,大约 2010 年 6 月 13 日)和 5830 或 5850 来运行它。SDK 和 g++ 不是最新的。上次我为了获得更新的 g++ 安装了更新的 linux 发行版时,我的代码以一半的速度运行(至少 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);

每个线程是否具有唯一的上下文或命令队列似乎没有区别。我真的怀疑这是我提到它的原因。:)

更新:使用 fork() 生成子进程将适用于此。

4

1 回答 1

2

您可能想在 AMD 的支持论坛上发布一些关于此的内容。考虑到规范要求的许多关于线程一致性的失败 OpenGL 实现,OpenCL 驱动程序在这个意义上仍然不是最优的也就不足为奇了。他们可以在内部使用进程 ID 来分隔数据,谁知道呢。

如果您有一个工作的多处理生成,那么我建议您保留它,并使用 IPC 传达结果。您可以使用 boost::ipc ,它具有使用序列化的有趣方式(例如,使用 boost::spirit 来反映数据结构)。或者您可以使用 posix 管道或共享内存,或者只是将编译结果转储到文件并从父进程轮询目录,使用 boost::filesystem 和目录迭代器...

分叉的进程可能会继承一些句柄;所以我相信还有一些方法可以使用未命名的管道,这可以帮助您避免创建将实例化客户端管道的管道服务器的需要,这可能导致广泛的协议编码。

于 2013-02-02T02:34:23.527 回答