From 338bf1dc55b661b8926ed126098e0f55b7cd2ce6 Mon Sep 17 00:00:00 2001 From: Chao Wang <26245345+ChaoWao@users.noreply.github.com> Date: Mon, 9 Mar 2026 15:31:12 +0800 Subject: [PATCH] Refactor: unify AICPU spin-wait macros to SPIN_WAIT_HINT Remove PTO2_SPIN_PAUSE() and PTO2_SPIN_PAUSE_LIGHT() from pto_runtime2_types.h; replace all call sites with SPIN_WAIT_HINT(). PTO2_SPIN_PAUSE() violated codestyle rule #5 by calling sched_yield() on hardware. Use __has_include guard for spin_hint.h so Host .so (which lacks the AICPU include path) compiles with a no-op fallback. --- .../aicpu/aicpu_executor.cpp | 1 - .../runtime/pto_orchestrator.cpp | 2 +- .../runtime/pto_ring_buffer.h | 4 +-- .../runtime/pto_runtime2_types.h | 25 ++++++++----------- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/a2a3/runtime/tensormap_and_ringbuffer/aicpu/aicpu_executor.cpp b/src/a2a3/runtime/tensormap_and_ringbuffer/aicpu/aicpu_executor.cpp index bbb72e764a..a45a672347 100644 --- a/src/a2a3/runtime/tensormap_and_ringbuffer/aicpu/aicpu_executor.cpp +++ b/src/a2a3/runtime/tensormap_and_ringbuffer/aicpu/aicpu_executor.cpp @@ -792,7 +792,6 @@ int AicpuExecutor::resolve_and_dispatch_pto2(Runtime* runtime, int thread_idx, } else { SPIN_WAIT_HINT(); } - PTO2_SPIN_PAUSE_LIGHT(); CYCLE_COUNT_LAP(sched_idle_cycle); #if PTO2_PROFILING if (profiling_enabled) { diff --git a/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.cpp b/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.cpp index 78d11ca5f7..90210a712c 100644 --- a/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.cpp +++ b/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.cpp @@ -453,7 +453,7 @@ void pto2_orchestrator_wait_all(PTO2OrchestratorState* orch) { // Spin-wait until scheduler reports all tasks done while (!orch->scheduler->is_done()) { - PTO2_SPIN_PAUSE(); + SPIN_WAIT_HINT(); } } diff --git a/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_ring_buffer.h b/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_ring_buffer.h index 33dcac2435..0e43a877cb 100644 --- a/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_ring_buffer.h +++ b/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_ring_buffer.h @@ -144,7 +144,7 @@ struct PTO2HeapRing { exit(1); } - PTO2_SPIN_PAUSE(); + SPIN_WAIT_HINT(); } } @@ -343,7 +343,7 @@ struct PTO2TaskRing { exit(1); } - PTO2_SPIN_PAUSE(); + SPIN_WAIT_HINT(); } } diff --git a/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_runtime2_types.h b/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_runtime2_types.h index 9e124c3a98..6fee96f642 100644 --- a/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_runtime2_types.h +++ b/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_runtime2_types.h @@ -344,20 +344,15 @@ typedef void (*PTO2InCoreFunc)(void** args, int32_t num_args); #define PTO2_MEMORY_BARRIER() __sync_synchronize() #endif -/** - * Pause instruction for spin-wait loops - * Include sched_yield() to prevent CPU starvation of other threads - */ -#include -#if defined(__aarch64__) - #define PTO2_SPIN_PAUSE() do { __asm__ __volatile__("yield" ::: "memory"); sched_yield(); } while(0) - #define PTO2_SPIN_PAUSE_LIGHT() __asm__ __volatile__("yield" ::: "memory") -#elif defined(__x86_64__) - #define PTO2_SPIN_PAUSE() do { __builtin_ia32_pause(); sched_yield(); } while(0) - #define PTO2_SPIN_PAUSE_LIGHT() __builtin_ia32_pause() +// Spin-wait hint for AICPU threads. On real hardware the AICPU has dedicated +// ARM A55 cores — no OS yield is needed, so the hint is a no-op. In simulation +// all threads share host CPU cores, so we yield to prevent starvation. +// This header is also compiled into the Host .so (for struct definitions only), +// where the hint is never called — the fallback no-op keeps Host builds clean. +#if __has_include("spin_hint.h") +#include "spin_hint.h" #else - #define PTO2_SPIN_PAUSE() sched_yield() - #define PTO2_SPIN_PAUSE_LIGHT() ((void)0) +#define SPIN_WAIT_HINT() ((void)0) #endif // ============================================================================= @@ -387,7 +382,7 @@ static inline void pto2_fanout_lock(PTO2TaskDescriptor* task, while (task->fanout_lock.load(std::memory_order_acquire) != 0) { contended = true; atomic_ops++; // each load = 1 atomic - PTO2_SPIN_PAUSE_LIGHT(); + SPIN_WAIT_HINT(); } int32_t expected = 0; if (task->fanout_lock.compare_exchange_weak(expected, 1, @@ -408,7 +403,7 @@ static inline void pto2_fanout_lock(PTO2TaskDescriptor* task, static inline void pto2_fanout_lock(PTO2TaskDescriptor* task) { for (;;) { while (task->fanout_lock.load(std::memory_order_acquire) != 0) { - PTO2_SPIN_PAUSE_LIGHT(); + SPIN_WAIT_HINT(); } int32_t expected = 0; if (task->fanout_lock.compare_exchange_weak(expected, 1,