2017-04-05 1 views
1

Ich habe eine Klasse, die ich eine globale Variable zu instanziiert verwenden:Wie behandeln cudaFree auf global instanziiert Variablen

class BitUnpackPtrs 
{ 
public: 
    ushort* d_dataIn; 

    BitUnpackPtrs() : d_dataIn(NULL) {}; 

    ~BitUnpackPtrs() 
    { 
     cudaFree(d_dataIn); 
    } 

    void update(...) { ... } 
}; 

Die Klasse instanziiert wird global als Griff häufige Vergabe von CUDA-Speicher zu reduzieren. Wenn jedoch mein Programm beendet, CUDA-memcheck erzeugt eine Warnung:

Programm cudaErrorCudartUnloading getroffen (Fehler 29) aufgrund "Treiber heruntergefahren" auf CUDA-API-Aufruf zu cudaFree.

Was ist der richtige Weg, damit umzugehen? Ich könnte das cudaFree entfernen, aber wenn diese Klasse zu einem späteren Zeitpunkt auf einer nicht-globalen Ebene verwendet wird, würde dies zu einem Speicherverlust führen. Ich könnte ein Flag im Konstruktor verwenden, um anzugeben, wie der Speicher behandelt werden soll.

Alternativ gibt es eine Möglichkeit zu erkennen, ob der Cuda-Treiber heruntergefahren ist und cudaFree in diesem Fall nicht aufrufen?

+2

Instanziieren Sie keine globalen Objekte von Klassen, die Cuda-Laufzeit-API-Funktionen im Konstruktor oder Destruktor aufrufen oder aufrufen müssen. Die CUDA-Runtime-Initialisierung/Teardown kann sowohl beim Programmstart als auch beim Herunterfahren Probleme verursachen, je nachdem, was genau Sie im Klassenkonstruktor und Destruktor tun. Es gibt keine Möglichkeit zu erkennen, ob der cuda-Treiber heruntergefahren ist (auf eine Weise, die nicht in cuda-memcheck markiert ist) und nicht "cudaFree" in dieser Instanz aufzurufen. –

Antwort

1

Anstatt dieses Objekt global zu machen, instanziieren Sie es in Ihrer main()-Funktion (oder irgendwo, die von main() aufgerufen wird und die gesamte Ausführung Ihrer Anwendung umschließt). Dadurch wird sichergestellt, dass Ihr Anruf cudaFree() vor dem CUDA-Abbau aufgerufen wird. Eine andere Alternative ist die Verwendung eines std::shared_ptr mit einem custom deleter, der cudaFree() aufruft. Wenn Sie das tun, wird der cudaFree() Aufruf auftreten, nachdem der letzte "Benutzer" seine Kopie des freigegebenen Zeigers zerstört - das ist bevor main() getan wird und bevor CUDA abreißt.

+0

Ich erwog, einen gemeinsamen Zeiger zu verwenden, aber das globale Objekt ist tatsächlich Teil einer Bibliothek. Letztendlich denke ich, dass die wirkliche Lösung eine Umstrukturierung des Codes erfordert. Zur Zeit habe ich dem Konstruktor einen Parameter hinzugefügt, um die Speicherbehandlung des Destruktors anzuzeigen. Ich lasse einfach das System auf den cudaFree aufpassen. – AaronS

+0

@AaronS: Fair genug; Denken Sie jedoch daran, dass andere Benutzer diese Frage lesen und für sie die zweite Alternative möglicherweise noch relevant ist. – einpoklum

Verwandte Themen