Heterogeneous Compute SDK buffer FW_Two



  • 大家好,今天小白继续给大家简单分享下Hetcompute sdk中buffer相关的基础知识,欢迎一起交流学习。

    一、同步和并发使用

    1)跨主机代码和任务同步访问Buffer

    (1)当一个任务完成后,HetCompute不在通过任务自动同步所有Buffer的访问。主机代码必须通过显示同步才能访问有任务更新的Buffer数据。

    (2)不建议HetCompute在创建Buffer期间使用如下语句: buffer_mode::synchronized & buffer_mode::relaxed

    2)通过任务并发访问Buffer /-/

    (1)HetCompute runtime允许多个任务同时访问Buffer,但是前提是他们仅仅作为输入的Buffer。(2)Runtime确保以输出或输入输出方式访问缓冲区的任务不会与访问该缓冲区的其他任务同时执行。HetCompute不允许在Buffer被修改的时候,执行并发访问。

    (3)当一个并发任务和模式已经获取了Buffer的读写或者制度权限的时候,采集Buffer内容动作会被阻止。在极少数的情况下,当并发任务/模式具有只读访问权限时,采集Buffer内容也会被阻止。但在并发任务/模式完成之前,hetcompute无法同步用于主机访问的缓冲区数据。

    二、如何创建Buffer

    1)通过HetCompute使用完全管理存储。

    (1)用户需要指定buffer的数据类型和元素数量。HetCompute在内部管理所有分配的Buffer的存储空间。 auto b = hetcompute::create_buffer<int>(100);

    2用户提供初始化存储和数据=-09=(1)HetCompute runtime根据需要分配额外的备份存储,并将处理用户提供的存储和任何内部备份存储之间的同步。

                                    

    3)一个Memory区域

    (1)hetcompute::memregion允许用户分配专用内存或创建来自其它框架的可操作数据。

    (2)用户可以创建一个Buffer引用上一个已经创建过的memory区域。

    (3)如下是通过ION内存区域创建一个buffer

                                    

     三、使用Buffer对性能和存储进行优化

    1)HetCompute runtime试图利用一些高级的方式和知识访问设备的Buffer数据。当用户为特定设备创建任务时,可以从HetCompute的内部调度图获得路径,也可以直接从用户获取知识,作为创建缓冲区时提供的提示。

    2)HetCompute使用目前最流行的方法来合理的分配有限的资源(例如:ION内存管理),并且最大限度地减少专用后备存储之间的数据复制和同步步骤的使用。例如,如果预先知道DSP任务将访问缓冲区,则HetCompute可以在创建缓冲区时分配ION内存,即使访问缓冲区的第一个任务仅仅只在CPU和GPU上运行。将ION内存分配为后被存储可以有效的消除设置之间的所有数据备份副本。然而,如果事先不知道Hexagon任务会访问缓冲区,那么runtime会从开销更低的系统主内存中分配后备存储区。最后,执行Hexagon任务将强制分配ION后备存储,然后在主内存和ION后备存储之间进行数据复制

    3)如果不期望CPU访问缓冲区数据,则可以完全跳过主内存后备存储的分配,从而减少其内容必须保持同步的后备存储的数量。主机代码可以读取新写入的内容。

    4)存储与主机代码显示同步

    (1)HetCompute提供了一些API用于主机调用Buffer

             a、acquire_ro(): 主机代码获取只读Buffer权限。上一个任务的结果对主机可见。

             b、acquire_rw():  主机代码获取读写Buffer权限。上一个任务的结果对主机可见。主机代码对缓冲区数据的修改将对任何后                 续任务可见。

             c、acquire_rw():  主机代码上一个缓冲区内容无效。上一个任务返回的结果会丢失。缓冲区的全部内容将无效,保存主机代码同步写入的新内容。Buffer新的内容对于后续的任务是可见的。

    (2)Buffer同步允许主机代码通过任务访问已经更新的Buffer数据。acquire_ro()通过主机代码获取底层Buffer只读权限。主机代码也可以修改Buffer数据通过尝试获取底层Buffer的写权限,通过acquire_wi()或者acquire_rw()的Buffer API。

    (3)所有acquire_*请求出现冲突的时候将会被阻止,直到操作完成后(一个任务并发执行对一个Buffer的读写访问),获取缓冲区以供主机代码访问,并且调用解除阻塞。但是,如果在此之前acquire_()已经为主机代码获取了缓冲区,则调用立即返回。

    (4)主机代码可以使用acquire_ro(),acquire_wi()和acquire_rw()调用的组合递归地获取缓冲区。第一次使用的acquire_为主机代码建立Buffer写入模式(只读、写入无效或者读写)。只有当主机代码与上一次建立的访问类型兼容时,后续的递归acquire_调用才会成功。假如第一次递归获取是acquire_ro(),则后续递归的acquire_wi()和acquire_rw()调用将返回失败,因为这些调用的访问类型与已建立的只读访问不兼容。但是,如果第一次采集Buffer是写入无效或读写,则任何后续的acquire_()递归调用都将成功。

    (5)当建立的访问类型为写入无效时,后续的递归只读或读写采集会被认为可以访问在原始写入无效之后写入缓冲区的任何数据。当建立的访问类型是读写时,后续的递归写无效不会破坏任何先前的数据,因为在设备存储器之间不需要额外的同步来访问最新的数据。

    (6)当多个release()的调用与acquire_()成功返回的数量相等的时候,主机代码才能释放缓冲区。 Note: 即使获取释放调用没有正确地跨线程嵌套,主机代码的并发线程访问也被认为是递归的。任何一个线程的第一次获取都会为主机代码的所有线程建立主机访问类型,直到主机代码运行结束。

                                       

    (7)如果主机代码在需要同步时(例如在任务访问之后)访问缓冲区数据而没有显式同步,或者如果主机代码执行与所选访问类型不兼容的访问(例如写入调用ro_sync())后的缓冲区。

    5)提供设备提示

    (1)每一个hetcompute::create_buffer()返回的auto变量,都可以选择一个可能访问缓冲区的设备列表。HetCompute会更加注重优化后备存储空间。例如,相对于主内存来说,平台端对ION内存的限制旺旺会更多一些。

    (2)假如,CPU、GPU和Hexagon要访问一个Buffer,则需要在ION内存中分配缓冲区的后备存储可确保每个设备上的任务可以访问相同的ION后备存储,并且没有副本以及后备存储的进一步分配/取消分配。

    (3)假如设备后备Buffer是不可用的,HetCompute runtime将根据已知任务分配成本最低的存储:GPU任务将导致将OpenCL AHP缓冲区分配为后备存储,然后CPU任务会将数据复制到主内存后备存储,然后最终当Hexagon任务执行单独的ION后备存储时并将数据复制到其中。

    (4)如何在创建Buffer期间提供一个可能的设备提示: auto b = hetcompute::create_task(100, {hetcompute::gpu, hetcompute::dsp}); 这个可能的设备信息常常被作为一个优化提示。假如信息仅仅是一部分或者是错误的,那么仅仅会损失一些可避免的后备存储,以及可以避免一些后备存储和缓冲区的数据复制带来的性能损失。

    四、内存区域

    1)hetcompue::memregion允许抽象分配指定设备的内存区域(例如ION内存)和与其他家架构分配的数据可以容易的互相操作(例如现有的OpenGL的Buffer和通过HetCompute预先分配的ION内存)

    2)hetcompue::memregion在它的专用内存和框架数据上提供RAII语义:用户构造对象以分配相应的内存或设置互操作,并控制对象的生命周期以控制分配的内存或互操作的生命周期

    3)现在,HetCompute提供3中内存区的类型:

    (1)主Memory存储区hetcompute::main_memregion: 可以使用简单的机制来分配内存,并且做内存对齐。

    (2)IONMemory存储区hetcompute::ion_memregion: 分配ION内存。用户可以选择存储区是否需要缓存。用户也可以将预分配的ION内存打包到hetcompute::ion_memregion。

    (3)OpenGL互操作存储区hetcompute::glbuffer_memregion: 根据现有的OpenGL Buffer创建一个存储包。

    4)hetcompue::memregion一个基础类,hetcompue::create_buffer继承了这个基础类,可以容易的创建一个后备存储区。用户需要负责缓冲区中后备存储区保持活动状态,同时能够访问缓冲区本身。如果超出了访问时间,用户不需要一直保持内存区对象的活动状态。
     ———————————————— 
    版权声明:本文为CSDN博主「weixin_38498942」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/weixin_3...


Log in to reply