Код: Выделить всё
std::vectorМне удалось добиться стабильной работы при использовании cudaMalloc и cufftPlan2d для размещения данных и планирования. память устройства (NVIDIA RTX 2000 Ada Generation GPU Laptop GPU с 8 ГБ ОЗУ), где преобразование выполняется в реальном времени, поэтому входная и выходная переменная совпадают.
Когда я масштабировал вектор размер, мне пришлось перейти к использованию cudaMallocHost и назначить рабочую область для плана вручную в памяти хоста, иначе устройству не хватит памяти для выполнения преобразования. Этот предел составлял ~3 ГБ для размера векторной памяти, поскольку, насколько я понимаю, для функционирования плана требуется примерно такой же объем рабочей области (заявление основано на выводах cufftEstimate2d и cufftGetSize2d). Это работало с теми же размерами ниже 3 ГБ и работает с размерами выше 3 ГБ, в отличие от исходной версии, как и ожидалось, за счет производительности. Однако некоторые размеры просто не работают, даже если работают большие размеры.
Для настройки и выполнения преобразования я использую следующий код:
Код: Выделить всё
// Creates vector with 187553025 elements, i.e. 13695 x 13695 matrix
// Takes up 3000.848424 MB of RAM as I requested 3001[MB] be used at max
Data source = Data( 3001 );
// Create cufftDoubleComplex pointer as it was the simplest way to achieve what I
// wanted, I intend on refining this to not require two copies of the data to be
// present.
cufftDoubleComplex *x{};
// full_size() is a method to return the number of elements in the vector
// in this case that is 187553025
cudaMallocHost(&x, source.full_size() * sizeof(cufftDoubleComplex));
// The data() method returns the pointer from vector.data() .
cudaError_t in_status = cudaMemcpy(
x,
reinterpret_cast(source.data()),
(std::size_t)(source.full_size() * sizeof(cufftDoubleComplex)),
cudaMemcpyHostToHost);
if (in_status != cudaSuccess)
throw std::invalid_argument( "CUDA Memory Copy error." );
// Create the cufftHandle that will become the plan but make it so
// no workArea is assigned by default
cufftHandle p;
cufftSetAutoAllocation(p, false);
// The size() method returns the length of one side of the matrix being represented
// in this case 13695
cufftPlan2d(&p, source.size(), source.size(), CUFFT_Z2Z);
size_t *workArea;
// get_memory_size() is a method to return the memory size the vector requires.
// This size is chosen as cufftGetSize2d returns a value equal to or lower than
// this, most of the time.
cudaMallocHost(&workArea, size_t(source.get_memory_size()));
cufftSetWorkArea(p, workArea);
// using Z2Z as I am using double precision.
cufftExecZ2Z(p, x, x, CUFFT_FORWARD);
cudaDeviceSynchronize();
cufftDestroy(p);
cudaError_t out_status = cudaMemcpy(
source.data(),
reinterpret_cast(x),
(std::size_t)(source.full_size() * sizeof(cufftDoubleComplex)),
cudaMemcpyHostToHost);
if (out_status != cudaSuccess)
throw std::invalid_argument( "CUDA Memory Copy error." );
cudaFree(x);
Подробнее здесь: https://stackoverflow.com/questions/793 ... input-size
Мобильная версия