Full-volume acc/cnt device buffers (~115 MB for the 9.6M-voxel grid) plus the CUDA context did not fit next to a desktop session that had taken the T600's 4 GB down to ~190 MB free, so every frame died with cuMemAlloc OOM and the GUI showed no sar3d picture. The kernel now processes [gid_begin, gid_end) ranges and the host launches it in 2M-voxel chunks reusing one ~24 MB buffer pair. Parity vs the reference volumes is unchanged (max diff 1.3e-6). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gpr_cpp — C++/CUDA счёт-ядро MIMO GPR 3D SAR
Инфраструктура (сборка, NVRTC, PocketFFT, npy) вендорена из репозитория VNA_AlGo (
gpr_cpp/, коммит544dc59) без python-биндингов (GPR_BUILD_PYTHON=OFF). АЛГОРИТМ с сентября 2026 переписан: это порт эталонного ноутбукаMulti_antenna_3D_clean_v1.ipynb(ячейки 0 и 4), а не старогоgpr_core/Horns_3D. Паритет с ноутбуком проверяется инструментомsar3d_parity+python_app/scripts/sar3d_volume_compare.pyпо референсным*_volume.npz. Собирается из корневого Makefile radar_system (цель$(GPR_CPP_LIB)вызываетbuild_cmake.sh).
Что внутри
В C++ (libgpr_core_cpp): сегментированный тайминг кадра по per-trace
меткам захвата (compute_pair_timestamps), препроцессинг A-сканов (bg-subtract,
полная фазовая коррекция движения intra+pair до IFFT, k0-вставка + Ханн + IFFT
через PocketFFT, нормировка пар), полнообластная ground-сетка
(build_full_region_grid), 3D SAR апертурный объём (одно CUDA-ядро на всю
апертуру; геометрия в double, A-сканы float32) и финализация
(finish_volume: |acc/cnt| → маска глубины → нормировка без Y-краёв → гаусс
по (Z,X) → нормировка; возвращает объём [0,1] + level).
Ключевое решение: CUDA без nvcc (NVRTC + Driver API)
На целевых машинах (x86+T600, Jetson) нет полного CUDA toolkit — только runtime +
NVRTC (как у cupy). Поэтому ядро не компилируется nvcc'ом: его исходник
встроен строкой (src/kernel_src.hpp), компилируется в рантайме
через NVRTC в cubin под точную арх устройства (запрос compute capability →
sm_XY, без JIT PTX), грузится и запускается через CUDA Driver API. Хост-часть
собирается обычным g++. Плюс: без toolkit и без привязки к SM — один код для
x86 (sm_75) и Jetson (sm_87).
Сборка
bash build_cmake.sh # авто-детект pip CUDA-путей; собирает всё
# артефакты в build/: libgpr_core_cpp.a, _gpr_cpp*.so, standalone_bp
Требуется: g++ ≥13, cmake ≥3.24, pybind11 (pip install pybind11), pip-пакеты
nvidia-* (nvrtc+cudart, идут с cupy), системный libcuda. rpath на каталог
libnvrtc прописан — бинарники/модуль грузятся без LD_LIBRARY_PATH.
Публичный C++ API (include/gpr/)
#include "gpr/config.hpp" // GeometryConfig/BPConfig/MotionConfig/SARConfig (дефолты = ноутбук)
#include "gpr/ascan.hpp" // compute_pair_timestamps, preprocess_snapshot(...) -> AScanSet
#include "gpr/sar3d.hpp" // SarEngine::aperture_volume -> VolumeRaw; finish_volume -> FinishedVolume
#include "gpr/geometry.hpp" // frame_offsets, frame_weights, build_full_region_grid
gpr::SarEngine engine(geom, bp, mot, sar); // компилит ядро под устройство
auto raw = engine.aperture_volume(frames, grid); // один запуск ядра на апертуру
auto fin = gpr::finish_volume(raw, grid, mot.pitch_deg, bp, sar); // объём [0,1] + level
Пример без Python: examples/standalone_bp.cpp — грузит
S21 из .npy, строит объём, печатает максимум.
./build/standalone_bp <preprocessed_dir> 0038_id39_ns11361438137486
Python-модуль
import _gpr_cpp # из gpr_cpp/build
eng = _gpr_cpp.SarEngine(_gpr_cpp.GeometryConfig(), _gpr_cpp.BPConfig(),
_gpr_cpp.MotionConfig(), _gpr_cpp.SARConfig())
a = _gpr_cpp.preprocess_snapshot(s21, freq, background, mot, geom, bp, True) # -> AScanSet
acc, cnt = eng.aperture_volume([(a, dx, dy, dz, w), ...], gx, gy, gz) # numpy
Паритет с ноутбуком (проверено на x86 T600, датасет 20260922_mine_fast_true)
Кадры 0034/0035/0036 против референсных *_volume.npz ноутбука
(make sar3d_parity + python_app/scripts/sar3d_volume_compare.py):
max|Δ| ≤ 1.6e-6 вне ножевой границы маски глубины, argmax и level совпадают
(level rel ≤ 7e-7). Python-эталон той же цепочки:
python_app/scripts/sar3d_reference_check.py.
Статус
- x86 (T600, sm_75, CUDA 13): собрано, паритет, standalone работает.
- Jetson (Orin NX, sm_87, CUDA 12.6): порт тривиален (NVRTC сам берёт sm_87);
собрать
build_cmake.shна Jetson с его venv. - Опц.: ветка
impl='cpp'вgpr_core/sar3d.py(адаптерgpr_cpp_backend.py), кэш device-A-сканов (сейчас каждый вызов грузит стек на GPU).