如何优化此OpenCL内核?

恩里克·米格尔·莫拉·梅萨(Enrique Miguel Mora Meza)

我正在开发一个项目,但此OpenCL内核存在一些问题:-(

__kernel void gemm_fast_5(
    __global double *ar, __global double *br, __global double *cr,
    __global double *pr, __global double *ur,

    unsigned long c, unsigned long c2,
    unsigned long c3, unsigned long c4,
    unsigned long c5, unsigned long m,
    unsigned char com
){
    unsigned long i = get_global_id(0);
    unsigned long j = get_global_id(1);

    unsigned long x = get_local_id(0);
    unsigned long y = get_local_id(1);

    unsigned long cur = i*c3 + j, rl, rl2, rl3;

    #if ks == 1 || ks == 2 || ks == 3 || ks == 4
    unsigned long rl4;
    #endif


    #if ks == 2
    rl = (i << 1)*c;
    #elif ks == 3
    rl = ((i << 1) + 1)*c;
    #else
    rl = i*c;
    #endif

    __local double ut, pt;

    if (x == 0) pt = pr[i*c4 + ks];
    if (y == 0) ut = ur[j*c5 + ks];

    double aa = 0.0;

    double bb, cc;
    double dd, ee;

    for (unsigned long k=0; k<m; k++){
        #if ks == 1 || ks == 4
        rl3 = (k << 1) + 1; rl4 = (k << 2) + 3;

        bb = ar[rl + rl3 - 1]; cc = ar[rl + rl3];
        dd = br[rl2 + rl4 - 1]; ee = br[rl2 + rl4 - 3];
        #elif ks == 2 || ks == 3
        rl3 = (k << 2) + 3; rl4 = (k << 1) + 1;

        bb = ar[rl + rl3 - 3]; cc = ar[rl + rl3 - 2];
        dd = br[rl2 + rl4]; ee = br[rl2 + rl4 - 1];
        #else
        rl3 = (k << 1) + 1;

        bb = ar[rl + rl3 - 1]; cc = ar[rl + rl3];
        dd = br[rl2 + rl3]; ee = br[rl2 + rl3 - 1];
        #endif

        aa += (bb + dd)*(cc + ee);
    }
    cr[cur] = aa - pt - ut;
}

在工作时,我注意到,如果删除最后一行,即使cr[cur] = 5.0 - pt - ut;例如更改最后一行,内核运行的时间也减少了6倍

它不应该一样吗,或者至少类似吗?即使利用我拥有CPU和GPU的事实寻找答案,我也在多个运行时(PoCL和opencl-amd)中进行了尝试,并且发生了相同的事情:-/

如果有人能帮助我理解为什么会发生,我将不胜感激。我不明白:“ v

马克·博内利

循环内的所有操作都没有副作用,您只能从那些__global指针中读取内容,并计算一些临时值,这些临时值最终将aa通过该final累积到aa += ...换句话说,该循环的唯一目的是计算的值aa

因此,如果您aa从最后一行(循环之外)删除,循环内的所有操作都是完全无用的,最后您将得到一个循环,该循环除了读取某些值并更新将在函数返回时丢弃的局部变量外,什么也不做。在启用优化的情况下编译以上代码(我假设您正在这样做,否则您的问题就没有多大意义了),编译器很可能会摆脱整个循环。因此,没有最终代码的代码aa运行得更快。

这是一个GCC示例(适应于删除CUDA注释),您可以看到,即使是最低级别的优化(-O1也会删除整个循环,仅留下比较和的增量i使用-O2整个循环将被删除

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章