我刚开始学习CUDA编程。我浏览了一些简单的CUDA C范例,一切都顺利进行。然而!突然发现了Thrust!我认为自己对C++函数对象很熟悉,但是对于CUDA C和Thrust之间的区别感到惊讶。
我觉得很难相信。
我有疑问,上面的代码是在GPU上运行吗?Thrust是一个很好的工具,但我怀疑它是否能处理所有繁重的C风格内存管理。
以下是需要回答的问题:
我觉得很难相信。
__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代码是否在GPU上执行?如何判断?
- Thrust如何消除调用内核时奇怪的语法?
- Thrust是否真正调用内核?
- Thrust是否自动处理线程索引计算?
thrust::transform
函数会调用我的square
内核吗?它如何知道如何分配线程? - Tyler Jandreautransform
),因此每个数据元素一个线程是有意义的。 - Robert Crovella