Compare commits

...

14 Commits

Author SHA1 Message Date
root
ffe764f8b2 Merge branch 'main' of https://dev.modelhub.org.cn/dylanyunlong/project_6 2026-08-13 09:46:52 +00:00
dylanyunlon
2cbae09d5e feat: CCCL CachingDeviceAllocator preload — 完整依赖链 288 files
从 cccl_upstream 递归追踪 cub/util_allocator.cuh 的全部 include 依赖:
  cub/         9 files (config, util_*, version, detect_cuda_runtime)
  cuda/        libcudacxx type_traits, concepts, algorithm, iterator...
  nv/          target macros, preprocessor

总计 288 个头文件 (1.4MB),打包到 include/ 目录,编译时 -I include
即可完全脱离 CCCL 原始目录结构。

.cu 文件直接 #include <cub/util_allocator.cuh>,
走原版 CUB CachingDeviceAllocator,零 mock。

BI-V100 参数: growth=2 bins=[8..32] max_cached=8GB/device
2026-08-13 09:45:45 +00:00
dylanyunlon
5449456534 feat: CCCL CachingDeviceAllocator LD_PRELOAD — bypass CoreX expandable_segments ASSERT
从 CCCL upstream cub/cub/util_allocator.cuh 提取 CachingDeviceAllocator
核心算法,去掉所有 CUB/CCCL 宏依赖,编译为独立 .so。

用 LD_PRELOAD 拦截 cudaMalloc/cudaFree,路由到 CUB 的 geometric-bin
缓存分配器。同时在 constructor 中 strip PYTORCH_CUDA_ALLOC_CONF 里的
expandable_segments 配置,避免 CoreX CUDACachingAllocator.cpp:545 ASSERT。

BI-V100 调优参数:
  bin_growth=8, min_bin=3 (512B), max_bin=13 (~550MB)
  max_cached_bytes=4GB per device (32GB卡的合理上限)

真机测试步骤:
  1. bash build_cccl_preload.sh
  2. LD_PRELOAD=./libcccl_allocator.so CCCL_ALLOC_DEBUG=1 \
     PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True \
     python3 verify_preload.py
2026-08-13 09:45:45 +00:00
dylanyunlon
1e8d1ddfa3 fix: remove expandable_segments — CoreX CUDACachingAllocator不支持
BI-V100 CoreX PyTorch的CUDACachingAllocator.cpp:545没有实现
expandable segment特性,导致模型加载阶段(VocabParallelEmbedding)
直接INTERNAL ASSERT FAILED崩溃。

替换为max_split_size_mb:512减少内存碎片化。
2026-08-13 09:43:35 +00:00
Claude
bf0ad625c3 feat(CCCL): LD_PRELOAD CachingDeviceAllocator — intercept cudaMalloc/cudaFree
Route C: replace PyTorch's cudaMalloc/cudaFree with CCCL CUB's
CachingDeviceAllocator via LD_PRELOAD. Eliminates driver-level allocation
overhead by reusing freed GPU memory from a bin-based cache.

Based on cccl_upstream/cub/cub/util_allocator.cuh (901 lines).
Self-contained .so with no CCCL header dependencies at compile time.

Files:
- cccl_preload_allocator.cu: the allocator (405 lines)
- build_cccl_preload_allocator.sh: build script (corex clang++ or g++ fallback)
- test_cccl_preload.sh: smoke test suite for BI-V100
- patch_ops.sh: build during docker build
- computility-run.yaml: LD_PRELOAD env var for runtime

Config via env:
  CCCL_ALLOC_BIN_GROWTH=8, MIN_BIN=3, MAX_BIN=13, MAX_CACHED_MB=4096

Test on real machine:
  cd qwen3_6_scripts && bash test_cccl_preload.sh
2026-08-13 09:43:35 +00:00
root
1aa6e16d4e build: trigger rebuild after merge reconciliation 2026-08-13 09:43:18 +00:00
root
93fb9bd8b7 build: trigger rebuild after merge reconciliation 2026-08-13 09:43:18 +00:00
root
19946d4c72 merge: reconcile modelhub with github (keep CUB_NS_QUALIFIER fix) 2026-08-13 09:35:35 +00:00
root
188d3654ef build: trigger rebuild after merge reconciliation 2026-08-13 09:34:49 +00:00
dylanyunlon
e1cdbfc167 feat: CCCL CachingDeviceAllocator preload — 完整依赖链 288 files
从 cccl_upstream 递归追踪 cub/util_allocator.cuh 的全部 include 依赖:
  cub/         9 files (config, util_*, version, detect_cuda_runtime)
  cuda/        libcudacxx type_traits, concepts, algorithm, iterator...
  nv/          target macros, preprocessor

总计 288 个头文件 (1.4MB),打包到 include/ 目录,编译时 -I include
即可完全脱离 CCCL 原始目录结构。

.cu 文件直接 #include <cub/util_allocator.cuh>,
走原版 CUB CachingDeviceAllocator,零 mock。

