我尝试使用 PGI 13.10 编译器工具使用以下命令行编译您的程序:
pgcc -acc -ta=nvidia,cc20,cuda5.0 -o t1 t1.c -Minfo
并得到了这个输出:
scaled:
10, Generating present_or_copy(v1[0:n])
Generating present_or_copyin(v2[0:n])
Generating NVIDIA code
Generating compute capability 2.0 binary
11, Complex loop carried dependence of '*(v2)' prevents parallelization
Loop carried dependence of '*(v1)' prevents parallelization
Loop carried backward dependence of '*(v1)' prevents vectorization
Accelerator scalar kernel generated
14, Sum reduction generated for sum
虽然这确实表明编译是“成功的”,但有关“防止并行化”的消息表明编译器没有成功地真正利用加速器。当您看到消息时Accelerator scalar kernel generated
,您通常会对结果不满意。
当我运行上面编译的程序时,我确实收到了运行时错误:
call to cuLaunchKernel returned error 701: Launch out of resources
这是来自 CUDA 运行时子系统的错误。根据您尝试运行的加速器设备类型,您可能会看到也可能不会看到此类错误。我们可以深入研究如何解决这个问题,但这真的是无关紧要的,因为您的程序结构不正确,无法利用加速器。
vector1
编译器发出“防止并行化”消息,因为它对指针(or v1
) 和vector2
(or )非常严格v2
。它假定这些指针可以相互别名,因此在这种情况下无法创建正确的并行程序。由于这可能不是您的意图(您可能打算v1
并v2
引用单独的空格),您可以通过scaled
使用 C99restrict
关键字修改函数参数来“放心”编译器。这允许编译器按照您可能想要的方式完成其工作。
这是修改后的代码和结果:
$ cat t1.c
#include <stdio.h>
#include <stdlib.h>
float scaled(float *restrict v1, float *restrict v2, float a, int n)
{
int i;
float sum = 0.0f;
#pragma acc kernels
for(i=0;i<n;i++)
{
v1[i]+=a*v2[i];
sum+=v1[i];
}
return sum;
}
int main(int argc, char* argv[])
{
int n;
float *vector1;
float *vector2;
if( argc > 1 )
n = atoi( argv[1] );
else
n = 100000;
if( n <= 0 ) n = 100000;
vector1=(float*)malloc(n*sizeof(float));
vector2=(float*)malloc(n*sizeof(float));
scaled(vector1, vector2, 3.3, n);
printf("programming done\n");
return 0;
}
$ pgcc -acc -ta=nvidia,cc20,cuda5.0 -o t1 t1.c -Minfo
scaled:
10, Generating present_or_copy(v1[0:n])
Generating present_or_copyin(v2[0:n])
Generating NVIDIA code
Generating compute capability 2.0 binary
11, Loop is parallelizable
Accelerator kernel generated
11, #pragma acc loop gang, vector(128) /* blockIdx.x threadIdx.x */
14, Sum reduction generated for sum
$ ./t1
programming done
$
如果您无法获得这样的结果,则您尝试运行的机器/工具可能存在问题。