我是一个CUDA初学者,在阅读一些thrust教程。我写了一段简单但十分混乱的代码,并尝试找出如何加速thrust。(这个想法正确吗?)我试图将两个向量(每个向量有10000000个int)添加到另一个向量中,使用cpu上的数组相加和gpu上的device_vector相加。
以下是要注意的事项:
#include <iostream>
#include "cuda.h"
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#define N 10000000
int main(void)
{
float time_cpu;
float time_gpu;
int *a = new int[N];
int *b = new int[N];
int *c = new int[N];
for(int i=0;i<N;i++)
{
a[i]=i;
b[i]=i*i;
}
clock_t start_cpu,stop_cpu;
start_cpu=clock();
for(int i=0;i<N;i++)
{
c[i]=a[i]+b[i];
}
stop_cpu=clock();
time_cpu=(double)(stop_cpu-start_cpu)/CLOCKS_PER_SEC*1000;
std::cout<<"Time to generate (CPU):"<<time_cpu<<std::endl;
thrust::device_vector<int> X(N);
thrust::device_vector<int> Y(N);
thrust::device_vector<int> Z(N);
for(int i=0;i<N;i++)
{
X[i]=i;
Y[i]=i*i;
}
cudaEvent_t start, stop;
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start,0);
thrust::transform(X.begin(), X.end(),
Y.begin(),
Z.begin(),
thrust::plus<int>());
cudaEventRecord(stop,0);
cudaEventSynchronize(stop);
float elapsedTime;
cudaEventElapsedTime(&elapsedTime,start,stop);
std::cout<<"Time to generate (thrust):"<<elapsedTime<<std::endl;
cudaEventDestroy(start);
cudaEventDestroy(stop);
getchar();
return 0;
}
CPU的结果非常快,但是在我的机器上GPU运行非常慢(i5-2320,4G,GTX 560 Ti),CPU时间约为26,GPU时间约为30!我是不是在代码中做了愚蠢的thrust错误或者有更深层次的原因?
作为一个C++新手,我反复检查我的代码,使用thrust仍然得到了较慢的GPU时间,因此我进行了一些实验,展示了使用五种不同方法计算vectorAdd的差异。我使用Windows API QueryPerformanceFrequency() 作为统一的时间测量方法。
每个实验看起来都像这样:
f = large_interger.QuadPart;
QueryPerformanceCounter(&large_interger);
c1 = large_interger.QuadPart;
for(int j=0;j<10;j++)
{
for(int i=0;i<N;i++)//CPU array adding
{
c[i]=a[i]+b[i];
}
}
QueryPerformanceCounter(&large_interger);
c2 = large_interger.QuadPart;
printf("Time to generate (CPU array adding) %lf ms\n", (c2 - c1) * 1000 / f);
这是我的一个简单的__global__
函数,用于GPU数组相加:
__global__ void add(int *a, int *b, int *c)
{
int tid=threadIdx.x+blockIdx.x*blockDim.x;
while(tid<N)
{
c[tid]=a[tid]+b[tid];
tid+=blockDim.x*gridDim.x;
}
}
函数被称为:
for(int j=0;j<10;j++)
{
add<<<(N+127)/128,128>>>(dev_a,dev_b,dev_c);//GPU array adding
}
我使用以下循环十次将向量a[N]和b[N]加入到向量c[N]中:
- 在CPU上添加数组
- 在CPU上添加std::vector
- 在CPU上添加thrust::host_vector
- 在GPU上添加thrust::device_vector
- 在GPU上添加数组。这是结果
其中N=10000000。
我得到的结果如下:
- CPU数组添加时间:268.992968毫秒
- CPU std::vector添加时间:1908.013595毫秒
- CPU Thrust::host_vector添加时间: 10776.456803毫秒
- GPU Thrust::device_vector添加时间: 297.156610毫秒
- GPU数组添加时间: 5.210573毫秒
这让我感到困惑,因为我不熟悉模板库的实现。容器和原始数据结构之间的性能真的会有这么大的差异吗?
Y [i] = i * i
和c [i] = i * i
为Y [i] = i
和c [i] = i
。奇怪的是,我在想GPU时间是否被乘以10倍...您是如何在笔记本电脑上运行代码的?@ Robert @gpu - Tony