Wie kann eine große Anzahl von Zuweisungen zu demselben Array einen pyopencl.LogicError verursachen, wenn er auf einer GPU ausgeführt wird?

Ich benutze pyOpenCL, um einige komplexe Berechnungen durchzuführen. Es läuft gut auf der CPU, aber ich bekomme eine Fehlermeldung, wenn ich versuche, es auf einer NVIDIA GeForce 9400M (256 MB) auszuführen. Ich arbeite an Mac OS X Lion (10.7.5)

Das Merkwürdige ist, dass dieser Fehler nicht immer auftritt. Es scheint aufzutreten, wenn meine Berechnungen größere Zahlen verwenden (was zu größeren Iterationen führt), aber nur, wenn sie auf einer GPU ausgeführt werden.

Ich schreibe nicht an Speicherorte, an die ich nicht schreiben soll. Ich habe mögliche Probleme mit gleichzeitigen Änderungen ausgeschlossen, indem ich den Code als einzelnes Arbeitselement ausgeführt habe.

Ich habe meinen OpenCL-Code so weit wie möglich vereinfacht und aus dem, was übrig geblieben ist, einen sehr einfachen Code mit einem extrem seltsamen Verhalten erstellt, das das verursachtpyopencl.LogicError. Es besteht aus 2 verschachtelten Schleifen, in denen ein paar Zuweisungen an dieresult Array. Diese Zuordnung muss nicht einmal vom Zustand der Schleife abhängen. Dies wird auf einem einzelnen Thread (oder Workitem,shape = (1,)) auf der GPU.

__kernel void weirdError(__global unsigned int* result){
    unsigned int outer = (1<<30)-1;
    for(int i=20; i--; ){
        unsigned int inner = 0;
        while(inner != outer){
            result[0] = 1248;
            result[1] = 1337;
            inner++;
        }
        outer++;
    }
}

Der seltsame Teil ist, dass das Entfernen einer der Zuweisungen zum Ergebnis-Array den Fehler beseitigt. Verringern Sie außerdem den Anfangswert für Outer (bis auf(1<<20)-1 zum Beispiel) behebt auch den Fehler. In diesen Fällen wird der Code normal mit dem richtigen Ergebnis im entsprechenden Puffer zurückgegeben. Auf der CPU wird niemals ein Fehler ausgelöst.

Der OpenCL-Code wird in Python mit PyOpenCL ausgeführt.

Nichts Besonderes im Setup:

platform = cl.get_platforms()[0]
device = platform.get_devices(cl.device_type.GPU)[0]
context = cl.Context([device])
program = cl.Program(context, getProgramCode()).build()
queue = cl.CommandQueue(context)

In diesem Python-Code habe ich dieresult_buf zu0, dann führe ich die Berechnung in OpenCL aus, die ihre Werte in einer großen Iteration setzt. Danach versuche ich, diesen Wert aus dem Gerätespeicher zu sammeln, aber das ist, wo es schief geht:

result = numpy.zeros(2, numpy.uint32)
result_buf = cl.Buffer(context, mem_flags.READ_WRITE | mem_flags.COPY_HOST_PTR, hostbuf=result)

shape = (1,)
program.weirdError(queue, shape, None, result_buf)

cl.enqueue_copy(queue, result, result_buf)

Die letzte Zeile gibt mir:

pyopencl.LogicError: clEnqueueReadBuffer failed: invalid command queue

Wie kann diese wiederholte Zuordnung einen Fehler verursachen?

Und was noch wichtiger ist: Wie kann dies vermieden werden?

Ich verstehe, dass dieses Problem wahrscheinlich plattformabhängig ist und daher möglicherweise schwer zu reproduzieren ist. Dies ist jedoch die einzige Maschine, auf die ich Zugriff habe, sodass der Code auf dieser Maschine funktionieren sollte.

HAFTUNGSAUSSCHLUSS: Ich habe noch nie mit OpenCL (oder CUDA) gearbeitet. Ich habe den Code auf einem Computer geschrieben, auf dem die GPU OpenCL nicht unterstützt. Ich habe es immer auf CPU getestet. Nachdem ich auf GPU umgestiegen bin, finde ich es frustrierend, dass Fehler nicht immer auftreten und ich keine Ahnung habe, warum.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage