|
| 1 | +# UMF (Unified Memory Framework) - AI Coding Guide |
| 2 | + |
| 3 | +## Project Architecture |
| 4 | + |
| 5 | +UMF is a C library for constructing memory allocators and pools, built around a two-layer architecture: |
| 6 | + |
| 7 | +- **Memory Providers** (`src/provider/`): Handle coarse-grained OS-level memory allocation (mmap, CUDA, Level Zero, etc.) |
| 8 | +- **Memory Pools** (`src/pool/`): Handle fine-grained allocation using providers as backing store (jemalloc, scalable, disjoint) |
| 9 | + |
| 10 | +Key architectural patterns: |
| 11 | +- Provider/pool separation enables mixing any provider with any pool allocator |
| 12 | +- Operations structures (`*_ops_t`) define plugin interfaces for extensibility |
| 13 | +- Handle-based API (`*_handle_t`) abstracts implementation details |
| 14 | +- Result codes (`umf_result_t`) for consistent error handling |
| 15 | + |
| 16 | +## Development Workflows |
| 17 | + |
| 18 | +### Build System |
| 19 | +```bash |
| 20 | +# Standard build |
| 21 | +cmake -B build -DCMAKE_BUILD_TYPE=Release |
| 22 | +cmake --build build -j $(nproc) |
| 23 | + |
| 24 | +# Enable all features for development |
| 25 | +# GPU tests will work only in an environment with proper hardware and drivers |
| 26 | +cmake -B build -DCMAKE_BUILD_TYPE=Debug \ |
| 27 | + -DUMF_BUILD_TESTS=ON -DUMF_BUILD_GPU_TESTS=OFF \ |
| 28 | + -DUMF_BUILD_EXAMPLES=ON -DUMF_DEVELOPER_MODE=ON \ |
| 29 | + -DUMF_FORMAT_CODE_STYLE=ON |
| 30 | +``` |
| 31 | + |
| 32 | +### Version Management |
| 33 | +- Version determined by: |
| 34 | + 1. `git describe` (preferred) |
| 35 | + 2. `VERSION` file fallback |
| 36 | + 3. "0.0.0" default |
| 37 | +- `set_version_variables()` in `cmake/helpers.cmake` handles version detection |
| 38 | +- For releases: create `VERSION` file with semver format (e.g., "1.0.3") |
| 39 | + |
| 40 | +### Code Formatting |
| 41 | +- **Always format code before committing**: `make format-apply` |
| 42 | +- Requires build with `-DUMF_FORMAT_CODE_STYLE=ON` |
| 43 | +- Uses clang-format-15.0, cmake-format-0.6, and black for Python |
| 44 | + |
| 45 | +### Testing Patterns |
| 46 | +- Use `build_umf_test()` CMake function in `test/CMakeLists.txt` |
| 47 | +- GPU tests require `UMF_BUILD_GPU_TESTS=ON` and hardware/drivers |
| 48 | +- IPC tests use producer/consumer pattern with shell scripts |
| 49 | +- Platform-specific tests: `.c` files for portability, `.cpp` for C++ features, utils, and selected tests |
| 50 | + |
| 51 | +### CI/CD Structure |
| 52 | +- `pr_push.yml`: Main workflow calling reusable workflows. It's called for each PR change or push to main/stable branches |
| 53 | +- Separate workflows for different configurations: `reusable_gpu.yml`, `reusable_sanitizers.yml`, etc. |
| 54 | +- Provider-specific testing: Level Zero, CUDA runners with actual hardware |
| 55 | + |
| 56 | +## Coding Conventions |
| 57 | + |
| 58 | +### Naming Patterns |
| 59 | +- Public API: `umf*` prefix (e.g., `umfMemoryProviderCreate`) |
| 60 | +- Internal functions: `snake_case` without prefix |
| 61 | +- Structures: `*_t` suffix for types, `*_handle_t` for opaque handles |
| 62 | +- Constants: `UMF_*` uppercase with underscores |
| 63 | + |
| 64 | +### Memory Management Patterns |
| 65 | +- Always pair create/destroy functions (e.g., `umfMemoryProviderCreate`/`umfMemoryProviderDestroy`) |
| 66 | +- Use `umf_result_t` return codes, never throw exceptions |
| 67 | +- Provider params have separate create/destroy lifecycle |
| 68 | +- Thread-local storage (`__TLS`) for error state in providers |
| 69 | + |
| 70 | +### Provider Implementation Pattern |
| 71 | +```c |
| 72 | +// Standard provider structure |
| 73 | +typedef struct my_provider_t { |
| 74 | + // Provider-specific state |
| 75 | +} my_provider_t; |
| 76 | + |
| 77 | +static umf_result_t my_initialize(const void *params, void **provider); |
| 78 | +static umf_result_t my_finalize(void *provider); |
| 79 | +static umf_result_t my_alloc(void *provider, size_t size, size_t alignment, void **ptr); |
| 80 | +static umf_result_t my_free(void *provider, void *ptr, size_t size); |
| 81 | + |
| 82 | +static const umf_memory_provider_ops_t MY_PROVIDER_OPS = { |
| 83 | + .version = UMF_PROVIDER_OPS_VERSION_CURRENT, |
| 84 | + .initialize = my_initialize, |
| 85 | + .finalize = my_finalize, |
| 86 | + .alloc = my_alloc, |
| 87 | + .free = my_free, |
| 88 | + // ... other required ops |
| 89 | +}; |
| 90 | +``` |
| 91 | +
|
| 92 | +## Key Files and Patterns |
| 93 | +
|
| 94 | +### Core APIs |
| 95 | +- `include/umf.h`: Main header, include this for basic usage |
| 96 | +- `include/umf/memory_provider_ops.h`: Provider plugin interface |
| 97 | +- `include/umf/memory_pool_ops.h`: Pool plugin interface |
| 98 | +
|
| 99 | +### Common Utilities |
| 100 | +- `src/utils/`: Logging (`utils_log.h`), concurrency (`utils_concurrency.h`), assertions |
| 101 | +- `src/critnib/`: Concurrent radix tree for address tracking |
| 102 | +- `src/base_alloc/`: Base allocation utilities |
| 103 | +
|
| 104 | +### Platform Abstractions |
| 105 | +- `libumf_linux.c`/`libumf_windows.c`: OS-specific implementations |
| 106 | +- `topology.c`: HWLOC integration for NUMA topology discovery |
| 107 | +- Provider files handle platform-specific allocation (CUDA, Level Zero, OS memory) |
| 108 | +
|
| 109 | +## Integration Points |
| 110 | +
|
| 111 | +### NUMA Support |
| 112 | +- Uses HWLOC for topology discovery (`topology.c`, `umf_hwloc.h`) |
| 113 | +- NUMA policies in `mempolicy.c`: bind, interleave, split modes |
| 114 | +- Memory spaces (`memspace.c`) and targets (`memtarget.c`) for NUMA abstraction |
| 115 | +
|
| 116 | +### GPU Integration |
| 117 | +- Level Zero provider: `provider_level_zero.c` for Intel GPUs |
| 118 | +- CUDA provider: `provider_cuda.c` for NVIDIA GPUs |
| 119 | +- Examples in `examples/level_zero_shared_memory/` and `examples/cuda_shared_memory/` |
| 120 | +
|
| 121 | +### IPC (Inter-Process Communication) |
| 122 | +- Linux-specific implementation using file descriptor passing |
| 123 | +- Requires `PTRACE_MODE_ATTACH_REALCREDS` permission |
| 124 | +- Uses `memfd_create()` or `memfd_secret()` for anonymous shared memory |
| 125 | +
|
| 126 | +When implementing new providers or pools, follow the existing patterns in |
| 127 | +`src/provider/provider_os_memory.c` and `src/pool/pool_scalable.c` as reference implementations. |
0 commit comments