From 494092686603c1c96f84255433b577f894a80a97 Mon Sep 17 00:00:00 2001 From: sladro Date: Thu, 29 Jan 2026 20:44:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=A8=B3=E5=AE=9A=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build.yml | 123 ------------------------------------ include/utils/spsc_queue.h | 4 +- src/ai_scheduler.cpp | 59 +++++++++++++++-- 3 files changed, 58 insertions(+), 128 deletions(-) delete mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 61828aa..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,123 +0,0 @@ -name: CI - -on: - push: - branches: [ master, main ] - pull_request: - branches: [ master, main ] - workflow_dispatch: - inputs: - enable_cross_build: - description: "Enable RK3588 cross build job" - required: false - default: "false" - -jobs: - host-build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y ninja-build clang-format cppcheck - - - name: Quality gates (clang-format + cppcheck on changed files) - shell: bash - run: | - set -euo pipefail - python3 - <<'PY' - import json, os, subprocess, sys - - def sh(*args): - return subprocess.check_output(list(args), text=True).strip() - - event = os.environ.get('GITHUB_EVENT_NAME','') - event_path = os.environ.get('GITHUB_EVENT_PATH','') - payload = {} - if event_path: - with open(event_path, 'r', encoding='utf-8') as f: - payload = json.load(f) - base = None - head = os.environ.get('GITHUB_SHA','HEAD') - - if event == 'pull_request': - base = (((payload.get('pull_request') or {}).get('base') or {}).get('sha')) - else: - base = payload.get('before') - if base and set(base) == {'0'}: - base = None - - if not base: - # Fallback to previous commit if possible. - try: - base = sh('git','rev-parse','HEAD~1') - except Exception: - base = None - - if base: - diff = subprocess.check_output(['git','diff','--name-only',f'{base}...{head}'], text=True) - paths = [p.strip() for p in diff.splitlines() if p.strip()] - else: - paths = [p.strip() for p in sh('git','ls-files').splitlines() if p.strip()] - - exts = ('.c','.cc','.cpp','.cxx','.h','.hh','.hpp','.hxx') - files = [] - for p in paths: - if not p.endswith(exts): - continue - if p.startswith(('third_party/','build/','.git/')): - continue - files.append(p) - if not files: - print('No C/C++ files changed; skipping format/cppcheck.') - sys.exit(0) - - # clang-format - subprocess.check_call(['clang-format','--version']) - subprocess.check_call(['clang-format','--dry-run','--Werror',*files]) - - # cppcheck - subprocess.check_call(['cppcheck','--version']) - subprocess.check_call([ - 'cppcheck', - '--error-exitcode=1', - '--enable=warning,style,performance,portability', - '--inline-suppr', - '--suppress=missingIncludeSystem', - '--std=c++17', - '-I','include', - '-I','third_party', - *files, - ]) - PY - - - name: Configure & build (host) - env: - CMAKE_ARGS: -DBUILD_TESTS=ON - run: | - ./scripts/build_host.sh - - - name: Run unit tests - run: | - ctest --test-dir build/host --output-on-failure - - rk3588-cross-build: - if: github.event_name == 'workflow_dispatch' && github.event.inputs.enable_cross_build == 'true' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Install toolchain - run: | - sudo apt-get update - sudo apt-get install -y ninja-build gcc-aarch64-linux-gnu g++-aarch64-linux-gnu - - name: Build (cross) - env: - RK3588_SYSROOT: /opt/rk3588-sysroot - run: | - mkdir -p "$RK3588_SYSROOT" - ./scripts/build_board.sh diff --git a/include/utils/spsc_queue.h b/include/utils/spsc_queue.h index dcaeecc..197ec34 100644 --- a/include/utils/spsc_queue.h +++ b/include/utils/spsc_queue.h @@ -249,7 +249,9 @@ private: const intptr_t dif = static_cast(seq) - static_cast(pos + 1); if (dif == 0) { if (dequeue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed)) { - // Drop without moving data out. + // Drop the item and release its resources eagerly. + T dropped_item = std::move(cell.data); + (void)dropped_item; cell.seq.store(pos + capacity_, std::memory_order_release); size_.fetch_sub(1, std::memory_order_acq_rel); dropped_.fetch_add(1, std::memory_order_relaxed); diff --git a/src/ai_scheduler.cpp b/src/ai_scheduler.cpp index be81181..ed08d7e 100644 --- a/src/ai_scheduler.cpp +++ b/src/ai_scheduler.cpp @@ -1,8 +1,10 @@ #include "ai_scheduler.h" +#include #include #include #include +#include #include "utils/logger.h" @@ -22,6 +24,26 @@ int GetEnvInt(const char* name, int default_value) { } } +uint64_t GetEnvU64(const char* name, uint64_t default_value) { + if (!name) return default_value; + const char* v = std::getenv(name); + if (!v || !*v) return default_value; + try { + return static_cast(std::stoull(v)); + } catch (...) { + return default_value; + } +} + +uint64_t DefaultMaxModelBytes() { + // Guardrail against tellg() failures or accidentally huge model files. + // Override with env: RK3588_MODEL_MAX_BYTES. + const uint64_t def = 512ull * 1024ull * 1024ull; + const uint64_t v = GetEnvU64("RK3588_MODEL_MAX_BYTES", def); + // Clamp to a sane range. + return std::min(std::max(v, 4ull * 1024ull * 1024ull), 4ull * 1024ull * 1024ull * 1024ull); +} + int ClampInt(int v, int lo, int hi) { if (v < lo) return lo; if (v > hi) return hi; @@ -105,12 +127,29 @@ ModelHandle AiScheduler::LoadModel(const std::string& model_path, std::string& e return kInvalidModelHandle; } - size_t model_size = file.tellg(); + const std::streampos end_pos = file.tellg(); + if (end_pos <= 0) { + err = "Failed to read model size: " + model_path; + return kInvalidModelHandle; + } + const uint64_t model_size_u64 = static_cast(end_pos); + const uint64_t max_bytes = DefaultMaxModelBytes(); + if (model_size_u64 > max_bytes) { + err = "Model file too large (" + std::to_string(model_size_u64) + " bytes, max=" + + std::to_string(max_bytes) + "): " + model_path; + return kInvalidModelHandle; + } + if (model_size_u64 > static_cast(std::numeric_limits::max())) { + err = "Model file too large for this build: " + model_path; + return kInvalidModelHandle; + } + + const size_t model_size = static_cast(model_size_u64); file.seekg(0, std::ios::beg); auto model_data = std::make_shared>(); model_data->resize(model_size); - if (!file.read(reinterpret_cast(model_data->data()), model_size)) { + if (!file.read(reinterpret_cast(model_data->data()), static_cast(model_size))) { err = "Failed to read model file: " + model_path; return kInvalidModelHandle; } @@ -306,6 +345,12 @@ InferResult AiScheduler::Infer(ModelHandle handle, const InferInput& input) { return result; } + if (ctx->n_input != 1) { + result.error = "Model expects " + std::to_string(ctx->n_input) + " inputs; current pipeline provides 1"; + total_errors_.fetch_add(1); + return result; + } + // Lock this specific model for inference. std::lock_guard infer_lock(ctx->infer_mutex); @@ -381,7 +426,7 @@ InferResult AiScheduler::Infer(ModelHandle handle, const InferInput& input) { inputs[0].buf = const_cast(input.data); inputs[0].pass_through = 0; - int ret = rknn_inputs_set(ctx->ctx, ctx->n_input, inputs); + int ret = rknn_inputs_set(ctx->ctx, 1, inputs); if (ret < 0) { result.error = "rknn_inputs_set failed: " + std::to_string(ret); total_errors_.fetch_add(1); @@ -475,6 +520,12 @@ AiScheduler::BorrowedInferResult AiScheduler::InferBorrowed(ModelHandle handle, return result; } + if (ctx->n_input != 1) { + result.error = "Model expects " + std::to_string(ctx->n_input) + " inputs; current pipeline provides 1"; + total_errors_.fetch_add(1); + return result; + } + if (!input.data || input.size == 0) { result.error = "Invalid input data"; total_errors_.fetch_add(1); @@ -548,7 +599,7 @@ AiScheduler::BorrowedInferResult AiScheduler::InferBorrowed(ModelHandle handle, inputs[0].buf = const_cast(input.data); inputs[0].pass_through = 0; - int ret = rknn_inputs_set(ctx->ctx, ctx->n_input, inputs); + int ret = rknn_inputs_set(ctx->ctx, 1, inputs); if (ret < 0) { result.error = "rknn_inputs_set failed: " + std::to_string(ret); total_errors_.fetch_add(1);