我正在学习CUDA.今天,我在书中尝试了一些代码:CUDA Application Design And Development这让我感到惊讶.为什么CUDA推力如此之慢?这是代码和输出.
#include <iostream>
using namespace std;
#include<thrust/reduce.h>
#include<thrust/sequence.h>
#include<thrust/host_vector.h>
#include<thrust/device_vector.h>
#include <device_launch_parameters.h>
#include "GpuTimer.h"
__global__ void fillKernel(int *a, int n)
{
int tid = blockDim.x * blockIdx.x + threadIdx.x;
if(tid <n) a[tid] = tid;
}
void fill(int *d_a, int n)
{
int nThreadsPerBlock = 512;
int nBlock = n/nThreadsPerBlock + ((n/nThreadsPerBlock)?1:0);
fillKernel<<<nBlock, nThreadsPerBlock>>>(d_a, n);
}
int main()
{
const int N = 500000;
GpuTimer timer1, timer2;
thrust::device_vector<int> a(N);
fill(thrust::raw_pointer_cast(&a[0]), N);
timer1.Start();
int sumA = thrust::reduce(a.begin(), a.end(), 0);
timer1.Stop();
cout << "Thrust reduce costs " << timer1.Elapsed() << "ms." << endl;
int sumCheck = 0;
timer2.Start();
for(int i = 0; i < N; i++)
sumCheck += i;
timer2.Stop();
cout << "Traditional reduce costs " << timer2.Elapsed() << "ms." << endl;
if (sumA == sumCheck)
cout << "Correct!" << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)

您没有有效的比较.你的GPU代码是这样做的:
int sumA = thrust::reduce(a.begin(), a.end(), 0);
Run Code Online (Sandbox Code Playgroud)
你的CPU代码是这样做的:
for(int i = 0; i < N; i++)
sumCheck += i;
Run Code Online (Sandbox Code Playgroud)
这种方法存在很多问题,我不知道从哪里开始.首先,GPU操作是有效的减少,它将为向量中的任何数字序列提供有效的结果a.碰巧你有从1到N的序列a,但它不一定是这样,它仍然会给出正确的结果.CPU代码仅为 1到N 的特定序列提供正确答案.其次,智能编译器可能能够优化CPU代码,实质上将整个循环减少为常量赋值语句.(从1到N的求和只是(N + 1)(N/2)不是吗?)我不知道在CPU端可能会进行哪些优化.
更有效的比较是在两种情况下进行实际的任意减少.一个例子可能是对设备矢量上的推力::减少操作与主机矢量上的操作进行基准测试.或者编写自己的串行CPU减少代码,实际操作在向量上,而不是将整数从1加到N.
如评论中所示,如果您真的想要帮助,请记录您正在运行的硬件和软件平台等内容,并提供所有代码.我不知道GPUtimer做了什么.我投票把它关闭为"过于本地化",因为我认为没有人会发现这是一个有用的比较,使用这样的方法.
| 归档时间: |
|
| 查看次数: |
1580 次 |
| 最近记录: |