• OneFlow源码解析:算子指令在虚拟机中的执行


    4a78979c58dbc5b32d8bb9dec742e90e.jpeg

    撰文|郑建华、赵露阳

    1 

    Op在虚拟机里的执行

    1.1 PhysicalRun和InstructionsBuilder

    上一篇文章OneFlow源码解析:Op、Kernel与解释器提到:

    PhysicalRun接受一个lambda函数作为参数,这里即InstructionsBuilder->Call方法,该方法接受kernel、input/output的eager blob object、kernel执行的上下文作为参数。Call方法实际会完成OpCall指令的构建,并最终将其派发至vm指令列表中,等待VM实际调度执行。

    这个PhysicalRun函数里包裹着一个lambda函数:

     
     
    1. JUST(PhysicalRun([&](InstructionsBuilder* builder) -> Maybe<void> {
    2. return builder->Call(xxx);
    3. }));

    其中,lambda函数接受一个InstructionsBuilder指针(builder),并调用builder->Call方法,用于实际完成Op指令在VM中的构建。而PhysicalRun(https://github.com/Oneflow-Inc/oneflow/blob/88f147d50e75d1644e552ed445dd58f9b5121ea5/oneflow/core/framework/instructions_builder.h#L160)在 oneflow/core/framework/instructions_builder.h中定义,其接受lambda函数作为模版参数(CallbackT):

     
     
    1. // Make VM instructions with instruction builder and run instructions with physical/local view.
    2. template<typename CallbackT>
    3. Maybe<void> PhysicalRun(const CallbackT& Build) {
    4. vm::InstructionList instruction_list;
    5. InstructionsBuilder instructions_builder(&instruction_list);
    6. JUST(Build(&instructions_builder));
    7. JUST(vm::Run(instructions_builder.mut_instruction_list()));
    8. return Maybe<void>::Ok();
    9. }

    可见,PhysicalRun函数中,首先初始化一个InstructionsBuilder,然后将InstructionsBuilder指针作为参数传给lambda函数,完成实际指令的构建;最后通过vm::Run()方法将该指令发送至VM,等候VM实际调度和执行。Run方法如下:

     
     
    1. Maybe<void> Run(vm::InstructionList* instruction_list) {
    2. auto* virtual_machine = JUST(SingletonMaybe());
    3. JUST(virtual_machine->Receive(instruction_list));
    4. return Maybe<void>::Ok();
    5. }

    可以看见,Run()方法获取了全局单例的VM对象指针,然后通过vm的Receive()方法,将该条指令发送给虚拟机(所以这里Run其实有点歧义,更贴切的意思,其实是指令发送或传送)。

    这个VirtualMachine->Receive方法很重要,会在后面的第2.章节中详细展开。

    1.2 InstructionsBuilder

    上面PhysicalRun函数中的InstructionsBuilder,类似一个指令构建的helper,InstructionsBuilder的系列方法配合指令策略(InstructionPolicy),可以帮助构建不同类型的vm指令。

    从InstructionsBuilder

    https://github.com/Oneflow-Inc/oneflow/blob/88f147d50e75d1644e552ed445dd58f9b5121ea5/oneflow/core/framework/instructions_builder.h#L47)的定义中,我们可以看到指令的构建方法,其中常用方法如下:

     
     
    1. // 用于lazy mode(nn.Graph)
    2. // Build VM execution instructions with NNGraph's inputs/outputs/parameters for NNGraph execution.
    3. Maybe<void> LaunchLazyJob(const vm::EagerBlobObjectListPtr& inputs,
    4. const vm::EagerBlobObjectListPtr& outputs,
    5. const vm::EagerBlobObjectListPtr& parameters,
    6. const std::shared_ptr& nn_graph);
    7. // 用于全局同步,同步等待所有指令调用完成
    8. Maybe<void> GlobalSync();
    9. // 用于Tensor内存释放(归还allocator)
    10. Maybe<void> ReleaseTensor(const std::shared_ptr& eager_blob_object);
    11. // 操作Tensor实际内存(blob)
    12. template<typename T>
    13. Maybe<void> AccessBlobByCallback(
    14. const T tensor,
    15. const std::function<void(ep::Stream*, const std::shared_ptr&)>& callback,
    16. const std::string& modifier);
    17. // 最常用的指令构建方法,用于构造op执行所需的OpCall指令
    18. Maybe<void> Call(const std::shared_ptr& opkernel,
    19. vm::EagerBlobObjectList&& input_eager_blob_objects,
    20. vm::EagerBlobObjectList&& output_eager_blob_objects,
    21. const one::OpExprInterpContext& ctx, Symbol stream);

    1.3 InstructionPolicy

    InstructionPolicy

    https://github.com/Oneflow-Inc/oneflow/blob/88f147d50e75d1644e552ed445dd58f9b5121ea5/oneflow/core/vm/instruction_policy.h#L34)——指令策略,通常用于配合InstructionsBuilder实际构建出不同的vm指令。InstructionPolicy的子类实现如下:

    90fab6bddebe262b688251f6ffdee1a6.png

    这些子类的InstructionPolicy可近似认为是指令类型。如,用于Op执行的OpCallInstructionPolicy、用于Tensor内存释放的ReleaseTensorInstructionPolicy、用于屏障阻塞的BarrierInstructionPolicy等。

    以Op执行为例:

     
     
    1. JUST(PhysicalRun([&](InstructionsBuilder* builder) -> Maybe<void> {
    2. return builder->Call(xxx);
    3. }));

    实际上是通过InstructionsBuilder的Call方法

    https://github.com/Oneflow-Inc/oneflow/blob/88f147d50e75d1644e552ed445dd58f9b512

  • 相关阅读:
    View#post(Runnable)的执行流程
    eyb:SpringSecurity:Oauth2协议
    《Flink学习笔记》——第十一章 Flink Table API和 Flink SQL
    LightDB版本发布 13.8-23.3
    linux驱动之阻塞与非阻塞I/O
    实用最新的网络进行吗咿呀嘿的浮现 深度学习算法
    verilog语法-008—几种可综合的for循环语句
    PostgreSQL的主从复制方式
    aspnetcore微服务之间grpc通信,无proto文件
    各种 sql 语句
  • 原文地址:https://blog.csdn.net/OneFlow_Official/article/details/126258763