-1

我正在用 C++ 和 OpenCL 开发这个测试应用程序,但我只是不明白为什么我会遇到这个非常奇怪的问题,这会进一步导致分段错误。

部分代码:

output = new cl_float[TestCount*TrainCount]; // output array
output_buf = new cl::Buffer(*context, CL_MEM_WRITE_ONLY, sizeof(cl_float)*TestCount*TrainCount, NULL);
// .... some more stuff
queue->enqueueReadBuffer(*output_buf, CL_TRUE, 0, TestCount*TrainCount, output);

这里, output 和 output_buf 是指向它们各自数据的指针。

当我在处理完所有内容后尝试访问输出数组的任何元素时,就会发生段错误。经过进一步调试,我发现它存储的最大元素数是 562,而应该是 2250(TestCount=150,TrainCount=15)。此外,令人惊讶的是,我可以访问 GDB 中的任何元素,但不能访问 562 以上的元素。

我毫不怀疑代码中没有错误,并且我绝对确定所有 2250 输出都由 GPU 处理。这是通过在每个线程中以原子方式递增输出数组的第一个元素然后通过 GDB 输出来进行测试的。

似乎我已经排除了很多可能性,但我仍然无法弄清楚是什么导致了这个问题。堆被填满的可能性很小,但我发现我的应用程序只使用了 37M 的内存。

任何帮助,将不胜感激!

更新:詹姆斯是对的。这是因为没有从内存中读取足够的字节。段故障的回溯如下 -

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x000000000000000c
0x0000000100002402 in main (argc=4, argv=0x7fff5fbffb88)
    at TestApplication.cpp:202
202     cout << OpenCL_KNN::output[0] << " " << OpenCL_KNN::output[1] << " " << OpenCL_KNN::output[2] << " " << OpenCL_KNN::output[3];

被访问的 4 个索引是明确定义的。在这行之前没有给我任何错误。除了我之前提到的以外,输出数组不会在任何地方更改/创建。

更新 2:错误已解决。它只发生在 Mac OS X 中。它与我访问输出的方式有关。一旦我在 OpenCL_KNN 命名空间中创建了一个返回输出的函数,它就会完美运行。

4

2 回答 2

2

我不熟悉 CL 的 C++ 包装器,但我猜这是从 GPU 读取的字节太少TestCount*TrainCount的一个因素。sizeof(cl_float)您的代码应该是:

queue->enqueueReadBuffer(*output_buf, CL_TRUE, 0, sizeof(cl_float)*TestCount*TrainCount, output);

但是,这并不能解释您的段错误。也许您在其他地方也犯了同样的错误?

于 2012-07-12T03:34:24.930 回答
0

发生此错误是因为您正在访问未初始化或正在删除的内存。错误在这行代码中。

queue->enqueueReadBuffer(*output_buf, CL_TRUE, 0, TestCount*TrainCount, output);

检查代码中的每个对象和变量(指针)是否已正确初始化。完成后,此错误将消失。不必在指定的代码行上生成错误,它可能发生在您访问的位置一个未初始化的内存地址。

于 2012-07-12T04:20:05.657 回答