我瞭解到std :: vector是C++中原始數組的一個很好的包裝,因此我開始使用它來管理CUDA應用程序中的主機數據[1]。由於不得不手動分配和複製東西,所以代碼更復雜,可讀性更差,所以我想擴展std :: vector。由於我不是很有經驗,我想知道你對此有何看法。特別是天氣它正確完成(例如std :: vector的析構函數隱式調用,對嗎?),如果你認爲它是一個好主意。CUDA擴展std :: vector以管理主機和設備數據
我寫了一個小例子說明本
#include <vector>
#include <cuda.h>
#include <cstdio>
void checkCUDAError(const char *msg)
{
cudaError_t err = cudaGetLastError();
if(cudaSuccess != err) {
fprintf(stderr, "Cuda error: %s: %s.\n", msg, cudaGetErrorString(err));
exit(EXIT_FAILURE);
}
}
// Wrapper around CUDA memory
template<class T>
class UniversalVector: public std::vector<T>
{
T* devicePtr_;
bool allocated;
public:
// Constructor
UniversalVector(unsigned int length)
:std::vector<T>(length),
allocated(false)
{}
// Destructor
~UniversalVector()
{
if(allocated)
cudaFree(devicePtr_);
}
cudaError_t allocateDevice()
{
if(allocated) free(devicePtr_);
cudaError_t err =
cudaMalloc((void**)&devicePtr_, sizeof(T) * this->size());
allocated = true;
return err;
}
cudaError_t loadToDevice()
{
return cudaMemcpy(devicePtr_, &(*this)[0], sizeof(T) * this->size(),
cudaMemcpyHostToDevice);
}
cudaError_t loadFromDevice()
{
return cudaMemcpy(&(*this)[0], devicePtr_, sizeof(T) * this->size(),
cudaMemcpyDeviceToHost);
}
// Accessors
inline T* devicePtr() {
return devicePtr_;
}
};
__global__ void kernel(int* a)
{
int i = threadIdx.x;
printf("%i\n", a[i]);
}
int main()
{
UniversalVector<int> vec(3);
vec.at(0) = 1;
vec.at(1) = 2;
vec.at(2) = 3;
vec.allocateDevice();
vec.loadToDevice();
kernel<<<1, 3>>>(vec.devicePtr());
checkCUDAError("Error when doing something");
return 0;
}
[1]在CUDA它的主機和設備存儲器,其中主機存儲器是由GPU和設備內存在GPU編程的存儲器訪問的存儲器之間分辨必須將內存從主機移動到GPU並返回。
一般來說,擴展STL容器是一個壞主意。在大多數情況下,通過使用組合併爲實際使用的STL容器中的方法提供簡單的外觀,您會更好。 – 2011-05-24 18:03:51
@Heandel不,我只是希望主機端的代碼更清潔一些。設備上的動態大小的陣列甚至可能嗎? – Nils 2011-05-24 18:06:17
@David Thx的評論,但究竟是什麼可能會導致問題,我只是懶得寫一個包裝[],.at()和resize()..的門面。 – Nils 2011-05-24 18:07:30