【问题标题】:How to optimize SYCL kernel如何优化SYCL内核
【发布时间】:2022-07-01 16:02:22
【问题描述】:

我正在大学学习 SYCL,我有一个关于代码性能的问题。 特别是我有这个 C/C++ 代码:

我需要在 SYCL 内核中进行并行翻译,我这样做:

#include <sycl/sycl.hpp>
#include <vector>
#include <iostream>
using namespace sycl;
constexpr int size = 131072; // 2^17
    int main(int argc, char** argv) {
//Create a vector with size elements and initialize them to 1
std::vector<float> dA(size); 
try {
   queue gpuQueue{ gpu_selector{} };
   buffer<float, 1> bufA(dA.data(), range<1>(dA.size()));
   gpuQueue.submit([&](handler& cgh) {
   accessor inA{ bufA,cgh };
cgh.parallel_for(range<1>(size),
[=](id<1> i) { inA[i] = inA[i] + 2; }
);
});
gpuQueue.wait_and_throw();
}
catch (std::exception& e) { throw e; }

所以我的问题是关于 c 值的,在这种情况下我直接使用值 2 但这会影响我运行代码时的性能吗?我需要创建一个变量或者这种方式是正确的并且性能好?

提前感谢您的帮助!

【问题讨论】:

    标签: parallel-processing gpu nvidia amd sycl


    【解决方案1】:

    有趣的问题。在这种情况下,2 的值将是 SYCL 内核中指令中的文字 - 我认为这是最有效的!从intfloat 的隐式转换有点复杂。我的猜测是,您最终可能会在您的设备组件中使用 float 文字 2.0。您的 SYCL 设备不必从内存中获取 2 或在运行时强制转换或类似的东西,它只存在于指令中。

    同样,如果你有:

    constexpr int c = 2;
    // the rest of your code
    [=](id<1> i) { inA[i] = inA[i] + c; }
    // etc
    

    几乎可以肯定,编译器足够聪明,可以将c 的常量值传播到内核代码中。因此,2.0 文字再次出现在指令中。

    我使用 DPC++ 编译了您的示例并提取了 LLVM IR,发现以下行:

      %5 = load float, float addrspace(4)* %arrayidx.ascast.i.i, align 4, !tbaa !17
      %add.i = fadd float %5, 2.000000e+00
      store float %add.i, float addrspace(4)* %arrayidx.ascast.i.i, align 4, !tbaa !17
    

    这显示了一个浮动加载和存储到/来自同一地址,中间有一个“添加 2.0”指令。如果我修改为使用变量c,就像我演示的那样,我会得到相同的 LLVM IR。

    结论:你已经达到了最高效率,编译器很聪明!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-22
      • 2016-01-17
      相关资源
      最近更新 更多