Можно ли получить доступ к жесткому диску непосредственно из gpu?
Можно ли получить доступ к жесткому диску/флеш-памяти непосредственно с GPU (CUDA/openCL) и загрузить/сохранить контент непосредственно из памяти GPU?
Я пытаюсь избежать копирования файлов с диска в память и затем скопировать его в память GPU.
Я читал о Nvidia GPUDirect, но не уверен, что он делает то, что я объяснил выше. В нем рассказывается о удаленной памяти и дисках GPU, но диски в моем случае являются локальными для GPU.
Основная идея - загрузить содержимое (что-то вроде dma) → выполнить некоторые операции → сохранить содержимое обратно на диск (снова в режиме dma).
Я пытаюсь задействовать CPU и RAM как можно меньше здесь.
Пожалуйста, не стесняйтесь предлагать какие-либо предложения по дизайну.
Ответы
Ответ 1
Для всех, кто ищет это, "ленивый отказ" сделал более или менее то, что я хочу.
Прочтите следующее, чтобы узнать, может ли это быть полезным для вас.
Наиболее простая реализация, использующая RDMA для GPUDirect, памяти перед каждой передачей и отключить ее сразу после передачи завершено. К сожалению, это будет плохо работать в целом, поскольку пиннинг и открепление памяти - это дорогостоящие операции. Остаток от однако шаги, необходимые для выполнения передачи RDMA, могут выполняться быстро без ввода ядра (список DMA можно кэшировать и воспроизводится с использованием регистров MMIO/списков команд).
Следовательно, лениво неокрашиваемая память является ключом к высокопроизводительной RDMA реализация. То, что это подразумевает, удерживает память, закрепленную даже после завершения передачи. Это использует тот факт, что вполне вероятно, что одна и та же область памяти будет использоваться для будущего DMA поэтому lazy unpinning сохраняет операции pin/unpin.
Пример реализации ленивого отказа будет содержать набор закрепленных областей памяти и только некоторые из них (например, наименее недавно использовали один), если общий размер регионов достиг некоторого пороговое значение, или если сбой в новой области не удался из-за пространства BAR (см. размеры PCI BAR).
Вот ссылка на руководство по применению и nvidia документы.
Ответ 2
Пытаясь использовать эту функцию, я написал небольшой пример для Windows x64, чтобы реализовать это. В этом примере ядро "напрямую" обращается к дисковым пространствам. На самом деле, как упоминал ранее @RobertCrovella, операционная система выполняет свою работу, возможно, с некоторой работой процессора; но никакого дополнительного кодирования.
__global__ void kernel(int4* ptr)
{
int4 val ; val.x = threadIdx.x ; val.y = blockDim.x ; val.z = blockIdx.x ; val.w = gridDim.x ;
ptr[threadIdx.x + blockDim.x * blockIdx.x] = val ;
ptr[160*1024*1024 + threadIdx.x + blockDim.x * blockIdx.x] = val ;
}
#include "Windows.h"
int main()
{
// 4GB - larger than installed GPU memory
size_t size = 256 * 1024 * 1024 * sizeof(int4) ;
HANDLE hFile = ::CreateFile ("GPU.dump", (GENERIC_READ | GENERIC_WRITE), 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) ;
HANDLE hFileMapping = ::CreateFileMapping (hFile, 0, PAGE_READWRITE, (size >> 32), (int)size, 0) ;
void* ptr = ::MapViewOfFile (hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, size) ;
::cudaSetDeviceFlags (cudaDeviceMapHost) ;
cudaError_t er = ::cudaHostRegister (ptr, size, cudaHostRegisterMapped) ;
if (cudaSuccess != er)
{
printf ("could not register\n") ;
return 1 ;
}
void* d_ptr ;
er = ::cudaHostGetDevicePointer (&d_ptr, ptr, 0) ;
if (cudaSuccess != er)
{
printf ("could not get device pointer\n") ;
return 1 ;
}
kernel<<<256,256>>> ((int4*)d_ptr) ;
if (cudaSuccess != ::cudaDeviceSynchronize())
{
printf ("error in kernel\n") ;
return 1 ;
}
if (cudaSuccess != ::cudaHostUnregister (ptr))
{
printf ("could not unregister\n") ;
return 1 ;
}
::UnmapViewOfFile (ptr) ;
::CloseHandle (hFileMapping) ;
::CloseHandle (hFile) ;
::cudaDeviceReset() ;
printf ("DONE\n");
return 0 ;
}