Я ищу удобный дизайн, чтобы можно было использовать класс на устройстве с неизвестным размером во время компиляции.Только один экземпляр этого класса должен быть отправлен на устройство, для которого должен быть один вызов cudaMalloc и cudaMemcpy (в идеале).
Хост-версия класса будет выглядеть следующим образом:
Class A {
public:
A(int size) : table(size) {
// some useful initialization of table
}
double get(int i) const {
// return some processed element from table
}
private:
std::vector<int> table;
};
Ядро:
__global__ void kernel(const A *a){
int idx = threadIdx.x + blockDim.x * blockIdx.x;
a->get(idx); // do something useful with it
}
До сих пор способ, которым я проектировал бы версию устройства класса, был следующим:
const int sizeMax = 1000;
Class A {
public:
A(int size) {
// size checking + some useful initialization of table
}
__host__ __device__
double get(int i) const {
//
}
private:
int table[sizeMax];
};
И код клиента:
A a(128);
A* da;
cudaMalloc((void**)&da, sizeof(A));
cudaMemcpy(da, &a, sizeof(A), cudaMemcpyHostToDevice);
kernel<<<1, 32>>>(da);
cudaDeviceSynchronize();
cudaFree(da);
Это довольно уродливо, потому что:
- он тратит впустую пропускную способность из-за необходимости использовать слишком большой sizeMax, чтобы быть на безопасной стороне
- класс не закрыт для модификации, значение sizeMax неизбежно необходимо будет повысить в какой-то момент
Есть ли другой способ добиться того же самого более чистого способа без негативного влияния на производительность?Чтобы было ясно, мне нужна только версия класса устройства, первая версия - это просто эквивалентный код, отличный от CUDA, чтобы проиллюстрировать тот факт, что размер таблицы должен быть динамическим.