Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
876a553
Add: document manual dependency scope design
uv-xiao Apr 1, 2026
2e0ee41
Update: tighten manual dependency design constraints
uv-xiao Apr 2, 2026
23a1fe2
docs: refine manual tensormap dependency design
uv-xiao Apr 3, 2026
37a0fae
Update: add partial manual TensorMap scope support
uv-xiao Apr 3, 2026
54e5324
Add unmodified tensormap runtime baseline
uv-xiao Apr 5, 2026
bf1fc84
Restore zero-overhead auto path
uv-xiao Apr 5, 2026
c4b5fa8
Restore zero-overhead auto scope path
uv-xiao Apr 5, 2026
5b10117
Add manual scope guard regression tests
uv-xiao Apr 5, 2026
0bb19c9
Harden manual scope guard coverage
uv-xiao Apr 5, 2026
58d3c1a
Add manual scope outer-write boundary test
uv-xiao Apr 5, 2026
eed20b5
Support: add partial-manual benchmark selector
uv-xiao Apr 5, 2026
a3b96ba
Update: refresh manual-dep benchmark data
uv-xiao Apr 5, 2026
5787470
Update: cut manual scope overhead
uv-xiao Apr 5, 2026
bd9a760
Fix: stabilize partial-manual paged attention chunking
uv-xiao Apr 5, 2026
988eddc
Fix: restore deferred manual submit path
uv-xiao Apr 5, 2026
a247f59
Update: move manual boundary discovery to submit
uv-xiao Apr 7, 2026
431a9ea
Fix: remove manual scope membership scan
uv-xiao Apr 7, 2026
9f628e8
Update: speed up manual scope edge replay
uv-xiao Apr 7, 2026
c3e5951
Update: streamline partial-manual paged attention
uv-xiao Apr 8, 2026
77f548f
Update: mark partial-manual paged attention boundaries
uv-xiao Apr 8, 2026
c1722c1
Update: refresh manual-dep benchmark findings
uv-xiao Apr 8, 2026
3e34a71
Update: refresh manual-dep benchmark findings
uv-xiao Apr 8, 2026
97e0242
Update: clarify manual-scope dependency model
uv-xiao Apr 8, 2026
e0aa3c4
Update: explain manual-scope design tradeoffs
uv-xiao Apr 8, 2026
29f1eb6
Refactor: remove branch-local unmodified runtime support
uv-xiao Apr 8, 2026
c72fa9d
Fix: auto-pick free NPU for manual-scope tests
uv-xiao Apr 8, 2026
af357ad
Fix: harden manual-scope metadata growth
uv-xiao Apr 8, 2026
abace34
Update: move manual external wiring to submit
uv-xiao Apr 8, 2026
4530e81
Update: collapse manual scope bookkeeping
uv-xiao Apr 8, 2026
9a9974d
Update: refresh manual dependency design note
uv-xiao Apr 8, 2026
aed3526
Update: align manual dependency doc with fresh matrix
uv-xiao Apr 8, 2026
a5332ef
Update: collapse manual scope_end scan
uv-xiao Apr 8, 2026
38bb942
Support: ignore local worktrees
uv-xiao Apr 9, 2026
01d0723
Fix: restore rebased manual benchmark paths
uv-xiao Apr 9, 2026
e5fa1bc
Fix: align rebased unroll partial-manual ABI
uv-xiao Apr 10, 2026
9896375
Add: spec manual non-unroll optimization pass
uv-xiao Apr 10, 2026
3c6ec41
Add: plan manual non-unroll optimization pass
uv-xiao Apr 10, 2026
ff98f80
Add: manual scope optimization guard tests
uv-xiao Apr 10, 2026
cc662ba
Update: add manual scope repair state
uv-xiao Apr 10, 2026
6dc2e1e
Update: cache manual explicit fanin ranges
uv-xiao Apr 10, 2026
9739b2a
Update: align manual dependency design note
uv-xiao Apr 10, 2026
2936adf
Update: skip no-op manual boundary bookkeeping
uv-xiao Apr 11, 2026
a65894a
Update: collapse empty manual submit map work
uv-xiao Apr 11, 2026
6d33941
Update: cache tensor start offsets at creation
uv-xiao Apr 11, 2026
f5afc3e
Update: refresh manual-dep benchmark results
uv-xiao Apr 11, 2026
3b60ac1
Support: trim branch scope to code paths
uv-xiao Apr 12, 2026
16a36f0
Add: cover partial-manual benchmark scenes
uv-xiao Apr 12, 2026
e4ff0b4
fix(runtime): clarify manual scope review semantics
uv-xiao Apr 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from pathlib import Path
import sys

