我是一个 CUDA 初学者,正在阅读一些推力教程。我编写了一个简单但组织得非常糟糕的代码,并试图弄清楚推力的加速度。(这个想法正确吗?)。我尝试通过在 cpu 上添加数组并在 gpu 上添加 device_vector 来将两个向量(具有 10000000 int)添加到另一个向量。
事情是这样的:
#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!我只是在代码中犯了愚蠢的错误吗?还是有更深层次的原因?
作为一个 C++ 菜鸟,我一遍又一遍地检查我的代码,但在 GPU 上的推力仍然很慢,所以我做了一些实验来展示用五种不同方法计算 vectorAdd 的区别。我使用 windows APIQueryPerformanceFrequency()
作为统一的时间测量方法。
每个实验看起来像这样:
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);
这是我添加 GPU 数组的简单__global__
函数:
__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] 中,循环 10 次:
- 在 CPU 上添加数组
- 在 CPU 上添加 std::vector
- 在 CPU 上添加推力::host_vector
- 在 GPU 上添加推力::device_vector
- 在 GPU 上添加数组。这是结果
N=10000000
我得到了结果:
- CPU阵列增加268.992968ms
- CPU std::vector 添加 1908.013595ms
- CPU Thrust::host_vector 添加 10776.456803ms
- GPU Thrust::device_vector 添加 297.156610ms
- GPU阵列增加5.210573ms
这让我很困惑,我不熟悉模板库的实现。容器和原始数据结构之间的性能真的差别很大吗?