【发布时间】:2011-12-03 03:09:36
【问题描述】:
这是我正在处理的 OpenCL 内核中的两段代码;它们显示出截然不同的运行时间。
代码比较复杂,我把它简化了。
这个版本运行不到一秒:
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;
}
}
这个版本大约需要 38 秒才能运行:
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;
}
正如我所说,代码比这要复杂一些(循环中还有很多其他事情),但变量“nothing”确实会从大括号之前立即移动到大括号之后。
我对 OpenCL 很陌生,我无法弄清楚发生了什么,更不用说如何解决它了。不用说,缓慢的情况实际上是我在实施中所需要的。我试过搞乱地址空间(这里的所有变量都在 __private 中)。
我只能想象,由于某种原因,当大括号关闭时,GPU 会将变量“value1”推到较慢的内存中。这是一个可能的解释吗?我能做什么?
提前致谢!
更新:这也在不到一秒的时间内运行:(但如果取消注释任何一行,它就会恢复到极度缓慢)。这没有对循环进行任何其他更改,并且 value1 仍然声明在与以前相同的位置。
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;
}
更新 2:代码实际上嵌套在另一个循环中,如下所示,value1 的声明:
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;
}
}
移动到声明 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;
}
}
OpenCL 似乎是一门非常棘手的艺术!我仍然不明白发生了什么,但至少我现在知道如何解决它!
【问题讨论】:
-
这很奇怪。您确定需要使用较慢的版本吗?从这些 sn-ps 来看,它们在功能上是相同的。
-
感谢您的回复。是的,我敢肯定,但你是对的,我给出的示例在功能上是相同的。内大括号中的代码应该有一个 +=。
-
根据这些代码 sn-ps,我看不出第二个应该变慢的任何原因。我猜想移动分配一定会在某处产生副作用,例如增加分支(一个工作单元执行
if,下一个执行else),这确实会减慢GPU。 -
另外,我知道你说过所有的变量都是
__private,但是如果你完全与全局内存同步,你可能会破坏对内存的合并访问。优化 OpenCL 内存访问可能很棘手:stackoverflow.com/questions/3841877/… 只是抛出一些想法。 :) -
这给了我很多思考。我已经用一些可能会带来更多启示的东西更新了我的问题。该代码没有
ifs。我怀疑这将成为一个合并问题。
标签: performance opencl