_BASE = Path(__file__).resolve().parents[1] / "paged_attention"
sys.path.insert(0, str(_BASE))

from golden import ALL_CASES, ATOL, DEFAULT_CASE, RTOL, __outputs__, compute_golden, generate_inputs # noqa: E402,F401
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Copyright (c) PyPTO Contributors.
# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
# CANN Open Software License Agreement Version 2.0 (the "License").
# Please refer to the License for details. You may not use this file except in compliance with the License.
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
# See LICENSE in the root of the software repository for the full text of the License.
# -----------------------------------------------------------------------------------------------------------
from pathlib import Path

from task_interface import ArgDirection as D # pyright: ignore[reportAttributeAccessIssue]

_ROOT = Path(__file__).parent
_PA_KERNELS = _ROOT.parent.parent / "paged_attention" / "kernels"

ORCHESTRATION = {
"source": str(_ROOT / "orchestration" / "paged_attention_orch.cpp"),
"function_name": "aicpu_orchestration_entry",
"signature": [D.IN, D.IN, D.IN, D.IN, D.IN, D.OUT],
}

KERNELS = [
{
"func_id": 0,
"name": "QK",
"source": str(_PA_KERNELS / "aic" / "aic_qk_matmul.cpp"),
"core_type": "aic",
"signature": [D.IN, D.IN, D.OUT],
},
{
"func_id": 2,
"name": "PV",
"source": str(_PA_KERNELS / "aic" / "aic_pv_matmul.cpp"),
"core_type": "aic",
"signature": [D.IN, D.IN, D.OUT],
},
{
"func_id": 4,
"name": "AIC_HUB",
"source": str(_PA_KERNELS / "aic" / "aic_hub.cpp"),
"core_type": "aic",
"signature": [],
},
{
"func_id": 1,
"name": "SF",
"source": str(_PA_KERNELS / "aiv" / "aiv_softmax_prepare.cpp"),
"core_type": "aiv",
"signature": [D.IN, D.OUT, D.OUT, D.OUT],
},
{
"func_id": 3,
"name": "UP",
"source": str(_PA_KERNELS / "aiv" / "aiv_online_update.cpp"),
"core_type": "aiv",
"signature": [D.IN, D.IN, D.IN, D.INOUT, D.INOUT, D.INOUT, D.INOUT],
},
{
"func_id": 5,
"name": "AIV_HUB",
"source": str(_PA_KERNELS / "aiv" / "aiv_hub.cpp"),
"core_type": "aiv",
"signature": [],
},
]

