说我有一个这样的结构:
for(int i=0;i<5000;i++){
const int upper_bound = f(i);
#pragma acc parallel loop
for(int j=0;j<upper_bound;j++){
//Do work...
}
}
f
是i
的单调递减函数。
由于未设置num_gangs
,num_workers
和vector_length
,因此OpenACC选择它认为合适的计划。
但是,每次遇到实用程序时,还是仅在第一次遇到实用程序时,才重新选择这样的计划?
查看PGI_ACC_TIME
的输出,表明调度仅执行一次。
答案 0 :(得分:1)
PGI编译器将选择在编译时如何分解工作,但通常会在运行时确定组的数量。帮派本质上是可扩展的并行性,因此可以决定将多少个推迟到运行时。向量的长度和数量会影响底层内核的生成方式,因此通常在编译时选择它们,以最大限度地提高优化机会。对于像这样的循环,在编译时并没有真正知道边界,编译器必须在内核中生成一些额外的代码,以确保执行正确的迭代次数。
答案 1 :(得分:0)
根据OpenAcc 2.6规范[1]第1357和1358行:
必须编写与没有seq子句的循环构造相关联的循环,以便在进入循环构造时可以计算循环迭代计数。
似乎是这种情况,因此您的代码有效。
但是,请注意,实现定义了如何在帮派和工人之间分配工作,并且可能是PGI编译器只是在简单地对迭代进行分区。 您可以使用num_gangs和num_workers手动定义gang / workers的值,传递给这些子句的整数表达式可以取决于函数的值(请参见OpenACC规范的2.5.7和2.5.8)。
[1] https://www.openacc.org/sites/default/files/inline-files/OpenACC.2.6.final.pdf