运行时(Runtime)#
运行时 visionflow::Runtime
是检测流程 FLow 中若干算子 Operator 执行的句柄。
而运行时策略 visionflow::runtime::IStrategy
是算子如何执行的配置,
尤其是用户没有明确指定,但对于能正确执行又必须的配置。
通过运行时和运行时策略,你可以在不清楚检测流程 FLow 中算子细节和样本 Sample 属性 Property 细节的情况下推理样本。
创建运行时#
例如,你有一个已经训练好的工程 visionflow::Project
my_project,
通过预设的运行时策略,那么你可以方便创建对应的运行时。
// 预设的运行时策略,下面会详细介绍。
visionflow::runtime::AllTools strategy;
// 大部分情况下这么配置即可。
strategy.options.ignore_update_time_requirement = true;
strategy.options.allow_auto_update = true;
strategy.options.allow_unrealized_oper = true;
auto runtime = my_project->create_runtime(strategy);
Note
运行时也可以在正确参数配置和完善样本数据下,自动依次完成训练和推理两部分,并不强制要求是已训练的工程。
创建运行时的策略#
VisionFlow 提供了若干预设策略方便用户使用,它们共同使用 visionflow::runtime::StrategyOptions
来作为策略的共同部分:
visionflow::runtime::StrategyOptions::ignore_update_time_requirement
是否忽略参数更新时间。运行时通过参数 Parameter 更新时间来判断是否为最新的有效数据。
允许则忽略参数更新时间,运行时会采用旧数据或者空数据来执行。 对于空数据则会在创建运行时抛出异常
visionflow::excepts::CannotConstructRuntime
。否则会根据
visionflow::runtime::StrategyOptions::allow_auto_update
,决定是否在运行时自动更新参数。
visionflow::runtime::StrategyOptions::allow_auto_update
是否允许参数自动更新。对于算子 Operator 而言,依赖的参数 Parameter 节点可能为空,或者因为依赖链上的节点更新而导致该节点失效。
允许则会在运行时对失效参数节点自动更新节点值。
否则会在创建运行时抛出异常
visionflow::excepts::NodeNotFullUpdated
。
visionflow::runtime::StrategyOptions::allow_auto_update_rely_on_prop
是否允许依赖属性的参数自动更新。只有当
visionflow::runtime::StrategyOptions::allow_auto_update
启用时才会生效。否则会在创建运行时抛出异常
visionflow::excepts::AutoExecuteRequirementsNotSatisfied
。
visionflow::runtime::StrategyOptions::allow_unrealized_oper
是否允许执行虚拟算子。一次运行时允许执行多个算子,自然不乏 虚拟算子 。 允许则创建运行时会跳过对于虚拟算子的检查。
否则会在创建运行时抛出异常
visionflow::excepts::UnregisteredOperator
。
visionflow::runtime::StrategyOptions::allow_max_gpu_num
允许使用的最大GPU数目。如果GPU实际数量小于等于该值,运行时将使用全部GPU。
如果允许使用的GPU为0,或者实际GPU数量为0, 会根据
visionflow::runtime::StrategyOptions::allow_run_on_cpu
来决定是否在CPU上运行。
visionflow::runtime::StrategyOptions::specified_gpu_ids
指定优先使用的GPU编号。对于无效的GPU编号会自动去除并输出对应日志信息。
如果
visionflow::runtime::StrategyOptions::allow_max_gpu_num
数量超过了优先使用GPU的数量, 将自动查找并选择其他可用的GPU。
visionflow::runtime::StrategyOptions::allow_run_on_cpu
是否允许在CPU上运行。运行时会尽可能地在GPU上运行。
允许则当不能在GPU上运行时,会改为在CPU上运行。
否则会在创建运行时抛出异常
visionflow::excepts::CpuEnableError
。但在某些情况下用户可能希望强制在CPU上运行, 这时需要配置
visionflow::runtime::StrategyOptions::allow_max_gpu_num
为0。
visionflow::runtime::StrategyOptions::call_back
回调函数。这里不做过多介绍,具体可以看
visionflow::util::IProgressCallback
。
Note
虚拟算子,即是未实现,未注册的算子 Operator 。 VisionFlow 中有部分属性 Property 依赖用户在使用时给出,例如图片和视窗等信息。 输出这类属性的算子即为虚拟算子。 VisionFlow 允许用户通过注册虚拟算子来在运行时自动输出对应属性,或者用户保证在创建运行时前给出该属性值即可。
具体到每种策略,描述了运行时的执行算子的范围:
visionflow::runtime::AllTools
执行所有工具。自动执行工程内所有工具的输出及其依赖链上的所有算子。
适用于大部分情况。
visionflow::runtime::SingleTool
执行单个工具。自动执行指定工具输出及其依赖链上的工具内算子。
依赖链限定在指定工具内,因此不能自动处理对于工具与工具之间的输入输出依赖关系。
对于缺少输入的工具,会在运行时抛出异常
visionflow::excepts::DataNotFound
。
visionflow::runtime::ToolsAndDepends
执行指定工具集及其依赖工具。自动执行指定工具集输出及其依赖链上的所有算子。
visionflow::runtime::SingleNode
执行指定算子。单独执行指定算子。
该算子需要的所有输入属性都需要用户输入。
否则会在运行时抛出异常
visionflow::excepts::DataNotFound
。
Warning
对于以工具为范围的策略而言,所需执行的算子为工具输出及其依赖链上的所有算子。
但如果某些算子并不在工具输出的依赖链上(例如只依赖某工具输出,却又不在其他工具输出的依赖链上),则不会自动执行。
这时候需要通过 visionflow::runtime::SingleNode
来单独执行。
Note
目前 VisionFlow 只支持上述预设策略,并不允许用户自定义实现注册运行时策略。
获取运行时信息#
成功创建运行时后, visionflow::Runtime
还提供了方便获取相关信息的接口:
visionflow::Runtime::used_device()
允许使用的GPU编号。visionflow::Runtime::input_properties()
运行时需要的输入属性,需要用户给出。visionflow::Runtime::virtual_output_properties()
虚拟算子 输出的属性,需要用户给出。visionflow::Runtime::final_output_properties()
运行时最终输出的属性,不包括中间结果。visionflow::Runtime::all_output_properties()
运行时输出的所有属性,包括中间结果。visionflow::Runtime::required_properties()
运行时所需的所有属性, 为visionflow::Runtime::input_properties()
和visionflow::Runtime::all_output_properties()
的并集。visionflow::Runtime::register_observer()
方便用户观察运行时。例如评估算子和运行时的执行时间
visionflow::runtime::RuntimeProfiler
。
visionflow::Runtime::create_sample()
创建出一个满足运行时所需的样本 Sample 。方便用户输入需要给出的属性。
visionflow::Runtime::is_meeting_requirement()
判断样本是否满足运行时。满足运行时即样本拥有所需的所有属性,并且需要用户给出的属性都已有数据。
通过运行时信息,可以方便创建一个满足运行时要求的样本:
// 创建满足运行时的样本,它需要用户输入图片。
auto sample = runtime.create_sample();
// 从外部读取图片。
auto image = visionflow::Image::FromFile("D:/path/to/image.png");
// 在样本中输入属性。
sample.get_or_create<visionflow::props::Image>({"Input", "image"})
->set_image(image);
// 判断样本是否满足运行时。
if (runtime.is_meeting_requirement(sample))
runtime.execute(sample);
使用运行时进行推理#
对于样本集 SampleSet 而言,其中的样本可能并不同时满足同一个运行时,
VisionFlow 提供了 visionflow::RuntimeSampleSetAdapter
来帮助用户自动从样本集中过滤不符合运行时要求的样本。
对于符合要求的样本,只读取运行时所需要的属性。
// 这里以工程主数据集为例,推理自然也可以使用别的数据集。
auto dataset_name = my_project->main_sample_set_name();
auto sample_set = my_project->get_sample_set(dataset_name);
// 帮助用户直接适配数据集和运行时。
auto adapter = adapt(&sample_set, runtime);
// 简单遍历执行后将结果存回数据集即可。
for (auto [id, sample] : adapter) {
runtime.execute(sample);
adapter.update(id, sample);
}