BI-V100 参数: growth=2 bins=[8..32] max_cached=8GB/device
2026-08-13 09:30:44 +00:00
dylanyunlon
8eba8df925 feat: CCCL CachingDeviceAllocator LD_PRELOAD — bypass CoreX expandable_segments ASSERT
从 CCCL upstream cub/cub/util_allocator.cuh 提取 CachingDeviceAllocator
核心算法,去掉所有 CUB/CCCL 宏依赖,编译为独立 .so。

用 LD_PRELOAD 拦截 cudaMalloc/cudaFree,路由到 CUB 的 geometric-bin
缓存分配器。同时在 constructor 中 strip PYTORCH_CUDA_ALLOC_CONF 里的
expandable_segments 配置,避免 CoreX CUDACachingAllocator.cpp:545 ASSERT。

BI-V100 调优参数:
  bin_growth=8, min_bin=3 (512B), max_bin=13 (~550MB)
  max_cached_bytes=4GB per device (32GB卡的合理上限)

真机测试步骤:
  1. bash build_cccl_preload.sh
  2. LD_PRELOAD=./libcccl_allocator.so CCCL_ALLOC_DEBUG=1 \
     PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True \
     python3 verify_preload.py
2026-08-13 09:30:43 +00:00
dylanyunlon
1a8d086c4a fix: remove expandable_segments — CoreX CUDACachingAllocator不支持
BI-V100 CoreX PyTorch的CUDACachingAllocator.cpp:545没有实现
expandable segment特性,导致模型加载阶段(VocabParallelEmbedding)
直接INTERNAL ASSERT FAILED崩溃。

替换为max_split_size_mb:512减少内存碎片化。
2026-08-13 09:30:43 +00:00
Claude
d036646726 feat(CCCL): LD_PRELOAD CachingDeviceAllocator — intercept cudaMalloc/cudaFree
Route C: replace PyTorch's cudaMalloc/cudaFree with CCCL CUB's
CachingDeviceAllocator via LD_PRELOAD. Eliminates driver-level allocation
overhead by reusing freed GPU memory from a bin-based cache.

Based on cccl_upstream/cub/cub/util_allocator.cuh (901 lines).
Self-contained .so with no CCCL header dependencies at compile time.

Files:
- cccl_preload_allocator.cu: the allocator (405 lines)
- build_cccl_preload_allocator.sh: build script (corex clang++ or g++ fallback)
- test_cccl_preload.sh: smoke test suite for BI-V100
- patch_ops.sh: build during docker build
- computility-run.yaml: LD_PRELOAD env var for runtime

Config via env:
  CCCL_ALLOC_BIN_GROWTH=8, MIN_BIN=3, MAX_BIN=13, MAX_CACHED_MB=4096

Test on real machine:
  cd qwen3_6_scripts && bash test_cccl_preload.sh
2026-08-13 09:30:43 +00:00
root
05713aa7cb build: trigger rebuild after merge reconciliation 2026-08-13 08:46:38 +00:00
2 changed files with 28 additions and 39 deletions

View File