RUNTIME_CONFIG = {
"runtime": "tensormap_and_ringbuffer",
"aicpu_thread_num": 4,
"orch_thread_num": 1,
"block_dim": 24,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* Copyright (c) PyPTO Contributors.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
* -----------------------------------------------------------------------------------------------------------
*/

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <cinttypes>

#include "pto_orchestration_api.h" // NOLINT(build/include_subdir)

#define FUNC_QK_MATMUL 0
#define FUNC_SOFTMAX_PREPARE 1
#define FUNC_PV_MATMUL 2
#define FUNC_ONLINE_UPDATE 3
#define FUNC_AIC_HUB 4
#define FUNC_AIV_HUB 5

extern "C" {

__attribute__((visibility("default"))) PTO2OrchestrationConfig
aicpu_orchestration_config(const ChipStorageTaskArgs &orch_args) {
(void)orch_args; // NOLINT(readability/casting)
return PTO2OrchestrationConfig{
.expected_arg_count = 7,
};
}

__attribute__((visibility("default"))) void
aicpu_orchestration_entry(const ChipStorageTaskArgs &orch_args, int orch_thread_num, int orch_thread_index) {
uint64_t batch = orch_args.tensor(0).shapes[0];
uint64_t num_heads = orch_args.tensor(0).shapes[1];
uint64_t head_dim = orch_args.tensor(0).shapes[2];
DataType data_type = orch_args.tensor(0).dtype;
uint64_t block_size = orch_args.tensor(1).shapes[1];
uint64_t block_num = orch_args.tensor(3).shapes[1];
uint64_t scale_value = orch_args.scalar(0);

uint64_t q_head_num = num_heads;
uint64_t q_tile = 16;
uint64_t q_loop = (q_head_num + q_tile - 1) / q_tile;

uint64_t b_start = batch * orch_thread_index / orch_thread_num;
uint64_t b_end = batch * (orch_thread_index + 1) / orch_thread_num;

void *query_ptr = orch_args.tensor(0).data_as<void>();
void *kc_ptr = orch_args.tensor(1).data_as<void>();
void *vc_ptr = orch_args.tensor(2).data_as<void>();
void *out_ptr = orch_args.tensor(5).data_as<void>();

uint64_t total_blocks_count = orch_args.tensor(1).shapes[0];
uint64_t kv_total_rows = total_blocks_count * block_size;

uint32_t query_shapes[2] = {static_cast<uint32_t>(batch * num_heads), static_cast<uint32_t>(head_dim)};
uint32_t key_cache_shapes[2] = {static_cast<uint32_t>(kv_total_rows), static_cast<uint32_t>(head_dim)};
uint32_t value_cache_shapes[2] = {static_cast<uint32_t>(kv_total_rows), static_cast<uint32_t>(head_dim)};
uint32_t out_shapes[2] = {static_cast<uint32_t>(batch * num_heads), static_cast<uint32_t>(head_dim)};
Tensor query = make_tensor_external(query_ptr, query_shapes, 2, data_type);
Tensor key_cache = make_tensor_external(kc_ptr, key_cache_shapes, 2, data_type);
Tensor value_cache = make_tensor_external(vc_ptr, value_cache_shapes, 2, data_type);
Tensor out = make_tensor_external(out_ptr, out_shapes, 2, DataType::FLOAT32);

int *host_block_table = orch_args.tensor(3).data_as<int>();
int *host_context_lens = orch_args.tensor(4).data_as<int>();

uint32_t tile2d_shapes[2] = {static_cast<uint32_t>(q_tile), static_cast<uint32_t>(head_dim)};
uint32_t scalar_shapes[1] = {static_cast<uint32_t>(q_tile)};
uint32_t sij_shapes[2] = {static_cast<uint32_t>(q_tile), static_cast<uint32_t>(block_size)};
TensorCreateInfo tile2d_ci(tile2d_shapes, 2, DataType::FLOAT32);
TensorCreateInfo scalar_ci(scalar_shapes, 1, DataType::FLOAT32);
TensorCreateInfo sij_ci(sij_shapes, 2, DataType::FLOAT32);
TensorCreateInfo pij_f16_ci(sij_shapes, 2, data_type);

for (uint64_t b_idx = b_start; b_idx < b_end; b_idx++) {
uint64_t cur_seq = host_context_lens[b_idx];
uint64_t bn_this_batch = (cur_seq + block_size - 1) / block_size;
for (uint64_t q_idx = 0; q_idx < q_loop; q_idx++) {
PTO2_SCOPE() {
uint32_t cur_offset = static_cast<uint32_t>(b_idx * q_head_num + q_idx * q_tile);
uint32_t qi_offsets[2] = {cur_offset, 0};
uint32_t out_view_offsets[2] = {cur_offset, 0};
Tensor qi = query.view(tile2d_shapes, qi_offsets);
Tensor out_view = out.view(tile2d_shapes, out_view_offsets);

Arg params_inplace;
params_inplace.add_output(tile2d_ci);
params_inplace.add_output(scalar_ci);
params_inplace.add_output(scalar_ci);
TaskOutputTensors hub_outs = pto2_rt_submit_aiv_task(FUNC_AIV_HUB, params_inplace);
const Tensor &oi = hub_outs.get_ref(0);
const Tensor &li_update = hub_outs.get_ref(1);
const Tensor &mi_update = hub_outs.get_ref(2);

for (uint64_t bn = 0; bn < bn_this_batch; bn++) {
uint64_t cur_block_idx = host_block_table[b_idx * block_num + bn];
uint64_t valid_len = std::min(block_size, cur_seq - bn * block_size);
uint32_t kv_shapes[2] = {static_cast<uint32_t>(block_size), static_cast<uint32_t>(head_dim)};
uint32_t kv_offsets[2] = {static_cast<uint32_t>(cur_block_idx * block_size), 0};
Tensor kj = key_cache.view(kv_shapes, kv_offsets);
Tensor vj = value_cache.view(kv_shapes, kv_offsets);

PTO2_SCOPE(PTO2ScopeMode::MANUAL) {
Arg params_qk;
params_qk.add_input(qi);
params_qk.add_input(kj);
params_qk.add_output(sij_ci);
PTO2ManualSubmitResult qk_outs = pto2_rt_submit_aic_task_manual(FUNC_QK_MATMUL, params_qk);
const Tensor &sij = qk_outs.outputs.get_ref(0);

uint32_t sij_valid_shapes[2] = {
static_cast<uint32_t>(q_tile), static_cast<uint32_t>(valid_len)
};
uint32_t sij_valid_offsets[2] = {0, 0};
Tensor sij_valid = sij.view(sij_valid_shapes, sij_valid_offsets);

Arg params_sf;
params_sf.add_input(sij_valid);
params_sf.add_output(pij_f16_ci);
params_sf.add_output(scalar_ci);
params_sf.add_output(scalar_ci);
params_sf.add_scalar(scale_value);
PTO2ManualSubmitResult sf_outs = pto2_rt_submit_aiv_task_manual_with_deps(
FUNC_SOFTMAX_PREPARE, params_sf, {qk_outs.task_id}
);
const Tensor &pij_f16 = sf_outs.outputs.get_ref(0);
const Tensor &mi = sf_outs.outputs.get_ref(1);
const Tensor &li = sf_outs.outputs.get_ref(2);

Arg params_pv;
params_pv.add_input(pij_f16);
params_pv.add_input(vj);
params_pv.add_output(tile2d_ci);
PTO2ManualSubmitResult pv_outs =
pto2_rt_submit_aic_task_manual_with_deps(FUNC_PV_MATMUL, params_pv, {sf_outs.task_id});
const Tensor &oi_tmp = pv_outs.outputs.get_ref(0);

uint64_t is_first = (bn == 0) ? 1 : 0;
uint64_t is_last = (bn == bn_this_batch - 1) ? 1 : 0;

Arg params_up;
params_up.add_input(mi);
params_up.add_input(li);
params_up.add_input(oi_tmp);
params_up.add_inout(mi_update);
params_up.add_inout(li_update);
params_up.add_inout(oi);
params_up.add_inout(out_view);
params_up.add_scalar(is_first);
params_up.add_scalar(is_last);
PTO2ManualSubmitResult up_outs = pto2_rt_submit_aiv_task_manual_with_deps(
FUNC_ONLINE_UPDATE, params_up, {sf_outs.task_id, pv_outs.task_id}
);
}
}
}
}
}
}

} // extern "C"
8 changes: 4 additions & 4 deletions examples/scripts/run_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@

Examples:
# Run hardware example (requires Ascend device)
python examples/scripts/run_example.py -k examples/host_build_graph/vector_example/kernels \
-g examples/host_build_graph/vector_example/golden.py
python examples/scripts/run_example.py -k examples/a2a3/host_build_graph/vector_example/kernels \
-g examples/a2a3/host_build_graph/vector_example/golden.py

# Run simulation example (no hardware required)
python examples/scripts/run_example.py -k examples/host_build_graph/vector_example/kernels \
-g examples/host_build_graph/vector_example/golden.py \
python examples/scripts/run_example.py -k examples/a2a3/host_build_graph/vector_example/kernels \
-g examples/a2a3/host_build_graph/vector_example/golden.py \
-p a2a3sim

# Run with specific device
Expand Down
11 changes: 11 additions & 0 deletions src/a2a3/runtime/tensormap_and_ringbuffer/aicpu/aicpu_executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2364,6 +2364,17 @@ int32_t AicpuExecutor::run(Runtime *runtime) {
}
}

if (rt != nullptr) {
void* sm = runtime->get_pto2_gm_sm_ptr();
if (sm != nullptr) {
int32_t orch_err = static_cast<PTO2SharedMemoryHeader*>(sm)->orch_error_code.load(std::memory_order_acquire);
if (orch_err != PTO2_ERROR_NONE) {
DEV_ERROR("Thread %d: Exiting with orchestrator error code=%d", thread_idx, orch_err);
return -1;
}
}
}

return 0;
}

Expand Down
Loading