2016-08-12 3 views
1

Ich möchte einen globalen Zähler in OpenCL haben, die von jedem Arbeitselement in jeder Arbeitsgruppe erhöht werden kann.Wie atomare Inkrementierung eines globalen Zählers in OpenCL

In meinem Kernel ich tun:

#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable 

void increase(volatile __global int* counter) 
{ 
    atomic_inc(counter); 
} 

__kernel void test() 
{ 
    volatile __global int* counter = 0; 
    increase(counter); 
    printf("Counter: %i",&counter); 
} 

Mein HOSTCODE Minimum PyOpenCL ist die Kernel einzureihen:

import pyopencl as cl 

platform = cl.get_platforms()[0] 
devs = platform.get_devices() 
device = devs[0] 
ctx = cl.Context([device]) 
queue = cl.CommandQueue(ctx) 
mf = cl.mem_flags 

f = open('Minimal.cl', 'r') 
fstr = "".join(f.readlines()) 
prg = cl.Program(ctx, fstr).build() 
test_knl = prg.test 

def f(): 
    cl.enqueue_nd_range_kernel(queue,test_knl,(1,1,2),None) 
f() 

ich einen Ausgang erwarten, eine (möglicherweise zufällig bestellt) Aussehen von "Counter: i" zu zeigen, Dabei ist i die Anzahl der gesamten Arbeitselemente (in meinem Fall 2). Stattdessen bekomme ich keinen Ausdruck. Wenn ich das Programm erneut ausführen, schlägt es mit

pyopencl.cffi_cl.LogicError: clcreatecontext failed: <unknown error -9999> 

töten meine IDE (Spyder) vollständig.

Antwort

3
volatile __global int* counter = 0; 

Das Erstellen eines Zeigers zum globalen Speicher ist nicht genug. Es muss einen globalen Speicher dahinter geben.

Es gibt zwei Möglichkeiten, zumindest:

1) Sie einen Programmbereich Variable erstellen können, wenn Sie OpenCL 2.0 verwenden Umsetzung:

void increase(volatile __global int* counter) 
{ 
    atomic_inc(counter); 
} 

__global int counter = 0; 

__kernel void test() 
{ 
    volatile __global int* counterPtr = &counter; 
    increase(counterPtr); // or increase(&counter); 
    printf("Counter: %i",*counterPtr); 
} 

2) Erstellen Sie eine OpenCL-Puffer und gibt sie durch einen Kernel Argument:

void increase(volatile __global int* counter) 
{ 
    atomic_inc(counter); 
} 

__kernel void test(__global int *counterArg) 
{ 
    volatile __global int* counterPtr = counterArg; 
    increase(counterPtr); // or increase(counterArg); 
    printf("Counter: %i",*counterPtr); 
} 
+0

Sieht gut aus, aber 1) für mich nicht funktioniert, weil ich nicht auf OpenCL bin 2 und 2) gibt mir die Fehlermeldung „ungültige Adressraum für pointee der Zeiger Argument __kernel Funktion __kernel void test (int * counterArg) " und " implizite Konvertierung vom Adressraum "private" zum Adressraum "global" wird im Initialisierungsausdruck nicht unterstützt volatile __global int * counterPtr = counterArg; " – Dschoni

+0

Wechsel zu __kernel void test (__ global int * counterArg) scheint den Trick zu machen. – Dschoni

Verwandte Themen