OpenCL&x27;s排队写入缓冲区导致u memcpy_sse2_未对齐分段错误 我有以下OpenCL代码,使用C++包装器和英特尔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]); #包括 ... typedef样本浮点数 typedef std::向量采样阵列; ... 样本阵列数据(ns*nt); ... mdata=cl::Buffer(上下文,cl\u MEM\u只读,sizeof(Sample\u t)*data.size()); queue.enqueueWriteBuffer(mdata,CL_FALSE,0,sizeof(Sample_t)*data.size(),&data[0]);

OpenCL&x27;s排队写入缓冲区导致u memcpy_sse2_未对齐分段错误 我有以下OpenCL代码,使用C++包装器和英特尔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]); #包括 ... typedef样本浮点数 typedef std::向量采样阵列; ... 样本阵列数据(ns*nt); ... mdata=cl::Buffer(上下文,cl\u MEM\u只读,sizeof(Sample\u t)*data.size()); queue.enqueueWriteBuffer(mdata,CL_FALSE,0,sizeof(Sample_t)*data.size(),&data[0]);,c++,segmentation-fault,opencl,memory-alignment,C++,Segmentation Fault,Opencl,Memory Alignment,当使用-O3、march=native和mtune=native标志编译时,会导致TBB代码出现以下分段错误: __memcpy_sse2_unaligned()位于memcpy-sse2-unaligned.S:116 0x7ffff6e64ba4 没有任何优化,程序运行良好 我将问题追溯到queue.enqueueWriteBuffer调用,没有它我就没有任何问题 我试图注释掉修改变量“data”的代码部分,以防访问无效的内存位置,但问题仍然存在 如果我从std::vector中删除对齐的_

当使用-O3、march=native和mtune=native标志编译时,会导致TBB代码出现以下分段错误:

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

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

我将问题追溯到queue.enqueueWriteBuffer调用,没有它我就没有任何问题

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

如果我从std::vector中删除对齐的_分配器,那么没有优化的构建也会开始中断

总的来说,我试图在这个缓冲区中存储70MB,远低于CL_DEVICE_MAX_MEM_ALLOC_SIZE报告的3.8GB。但是如果我减小数组的大小,问题就停止了。我在后面的案例中尝试的尺寸是5

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

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

有什么问题吗


谢谢

正如在评论中的对话中所确认的,这里的问题是
enqueueWriteBuffer()
操作是非阻塞的(
CL\u FALSE
作为阻塞参数传递),并且源缓冲区(
SampleArray
vector)在基础复制操作保证完成之前超出范围

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

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

  • 这些基本上是按照并行性/效率的递增顺序进行的。

    正如在注释中的对话中确认的,这里的问题是
    enqueueWriteBuffer()
    操作是非阻塞的(
    CL\u FALSE
    作为阻塞参数传递),并且源缓冲区(
    SampleArray
    vector)在基础复制操作保证完成之前超出范围

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

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

  • 这些基本上是按照并行性/效率的递增顺序排列的。

    请向下投票人澄清原因,以及偏离主题的结束请求?因为您使用的是异步写入,在确保
    enqueueWriteBuffer
    操作完成之前,您是否确保不会销毁/调整SampleArray的大小?@pmdj数组的创建以及OpenCL操作在同一方法和主线程中发生。我已编辑了包含更多信息的问题。clFlush不保证复制操作将完成,只保证复制操作将开始。您需要等待事件触发,或者将true作为“阻塞”参数传递。当向量超出范围时,OpenCL可能仍在忙于复制数据。事实上,添加clFinish解决了这个问题。请将此转换为正式答案,以便我可以标记它。downvoter可以,请,澄清原因,以及脱离主题的结束请求?因为您使用的是异步写入,在确保
    enqueueWriteBuffer
    操作完成之前,您是否确保不会销毁/调整SampleArray的大小?@pmdj数组的创建以及OpenCL操作在同一方法和主线程中发生。我已编辑了包含更多信息的问题。clFlush不保证复制操作将完成,只保证复制操作将开始。您需要等待事件触发,或者将true作为“阻塞”参数传递。当向量超出范围时,OpenCL可能仍在忙于复制数据。事实上,添加clFinish解决了这个问题。请把这个正式地变成一个答案,这样我就可以标记它了。