CUDA: asignación de memoria del dispositivo de envoltura en C ++

Estoy empezando a usar CUDA en este momento y tengo que admitir que estoy un poco decepcionado con la API de C. Entiendo las razones para elegir C, pero si el lenguaje se hubiera basado en C ++, varios aspectos habrían sido mucho más simples, p. asignación de memoria del dispositivo (a través decudaMalloc)

Mi plan era hacerlo yo mismo, usando sobrecargadooperator new con colocaciónnew y RAII (dos alternativas). Me pregunto si hay algunas advertencias que no he notado hasta ahora. El códigoparece para trabajar pero todavía me pregunto sobre posibles pérdidas de memoria.

El uso de laRAII el código sería el siguiente:

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

Quizás una clase es exagerada en este contexto (especialmente porque todavía tendría que usarcudaMemcpy, la clase solo encapsula RAII) por lo que el otro enfoque seríacolocaciónnew:

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

Aquí,cudaDevice simplemente actúa como una etiqueta para desencadenar la sobrecarga. Sin embargo, ya que en la colocación normalnew esto indicaría la ubicación, creo que la sintaxis es extrañamente consistente y quizás incluso preferible a usar una clase.

Agradecería las críticas de todo tipo. ¿Alguien 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 ++, sea lo que sea que quieran decir con eso).

Entonces, mi pregunta es realmente triple:

Es mi colocaciónnew sobrecarga semánticamente correcta? ¿Pierde memoria?¿Alguien tiene información sobre futuros desarrollos de CUDA que vayan en esta dirección general (seamos sinceros: interfaces C en C ++ s * ck)?¿Cómo puedo llevar esto más lejos de manera consistente (hay otras API a tener en cuenta, por ejemplo, no solo hay memoria del dispositivo sino también un almacenamiento 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 pudiera copiar. Todo lo demás (es decir, consideraciones de subprocesos múltiples, tiempo de inicialización) no se aplica.

Respuestas a la pregunta(4)

Su respuesta a la pregunta