tutorial punteros puntero mundo memoria lenguaje hola español ejemplo dev asignar apuntadores c++ cuda raii placement-new

punteros - CUDA: asignación de memoria del dispositivo de empaquetado en C++



punteros c++ pdf (4)

Parece que nos ha acusado al decirnos qué planea hacer con explicar sus casos de uso de los datos (esto es probablemente porque es obvio para usted).

¿Quieres decir " sin "? Derecha, lo siento. CUDA es un lenguaje de programación GPGPU de NVIDIA, construido sobre C / C ++ al proporcionar una interfaz para GCC. Mi pregunta está dirigida principalmente a personas que ya conocen sus pormenores. Mi uso es bastante arbitrario, la pregunta realmente está más preocupada con CUDA porque CUDA solo te ofrece una interfaz C y por lo tanto te obliga a renunciar a muchas funciones útiles de C ++, incluso si trabajas en C ++ de todos modos.

La única API C que veo hasta ahora es cudaMalloc y cudaFree. ... ¿No puedes envolver estos dentro del constructor / destructor de tu CudoClass?

Si y no. Eso es más o menos lo que estoy haciendo en este momento, pero no estoy satisfecho con eso. Mi pregunta es en realidad triple (actualizaré la pregunta en consecuencia):

  1. ¿Es mi sobrecarga una new semánticamente correcta? ¿Pierde memoria?
  2. ¿Alguien tiene información sobre futuros desarrollos de CUDA que vayan en esta dirección general (seamos sinceros: interfaces C en C ++ s * ck)?
  3. ¿Cómo puedo llevar esto más allá de manera consistente (hay otras API a tener en cuenta, por ejemplo, no solo hay memoria del dispositivo, sino también un almacén de memoria constante y memoria de textura)?

Además de Malloc y Free, ¿qué otras API hay? Supongo que asignan memoria y copian datos del dispositivo en la memoria recién asignada.

Sí ... de hecho, también he pensado en una forma de encapsular la funcionalidad cudaMemcpy también. ;-)

¿Simplemente desea ver los datos sin formato como matrices de algún tipo específico? ¿O son las otras operaciones que desea realizar?

En realidad, una vez que se inicializa la memoria y se copian algunos datos en ella (ver cudaMemcpy arriba), ya casi cudaMemcpy . El resto de la acción forma parte de la GPU, donde solo necesito algunos accesos básicos a la matriz. El flujo de trabajo muy básico aquí es:

  1. Asignar memoria del dispositivo
  2. Copie sus datos a la memoria del dispositivo,
  3. Invocar la acción GPU (paralela) que procesa la memoria,
  4. Copia datos a la RAM.

El paso 3 está prácticamente grabado en piedra.

Estoy empezando a usar CUDA en este momento y tengo que admitir que estoy un poco decepcionado con la API C. Entiendo las razones para elegir C pero el lenguaje se basó en C ++, varios aspectos hubieran sido mucho más simples, por ejemplo, la asignación de memoria del dispositivo (a través de cudaMalloc ).

Mi plan era hacer esto yo mismo, utilizando un operator new sobrecargado operator new con ubicación new y RAII (dos alternativas). Me pregunto si hay algunas advertencias que no haya notado hasta ahora. El código parece funcionar, pero todavía me estoy preguntando sobre posibles pérdidas de memoria.

El uso del código RAII sería el siguiente:

CudaArray<float> device_data(SIZE); // Use `device_data` as if it were a raw pointer.

Tal vez una clase es exagerada en este contexto (especialmente porque todavía tendría que usar cudaMemcpy , la clase que solo encapsula RAII), por lo que el otro enfoque sería la ubicación new :

float* device_data = new (cudaDevice) float[SIZE]; // Use `device_data` … operator delete [](device_data, cudaDevice);

Aquí, cudaDevice simplemente actúa como una etiqueta para activar la sobrecarga. Sin embargo, dado que en una ubicación normal, esto indicaría la ubicación, creo que la sintaxis es extrañamente consistente y quizás incluso preferible al uso de una clase.

Agradecería las críticas de todo tipo. ¿Alguien quizás sabe si se planea algo en esta dirección para la próxima versión de CUDA (que, como he escuchado, mejorará su compatibilidad con C ++, lo que sea que signifiquen con eso).

Entonces, mi pregunta es en realidad triple:

  1. ¿Es mi sobrecarga una new semánticamente correcta? ¿Pierde memoria?
  2. ¿Alguien tiene información sobre futuros desarrollos de CUDA que vayan en esta dirección general (seamos sinceros: interfaces C en C ++ s * ck)?
  3. ¿Cómo puedo llevar esto más allá de manera consistente (hay otras API a tener en cuenta, por ejemplo, no solo hay memoria del dispositivo, sino también un almacén de memoria constante y memoria de textura)?

// Singleton tag for CUDA device memory placement. struct CudaDevice { static CudaDevice const& get() { return instance; } private: static CudaDevice const instance; CudaDevice() { } CudaDevice(CudaDevice const&); CudaDevice& operator =(CudaDevice const&); } const& cudaDevice = CudaDevice::get(); CudaDevice const CudaDevice::instance; inline void* operator new [](std::size_t nbytes, CudaDevice const&) { void* ret; cudaMalloc(&ret, nbytes); return ret; } inline void operator delete [](void* p, CudaDevice const&) throw() { cudaFree(p); } template <typename T> class CudaArray { public: explicit CudaArray(std::size_t size) : size(size), data(new (cudaDevice) T[size]) { } operator T* () { return data; } ~CudaArray() { operator delete [](data, cudaDevice); } private: std::size_t const size; T* const data; CudaArray(CudaArray const&); CudaArray& operator =(CudaArray const&); };

Sobre el singleton empleado aquí: Sí, soy consciente de sus inconvenientes. Sin embargo, estos no son relevantes en este contexto. Todo lo que necesitaba aquí era una pequeña etiqueta de tipo que no se podía copiar. Todo lo demás (es decir, consideraciones de subprocesamiento múltiple, tiempo de inicialización) no se aplica.


Me gustaría ir con el nuevo enfoque de colocación. Entonces definiría una clase que se ajuste a la interfaz std :: allocator <>. En teoría, podría pasar esta clase como un parámetro de plantilla en std :: vector <> y std :: map <> y demás.

Tenga cuidado, he oído que hacer tales cosas está plagado de dificultades, pero al menos aprenderá mucho más sobre el STL de esta manera. Y no necesita reinventar sus contenedores y algoritmos.


Ya hay dos proyectos que intentan algo similar:

Mientras tanto, sin embargo, he implementado mi asignador y funciona muy bien y fue completamente sencillo (> 95% de código repetitivo).


Mientras tanto hubo algunos desarrollos adicionales (no tanto en términos de la API de CUDA, sino al menos en términos de proyectos que intentan un enfoque tipo STL para la administración de datos de CUDA).

Lo más notable es que hay un proyecto de investigación de NVIDIA: empuje