我在使用 CUDA 时遇到以下性能问题。当我在 Titan V 和 Titan X 卡上运行一个简单的示例代码时,运行时间符合预期。
Titan X: 0.269299 ms
Titan V: 0.111766 ms
现在,当我在代码中添加另一个内核时,它使用动态并行,但仍然不调用它或根本不使用它,Volta GPU 的性能急剧下降,但在其他卡上性能不受影响。
Titan X: 0.270602 ms
Titan V: 1.999299 ms
重要的是要强调第二个内核根本没有使用,它只是位于其余代码旁边,即它仅与其余代码一起编译。还可以在创建流的同时注释递归内核调用,并看到 Volta 的运行时间再次变好。我怀疑动态并行性的存在会对代码产生负面影响,即使它根本没有在运行时使用。关于如何解决这个问题的任何想法?
#include <cuda.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
__global__ void MetNormal(int *a_d,const int N );
__global__ void rec(int *a_d ,int Nm,int xi, int yi, int zi, const int BlockSize){
int x=blockIdx.x*blockDim.x+threadIdx.x+xi;
int y=blockIdx.y*blockDim.y+threadIdx.y+yi;
int z=blockIdx.z*blockDim.z+threadIdx.z+zi;
int Nbloques= (Nm+BlockSize-1)/BlockSize;
dim3 b(BlockSize,BlockSize,BlockSize);
dim3 g(Nbloques,Nbloques,Nbloques);
cudaStream_t s1;//line of code to comment
cudaStreamCreateWithFlags(&s1,cudaStreamNonBlocking);// line of code to comment
rec<<<g,b,0,s1>>>(a_d,Nm,xi,yi,zi,BlockSize);//line of code to comment
}
__global__ void MetNormal(int *a_d,const int N){
int x= blockIdx.x*blockDim.x+threadIdx.x;
int y= blockIdx.y*blockDim.y+threadIdx.y;
int z= blockIdx.z*blockDim.z+threadIdx.z;
int ind=z*N*N+y*N+x;
a_d[ind]=1;
}
int main(int argc ,char **argv){
if (argc !=4){
fprintf(stderr,"Error, run program as ./prog N rep device\n");
exit(EXIT_FAILURE);
}
unsigned long N=atoi(argv[1]);
unsigned long rep=atoi(argv[2]);
cudaSetDevice(atoi(argv[3]));
int *a,*a_d, xi=0, yi=0,zi=0;
int BSize=8;
a=(int*)malloc(sizeof(int)*N*N*N);
cudaMalloc((void ** ) &a_d,N*N*N*sizeof(int));
dim3 Bloque(BSize,BSize,BSize);
float NB=(float)N/(float)(2*BSize);
int B=(int) ceil(NB);
dim3 GridBruto((N+BSize-1)/BSize,(N+BSize-1)/BSize,(N+BSize-1)/BSize);
fflush(stdout);
for(int i=0;i<N;i++){
for (int j=0;j<N;j++){
for(int k=0;k<N;k++){
a[N*N*k+i*N+j]=0;
}
}
}
cudaEvent_t start, stop;
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaMemcpy(a_d,a,N*N*N*sizeof(int),cudaMemcpyHostToDevice);
cudaEventRecord(start);
for(int i =0;i<rep;i++){
MetNormal<<<GridBruto,Bloque>>>(a_d,N);
cudaDeviceSynchronize();
}
cudaEventRecord(stop);
cudaEventSynchronize(stop);
float milliseconds = 0;
cudaEventElapsedTime(&milliseconds, start, stop);
printf("Time %f ms\n", milliseconds/(rep));
fflush(stdout);
cudaDeviceSynchronize();
cudaMemcpy(a,a_d,N*N*N*sizeof(int),cudaMemcpyDeviceToHost);
return 0;
}
编译行:
nvcc -O3 -std=c++11 -lm -arch sm_60 -rdc=true -lcudadevrt prog.cu -o prog