clGetKernelWorkGroupInfo中的JavaCL / OpenCL分段错误

时间:2014-09-17 12:01:38

标签: java java-native-interface segmentation-fault opencl

对于一个研究项目,我正在构建一个软件,能够使用工作大小偏移将内核的执行分配到不同的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
}

1 个答案:

答案 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)

奇怪的是,似乎只是调用此函数可以消除这个问题。我不确定这是否算作问题的答案,但它解决了问题。如果有人能想到合理的言论,我将很高兴听到它。