(Извините, если подобная проблема уже была опубликована — я не был уверен, что искать.)
Привет,
Я использую PyOpenCl, и мой код ядра OpenCl ведет себя иначе (неправильно), когда я помещаю его в функцию, а не когда он является частью основной программы ядра. Он корректно работает на одном из моих ноутбуков Dell с графическим процессором Nvidia, но не на моем другом с графическим процессором Dell. Оба используют Ubuntu 16.04.
Я пишу очень грубую функцию фильтрации изображений для плавного смещения пикселей на нецелое значение, например. перевод изображения на (.25, 0) пикселей будет иметь такой эффект: `newPixelHere = oldPixelHere * .75 + oldPixelToTheLeft * .25.
Я приложил версию кода в редуксе, где простой 3d-массив используется как подставка для цветного изображения. Как я отмечал в комментариях к коду, функция filterImg () содержит код, идентичный закомментированному коду в основном теле, но основное тело работает, а функция — нет — она просто устанавливает «ret» в постоянное значение из 49. Более того, функция ведет себя, как и ожидалось, если я меняю «я<4 «до» я<3 «в основном цикле, или если я избегаю использования целых / и%.
Я только начинаю с программирования на OpenCl, и я, правда, не в себе, но я прочитал кое-что об использовании циклов с осторожностью в OpenCl. Опять же, это работает на моем графическом процессоре Nvidia, но не на моем Dell.
Наконец, хотя OpenCl правильно работал на моем графическом процессоре Dell до этой проблемы, я получал следующее предупреждение при запуске OpenCl:
beignet-opencl-icd: no supported GPU found, this is probably the wrong opencl-icd package for this hardware
(If you have multiple ICDs installed and OpenCL works, you can ignore this message)
Я не очень беспокоился об этом, так как думал, что у меня может быть установлено несколько ICD, так как в / etc / OpenCL / vendors / есть несколько записей:
~:ls -1 /etc/OpenCL/vendors/
intel-beignet-x86_64-linux-gnu.icd
mesa.icd
~:
… но опять же, я действительно не знаю, что я делаю. Любая помощь приветствуется, большое спасибо заранее.
Джереми.
код Python:
#!/usr/bin/python
import pyopencl as cl
import numpy as np
def printLs3d(ls3d):
# Utility to print "red" channel of 3d array.
for y in range(len(ls3d[0])):
print
for x in range(len(ls3d)):
if ls3d[x][y][0] == 0:
print "...",
else:
print "%03d" % ls3d[x][y][0],
def shadeImg(lsIn):
printLs3d(lsIn)
cntxt = cl.create_some_context()
queue = cl.CommandQueue(cntxt)
res = (len(lsIn)-1, len(lsIn[0])-1)
print
# Inputs
srcImgAr_buf = cl.Buffer(cntxt, cl.mem_flags.READ_ONLY |
#cl.mem_flags.COPY_HOST_PTR,hostbuf=np.array(list(pygame.surfarray.array3d(srcImg))))
cl.mem_flags.COPY_HOST_PTR,hostbuf=np.array(lsIn))
# Outputs
shadedImg = np.zeros((len(lsIn), len(lsIn[0]), len(lsIn[0][0])), dtype=np.uint8)
shadedImg_buf = cl.Buffer(cntxt, cl.mem_flags.WRITE_ONLY |
cl.mem_flags.COPY_HOST_PTR,hostbuf=shadedImg)
kernelPath = "/home/jeremy/dev/warp/testOpenClLoops/testOpenClLoops.c"with open(kernelPath) as f:
kernel = "".join(f.readlines())
bld = cl.Program(cntxt, kernel).build()
launch = bld.krShadeImg(
queue,
#srcImgAr.shape,
res,
None,
np.int32(res[0]),
np.int32(res[1]),
srcImgAr_buf,
shadedImg_buf)
launch.wait()cl.enqueue_read_buffer(queue, shadedImg_buf, shadedImg).wait()
printLs3d(shadedImg)testIn = [
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [100, 100, 100], [100, 100, 100], [100, 100, 100], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [100, 100, 100], [100, 100, 100], [100, 100, 100], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [100, 100, 100], [100, 100, 100], [100, 100, 100], [0, 0, 0], [100, 100, 100], [100, 100, 100], [0, 0, 0]],
[[0, 0, 0], [100, 100, 100], [100, 100, 100], [100, 100, 100], [0, 0, 0], [100, 100, 100], [100, 100, 100], [0, 0, 0]],
[[0, 0, 0], [100, 100, 100], [100, 100, 100], [100, 100, 100], [0, 0, 0], [100, 100, 100], [100, 100, 100], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [100, 100, 100], [100, 100, 100], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]]testAr = np.array(testIn, dtype=np.uint8)shadeImg(testAr)
Код ядра C ++, содержащийся в «/home/jeremy/dev/warp/testOpenClLoops/testOpenClLoops.c»:
void setArrayCell(int x, int y, int xres, int yres,
uchar* val,
__global uchar* ret)
{
if (x >= 0 && x < xres && y >= 0 && y < yres) {
int i = (x * yres + y) * 3;
ret[i] = val[0];
ret[i+1] = val[1];
ret[i+2] = val[2];
}
}void filterImg (unsigned int x, unsigned int y, int xres, int yres,
__global uchar* img,
uchar* ret) {
// This function contains identical code to the commented-out
// block in the main body, except some comments.
// The main body code works; this function doesn't. Why???
// Offset xy lookup to weigh influence of each neighbour.
// If xOfs == yOfs == 0, pixel (x,y) gets full weight.
// If xOfs == yOfs == 1, pixel (x+1,y+1) gets full weight.
float xOfs = .75f;
float yOfs = .5f;
for (int i=0; i<4; i++) { // ***WORKS IF YOU CHANGE 4 TO 3!
// Sample 2x2 grid of neighbouring pixels in this order:
// (x,y), (x+1,y), (x,y+1), (x+1,y+1)
int dx = i%2; // ***WORKS IF YOU SET dx AND dy TO CONSTANT 0 OR 1
int dy = i/2;
int xx = x + dx;
int yy = y + dy;
// Calculate weight of this pixel (not 100% sure this is correct)
float wx = dx == 0 ? xOfs : 1.0f-xOfs;
float wy = dy == 0 ? yOfs : 1.0f-yOfs;
float k = wy*wx;int address = (xx * yres + yy) * 3;
for (int j=0; j<3; j++) {
ret[j] += img[address+j]*k;
}
}
}
__kernel void krShadeImg(
int xres,
int yres,
__global uchar* img,
__global uchar* shadedImg)
{
unsigned int x = get_global_id(0);
unsigned int y = get_global_id(1);if (x < xres-1 && y < yres-1) {
uchar ret[3] = {0, 0, 0};
filterImg(x, y, xres, yres, img, ret);
// *** TO MAKE THE CODE WORK, comment out the above
// *** line and uncomment the following block.
/*
// Offset xy lookup to weigh influence of each neighbour.
// If xOfs == yOfs == 0, pixel (x,y) gets full weight.
// If xOfs == yOfs == 1, pixel (x+1,y+1) gets full weight.
float xOfs = .75f;
float yOfs = .5f;
for (int i=0; i<4; i++) {
// Sample 2x2 grid of neighbouring pixels in this order:
// (x,y), (x+1,y), (x,y+1), (x+1,y+1)
int dx = i%2;
int dy = i/2;
int xx = x + dx;
int yy = y + dy;
// Calculate weight of this pixel (not 100% sure this is correct)
float wx = dx == 0 ? xOfs : 1.0f-xOfs;
float wy = dy == 0 ? yOfs : 1.0f-yOfs;
float k = wy*wx;int address = (xx * yres + yy) * 3;
for (int j=0; j<3; j++) {
ret[j] += img[address+j]*k;
}
}
*/
setArrayCell(x, y, xres, yres, ret, shadedImg);
}
}
Вывод при использовании функции filterImg (не работает):
Before OpenCl process:
... ... ... ... ... ... ... ... ... ...
... 100 100 100 100 100 ... ... ... ...
... 100 100 100 100 100 ... ... ... ...
... 100 100 100 100 100 ... ... ... ...
... ... ... ... ... ... ... ... ... ...
... ... ... 100 100 100 100 ... ... ...
... ... ... 100 100 100 100 ... ... ...
... ... ... ... ... ... ... ... ... ...
After OpenCl process:
049 049 049 049 049 049 049 049 049 ...
049 049 049 049 049 049 049 049 049 ...
049 049 049 049 049 049 049 049 049 ...
049 049 049 049 049 049 049 049 049 ...
049 049 049 049 049 049 049 049 049 ...
049 049 049 049 049 049 049 049 049 ...
049 049 049 049 049 049 049 049 049 ...
... ... ... ... ... ... ... ... ... ...
Вывод при использовании основного кода тела (правильный):
Before OpenCl process:
... ... ... ... ... ... ... ... ... ...
... 100 100 100 100 100 ... ... ... ...
... 100 100 100 100 100 ... ... ... ...
... 100 100 100 100 100 ... ... ... ...
... ... ... ... ... ... ... ... ... ...
... ... ... 100 100 100 100 ... ... ...
... ... ... 100 100 100 100 ... ... ...
... ... ... ... ... ... ... ... ... ...
After OpenCl process:
012 049 049 049 049 037 ... ... ... ...
024 098 098 098 098 074 ... ... ... ...
024 098 098 098 098 074 ... ... ... ...
012 049 049 049 049 037 ... ... ... ...
... ... 012 049 049 049 037 ... ... ...
... ... 024 098 098 098 074 ... ... ...
... ... 012 049 049 049 037 ... ... ...
... ... ... ... ... ... ... ... ... ...
Задача ещё не решена.
Других решений пока нет …