Optimization 使用布尔值计算表达式时的精度问题
我试图删除代码中的一些if语句,以使其更适合在Cuda内核中使用。if-else语句的格式如下:Optimization 使用布尔值计算表达式时的精度问题,optimization,cuda,kernel,boolean,Optimization,Cuda,Kernel,Boolean,我试图删除代码中的一些if语句,以使其更适合在Cuda内核中使用。if-else语句的格式如下: if(boolean 1) { double1 = expression1; } else if(boolean 2) { double1 = expression2; } else { double1 = expression3; } 我试图删除if语句的尝试如下所示: double1 = (boolean1) * expression1 + (!boolean
if(boolean 1) {
double1 = expression1;
}
else if(boolean 2) {
double1 = expression2;
}
else {
double1 = expression3;
}
我试图删除if语句的尝试如下所示:
double1 = (boolean1) * expression1 +
(!boolean1 && boolean2) * expression2 +
!(boolean1 && boolean2) * expression3;
转换为no-if语句形式显然效果很好(我得到的答案大致相当)。然而,两者之间有细微的区别。这适用于一个程序,该程序将在同一内核上迭代数千次,以计算材料点的位移。为了进行测试,我只在50个时间步后比较了if语句和no if语句,这就是区别:
if statements: -2.2900031243(9010440)e-004
no if statements: -2.2900031243(8959510)e-004
我已经仔细阅读了代码,分别计算了表达式,发现它们匹配,只有当与布尔表达式结合时,我才发现问题所在。我曾尝试将布尔表达式转换为双倍,但得到了相同的答案。有人知道有没有办法解决这个问题吗?我的目标是加速,所以使用if语句是最后的选择。上面的两个数字都来自我为比较代码而做的两个不同的CPU实现。这不是GPU和CPU计算之间的区别。谢谢你的建议。你误译了
double1 = (boolean1) * expression1 +
(!boolean1 && boolean2) * expression2 +
!(boolean1 && boolean2) * expression3;
每当boolean1
和boolean2
中的任何一个为false时,添加expression3
,但是
if(boolean 1) {
double1 = expression1;
}
else if(boolean 2) {
double1 = expression2;
}
else {
double1 = expression3;
}
仅当boolean1
和boolean2
均为false时,才使用expression3
正确的翻译将使用
+ !(boolean1 || boolean2) * expression3
通过这些变化,您想要实现什么?如果幸运的话,编译器会识别出该习语,并在内部将其转换回原来的形式。如果没有,你会得到劣质的代码。我基本上是用一个表达式替换If-else块,这样我就不会得到发散的线程。我不理解你关于转换回旧形式的评论,什么旧形式?如果你想这样做,写
double1=boolean1?expression1:(boolean2?expression2:expression3
。但是,当您使用cuobjdump-sass
查看结果代码时,您可能会发现编译器生成的代码与原始条件代码完全相同。不要低估现代优化编译器!以及“s/old/original/”在我的原始版本中(第一个版本)注释。只是想附和@tera所说的内容——即使你已经删除了if
语句,你仍然有条件代码。编译器将查看有多少条件代码,并通过分支或使用来实现它。这是多么令人震惊的时刻。谢谢!出于教育目的,你可以使用cuobjdump-sass
查看编译器从替换代码的更正版本生成的代码。将其与原始代码和我建议的替换代码进行比较,您可能会改变对整个练习有用性的看法。