2012-03-31 8 views
1

Ich habe ein Problem wie folgt. Grundsätzlich habe ich ein 2D-Gitter auf dem Host zugewiesen:OpenCL Random-Kernel-Verhalten, wenn bestimmte Systemgröße überschritten wird

double* grid = (double*)malloc(sizeof(double)*(ny*nx) * 9); 

folllowing normalen OpenCL Verfahren es auf dem OpenCL-Gerät zu setzen:

cl_mem cl_grid = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, sizeof(double) * (ny*nx) * 9, grid, &error); 

Und Enqueue und Start:

clEnqueueNDRangeKernel(queue, foo, 1, NULL, &global_ws, &local_ws, 0, NULL, NULL); 

In Die Kernfunktion, einfache Arithmetik wird in der ersten Spalte des Gitters durchgeführt:

__kernel void foo(__constant ocl_param* params, __global double* grid) 
{ 
    const int ii = get_global_id(0); 
    int jj; 
    jj=0; 

    if (ii < params->ny) { 
     grid[getIndexUsingMacro(ii,jj)] += params->someNumber; 
    } 
} 

Und schließlich lesen Sie den Puffer zurück und überprüfen Sie die Werte.

clEnqueueReadBuffer(queue, cl_grid, CL_TRUE, 0, sizeof(double) * 9 * nx * ny, checkGrid, 0, NULL, NULL); 

Das Problem ist, wenn die Rastergröße (d.h. nx ny * * 9) 16384 überschreitet * 9 * 8 Bytes = 1152KB (* 8, da doppelte Genauigkeit verwendet wird).

  • wenn OpenCL auf CPU verwendet, wird ein Fehler CL_OUT_OF_RESOURCES ausgelöst, wenn unabhängig von der Kernel startet, was ich für global_ws und local_ws gesetzt (ich setze sie auf 1 gesetzt und der Fehler ausgelöst wird, nach wie vor). Die CPU ist ein Intel i5 2415m mit 8GB RAM und 3MB Cache.

  • Wenn openCL auf der GPU (NVIDIA TESLA M2050) verwendet wird, wird kein Fehler ausgelöst. Beim Zurücklesen des Werts aus dem Puffer wird das Raster jedoch überhaupt nicht geändert. Es bedeutet, dass es das Gitter zurückgibt, dessen Werte genau dieselben sind wie vor dem Senden an die Kernel-Funktion.

Für z.B. Wenn ich nx = 30, ny = 546, nx * ny = 16380 setze, läuft alles gut. Das mit den Ergebnissen zurückgegebene Raster wurde wie erwartet geändert. Aber wenn ny = 547, nx * ny = 16410, tritt das Problem sowohl bei CPU als auch bei GPU auf, wie oben beschrieben. Das Problem ist dasselbe, wenn ich nx und ny vertausche, also wenn nx = 547, ny = 30, passiert es immer noch. Können Sie uns vorschlagen, was das Problem hier sein könnte?

Vielen Dank

Antwort

1

Es sieht aus wie ein Synchronisationsproblem. grid[index] += value mit demselben index Wert kann gleichzeitig von mehreren Arbeitselementen ausgeführt werden. Diese Operation ist nicht atomar, und alle diese Arbeitselemente laden grid[index], fügen ihren Wert hinzu und speichern sie zurück, wobei sie möglicherweise einige Inkremente im Prozess verlieren.

Um dies zu lösen, können Sie diese Arbeitselemente mit barrier synchronisieren, wenn sie sich in einer einzigen Arbeitsgruppe befinden, oder andere Kernel in die Warteschlange stellen.

Eine weitere Möglichkeit besteht darin, sicherzustellen, dass nur ein Arbeitselement ein bestimmtes Element des Rasters ändern kann (normalerweise die beste Lösung).

Wenn mehrere Arbeitsaufgaben an einer gemeinsamen Teilmenge des Gitters arbeiten müssen, kann die Verwendung von lokalem Speicher und lokalen Speicherbarrieren hilfreich sein.

+0

Sie können Barrieren nicht sicher verwenden, wenn Sie nur eine Arbeitsgruppe in die Warteschlange stellen. Eine Barriere in OpenCL stellt die Synchronisierung für alle Arbeitselemente in einer Arbeitsgruppe bereit, synchronisiert jedoch nicht den Zugriff zwischen Arbeitsgruppen. – sbabbi

+0

Nun, das meinte ich mit "wenn sie in einer einzigen Arbeitsgruppe sind". –

Verwandte Themen