Frage

Ich fange CUDA im Moment zu nutzen und muss zugeben, dass ich ein wenig enttäuscht von dem C-API bin. Ich verstehe die Gründe für C Wahl hatte aber die Sprache auf C ++ basiert stattdessen würden mehrere Aspekte viel einfacher gewesen, z.B. Gerät Speicherzuweisung (über cudaMalloc).

Mein Plan war, dies selbst zu tun, überlastete operator new mit der Platzierung new und RAII mit (zwei Alternativen). Ich frage mich, ob es irgendwelche Einschränkungen, die ich bisher nicht bemerkt haben. Der Code scheint zu arbeiten, aber ich frage mich immer noch über potenzielle Speicherlecks.

Die Verwendung des RAH Code würde wie folgt aussehen:

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

Vielleicht eine Klasse ist übertrieben in diesem Zusammenhang (zumal man noch cudaMemcpy verwenden müßte, nur die Klasse RAII Verkapselung), so dass der andere Ansatz wäre, Platzierung new :

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

Hier wirkt cudaDevice lediglich als Tag der Überlast auszulösen. da in normalen Platzierung new Dies würde jedoch die Platzierung angeben, finde ich die Syntax seltsam konsistent und vielleicht sogar vorzuziehen, um eine Klasse zu verwenden.

würde ich Kritik jeder Art zu schätzen wissen. Hat jemand vielleicht wissen, ob etwas in dieser Richtung für die nächste Version von CUDA geplant ist (die, wie ich gehört habe, werden seine C ++ Unterstützung verbessern, was sie damit meinen).

Also, meine Frage ist eigentlich dreifach:

  1. Ist meine Platzierung new Überlastung semantisch korrekt? Ist es ein Speicherleck?
  2. Hat jemand Informationen über zukünftige Entwicklungen CUDA haben, die in dieser allgemeinen Richtung gehen (seien wir ehrlich: C-Schnittstellen in C ++ s * ck)
  3. ?
  4. Wie kann ich das nehme weiter in konsistenter Weise (es gibt auch andere APIs zu berücksichtigen, zum Beispiel gibt es nicht nur Gerätespeicher, sondern auch eine konstanten Speicher speichern und Texturspeicher)?

// 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&);
};

Über den Singleton hier beschäftigt: Ja, ich bin mir dessen bewusst seine Nachteile. Diese sind jedoch in diesem Zusammenhang nicht relevant. Ich hier brauchte, war alles nur ein kleiner Typ-Tag, die nicht kopierbar ist. Alles andere (das heißt Multithreading Überlegungen, die Zeit der Initialisierung) nicht gelten.

War es hilfreich?

Lösung

würde ich mit der Platzierung neuer Ansatz gehen. Dann würde ich eine Klasse definieren, die den std :: allocator <> Schnittstelle entspricht. Theoretisch könnten Sie diese Klasse als Template-Parameter in std passieren :: vector <> und std :: map <> und so weiter.

Hüten Sie sich vor, ich habe gehört, dass solche Dinge zu tun, mit Schwierigkeiten behaftet ist, aber zumindest werden Sie viel mehr über die STL diese Art und Weise lernen. Und Sie brauchen nicht Ihre Container und Algorithmen neu zu erfinden.

Andere Tipps

In der Zwischenzeit gab es einige weitere Entwicklungen (nicht so sehr im Hinblick auf die CUDA-API, aber zumindest in Bezug auf die Projekte eine STL-ähnlichen Ansatz zu CUDA Datenmanagement versucht).

Vor allem gibt es ein Projekt von NVIDIA Forschung: Schub

  

Hat jemand Informationen über zukünftige Entwicklungen CUDA haben, die in dieser allgemeinen Richtung gehen (seien wir ehrlich: C-Schnittstellen in C ++ s * ck)?

Ja, ich habe etwas getan wie folgt aus:

https://github.com/eyalroz/cuda-api-wrappers/

  

nVIDIAs Runtime API für CUDA ist für den Einsatz sowohl in C und C ++ Code bestimmt. Als solches ist es verwendet einen C-Stil-API, die unteren gemeinsamen Nenner (mit einigen bemerkenswerten Ausnahmen von Templat Funktion Überlastungen).

     

Diese Bibliothek von Wrapper um die Runtime API soll uns viele der Funktionen von C zu umarmen, damit ++ (einschließlich einiger C ++ 11) für die Laufzeit-API - aber ohne Expressivität zu reduzieren oder die Abstraktionsebene zu erhöhen (wie in, zum Beispiel, die Schub-Bibliothek). CUDA-api-Wrapper verwenden, können Sie immer noch Ihre Geräte haben, Bäche, Veranstaltungen und so weiter - aber sie wird bequemer mit mehr C zu arbeiten ++ -. idiomatischen Möglichkeiten

Es gibt mehrere Projekte, die etwas ähnliches, zum Beispiel versuchen, CUDPP .

In der Zwischenzeit aber ich habe mein eigenes allocator umgesetzt und es funktioniert gut und war einfach (> 95% Standardcode).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top