Performance OpenCL:为什么这两种情况下的性能差异如此之大?

Performance OpenCL:为什么这两种情况下的性能差异如此之大?,performance,opencl,Performance,Opencl,下面是我正在处理的OpenCL内核中的两段代码;它们显示了截然不同的运行时间 代码相当复杂,所以我已经简化了 此版本在1秒内运行: for (int ii=0; ii<someNumber;ii++) { for (int jj=0; ii<someNumber2;jj++) { value1 = value2 + value3; value1 = value1 * someFunction(a,b,c); double

下面是我正在处理的OpenCL内核中的两段代码;它们显示了截然不同的运行时间

代码相当复杂,所以我已经简化了

此版本在1秒内运行:

for (int ii=0; ii<someNumber;ii++)
{
    for (int jj=0; ii<someNumber2;jj++)
    {
        value1 = value2 + value3;
        value1 = value1 * someFunction(a,b,c);
        double nothing = value1;
    }
}
在声明
value1
的位置移动也会让我们回到快速案例:

for (int kk=0; kk<someNumber3;kk++)
{
    double value1=0;
    for (int ii=0; ii<someNumber;ii++)
    {
        for (int jj=0; ii<someNumber2;jj++)
        {
            value1 = value2 + value3;
            value1 = value1 * someFunction(a,b,c);
        }
        double nothing = value1;
    }
}

for(int kk=0;kk第一种情况只是一个循环(通过编译器优化)
但是第二个是一个带有嵌套循环的循环。这是一个大问题。大量检查全局/局部变量。(确定它们是私有的吗?你在内核中声明了所有这些?)

我建议您在开始循环之前将其另存为私有变量(somenumber和somenumber2),因为这样您每次都将使用私有数据进行检查。 作为个人经验,用作OpenCL循环检查用例的每个var都必须是私有的。 这可以节省多达80%的全局内存访问(特别是当循环非常短或简单时)

例如,这应该可以快速工作:

int c_somenumber = someNumber;
for (int ii=0; ii<c_someNumber;ii++)
{
    int c_somenumber2 = someNumber2;    
    for (int jj=0; ii<c_someNumber2;jj++)
    {
        value1 = value2 + value3;
        value1 = value1 * someFunction(a,b,c);
    }
    double nothing = value1;
}
int c_somenumber=somenumber;

对于(int ii=0;ii您使用的是什么实现?我希望“double nothing=value1;”在任何情况下都可以被任何合理的编译器作为死代码删除。

这很奇怪。你确定需要使用较慢的版本吗?从这些代码片段中看,它们在功能上完全相同。感谢你的回答。是的,我确定,但你是对的,我给出的示例在功能上完全相同。内括号中的代码应该有+=。根据这些代码片段,我看不出第二个工作单元速度较慢的任何原因。我猜移动分配肯定会有副作用,例如增加分支(一个工作单元执行
如果
,下一个工作单元执行
否则
),这确实会减慢GPU的速度。此外,我知道你说过所有的VAR都是
\uu private
,但是如果你完全与全局内存同步,你可能会破坏对内存的联合访问。优化OpenCL内存访问可能很棘手:只是抛出一些想法而已。:)这给了我很多思考的空间。我已经用一些可能更清晰的东西更新了我的问题。代码没有
if
s。我怀疑这会成为一个凝聚的问题。多亏了你的帖子,我想我已经发现了问题。在案例1(我问题的第一个框)中,我认为编译器通过“消除为死代码”内部循环。在案例2中,它意识到内部循环外部需要变量
value1
,因此它运行它。函数
someFunction(a、b、c)
非常慢,因此这会导致速度减慢。仅供参考,该实现是AMD的Linux SDK。感谢大家的帮助!您的意思是因为value1未使用,编译器优化了对someFunction的调用。如何确保someFunction没有副作用?因为“nothing”未使用。我不是说value1。@vocaro我不确定,但这是我能找到的最好的解释。它实际上是一个非常简单的函数,它对内存的影响非常大(我自己实现的稀疏矩阵访问).我对编译器一无所知,但由于它实际上只是一个复杂的反引用,也许编译器会注意到?当然,它可能是完全不同的东西,但我不知道是什么!是的,所有内容都保存为私有。请参阅我对该问题的解释,作为对其他答案的评论!
double value1=0;
for (int kk=0; kk<someNumber3;kk++)
{
    for (int ii=0; ii<someNumber;ii++)
    {
        for (int jj=0; ii<someNumber2;jj++)
        {
            value1 = value2 + value3;
            value1 = value1 * someFunction(a,b,c);
        }
        double nothing = value1;
    }
}
for (int kk=0; kk<someNumber3;kk++)
{
    double value1=0;
    for (int ii=0; ii<someNumber;ii++)
    {
        for (int jj=0; ii<someNumber2;jj++)
        {
            value1 = value2 + value3;
            value1 = value1 * someFunction(a,b,c);
        }
        double nothing = value1;
    }
}
int c_somenumber = someNumber;
for (int ii=0; ii<c_someNumber;ii++)
{
    int c_somenumber2 = someNumber2;    
    for (int jj=0; ii<c_someNumber2;jj++)
    {
        value1 = value2 + value3;
        value1 = value1 * someFunction(a,b,c);
    }
    double nothing = value1;
}