我编写了一个涉及四个嵌套for循环的串行方法 - 我想使用OpenACC并行化这个方法(这是我第一次尝试使用它而且我对所有指令都不是很熟悉)。
我尝试了以下操作,但看到以下错误:call to cuStreamSynchronize returned error 700: Illegal address during kernel execution
我已经在下面粘贴了我的方法的简化伪代码版本,我非常感谢帮助找出并行化这四个嵌套循环结构的最佳方法。
// a, b, and c are input arguments to this method
#pragma acc parallel
for(int j = 0; j < a; j++){
for(int i = 0; i < b; i++){
// computing mins and maxs based on formulas with i, j, a, b, and c
int minX = ...
int maxX = ...
int minY = ...
int maxY = ...
double count = (maxX - minX + 1)*(maxY - minY + 1);
int sum1 = 0;
int sum2 = 0;
int sum3 = 0;
#pragma acc loop
for (int y = minY; y < maxY; y++) {
for (int x = minX; x < maxX; x++) {
#pragma acc routine(function_call_name) seq
sum1 += // some function call;
sum2 += // some function call;
sum3 += // some function call;
}
}
int result1 = (int)(sum1/count);
int result2 = (int)(sum2/count);
int result3 = (int)(sum3/count);
#pragma acc routine(function_call_name) seq
// calling some function call to store result1, result2, result3 in the output
}
}
答案 0 :(得分:1)
&#34;非法地址&#34;表示您的程序正在访问GPU上的错误地址。通常,这是由于越界访问,访问设备上的主机地址,使用带有动态数据成员的聚合数据结构而不是&#34;附加&#34;成员(即在父结构中设置设备指针)。不太常见的情况是堆或堆栈溢出。
您如何管理数据?代码中其他地方的数据区域?
如果使用PGI,请首先尝试定位多核CPU(-ta =多核),这样您就不必担心数据移动了。一旦平行区域工作,您就可以返回使用GPU并处理数据移动。我建议您首先使用CUDA统一内存(-ta = tesla:managed),以便CUDA驱动程序为您处理数据移动(仅限动态数据)。然后,一旦此功能正常,请尝试添加数据区域以手动管理数据。
我看到的其他事情:
parallel构造需要外部循环的循环指令。
#pragma acc parallel loop
for(int j = 0; j < a; j++){
for(int i = 0; i < b; i++){
您可以考虑根据循环行程计数折叠循环:
#pragma acc parallel loop collapse(2)
for(int j = 0; j < a; j++){
for(int i = 0; i < b; i++){
此外,&#34;例程&#34;指令应该修饰例程的原型或定义,但不应该在计算区域中使用。
如果您在设备例程中使用任何全局变量,请务必将其放入&#34;声明&#34;指令因此在设备上创建数据的全局副本。
如果您正在使用PGI,请添加&#34; -Minfo = accel&#34;编译器的选项。这将为编译器提供有关编译器如何并行化代码的反馈消息。
如果您没有使用数据指令,编译器将需要隐式复制数据。这些消息将告诉您正在复制的数组以及要复制的大小。
如果您无法理解反馈消息,请发布编辑中的输出,我将帮助您完成这些消息。