Opencl 添加不相关的代码后,内核运行速度明显减慢

Opencl 添加不相关的代码后,内核运行速度明显减慢,opencl,Opencl,我正在使用OpenCL在Adreno GPU上实现GEMM。总体思路是将结果矩阵C划分为矩形块,每个工作项负责计算其中一个。我的原始代码通常如下所示: __kernel void simple_gemm(const __global float4* A, __read_only image2d_t B, __global float4* C) { // some code to cal

我正在使用OpenCL在Adreno GPU上实现GEMM。总体思路是将结果矩阵C划分为矩形块,每个工作项负责计算其中一个。我的原始代码通常如下所示:

__kernel void simple_gemm(const __global float4* A,
                          __read_only image2d_t B,
                          __global float4* C)
{
    // some code to calculate the corresponding piece of matrix C
}
最初的内核假设矩阵C可以被完美地分割成几个部分,在我的设备上,它的最大运行速度为50gflops。然后,我添加了代码,以支持当C的边界上有一些剩余部分被划分成若干部分时的情况,我的第二个内核如下所示:

__kernel void gemm(const __global float4* A,
                   __read_only image2d_t B,
                   __global float4* C)
{
    if (corresponding_piece_not_on_border)
    {
        // some code to calculate a whole piece of matrix C
    }
    else
    {
        // some code to calculate a partial piece of matrix C
    }
}
然而,当我回到测试原始用例时(也就是说,没有边界用例,因此永远不会执行else中的代码),我发现我的内核的性能已经下降到大约30gflops,这是不可预料的。我已经仔细检查了我的内核是否从未到达
else
块中的代码,这意味着当输入原始测试数据时,第二个内核在逻辑上与第一个内核相同

(我试图获取内核的“低级代码”,看看是否有问题,但高通公司似乎还没有发布他们的低级规范)


那么,我的情况会有什么问题呢?如果有任何帮助,我们将不胜感激。

编译器是否可以同时计算if和else部分,并仅将结果赋值为类似于cpu SIMD风格的三值?如果你把它设为3种情况,它是否会变得更慢(15gflops)?你如何计算“对应的\u块\u而不是\u边界上的\u”?它会引入额外的内存访问吗?您是否100%确定else代码永远不会执行?即使输入了0.1%的时间,也会导致所有工作人员输入代码。@huseyintugrulbuyukisik实际上,我省略的代码相当耗时,所以我不认为编译器会做这样愚蠢的事情。此外,我还尝试添加第三个块,但速度仍然与两个块相同。谢谢您的帮助。@DarkZeros这只是一个使用全局和局部id以及一些常量参数的简单公式。我一直在反复编辑我的代码,效率并没有像这样剧烈波动。我使用printf语句来确保第二个块没有被执行,因为我不知道更好的检查方法。谢谢。是不是您遇到了寄存器分配问题?所有可能执行路径上的所有
private
变量(即内核/函数中未标记为
local
的局部变量)通常在GPU的寄存器文件中静态分配。如果您的稀有执行路径使用了大量私有变量,那么即使代码从未运行,您也会为此付出代价。寄存器压力降低了线程占用率/并行性,可能会降低吞吐量。尽量减少稀有代码对寄存器文件的使用,看看这是否有帮助。(或者使用特定于实现的工具进行检查。)编译器是否可以同时计算if和else部分,并仅将结果分配给类似于cpu SIMD风格的三元结构?如果你把它设为3种情况,它是否会变得更慢(15gflops)?你如何计算“对应的\u块\u而不是\u边界上的\u”?它会引入额外的内存访问吗?您是否100%确定else代码永远不会执行?即使输入了0.1%的时间,也会导致所有工作人员输入代码。@huseyintugrulbuyukisik实际上,我省略的代码相当耗时,所以我不认为编译器会做这样愚蠢的事情。此外,我还尝试添加第三个块,但速度仍然与两个块相同。谢谢您的帮助。@DarkZeros这只是一个使用全局和局部id以及一些常量参数的简单公式。我一直在反复编辑我的代码,效率并没有像这样剧烈波动。我使用printf语句来确保第二个块没有被执行,因为我不知道更好的检查方法。谢谢。是不是您遇到了寄存器分配问题?所有可能执行路径上的所有
private
变量(即内核/函数中未标记为
local
的局部变量)通常在GPU的寄存器文件中静态分配。如果您的稀有执行路径使用了大量私有变量,那么即使代码从未运行,您也会为此付出代价。寄存器压力降低了线程占用率/并行性,可能会降低吞吐量。尽量减少稀有代码对寄存器文件的使用,看看这是否有帮助。(或使用特定于实施的工具进行检查。)