我刚开始学习CUDA
编程。我正在通过一些简单的CUDA C
示例,一切都在游动。然后!突然!推力!我认为自己精通C ++仿函数,对CUDA C
和Thrust
我觉得很难相信
__global__ void square(float *a, int N) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < N) {
a[idx] = a[idx] * a[idx];
}
}
int main(int argc, char** argv) {
float *aHost, *aDevice;
const int N = 10;
size_t size = N * sizeof(float);
aHost = (float*)malloc(size);
cudaMalloc((void**)&aDevice, size);
for (int i = 0; i < N; i++) {
aHost[i] = (float)i;
}
cudaMemcpy(aDevice, aHost, size, cudaMemcpyHostToDevice);
int block = 4;
int nBlock = N/block + (N % block == 0 ? 0:1);
square<<<nBlock, block>>>(aDevice, N);
cudaMemcpy(aHost, aDevice, size, cudaMemcpyDeviceToHost);
for (int i = 0; i < N; i++) {
printf("%d, %f\n", i, aHost[i]);
}
free(aHost);
cudaFree(aDevice);
}
等于
template <typename T>
struct square {
__host__ __device__ T operator()(const T& x) const {
return x * x;
}
};
int main(int argc, char** argv) {
const int N = 10;
thrust::device_vector<float> dVec(N);
thrust::sequence(dVec.begin(), dVec.end());
thrust::transform(dVec.begin(), dVec.end(), dVec.begin(), square<float>());
thrust::copy(dVec.begin(), dVec.end(), std::ostream_iterator<float>(std::cout, "\n"));
}
我错过了什么吗?上面的代码是在GPU上运行的吗? Thrust是一个很好的工具,但我怀疑它会处理所有繁重的C风格内存管理。
Thrust
代码?我该怎么说?Thrust
如何消除唤起内核的奇怪语法?Thrust
实际上是在唤起内核吗?Thrust
会自动处理线程索引计算吗?感谢您的时间。很抱歉,如果这些都是愚蠢的问题,但我发现我看到的例子很快就从可以被描述为模型T转变为M3的过程中感到难以置信。
答案 0 :(得分:6)
粗略地说:是的,当然。 Thrust是一个图书馆,所以它们都是为了让它变得更容易而诞生的。它的重点在于避免使用所有显式CUDA代码,这对于其他程序员来说看起来很奇怪,提供了一个友好的类似C ++的接口。
Thrust使用GPU,但不是只是 GPU。如果您编写自己的代码,它会进行相同的操作,即用于分配内存,复制,设置网格和块大小的C / C ++代码......然后调用GPU执行内核。
对于那些不想进入低级CUDA内容但是在一个简单(但经常)的问题中利用GPU并行性的人来说,这是一个很好的选择,比如矢量操作。