Как эффективно передать переменную из Matlab в GPU асинхронным способом?

В моем проекте CUDA я мог бы определить закрепленную память, скопировать данные из файла .txt в закрепленную память и использовать потоковую передачу для копирования данных в GPU при выполнении обработки в ядре. Теперь я хочу создать файл CUDA MEX и передать ему переменную данных (называемую RfData) в Matlab. Однако я заметил, что нет способа выделить массивы MATLAB напрямую в виде закрепленной памяти CUDA. Итак, я должен сделать это с выгружаемой памятью следующим образом:

int* RfData;
RfData = (int *)mxGetPr(prhs[0]); 
int* Device_RfData;  
int ArrayByteSize_RfData = sizeof(int) * (96* 96* 2048);
cudaMalloc((int**)&Device_RfData, ArrayByteSize_RfData);
cudaMemcpy(Device_RfData, RfData, ArrayByteSize_RfData, cudaMemcpyHostToDevice);

это важно для меня, чтобы скопировать асинхронность RfData с потоковой передачей. Единственный способ, который я мог придумать, - это сначала скопировать мои RfData в закрепленную память, а затем использовать потоковую передачу:

 int* RfData_Pinned;
cudaHostAlloc((void**)&RfData_Pinned, ArrayByteSize_RfData,  cudaHostAllocWriteCombined);
for (int j = 0; j < (96* 96* 2048); j++)
{
    RfData_Pinned[j] = RfData[j];
}

Однако это увеличило общее время обработки моей функции MEX.

Итак, теперь возникает вопрос: как я могу асинхронно перенести свои данные из Matlab в GPU? Может быть, в CUDA есть команда, позволяющая быстро копировать данные из выгружаемой памяти в закрепленную!!!?

Заранее спасибо, Моэн.


person Moein Mozaffarzadeh    schedule 26.03.2021    source источник


Ответы (1)


Вы действительно можете выделить закрепленную память с помощью cudaHostAlloc, но если вы уже выделили память, вы можете вместо этого просто закрепить ее с помощью cudaHostRegister, который принимает уже выделенный указатель массива хостов (взятый из mxGetPr в вашем случае).

Обратите внимание, что это займет время, чтобы закрепить память, но, возможно, меньше, чем выполнение cudaHostAlloc, а затем ее копирование.

person Ander Biguri    schedule 26.03.2021
comment
В порядке. Итак, если я правильно понял, мне нужно использовать: cudaHostRegister(RfData, ArrayByteSize_RfData, cudaHostRegisterMapped); для закрепления уже определенной выгружаемой памяти (RfData), которая в моем случае поступает от mxGetPr. затем я могу использовать указатель RfData в качестве указателя на закрепленную память для потоковой передачи. Правильно? - person Moein Mozaffarzadeh; 26.03.2021
comment
@MoeinMozaffarzadeh да. Это правильно. Я использую cudaHostRegisterPortable, но сейчас не могу вспомнить, почему это, а не cudaHostRegisterMapped, и есть ли разница. После этого просто используйте cudaMemcpyAsync с последним аргументом, являющимся потоком. Я использую все это в наборе инструментов TIGRE на случай, если вам нужен пример, но, вероятно, он немного запутан, чтобы быть простым примером для подражания. - person Ander Biguri; 27.03.2021
comment
Спасибо. Еще один вопрос. Мне также нужно освободить эту память с помощью определенной команды или просто free (RfData) работает нормально? - person Moein Mozaffarzadeh; 27.03.2021
comment
@Moein, ты должен открепить это. Поскольку это массив Matlab (вы только что получили указатель), я считаю, что Matlab освободит его, когда сочтет нужным. - person Ander Biguri; 28.03.2021