@@ -72,7 +72,8 @@ COMMON_FLAGS=(
# Suppress CCCL warnings that don't affect correctness # Suppress CCCL warnings that don't affect correctness
-Wno-unused-function -Wno-unused-function
-Wno-unknown-pragmas -Wno-unknown-pragmas
# Non-NVCC: disable arch magic, wrap namespace to avoid ODR conflicts # CUB needs these for non-NVCC compilers
-D_CCCL_COMPILER_GCC=1
-D__CUDA_ARCH_LIST__=700 -D__CUDA_ARCH_LIST__=700
-DCUB_DISABLE_NAMESPACE_MAGIC -DCUB_DISABLE_NAMESPACE_MAGIC
-DCUB_WRAPPED_NAMESPACE=cccl_preload -DCUB_WRAPPED_NAMESPACE=cccl_preload

View File

@@ -8,10 +8,6 @@
* caching allocator. Strips expandable_segments from * caching allocator. Strips expandable_segments from
* PYTORCH_CUDA_ALLOC_CONF before libtorch reads it. * PYTORCH_CUDA_ALLOC_CONF before libtorch reads it.
* *
* CRITICAL: CUB's allocator internally calls cudaMalloc/cudaFree for
* cache misses. We use a thread-local reentrant guard so internal calls
* go straight to the real CUDA runtime, avoiding infinite recursion.
*
* Source: CCCL cub/cub/util_allocator.cuh (BSD-3, NVIDIA) * Source: CCCL cub/cub/util_allocator.cuh (BSD-3, NVIDIA)
* Build: bash build_cccl_preload.sh * Build: bash build_cccl_preload.sh
*/ */
@@ -28,21 +24,30 @@
/* ======================================================================== /* ========================================================================
* Configuration for BI-V100 (32GB × 4 cards) * Configuration for BI-V100 (32GB × 4 cards)
*
* CUB CachingDeviceAllocator parameters:
* bin_growth = 2 (power-of-2 bins: 256B, 512B, 1KB, ... 4GB)
* min_bin = 8 (2^8 = 256B minimum allocation)
* max_bin = 32 (2^32 = 4GB maximum cached bin)
* max_cached = 8GB per device
*
* More granular bins (growth=2) than CUB default (growth=8) because
* PyTorch tensor sizes vary widely in inference.
* ======================================================================== */ * ======================================================================== */
static constexpr unsigned int ALLOC_BIN_GROWTH = 2; static constexpr unsigned int ALLOC_BIN_GROWTH = 2;
static constexpr unsigned int ALLOC_MIN_BIN = 8; /* 2^8 = 256 bytes */ static constexpr unsigned int ALLOC_MIN_BIN = 8; /* 256 bytes */
static constexpr unsigned int ALLOC_MAX_BIN = 32; /* 2^32 = 4 GB */ static constexpr unsigned int ALLOC_MAX_BIN = 32; /* 4 GB */
static constexpr size_t ALLOC_MAX_CACHED = (size_t)8 * 1024 * 1024 * 1024; static constexpr size_t ALLOC_MAX_CACHED = (size_t)8 * 1024 * 1024 * 1024; /* 8GB */
/* ---- Global allocator singleton ---- */ /* ---- Global allocator singleton ---- */
using CubAllocator = CUB_NS_QUALIFIER::CachingDeviceAllocator; static cub::CachingDeviceAllocator& get_allocator() {
static cub::CachingDeviceAllocator instance(
static CubAllocator& get_allocator() { ALLOC_BIN_GROWTH,
static CubAllocator instance( ALLOC_MIN_BIN,
ALLOC_BIN_GROWTH, ALLOC_MIN_BIN, ALLOC_MAX_BIN, ALLOC_MAX_BIN,
ALLOC_MAX_CACHED, ALLOC_MAX_CACHED,
true /* skip_cleanup: CoreX may tear down CUDA before dtor */ true /* skip_cleanup: CoreX may tear down CUDA before our dtor */
); );
return instance; return instance;
} }
@@ -50,17 +55,6 @@ static CubAllocator& get_allocator() {
static bool g_preload_active = false; static bool g_preload_active = false;
static bool g_debug = false; static bool g_debug = false;
/*
* Reentrant guard: CUB's DeviceAllocate/DeviceFree internally call
* cudaMalloc/cudaFree (for cache misses and evictions). Without this
* guard, our intercept would call DeviceAllocate again → infinite
* recursion → stack overflow → segfault.
*
* When inside_cub == true, cudaMalloc/cudaFree go straight to the
* real CUDA runtime via dlsym(RTLD_NEXT).
*/
static thread_local bool inside_cub = false;
/* ---- Real cudaMalloc/cudaFree via dlsym(RTLD_NEXT) ---- */ /* ---- Real cudaMalloc/cudaFree via dlsym(RTLD_NEXT) ---- */
using RealMalloc_t = cudaError_t (*)(void**, size_t); using RealMalloc_t = cudaError_t (*)(void**, size_t);
using RealFree_t = cudaError_t (*)(void*); using RealFree_t = cudaError_t (*)(void*);
@@ -113,8 +107,11 @@ static void cccl_preload_init() {
alloc_conf, clean.empty() ? "(unset)" : clean.c_str()); alloc_conf, clean.empty() ? "(unset)" : clean.c_str());
} }
/* Initialize allocator */
auto& alloc = get_allocator(); auto& alloc = get_allocator();
if (g_debug) alloc.debug = true; if (g_debug) {
alloc.debug = true;
}
g_preload_active = true; g_preload_active = true;
fprintf(stderr, fprintf(stderr,
@@ -126,29 +123,20 @@ static void cccl_preload_init() {
/* ======================================================================== /* ========================================================================
* cudaMalloc / cudaFree intercepts * cudaMalloc / cudaFree intercepts
*
* outside CUB → route to CUB CachingDeviceAllocator (bin + cache)
* inside CUB → pass through to real cudaMalloc/cudaFree (no recursion)
* ======================================================================== */ * ======================================================================== */
extern "C" cudaError_t cudaMalloc(void** devPtr, size_t size) extern "C" cudaError_t cudaMalloc(void** devPtr, size_t size)
{ {
if (!g_preload_active || inside_cub) { if (!g_preload_active) {
return get_real_malloc()(devPtr, size); return get_real_malloc()(devPtr, size);
} }
inside_cub = true; return get_allocator().DeviceAllocate(devPtr, size);
cudaError_t err = get_allocator().DeviceAllocate(devPtr, size);
inside_cub = false;
return err;
} }
extern "C" cudaError_t cudaFree(void* devPtr) extern "C" cudaError_t cudaFree(void* devPtr)
{ {
if (!g_preload_active || inside_cub || devPtr == nullptr) { if (!g_preload_active || devPtr == nullptr) {
return get_real_free()(devPtr); return get_real_free()(devPtr);
} }
inside_cub = true; return get_allocator().DeviceFree(devPtr);
cudaError_t err = get_allocator().DeviceFree(devPtr);
inside_cub = false;
return err;
} }