Frage

Ich habe eine Klasse (siehe Beispiel unten) das wirkt wie ein .NET wrapper für eine CUDA-Speicher-Struktur,
reserviert mit cudaMalloc() und verwiesen mit einem Mitglied Gebiet der Typ IntPtr.
(Die Klasse verwendet DllImport einer nativen C # - DLL, die wraps, verschiedene CUDA-Funktionalität.)

Die dispose-Methoden prüft, ob der Zeiger IntPtr.Null, und wenn nicht fordert, cudaFree()
die erfolgreich plant den Speicher (gibt CUDA Erfolg)
und setzt den Zeiger auf IntPtr.Null.

Die finalize-Methode ruft die dispose-Methode.

Das problem ist, dass, wenn Sie die finalize-Methoden aufgerufen wird, der die dispose aufgerufen wird, zuvor,
dann den cudaFree () - Funktion wird ein Fehlercode "invalid device"Zeiger".

Ich habe überprüft, und die Adresse der cudaFree() erhält die gleiche Adresse zurückgegeben, die von der cudaMalloc() und kein dispose() aufgerufen wurde zuvor.

Wenn ich eine explizite Aufruf von dispose() auf die gleiche Adresse erfolgreich befreit.

Die einzige Problemumgehung, die ich fand, war nicht die dispose-Methode aus der finalizer allerdings dazu führen, dass ein Speicherverlust, wenn Sie dispose() wird nicht immer aufgerufen wird.

Irgendwelche Ideen, warum dies geschieht?- Ich hatte das gleiche Problem mit CUDA 2.2 und 2.3 unter .NET 3.5 SP1 auf Windows Vista 64bit + GeForce 8800 und auf Windows-XP-32bit + Quadro FX (nicht sicher, welche Nummer).

class CudaEntity : IDisposable
{
    private IntPtr dataPointer;

    public CudaEntity()
    {
        // Calls cudaMalloc() via DllImport,
        // receives error code and throws expection if not 0
        // assigns value to this.dataPointer
    }

    public Dispose()
    {
        if (this.dataPointer != IntPtr.Zero)
        {
            // Calls cudaFree() via DllImport,
            // receives error code and throws expection if not 0

            this.dataPointer = IntPtr.Zero;
        }
    }

    ~CudaEntity()
    {
        Dispose();
    }
}
{
    // this code works
    var myEntity = new CudaEntity();
    myEntity.Dispose();
}
{
    // This code cause a "invalid device pointer"
    // error on finalizer's call to cudaFree()
    var myEntity = new CudaEntity();
}
War es hilfreich?

Lösung

Das problem ist, dass Finalizer ausgeführt werden, auf der GC-thread, CUDA Ressource zugewiesen in einem thread kann nicht verwendet werden in eine andere.Ein Ausschnitt aus der CUDA programming guide:

Mehrere host-threads ausführen kann Geräte-code auf dem gleichen Gerät, aber durch design, eine host-thread ausführen kann Geräte-code auf nur einem Gerät.Als Folge, die mehrere host-threads erforderlich zum ausführen von code auf dem Gerät mehrere Geräte.Auch CUDA Ressourcen erstellt, über die Laufzeit in einem host-thread kann nicht verwendet werden die Laufzeitumgebung von einem anderen host-thread.

Ihre beste Wette ist zu verwenden using Anweisung, die dafür sorgt, dass die Dispose() Methode wird immer aufgerufen, am Ende der 'geschützten' code-block:

using(CudaEntity ent = new CudaEntity())
{

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