为什么GTX760上的内核比GTX560慢

时间:2014-11-17 23:18:19

标签: cuda

我有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;
}

1 个答案:

答案 0 :(得分:4)

这几乎是评论的延伸,所以他们应该得到优点。

这里有两种不同的情况来研究:

  • A :启动了512个主题
  • B :已启动1000000个主题

A 上,你没有为你的GPU提供足够的工作,你基本上是在衡量内核执行/启动的开销。正如评论所指出的,这取决于您的系统。在GPU方面花费的时间可以忽略不计。

Herehere您可以找到一些信息和时间,例如此图表说明了不同GPU的执行开销:

enter image description here

B 上,随着线程数量的增加,在GPU端花费的时间会更长。在这种情况下,760具有更好的硬件,只需更快地完成工作,克服内核启动开销。

这里还有一些与CUDA编程模型本身相关的因素;提供更多工作会对GPU的性能产生积极影响,但我认为讨论超出了这个答案的范围。查看这些帖子(12)以了解该主题。

你的内核基本上受内存带宽的限制,760超过192 GB / s,而560的峰值带宽大约是128 GB / s,所以你的内核应该在760上运行得更快,即使你的卡有相同的核心数量。

关于内存传输的说明

您的代码不会受到内存传输开销的影响,因为它们超出了测量区域,但我仍然会在这里给出一个注释,因为它有助于解释完整代码的性能差异。

开销和转移时间也取决于整个系统;包括硬件和软件方面。想想机器的RAM内存带宽;这取决于主板芯片组,模块的时钟频率,通道和模块的数量,CPU可以处理的峰值带宽等等,其中一些参数也会影响PCI上的内存传输速度。

我建议您测量系统的可用带宽。您可以使用流基准来测量RAM内存带宽和CUDA示例(实用程序目录)中提供的带宽实用程序,以测量PCI上的CPU-GPU内存带宽。这样可以让您深入了解您的机器以及进一步比较的起点。