繁体   English   中英

OpenCL的enqueueWriteBuffer导致__memcpy_sse2_unaligned分段错误

[英]OpenCL's enqueueWriteBuffer causes __memcpy_sse2_unaligned segmentation fault

我有以下OpenCL代码,使用C ++包装程序和Intel的OpenCL工具包:

#include <Eigen/StdVector>

...

typedef Sample_t float
typedef std::vector<Sample_t, Eigen::aligned_allocator<Sample_t> > SampleArray;

...

SampleArray data(ns * nt);

...

mdata = cl::Buffer(context, CL_MEM_READ_ONLY, sizeof(Sample_t) * data.size());
queue.enqueueWriteBuffer(mdata, CL_FALSE, 0, sizeof(Sample_t) * data.size(), &data[0]);

当使用-O3,march = native和mtune = native标志进行编译时,它将导致以下来自TBB代码的分段错误:

__memcpy_sse2_unaligned()at memcpy-sse2-unaligned.S:116 0x7ffff6e64ba4

没有任何优化,该程序运行良好。

我将问题追溯到queue.enqueueWriteBuffer调用,没有它我什么都没有。

我试图注释掉修改变量“数据”的代码部分,以防万一我访问无效的内存位置,但是问题仍然存在。

如果我从std :: vector中删除了aligned_allocator,则没有优化的构建也会开始中断。

我总共有70MB试图存储在此缓冲区中,这远远小于CL_DEVICE_MAX_MEM_ALLOC_SIZE报告的3.8GB。 但是,如果我减小数组的大小,问题就停止了。 我在以后的案例中尝试的大小为5。

我还决定打印由向量分配的地址,它是0x7f21b797f010,因此它至少与16个字节对齐。

编辑:关于多线程,数组的创建以及OpenCL操作以相同的方法在主线程中进行。 没有使用异步标志创建命令队列,并且在写入缓冲区后执行了flush()操作。

可能是什么问题呢?

谢谢

如评论中的对话所确认,这里的问题是enqueueWriteBuffer()操作是非阻塞的(将CL_FALSE作为阻塞参数传递),并且在保证底层复制操作之前,源缓冲区( SampleArray向量)超出了范围完成。

至少有4种可能的解决方案:

  1. 使用enqueueWriteBuffer()的阻塞形式。 如文档所示,在这种情况下,一旦函数返回,就不会访问源缓冲区。
  2. 捕获返回的事件,并在SampleArray()超出范围之前调用clWaitForEvents()或调用clFinish() 如果您的程序在此期间做任何实质性的工作,则这实际上仅比阻塞变量好。
  3. 使源数据保留足够长的时间。
  4. 不要使用enqueueWriteBuffer()的复制形式:创建一个带有NULL源的缓冲区,将其映射到应用程序的内存空间,将数据写入其中,然后取消映射。 这样至少可以避免在集成GPU / APU上完全复制)

这些大致按并行度/效率的升序排列。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM