我有GTX560。我今天买了GTX760。为什么GTX760上的内核比GTX560(~0.0232ms)更慢(~0.031ms)。当我将n增加到1000000时,它更快(~25%),但对于小n则不是。我有两台电脑。第一个(GTX560内部)是Intel(R)Core(TM)i5 CPU,P7P55D-E LX,CUDA 5.0,Kubuntu 12.04。第二个(GTX760内部),AMD FX(tm)-6300,主板760GA-P43(FX),CUDA 6.5 Kubuntu 14.04。但我仍然认为,原因不在于CPU的不同等等......
GTX560: nvcc -arch=sm_20 -fmad=false -O3 -o vecc vecc.cu -lm
GTX760: nvcc -arch=sm_30 -fmad=false -O3 -o vecc vecc.cu -lm
我也试过更改块大小,但没有根本效果。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// CUDA kernel. Each thread takes care of one element of c
__global__ void vecAdd(double *a, double *b, double *c, int n)
{
// Get our global thread ID
int id = blockIdx.x*blockDim.x+threadIdx.x;
// Make sure we do not go out of bounds
if (id < n)
c[id] = sqrt(a[id]*b[id]);
}
int main( int argc, char* argv[] )
{
cudaEvent_t start, stop;
float elapsedTime;
// Size of vectors
int n = 512;
// Host input vectors
double *h_a;
double *h_b;
//Host output vector
double *h_c;
// Device input vectors
double *d_a;
double *d_b;
//Device output vector
double *d_c;
// Size, in bytes, of each vector
size_t bytes = n*sizeof(double);
// Allocate memory for each vector on host
h_a = (double*)malloc(bytes);
h_b = (double*)malloc(bytes);
h_c = (double*)malloc(bytes);
// Allocate memory for each vector on GPU
cudaMalloc(&d_a, bytes);
cudaMalloc(&d_b, bytes);
cudaMalloc(&d_c, bytes);
int i;
// Initialize vectors on host
for( i = 0; i < n; i++ ) {
h_a[i] = sin(i)*sin(i);
h_b[i] = cos(i)*cos(i);
}
// Copy host vectors to device
cudaMemcpy( d_a, h_a, bytes, cudaMemcpyHostToDevice);
cudaMemcpy( d_b, h_b, bytes, cudaMemcpyHostToDevice);
int blockSize, gridSize;
// Number of threads in each thread block
blockSize = 256;
// Number of thread blocks in grid
gridSize = (int)ceil((float)n/blockSize);
// Execute the kernel
cudaEventCreate(&start);
cudaEventRecord(start,0);
vecAdd<<<gridSize, blockSize>>>(d_a, d_b, d_c, n);
cudaEventCreate(&stop);
cudaEventRecord(stop,0);
cudaEventSynchronize(stop);
cudaEventElapsedTime(&elapsedTime, start,stop);
printf("Elapsed time : %f ms\n" ,elapsedTime);
// Copy array back to host
cudaMemcpy( h_c, d_c, bytes, cudaMemcpyDeviceToHost );
// Sum up vector c and print result divided by n, this should equal 1 within error
double sum = 0;
for(i=0; i<n; i++)
sum += h_c[i];
printf("final result: %f\n", sum/n);
// Release device memory
cudaFree(d_a);
cudaFree(d_b);
cudaFree(d_c);
// Release host memory
free(h_a);
free(h_b);
free(h_c);
return 0;
}
答案 0 :(得分:4)
这几乎是评论的延伸,所以他们应该得到优点。
这里有两种不同的情况来研究:
在 A 上,你没有为你的GPU提供足够的工作,你基本上是在衡量内核执行/启动的开销。正如评论所指出的,这取决于您的系统。在GPU方面花费的时间可以忽略不计。
Here和here您可以找到一些信息和时间,例如此图表说明了不同GPU的执行开销:
在 B 上,随着线程数量的增加,在GPU端花费的时间会更长。在这种情况下,760具有更好的硬件,只需更快地完成工作,克服内核启动开销。
这里还有一些与CUDA编程模型本身相关的因素;提供更多工作会对GPU的性能产生积极影响,但我认为讨论超出了这个答案的范围。查看这些帖子(1,2)以了解该主题。
你的内核基本上受内存带宽的限制,760超过192 GB / s,而560的峰值带宽大约是128 GB / s,所以你的内核应该在760上运行得更快,即使你的卡有相同的核心数量。
关于内存传输的说明
您的代码不会受到内存传输开销的影响,因为它们超出了测量区域,但我仍然会在这里给出一个注释,因为它有助于解释完整代码的性能差异。
开销和转移时间也取决于整个系统;包括硬件和软件方面。想想机器的RAM内存带宽;这取决于主板芯片组,模块的时钟频率,通道和模块的数量,CPU可以处理的峰值带宽等等,其中一些参数也会影响PCI上的内存传输速度。
我建议您测量系统的可用带宽。您可以使用流基准来测量RAM内存带宽和CUDA示例(实用程序目录)中提供的带宽实用程序,以测量PCI上的CPU-GPU内存带宽。这样可以让您深入了解您的机器以及进一步比较的起点。