10

我有几天悬而未决的问题没有答案。出现这些问题是因为我有相同问题的 OpenMP 和 OpenCL 实现。OpenCL 在 GPU 上完美运行,但在 CPU 上运行时性能降低 50%(与 OpenMP 实现相比)。一篇文章已经在处理 OpenMP 和 OpenCL 性能之间的差异,但它没有回答我的问题。目前我面临这些问题:

1)拥有“矢量化内核”(就英特尔离线编译器而言)真的那么重要吗?

有一个类似的帖子,但我认为我的问题更笼统。

据我了解:矢量化内核不一定意味着编译后的二进制文件中没有矢量/SIMD 指令。我检查了我的内核的汇编代码,并且有一堆 SIMD 指令。矢量化内核意味着通过使用 SIMD 指令,您可以在一个 CPU 线程中执行 4 个 (SSE) 或 8 个 (AVX) OpenCL“逻辑”线程。这只有在您的所有数据都连续存储在内存中时才能实现。但是谁拥有如此完美排序的数据呢?

所以我的问题是:从这个意义上说,让你的内核“矢量化”真的那么重要吗?

当然它可以提高性能,但是如果内核中的大多数计算密集型部分都是通过向量指令完成的,那么您可能会接近“最佳”性能。我认为我的问题的答案在于内存带宽。向量寄存器可能更适合高效的内存访问。在这种情况下,必须对内核参数(指针)进行矢量化。

2)如果我在CPU的本地内存中分配数据,它将分配到哪里?OpenCL 将 L1 缓存显示为本地内存,但它显然与 GPU 本地内存上的内存类型不同。如果它存储在 RAM/全局内存中,那么将数据复制到其中是没有意义的。如果它在缓存中,其他一些进程可能会将它刷新出来......所以这也没有意义。

3) “逻辑”OpenCL 线程如何映射到真正的 CPU 软件/硬件(Intel HTT)线程?因为如果我的内核运行时间很短,并且内核像在 TBB(线程构建块)或 OpenMP 中那样分叉,那么分叉开销将占主导地位。

4)线程分叉开销是多少?是否为每个“逻辑”OpenCL 线程派生了新的 CPU 线程,或者 CPU 线程是否被派生一次,然后再用于更多“逻辑”OpenCL 线程?

我希望我不是唯一对这些小东西感兴趣的人,你们中的一些人现在可能对这些问题有所了解。先感谢您!


更新

3) 目前,OpenCL 的开销比 OpenMP 更大,因此需要大量内核来实现高效的运行时执行。在 Intel OpenCL 中,工作组映射到 TBB 线程,因此 1 个虚拟 CPU 内核执行整个工作组(或线程块)。一个工作组是用 3 个嵌套的 for 循环实现的,如果可能的话,最里面的循环是矢量化的。所以你可以想象它是这样的:

#pragam omp parallel for
for(wg=0; wg < get_num_groups(2)*get_num_groups(1)*get_num_groups(0); wg++) {

  for(k=0; k<get_local_size(2); k++) {
    for(j=0; j<get_local_size(1); j++) {
      #pragma simd
      for(i=0; i<get_local_size(0); i++) {
        ... work-load...
      }
    }
  }
}

如果最里面的循环可以被矢量化,它会使用 SIMD 步骤:

for(i=0; i<get_local_size(0); i+=SIMD) {

4) 每个 TBB 线程在 OpenCL 执行期间被分叉一次并被重用。每个 TBB 线程都绑定到一个虚拟内核,即。计算过程中没有线程迁移。

我也接受@natchouf-s 的回答。

4

2 回答 2

8

我可能对你的问题有一些提示。根据我的经验,针对 CPU 调整的良好 OpenCL 实现无法击败良好的 OpenMP 实现。如果是这样,您可能会改进 OpenMP 代码以击败 OpenCL 代码。

1)拥有矢量化内核非常重要。它与您的问题编号 3 和 4 相关联。如果您有一个处理 4 或 8 个输入值的内核,您将拥有更少的工作项(线程),因此开销也更少。我建议使用 OpenCL 提供的向量指令和数据(如float4float8float16),而不是依赖自动向量化。不要犹豫使用float16(或double16):这将被映射到 4 个 sse 或 2 个 avx 向量,并将除以 16 所需的工作项数(这对 CPU 有好处,但并不总是对 GPU 有用:我使用 2 个不同的CPU 和 GPU 的内核)。

2)CPU上的本地内存是RAM。不要在 CPU 内核上使用它。

3 和 4)我真的不知道,这将取决于实现,但 fork 开销对我来说似乎很重要。

于 2012-11-16T11:16:08.083 回答
1

对于问题 3:

英特尔将逻辑 OpenCL 线程分组为一个硬件线程。组大小可以从 4、8 到 16 不等。逻辑 OpenCL 线程映射到执行单元的一个 SIMD 通道。一个执行单元有两个宽度为 4 的 SIMD 引擎。详细信息请参考以下文档。 https://software.intel.com/sites/default/files/Faster-Better-Pixels-on-the-Go-and-in-the-Cloud-with-OpenCL-on-Intel-Architecture.pdf

于 2015-08-26T22:38:39.200 回答