【问题标题】:Opencl buffer with already deleted host pointer已删除主机指针的 Opencl 缓冲区
【发布时间】:2012-10-10 15:00:56
【问题描述】:

我有一种情况,我(可能)想尝试使用std::vector(或更准确地说是它的存储)作为带有CL_MEM_USE_HOST_PTR 的opencl buffer 对象的主机指针。如果调整vector 的大小并因此重新分配其内存,这显然会出现问题。对我的vector 的修改是在程序的各个阶段,其中不使用buffer,所以我的想法是检查缓冲区的主机指针是否与指向@987654327 第一个元素的指针相同@ 如果不是这种情况,则重新创建缓冲区。我的问题是,如果 buffer 未被使用,我无法确定拥有一个主机指针已被释放的 buffer 是否合法。

我当然可以在使用它的阶段结束时销毁缓冲区,但是我事先不知道向量内容和/或长度是否被修改,如果没有,我宁愿保留旧缓冲区,因为 afaik 可以使其保持缓存在设备上,从而减少需要通过 pci-e 总线传输的数据量。

我的问题是:如果只存在buffer 对象,是否允许有一个opencl bufferCL_MEM_USE_HOST_PTR 的主机指针已经删除了主机指针,但不在内核中使用。

据记录,我目前正在针对 nvidias opencl 实现进行开发,使用 Tesla 2070 作为 gpu,并且该软件可能会在不久的将来移植到 amd gpus/cpus(后者是使用 @987654333 的主要原因@)。因此,如果答案是特定于实现的,那么这些是主要目标,尽管我对一般答案更感兴趣,因为我不知道以后还会运行什么。

【问题讨论】:

    标签: c++ opencl


    【解决方案1】:

    我相信,如果您不尝试更改 OpenCL 实现下的缓冲区,那会更安全。正如您所建议的,这可能会带来问题。例如:

    vector<int> v(25);
    cl_mem buf = clCreateBuffer(.v.data(),.CL_MEM_USE_HOST_PTR,...);
    v.resize(1000); //Or some other way of changing the size of the stack
    clReleaseMemObject(buf);
    

    当内存被释放时,它会尝试将数据同步回原始缓冲区(已被释放),这可能会导致段错误或其他一些令人讨厌的内存问题。

    根据this thread 上的一些讨论,应该假设一旦您使用CL_MEM_USE_HOST_PTR 标志调用 clCreateBuffer,您已经将该内存的控制权交给了 OpenCL 平台,并且您只能使用以下命令回收该内存释放该内存缓冲区的调用。

    虽然在您的具体实施中可能不是这种情况,但我认为总体而言最好发布数据。这样,如果您的底层系统在未来发生变化,您将不会看到与此行为相关的错误。

    或者,您可以扩展矢量类,以便在调整基础数据结构的大小时,您可以在设备上释放和重新分配数据。不过,我不确定这会有多困难,或者它会对您的程序的其余部分产生多大影响。

    【讨论】:

    • 这就是我所害怕的。呃,好吧。我可能会考虑编写一个自定义分配器以与std::vector 一起使用,它管理一个底层缓冲区
    【解决方案2】:

    您的问题的答案取决于用于创建缓冲区的标志。如果您使用 CL_MEM_ALLOC_HOST_PTR 或 CL_MEM_COPY_HOST_PTR 调用 clCreateBuffer,则 OpenCL 实现已经拥有您提供的主机位置内容的副本(在 CL_MEM_ALLOC_HOST_PTR 的情况下,也许 - 它应该用于 GPU 实现)。现在您可以随意使用该主机指针做任何您想做的事情,而 OpenCL 实现并不关心。

    另一方面,如果您使用 CL_MEM_USE_HOST_PTR(我不认为您这样做,甚至可以,因为这是一个 GPU 设备),那么内核很可能会在执行时崩溃或提供垃圾结果(基于现在那个位置有什么)。

    希望这会有所帮助!

    【讨论】:

    • 哦,抱歉,我的意思是使用CL_MEM_USE_HOST_PTR,忘记在问题中提及这一点(尽管我希望这很清楚,因为那可能会出现问题)。我将把它添加到问题中。而且(这还不清楚吗?)我不想使用该缓冲区调用内核,问题是它是否仍然会崩溃,如果缓冲区只是存在但未使用
    • 如果您在 GPU 设备上使用 CL_MEM_USE_HOST_PTR,我看不出该实现有什么选择,只能制作副本以传输到 GPU,因此应该没有区别。根据文档:OpenCL 实现允许将 host_ptr 指向的缓冲区内容缓存在设备内存中。当内核在设备上执行时可以使用此缓存副本。如果内容在缓冲区创建期间被缓存,则对底层指针执行任何操作都不应影响 GPU/驱动程序内存中的设备缓冲区内容。
    • @anathonline:我希望它以某种方式这样做(这意味着对于内核的执行,数据可能最终会出现在图形内存中(尽管我不确定这是否真的是必要的))。但这并不能真正回答问题。
    • 见我评论的最后一句话:如果内容在缓冲区创建期间被缓存,对底层指针做任何你想做的事情都不会影响GPU/驱动内存中的设备缓冲区内容。是的 - 对于内核执行,您的数据 HAS 必须在 GPU 内存中。这也非常依赖于实现,其他一些 CPU/GPU(比如 AMD 的 Fusion)可能会做其他事情。最好使用 DeviceType 来确定您是要复制还是共享 - 这是我在我的应用程序中所做的。
    • 我不希望它这样做,但这并不能保证它不会在任意时间(例如写回)访问主机上的实际数据。我希望它不会,但是基于代码的正确性并不是一个好主意)。此外,在创建缓冲区期间不需要缓存数据(从我读过的内容来看,它可能不需要,因为 gpu 可能能够自己获取它),所以在使用缓冲区时对指针做任何事情可能是个坏主意。我只是不确定是否有任何保证它不会在任意时间点访问数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-09
    • 2019-05-05
    • 1970-01-01
    • 1970-01-01
    • 2013-01-11
    • 1970-01-01
    • 2016-12-03
    相关资源
    最近更新 更多