diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000000..a897ef815b --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,127 @@ +# UMF (Unified Memory Framework) - AI Coding Guide + +## Project Architecture + +UMF is a C library for constructing memory allocators and pools, built around a two-layer architecture: + +- **Memory Providers** (`src/provider/`): Handle coarse-grained OS-level memory allocation (mmap, CUDA, Level Zero, etc.) +- **Memory Pools** (`src/pool/`): Handle fine-grained allocation using providers as backing store (jemalloc, scalable, disjoint) + +Key architectural patterns: +- Provider/pool separation enables mixing any provider with any pool allocator +- Operations structures (`*_ops_t`) define plugin interfaces for extensibility +- Handle-based API (`*_handle_t`) abstracts implementation details +- Result codes (`umf_result_t`) for consistent error handling + +## Development Workflows + +### Build System +```bash +# Standard build +cmake -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build -j $(nproc) + +# Enable all features for development +# GPU tests will work only in an environment with proper hardware and drivers +cmake -B build -DCMAKE_BUILD_TYPE=Debug \ + -DUMF_BUILD_TESTS=ON -DUMF_BUILD_GPU_TESTS=OFF \ + -DUMF_BUILD_EXAMPLES=ON -DUMF_DEVELOPER_MODE=ON \ + -DUMF_FORMAT_CODE_STYLE=ON +``` + +### Version Management +- Version determined by: + 1. `git describe` (preferred) + 2. `VERSION` file fallback + 3. "0.0.0" default +- `set_version_variables()` in `cmake/helpers.cmake` handles version detection +- For releases: create `VERSION` file with semver format (e.g., "1.0.3") + +### Code Formatting +- **Always format code before committing**: `make format-apply` +- Requires build with `-DUMF_FORMAT_CODE_STYLE=ON` +- Uses clang-format-15.0, cmake-format-0.6, and black for Python + +### Testing Patterns +- Use `build_umf_test()` CMake function in `test/CMakeLists.txt` +- GPU tests require `UMF_BUILD_GPU_TESTS=ON` and hardware/drivers +- IPC tests use producer/consumer pattern with shell scripts +- Platform-specific tests: `.c` files for portability, `.cpp` for C++ features, utils, and selected tests + +### CI/CD Structure +- `pr_push.yml`: Main workflow calling reusable workflows. It's called for each PR change or push to main/stable branches +- Separate workflows for different configurations: `reusable_gpu.yml`, `reusable_sanitizers.yml`, etc. +- Provider-specific testing: Level Zero, CUDA runners with actual hardware + +## Coding Conventions + +### Naming Patterns +- Public API: `umf*` prefix (e.g., `umfMemoryProviderCreate`) +- Internal functions: `snake_case` without prefix +- Structures: `*_t` suffix for types, `*_handle_t` for opaque handles +- Constants: `UMF_*` uppercase with underscores + +### Memory Management Patterns +- Always pair create/destroy functions (e.g., `umfMemoryProviderCreate`/`umfMemoryProviderDestroy`) +- Use `umf_result_t` return codes, never throw exceptions +- Provider params have separate create/destroy lifecycle +- Thread-local storage (`__TLS`) for error state in providers + +### Provider Implementation Pattern +```c +// Standard provider structure +typedef struct my_provider_t { + // Provider-specific state +} my_provider_t; + +static umf_result_t my_initialize(const void *params, void **provider); +static umf_result_t my_finalize(void *provider); +static umf_result_t my_alloc(void *provider, size_t size, size_t alignment, void **ptr); +static umf_result_t my_free(void *provider, void *ptr, size_t size); + +static const umf_memory_provider_ops_t MY_PROVIDER_OPS = { + .version = UMF_PROVIDER_OPS_VERSION_CURRENT, + .initialize = my_initialize, + .finalize = my_finalize, + .alloc = my_alloc, + .free = my_free, + // ... other required ops +}; +``` + +## Key Files and Patterns + +### Core APIs +- `include/umf.h`: Main header, include this for basic usage +- `include/umf/memory_provider_ops.h`: Provider plugin interface +- `include/umf/memory_pool_ops.h`: Pool plugin interface + +### Common Utilities +- `src/utils/`: Logging (`utils_log.h`), concurrency (`utils_concurrency.h`), assertions +- `src/critnib/`: Concurrent radix tree for address tracking +- `src/base_alloc/`: Base allocation utilities + +### Platform Abstractions +- `libumf_linux.c`/`libumf_windows.c`: OS-specific implementations +- `topology.c`: HWLOC integration for NUMA topology discovery +- Provider files handle platform-specific allocation (CUDA, Level Zero, OS memory) + +## Integration Points + +### NUMA Support +- Uses HWLOC for topology discovery (`topology.c`, `umf_hwloc.h`) +- NUMA policies in `mempolicy.c`: bind, interleave, split modes +- Memory spaces (`memspace.c`) and targets (`memtarget.c`) for NUMA abstraction + +### GPU Integration +- Level Zero provider: `provider_level_zero.c` for Intel GPUs +- CUDA provider: `provider_cuda.c` for NVIDIA GPUs +- Examples in `examples/level_zero_shared_memory/` and `examples/cuda_shared_memory/` + +### IPC (Inter-Process Communication) +- Linux-specific implementation using file descriptor passing +- Requires `PTRACE_MODE_ATTACH_REALCREDS` permission +- Uses `memfd_create()` or `memfd_secret()` for anonymous shared memory + +When implementing new providers or pools, follow the existing patterns in +`src/provider/provider_os_memory.c` and `src/pool/pool_scalable.c` as reference implementations. diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f00070d215..26262ec8a7 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,7 +4,7 @@ updates: - package-ecosystem: "pip" directory: "/third_party" # Location of package manifests schedule: - interval: "daily" + interval: "monthly" ignore: - dependency-name: "clang-format" - dependency-name: "cmake-format" @@ -14,3 +14,12 @@ updates: applies-to: version-updates patterns: - "*" + - package-ecosystem: "github-actions" + directory: "/.github/workflows/" + schedule: + interval: "monthly" + groups: + actions-dependencies: + applies-to: version-updates + patterns: + - "*" diff --git a/.github/docker/alpine-3.21.Dockerfile b/.github/docker/alpine-3.21.Dockerfile new file mode 100644 index 0000000000..fef9810703 --- /dev/null +++ b/.github/docker/alpine-3.21.Dockerfile @@ -0,0 +1,46 @@ +# Copyright (C) 2025 Intel Corporation +# Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# +# Dockerfile - a 'recipe' for Docker to build an image of Alpine +# environment for building the Unified Memory Framework project. +# + +# Pull base Alpine image version 3.21 +FROM registry.hub.docker.com/library/alpine@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c + +# Set environment variables +ENV OS=alpine +ENV OS_VER=3.21 + +# Base development packages +ARG BASE_DEPS="\ + bash \ + cmake \ + git \ + g++ \ + make \ + sudo" + +# UMF's dependencies +ARG UMF_DEPS="\ + hwloc-dev" + +# Dependencies for tests +ARG TEST_DEPS="\ + numactl-dev" + +# Update and install required packages +RUN apk update \ + && apk add --no-cache \ + ${BASE_DEPS} \ + ${TEST_DEPS} \ + ${UMF_DEPS} + +# Add a new (non-root) 'test_user' +ENV USER=test_user +RUN adduser -D -G wheel ${USER} +RUN echo '%wheel ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers + +USER test_user diff --git a/.github/docker/ubuntu-20.04.Dockerfile b/.github/docker/ubuntu-20.04.Dockerfile index a6a45a8c1b..9de50673fa 100644 --- a/.github/docker/ubuntu-20.04.Dockerfile +++ b/.github/docker/ubuntu-20.04.Dockerfile @@ -1,20 +1,20 @@ -# Copyright (C) 2024 Intel Corporation +# Copyright (C) 2024-2025 Intel Corporation # Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # # Dockerfile - a 'recipe' for Docker to build an image of ubuntu-based -# environment for building the Unified Memory Framework project. +# environment for building the Unified Memory Framework project. # # Pull base image ("20.04") FROM registry.hub.docker.com/library/ubuntu@sha256:f2034e7195f61334e6caff6ecf2e965f92d11e888309065da85ff50c617732b8 # Set environment variables -ENV OS ubuntu -ENV OS_VER 20.04 -ENV NOTTY 1 -ENV DEBIAN_FRONTEND noninteractive +ENV OS=ubuntu +ENV OS_VER=20.04 +ENV NOTTY=1 +ENV DEBIAN_FRONTEND=noninteractive # Base development packages ARG BASE_DEPS="\ @@ -22,43 +22,50 @@ ARG BASE_DEPS="\ cmake \ git" -# UMF's dependencies -ARG UMF_DEPS="\ - libhwloc-dev \ - libtbb-dev" +# Hwloc installation dependencies +ARG HWLOC_DEPS="\ + libtool" # Dependencies for tests (optional) ARG TEST_DEPS="\ - libnuma-dev" + libnuma-dev \ + libtbb-dev \ + valgrind" # Miscellaneous for our builds/CI (optional) ARG MISC_DEPS="\ automake \ clang \ g++-7 \ + lcov \ python3-pip \ sudo \ whois" +# libhwloc-dev is required - installed via script because hwloc version is too old on this OS +COPY .github/scripts/install_hwloc.sh /opt/umf/install_hwloc.sh + # Update and install required packages RUN apt-get update \ && apt-get install -y --no-install-recommends \ ${BASE_DEPS} \ - ${UMF_DEPS} \ ${TEST_DEPS} \ ${MISC_DEPS} \ + ${HWLOC_DEPS} \ + && /opt/umf/install_hwloc.sh \ && rm -rf /var/lib/apt/lists/* \ && apt-get clean all # Prepare a dir (accessible by anyone) -RUN mkdir --mode 777 /opt/umf/ +RUN mkdir -p --mode 777 /opt/umf/ # Additional dependencies (installed via pip) +# It's actively used and tested only on selected distros. Be aware +# they may not work, because pip packages list differ from OS to OS. COPY third_party/requirements.txt /opt/umf/requirements.txt -RUN pip3 install --no-cache-dir -r /opt/umf/requirements.txt # Add a new (non-root) 'test_user' -ENV USER test_user -ENV USERPASS pass -RUN useradd -m "${USER}" -g sudo -p "$(mkpasswd ${USERPASS})" +ENV USER=test_user +ENV USERPASS=pass +RUN useradd -m -u 1001 "${USER}" -g sudo -p "$(mkpasswd ${USERPASS})" USER test_user diff --git a/.github/docker/ubuntu-22.04.Dockerfile b/.github/docker/ubuntu-22.04.Dockerfile index 75c71c526c..748a2d544c 100644 --- a/.github/docker/ubuntu-22.04.Dockerfile +++ b/.github/docker/ubuntu-22.04.Dockerfile @@ -1,4 +1,4 @@ -# Copyright (C) 2024 Intel Corporation +# Copyright (C) 2024-2025 Intel Corporation # Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -11,30 +11,38 @@ FROM registry.hub.docker.com/library/ubuntu@sha256:e6173d4dc55e76b87c4af8db8821b1feae4146dd47341e4d431118c7dd060a74 # Set environment variables -ENV OS ubuntu -ENV OS_VER 22.04 -ENV NOTTY 1 -ENV DEBIAN_FRONTEND noninteractive +ENV OS=ubuntu +ENV OS_VER=22.04 +ENV NOTTY=1 +ENV DEBIAN_FRONTEND=noninteractive # Base development packages +# 'libtool' is required when hwloc is statically linked and built from source ARG BASE_DEPS="\ build-essential \ cmake \ - git" + git \ + libtool \ + wget" # UMF's dependencies ARG UMF_DEPS="\ - libhwloc-dev \ - libtbb-dev" + libhwloc-dev" # Dependencies for tests (optional) ARG TEST_DEPS="\ - libnuma-dev" + libnuma-dev \ + libtbb-dev \ + valgrind" # Miscellaneous for our builds/CI (optional) +# 'pkg-config' is added only on one Ubuntu image to test both: +# find_library and pkg-config methods of finding libraries. ARG MISC_DEPS="\ automake \ clang \ + lcov \ + pkg-config \ python3-pip \ sudo \ whois" @@ -43,21 +51,21 @@ ARG MISC_DEPS="\ RUN apt-get update \ && apt-get install -y --no-install-recommends \ ${BASE_DEPS} \ - ${UMF_DEPS} \ ${TEST_DEPS} \ ${MISC_DEPS} \ + ${UMF_DEPS} \ && rm -rf /var/lib/apt/lists/* \ && apt-get clean all # Prepare a dir (accessible by anyone) -RUN mkdir --mode 777 /opt/umf/ +RUN mkdir -p --mode 777 /opt/umf/ # Additional dependencies (installed via pip) COPY third_party/requirements.txt /opt/umf/requirements.txt RUN pip3 install --no-cache-dir -r /opt/umf/requirements.txt # Add a new (non-root) 'test_user' -ENV USER test_user -ENV USERPASS pass -RUN useradd -m "${USER}" -g sudo -p "$(mkpasswd ${USERPASS})" +ENV USER=test_user +ENV USERPASS=pass +RUN useradd -m -u 1001 "${USER}" -g sudo -p "$(mkpasswd ${USERPASS})" USER test_user diff --git a/.github/docker/ubuntu-24.04.Dockerfile b/.github/docker/ubuntu-24.04.Dockerfile new file mode 100644 index 0000000000..21e7f01602 --- /dev/null +++ b/.github/docker/ubuntu-24.04.Dockerfile @@ -0,0 +1,68 @@ +# Copyright (C) 2025 Intel Corporation +# Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# +# Dockerfile - a 'recipe' for Docker to build an image of ubuntu-based +# environment for building the Unified Memory Framework project. +# + +# Pull base image ("24.04") +FROM registry.hub.docker.com/library/ubuntu@sha256:72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782 + +# Set environment variables +ENV OS=ubuntu +ENV OS_VER=24.04 +ENV NOTTY=1 +ENV DEBIAN_FRONTEND=noninteractive + +# Base development packages +# 'libtool' is required when hwloc is statically linked and built from source +ARG BASE_DEPS="\ + build-essential \ + cmake \ + git \ + libtool \ + wget" + +# UMF's dependencies +ARG UMF_DEPS="\ + libhwloc-dev" + +# Dependencies for tests (optional) +ARG TEST_DEPS="\ + libnuma-dev \ + libtbb-dev \ + valgrind" + +# Miscellaneous for our builds/CI (optional) +ARG MISC_DEPS="\ + automake \ + clang \ + lcov \ + python3-pip \ + sudo \ + whois" + +# Update and install required packages +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + ${BASE_DEPS} \ + ${TEST_DEPS} \ + ${MISC_DEPS} \ + ${UMF_DEPS} \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean all + +# Prepare a dir (accessible by anyone) +RUN mkdir -p --mode 777 /opt/umf/ + +# Additional dependencies (installed via pip) +COPY third_party/requirements.txt /opt/umf/requirements.txt +RUN pip3 install --no-cache-dir --break-system-packages -r /opt/umf/requirements.txt + +# Add a new (non-root) 'test_user' +ENV USER=test_user +ENV USERPASS=pass +RUN useradd -m "${USER}" -g sudo -p "$(mkpasswd ${USERPASS})" +USER test_user diff --git a/.github/scripts/alpine_build.sh b/.github/scripts/alpine_build.sh new file mode 100755 index 0000000000..4bfdb44616 --- /dev/null +++ b/.github/scripts/alpine_build.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Copyright (C) 2025 Intel Corporation +# Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# alpine_build.sh - Script for building UMF on Alpine image + +set -e + +UMF_BUILD_TYPE=$1 +WORKDIR=$2 + +sudo chown $USER $WORKDIR +cd unified-memory-framework + +cmake -B build -DCMAKE_BUILD_TYPE=$UMF_BUILD_TYPE -DUMF_BUILD_TESTS=ON -DUMF_BUILD_EXAMPLES=ON +cmake --build build diff --git a/.github/scripts/get_system_info.sh b/.github/scripts/get_system_info.sh index 81c54ce980..2aa19a298e 100755 --- a/.github/scripts/get_system_info.sh +++ b/.github/scripts/get_system_info.sh @@ -7,7 +7,7 @@ function check_L0_version { if command -v dpkg &> /dev/null; then - dpkg -l | grep level-zero && return + dpkg -l | grep -iE "level-zero|libze|Compute Runtime|Level Zero" && return fi if command -v rpm &> /dev/null; then @@ -34,7 +34,7 @@ function system_info { numactl -H echo "**********VGA info**********" - lspci | grep -i VGA + lspci | grep -iE "vga|display|gpu" echo "**********CUDA Version**********" if command -v nvidia-smi &> /dev/null; then @@ -93,7 +93,7 @@ function system_info { echo "***************all installed packages***************" # Instructions below will return some minor errors, as they are dependent on the Linux distribution. - zypper se --installed-only 2>/dev/null || true + zypper -n se --installed-only 2>/dev/null || true apt list --installed 2>/dev/null || true yum list installed 2>/dev/null || true } diff --git a/.github/scripts/install_oneAPI.sh b/.github/scripts/install_oneAPI.sh new file mode 100755 index 0000000000..f2331e2eb7 --- /dev/null +++ b/.github/scripts/install_oneAPI.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright (C) 2025 Intel Corporation +# Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# install_oneAPI.sh - Script for installing Intel oneAPI from the official repository + +apt-get update +apt-get install -y gpg-agent gnupg wget +wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | gpg --dearmor -o /usr/share/keyrings/oneapi-archive-keyring.gpg +echo 'deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main' > /etc/apt/sources.list.d/oneAPI.list +apt-get update +apt-get install -y intel-oneapi-ippcp-devel intel-oneapi-ipp-devel intel-oneapi-common-oneapi-vars intel-oneapi-compiler-dpcpp-cpp diff --git a/.github/workflows/.spellcheck-conf.toml b/.github/workflows/.spellcheck-conf.toml index 24b9023fe3..bb0f480d69 100644 --- a/.github/workflows/.spellcheck-conf.toml +++ b/.github/workflows/.spellcheck-conf.toml @@ -1,6 +1,6 @@ [default] # Don't correct the following words: -extend-ignore-words-re = ["ASSER", "Tne", "ba", "BA"] +extend-ignore-words-re = ["ASSER", "Tne", "ba", "BA", "PN", "usm"] [files] # completely exclude those files from consideration: diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index 7eb3c7b06a..080b8f777f 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -7,25 +7,39 @@ on: description: PR number (if 0, it'll run on the main) type: number bench_script_params: + # If you want to save the results of the manual run in 'benchmark-results' branch, + # you have to pass '--save XXX', where XXX is the label of your results. description: Parameters passed to script executing benchmark type: string required: false default: '' - upload_report: - description: 'Upload HTML report' - type: boolean + bench_script_compare: + description: Compare label, passed to script executing benchmark as '--compare