plan 教程
本教程展示如何把数据并行操作描述为 Plan,按 v1 子集检查它,以及在计划被拒绝时阅读原因。计划是普通数据,因此这个包可以在所有目标上使用。
快速开始
导入该包,以及用于策略的 shared:
import {
"Luna-Flow/luna_thread/plan",
"Luna-Flow/luna_thread/shared",
}
构建一个作用于八个 Int 值的映射计划并验证它:
test "plan quick start" {
let plan = @plan.map("double", @plan.i32_type(), 8)
inspect(@plan.is_runnable(plan), content="true")
inspect(plan.label(), content="double")
}
日常任务
为计划指定策略
默认策略使用一个工作线程,块大小为一。用 make_execution_policy 构建一个并行策略,并把它传给构建函数:
test "policy" {
let policy = @shared.make_execution_policy(worker_count=4, chunk_size=16).unwrap()
let plan = @plan.map_reduce("sum", @plan.i64_type(), 64, @plan.sum_reduction(), policy~)
assert_eq(plan.policy().worker_count, 4)
assert_true(@plan.has_sum_reduction(plan))
assert_true(@plan.is_runnable(plan))
}
阅读计划被拒绝的原因
validate 一次返回所有问题,因此你可以把它们一起报告:
test "issues" {
let policy = @shared.make_execution_policy(worker_count=8, chunk_size=8).unwrap()
let plan = @plan.reduce("tiny", @plan.f32_type(), 4, @plan.custom_reduction("xor"), policy~)
let issues = @plan.validate(plan)
assert_true(issues.any(@plan.is_unsupported_value_type))
assert_true(issues.any(@plan.is_chunk_size_too_large))
assert_true(issues.any(@plan.is_unsupported_reduction_kernel))
assert_eq(issues.length(), 4)
}
第四个问题是 WorkerCountExceedsInput:四个元素却有八个工作线程。
手工构建不寻常的计划
Plan::new 会保存你给它的任何东西,借此可以测试各种验证规则,例如扫描的顺序要求:
test "relaxed scan" {
let plan = @plan.Plan::new(
"prefix",
@plan.scan_plan_kind(),
@plan.DataDomain::new(@plan.i32_type(), 8),
ordering=@shared.relaxed_order(),
)
let issues = @plan.validate(plan)
assert_true(issues.any(@plan.is_unsupported_ordering))
assert_true(issues.any(@plan.is_scan_requires_stable_ordering))
}
查看计划
访问器返回各个字段,种类谓词则省去了一次模式匹配:
test "inspect" {
let plan = @plan.scan("prefix", @plan.i64_type(), 32)
assert_true(@plan.is_scan(plan))
assert_eq(plan.reduction(), None)
assert_true(plan.ordering() is @shared.PreserveInputOrder)
assert_eq(plan.domain().input_length(), 32)
}
进阶
计划通过 backend/native 变得可执行:它的 map_request_from_plan、reduce_request_from_plan 和 scan_request_from_plan 把有效计划转换为带类型的请求;也可以通过工作流:@workflow.compute_node 把计划嵌入任务图,@workflow.validate 把计划的问题报告为 InvalidComputePlan。库代码应基于 Plan 和 ValidationIssue 而不是门面来编写,这样它可以在所有目标上构建。
常见陷阱
is_runnable不检查原生内核所要求的“每块一个工作线程”()。reduce和scan总是保持输入顺序;要尝试其他顺序,请使用Plan::new。- 扫描计划没有内核;原生扫描总是前缀和。
- 枚举类型在包外是只读的:构建值时请写
@plan.i32_type(),而不是@plan.I32。对@plan.I32做模式匹配是可以的。
下一步
plan API 列出了 validate 的每条规则。plan 设计解释了每种计划计算什么,以及为什么扫描需要有序的输入。workflow 教程把计划放进任务图。