增加稳定性
This commit is contained in:
parent
4399ecd601
commit
4940926866
123
.github/workflows/build.yml
vendored
123
.github/workflows/build.yml
vendored
@ -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
|
||||
@ -249,7 +249,9 @@ private:
|
||||
const intptr_t dif = static_cast<intptr_t>(seq) - static_cast<intptr_t>(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);
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
#include "ai_scheduler.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
|
||||
#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<uint64_t>(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<uint64_t>(std::max<uint64_t>(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<uint64_t>(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<uint64_t>(std::numeric_limits<std::streamsize>::max())) {
|
||||
err = "Model file too large for this build: " + model_path;
|
||||
return kInvalidModelHandle;
|
||||
}
|
||||
|
||||
const size_t model_size = static_cast<size_t>(model_size_u64);
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
auto model_data = std::make_shared<std::vector<uint8_t>>();
|
||||
model_data->resize(model_size);
|
||||
if (!file.read(reinterpret_cast<char*>(model_data->data()), model_size)) {
|
||||
if (!file.read(reinterpret_cast<char*>(model_data->data()), static_cast<std::streamsize>(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<std::mutex> infer_lock(ctx->infer_mutex);
|
||||
|
||||
@ -381,7 +426,7 @@ InferResult AiScheduler::Infer(ModelHandle handle, const InferInput& input) {
|
||||
inputs[0].buf = const_cast<void*>(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<void*>(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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user