对于一个研究项目,我正在构建一个软件,能够使用工作大小偏移将内核的执行分配到不同的OpenCL设备上。我正在使用JavaCL。出于某种原因,同样的分段错误不断出现:
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [libc++abi.dylib+0x25a13] __dynamic_cast+0x29
C [OpenCL+0x1c775] clGetKernelWorkGroupInfo+0x9e1
C [OpenCL+0x1ca64] clEnqueueNDRangeKernel+0x65
C [libbridj.dylib+0xd882] dcCall_x64_sysv+0x61
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j com.nativelibs4java.opencl.library.OpenCLLibrary.clEnqueueNDRangeKernel(JJIJJJIJJ)I+0
...
我正在测试三个内核: Mandelbrot set ,矩阵乘法和 Conway的生命游戏。奇怪的是,一切都适用于Mandelbrot内核。有时其他工作,有时我得到段错误(具有相同的输入配置)。它们之间的唯一区别(我能想到的)是Mandelbrot集不是在输入缓冲区上运行,其他内核是。我不确定这是否会对这个问题产生任何影响。什么可能导致这个奇怪的错误?
我正在使用MacBook Pro,i7 2.6GHz,OSX 10.9.4。我正在使用的设备:
Device: HD Graphics 4000
Hardware version: OpenCL 1.2
Driver version: 1.2(Jun 9 2014 13:24:09)
OpenCL version: OpenCL C 1.2
Compute units: 16
Clock frequency: 1200
Maximum work item sizes: 512, 512, 512
Device: GeForce GT 650M
Hardware version: OpenCL 1.2
Driver version: 8.26.26 310.40.45f01
OpenCL version: OpenCL C 1.2
Compute units: 2
Clock frequency: 900
Maximum work item sizes: 1024, 1024, 64
源代码:
val globalWorkSizes = Array(length.x, length.y)
val localWorkSizes:Array[Long] = null
val worksizeOffset = Array(offset.x, offset.y)
val result = clQueue.synchronized {
val event = kernel.enqueueNDRange(clQueue, worksizeOffset, globalWorkSizes, localWorkSizes)
val resultPointer = outBuffer.map(clQueue, CLMem.MapFlags.Read, offset, length, event)
clQueue.flush()
val floats = resultPointer.getFloats
resultPointer.release()
outBuffer.release()
floats
}
答案 0 :(得分:0)
好的,所以我查看了一个开源的OpenCL实现(pocl),以找出可能导致segfault的原因。事实证明“clEnqueueNDRangeKernel”会像这样调用“clGetKernelWorkGroupInfo”:
size_t preferred_wg_multiple;
cl_int retval =
POname(clGetKernelWorkGroupInfo)
(kernel, command_queue->device,
CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE,
sizeof (size_t), &preferred_wg_multiple, NULL);
这是我唯一的线索,我在我的内核上调用了JavaCL的“getPreferredWorkGroupSizeMultiple”,然后我将它排队读取值并看看发生了什么:
val multiple = kernel.getPreferredWorkGroupSizeMultiple()(device)
Logger.debug("Multiple: " + multiple)
val event = kernel.enqueueNDRange(clQueue, worksizeOffset, globalWorkSizes, localWorkSizes)
奇怪的是,似乎只是调用此函数可以消除这个问题。我不确定这是否算作问题的答案,但它解决了问题。如果有人能想到合理的言论,我将很高兴听到它。