diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index db93fa53b..aaaae6ddc 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -130,11 +130,20 @@ jobs: with: fetch-depth: 0 - - name: Set VCPKG_PATH without hwloc - if: matrix.static_hwloc == 'ON' - run: echo "VCPKG_PATH=${{env.VCPKG_PATH_NO_HWLOC}}" >> $env:GITHUB_ENV + - name: Restore vcpkg cache + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + id: cache + with: + path: vcpkg_pkgs_cache.zip + key: vcpkg-generators-windows-latest-${{ hashFiles('vcpkg.json') }} + + - name: Unpack vcpkg cache + if: steps.cache.outputs.cache-hit == 'true' + run: | + Expand-Archive -Path ${{github.workspace}}/vcpkg_pkgs_cache.zip -DestinationPath ${{env.BUILD_DIR}}/vcpkg -Force - name: Initialize vcpkg + if: steps.cache.outputs.cache-hit != 'true' uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 @@ -142,8 +151,13 @@ jobs: vcpkgJsonGlob: '**/vcpkg.json' - name: Install dependencies + if: steps.cache.outputs.cache-hit != 'true' run: vcpkg install --triplet x64-windows + - name: Set VCPKG_PATH without hwloc + if: matrix.static_hwloc == 'ON' + run: echo "VCPKG_PATH=${{env.VCPKG_PATH_NO_HWLOC}}" >> $env:GITHUB_ENV + - name: Install Ninja if: matrix.generator == 'Ninja' uses: seanmiddleditch/gha-setup-ninja@3b1f8f94a2f8254bd26914c4ab9474d4f0015f67 # v6 @@ -222,6 +236,18 @@ jobs: working-directory: ${{github.workspace}}/examples/fetch_content/build run: ctest -V + - name: Prepare vcpkg cache + if: steps.cache.outputs.cache-hit != 'true' + run: | + Compress-Archive -Path ${{env.BUILD_DIR}}/vcpkg/packages -DestinationPath ${{github.workspace}}/vcpkg_pkgs_cache.zip -Force -CompressionLevel Fastest + + - name: Save vcpkg cache + if: steps.cache.outputs.cache-hit != 'true' + uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: ${{github.workspace}}/vcpkg_pkgs_cache.zip + key: ${{ steps.cache.outputs.cache-primary-key }} + # Build and test UMF with Intel C++ Compiler (ICX) on Windows Windows-icx: env: @@ -241,71 +267,97 @@ jobs: runs-on: ${{matrix.os}} steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - fetch-depth: 0 - - - name: Initialize vcpkg - uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 - with: - vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 - vcpkgDirectory: ${{env.BUILD_DIR}}/vcpkg - vcpkgJsonGlob: '**/vcpkg.json' - - - name: Install dependencies - run: vcpkg install --triplet x64-windows - - - name: Install Ninja - uses: seanmiddleditch/gha-setup-ninja@3b1f8f94a2f8254bd26914c4ab9474d4f0015f67 # v6 - - - name: Download icx compiler - env: - # Link source: https://www.intel.com/content/www/us/en/developer/tools/oneapi/dpc-compiler-download.html - CMPLR_LINK: "https://registrationcenter-download.intel.com/akdlm/IRC_NAS/15a35578-2f9a-4f39-804b-3906e0a5f8fc/w_dpcpp-cpp-compiler_p_2024.2.1.83_offline.exe" - run: | - Invoke-WebRequest -Uri "${{ env.CMPLR_LINK }}" -OutFile compiler_install.exe - - - name: Install icx compiler - shell: cmd - run: | - start /b /wait .\compiler_install.exe -s -x -f extracted --log extract.log - extracted\bootstrapper.exe -s --action install --eula=accept -p=NEED_VS2017_INTEGRATION=0 ^ - -p=NEED_VS2019_INTEGRATION=0 -p=NEED_VS2022_INTEGRATION=0 --log-dir=. - - - name: Configure build - shell: cmd - run: | - call "C:\Program Files (x86)\Intel\oneAPI\setvars.bat" - call "C:\Program Files (x86)\Intel\oneAPI\setvars-vcvarsall.bat" - cmake ^ - -B ${{env.BUILD_DIR}} ^ - -DCMAKE_PREFIX_PATH="${{env.VCPKG_PATH}}" ^ - -DCMAKE_C_COMPILER=${{matrix.compiler.c}} ^ - -DCMAKE_CXX_COMPILER=${{matrix.compiler.cxx}} ^ - -G Ninja ^ - -DUMF_BUILD_SHARED_LIBRARY=${{matrix.shared_library}} ^ - -DUMF_FORMAT_CODE_STYLE=OFF ^ - -DUMF_DEVELOPER_MODE=ON ^ - -DUMF_BUILD_LIBUMF_POOL_JEMALLOC=ON ^ - -DUMF_BUILD_LEVEL_ZERO_PROVIDER=ON ^ - -DUMF_BUILD_CUDA_PROVIDER=ON ^ - -DUMF_TESTS_FAIL_ON_SKIP=ON - - - name: Build UMF - shell: cmd - run: | - call "C:\Program Files (x86)\Intel\oneAPI\setvars.bat" - call "C:\Program Files (x86)\Intel\oneAPI\setvars-vcvarsall.bat" - cmake --build ${{env.BUILD_DIR}} --config ${{matrix.build_type}} -j %NUMBER_OF_PROCESSORS% - - - name: Run tests - shell: cmd - working-directory: ${{env.BUILD_DIR}} - run: | - call "C:\Program Files (x86)\Intel\oneAPI\setvars.bat" - call "C:\Program Files (x86)\Intel\oneAPI\setvars-vcvarsall.bat" - ctest -C ${{matrix.build_type}} --output-on-failure --test-dir test + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + + - name: Restore vcpkg cache + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + id: cache + with: + path: vcpkg_pkgs_cache.zip + key: vcpkg-icx-${{matrix.os}}-${{ hashFiles('vcpkg.json') }} + + - name: Unpack vcpkg cache + if: steps.cache.outputs.cache-hit == 'true' + run: | + Expand-Archive -Path ${{github.workspace}}/vcpkg_pkgs_cache.zip -DestinationPath ${{env.BUILD_DIR}}/vcpkg -Force + + - name: Initialize vcpkg + if: steps.cache.outputs.cache-hit != 'true' + uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 + with: + vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 + vcpkgDirectory: ${{env.BUILD_DIR}}/vcpkg + vcpkgJsonGlob: '**/vcpkg.json' + + - name: Install dependencies + if: steps.cache.outputs.cache-hit != 'true' + run: vcpkg install --triplet x64-windows + + - name: Install Ninja + uses: seanmiddleditch/gha-setup-ninja@3b1f8f94a2f8254bd26914c4ab9474d4f0015f67 # v6 + + - name: Download icx compiler + env: + # Link source: https://www.intel.com/content/www/us/en/developer/tools/oneapi/dpc-compiler-download.html + CMPLR_LINK: "https://registrationcenter-download.intel.com/akdlm/IRC_NAS/15a35578-2f9a-4f39-804b-3906e0a5f8fc/w_dpcpp-cpp-compiler_p_2024.2.1.83_offline.exe" + run: | + Invoke-WebRequest -Uri "${{ env.CMPLR_LINK }}" -OutFile compiler_install.exe + + - name: Install icx compiler + shell: cmd + run: | + start /b /wait .\compiler_install.exe -s -x -f extracted --log extract.log + extracted\bootstrapper.exe -s --action install --eula=accept -p=NEED_VS2017_INTEGRATION=0 ^ + -p=NEED_VS2019_INTEGRATION=0 -p=NEED_VS2022_INTEGRATION=0 --log-dir=. + + - name: Configure build + shell: cmd + run: | + call "C:\Program Files (x86)\Intel\oneAPI\setvars.bat" + call "C:\Program Files (x86)\Intel\oneAPI\setvars-vcvarsall.bat" + cmake ^ + -B ${{env.BUILD_DIR}} ^ + -DCMAKE_PREFIX_PATH="${{env.VCPKG_PATH}}" ^ + -DCMAKE_C_COMPILER=${{matrix.compiler.c}} ^ + -DCMAKE_CXX_COMPILER=${{matrix.compiler.cxx}} ^ + -G Ninja ^ + -DUMF_BUILD_SHARED_LIBRARY=${{matrix.shared_library}} ^ + -DUMF_FORMAT_CODE_STYLE=OFF ^ + -DUMF_DEVELOPER_MODE=ON ^ + -DUMF_BUILD_LIBUMF_POOL_JEMALLOC=ON ^ + -DUMF_BUILD_LEVEL_ZERO_PROVIDER=ON ^ + -DUMF_BUILD_CUDA_PROVIDER=ON ^ + -DUMF_TESTS_FAIL_ON_SKIP=ON + + - name: Build UMF + shell: cmd + run: | + call "C:\Program Files (x86)\Intel\oneAPI\setvars.bat" + call "C:\Program Files (x86)\Intel\oneAPI\setvars-vcvarsall.bat" + cmake --build ${{env.BUILD_DIR}} --config ${{matrix.build_type}} -j %NUMBER_OF_PROCESSORS% + + - name: Run tests + shell: cmd + working-directory: ${{env.BUILD_DIR}} + run: | + call "C:\Program Files (x86)\Intel\oneAPI\setvars.bat" + call "C:\Program Files (x86)\Intel\oneAPI\setvars-vcvarsall.bat" + ctest -C ${{matrix.build_type}} --output-on-failure --test-dir test + + - name: Prepare vcpkg cache + if: steps.cache.outputs.cache-hit != 'true' + run: | + Compress-Archive -Path ${{env.BUILD_DIR}}/vcpkg/packages -DestinationPath ${{github.workspace}}/vcpkg_pkgs_cache.zip -Force -CompressionLevel Fastest + + - name: Save vcpkg cache + if: steps.cache.outputs.cache-hit != 'true' + uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: ${{github.workspace}}/vcpkg_pkgs_cache.zip + key: ${{ steps.cache.outputs.cache-primary-key }} # Scenarios where UMF_LINK_HWLOC_STATICALLY is set to OFF and hwloc is not installed in the system # The hwloc library is fetched implicitly diff --git a/.github/workflows/pr_push.yml b/.github/workflows/pr_push.yml index 49fb8e0d3..52bd73756 100644 --- a/.github/workflows/pr_push.yml +++ b/.github/workflows/pr_push.yml @@ -95,12 +95,10 @@ jobs: security-events: write uses: ./.github/workflows/reusable_trivy.yml Compatibility: - # TODO: bring back when new UMF version is ready - if: false needs: [Build] uses: ./.github/workflows/reusable_compatibility.yml strategy: matrix: - tag: ["v1.0.0-rc1"] + tag: ["v1.0.0"] with: tag: ${{matrix.tag}} diff --git a/.github/workflows/reusable_basic.yml b/.github/workflows/reusable_basic.yml index 1f4777f5f..2ac50d2a1 100644 --- a/.github/workflows/reusable_basic.yml +++ b/.github/workflows/reusable_basic.yml @@ -285,27 +285,40 @@ jobs: with: arch: x64 + - name: Restore vcpkg cache + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + id: cache + with: + path: vcpkg_pkgs_cache.zip + key: vcpkg-basic-${{matrix.os}}-${{ hashFiles('vcpkg.json') }} + + - name: Unpack vcpkg cache + if: steps.cache.outputs.cache-hit == 'true' + run: | + Expand-Archive -Path ${{github.workspace}}/vcpkg_pkgs_cache.zip -DestinationPath ${{github.workspace}}/vcpkg -Force + - name: Initialize vcpkg + if: steps.cache.outputs.cache-hit != 'true' uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 vcpkgDirectory: ${{github.workspace}}/vcpkg vcpkgJsonGlob: '**/vcpkg.json' - # Install the dependencies and add the bin folders to the PATH for older - # versions of CMake to correctly locate the libraries - name: Install dependencies + if: steps.cache.outputs.cache-hit != 'true' + run: vcpkg install --triplet x64-windows + + # Older versions of CMake require this step to correctly locate dependencies + - name: Add vcpkg bin dirs to PATH run: | - vcpkg install --triplet x64-windows $env:Path = "${{env.VCPKG_PATH_BIN}};$env:Path" echo "PATH=$env:Path" >> $env:GITHUB_ENV - shell: pwsh - name: Get UMF version run: | $version = (git describe --tags --abbrev=0 | Select-String -Pattern '\d+\.\d+\.\d+').Matches.Value echo "UMF_VERSION=$version" >> $env:GITHUB_ENV - shell: pwsh - name: Configure build (Debug) run: > @@ -416,6 +429,18 @@ jobs: run: ${{github.workspace}}/.github/scripts/check_dll_flags.ps1 ${{env.BUILD_RELEASE_DIR}}/src/proxy_lib/Release/umf_proxy.dll shell: pwsh + - name: Prepare vcpkg cache + if: steps.cache.outputs.cache-hit != 'true' + run: | + Compress-Archive -Path ${{github.workspace}}/vcpkg/packages -DestinationPath ${{github.workspace}}/vcpkg_pkgs_cache.zip -Force -CompressionLevel Fastest + + - name: Save vcpkg cache + if: steps.cache.outputs.cache-hit != 'true' + uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: ${{github.workspace}}/vcpkg_pkgs_cache.zip + key: ${{ steps.cache.outputs.cache-primary-key }} + windows-dynamic_build_hwloc: name: "Windows dynamic UMF + static hwloc" strategy: diff --git a/.github/workflows/reusable_codeql.yml b/.github/workflows/reusable_codeql.yml index 1d9159efd..6f7fff90c 100644 --- a/.github/workflows/reusable_codeql.yml +++ b/.github/workflows/reusable_codeql.yml @@ -46,19 +46,34 @@ jobs: languages: cpp trap-caching: false - - name: "[Win] Initialize vcpkg" + - name: "[Win] Restore vcpkg cache" if: matrix.os == 'windows-latest' + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + id: cache + with: + path: vcpkg_pkgs_cache.zip + key: vcpkg-codeql-${{matrix.os}}-${{ hashFiles('vcpkg.json') }} + + - name: "[Win] Unpack vcpkg cache" + if: matrix.os == 'windows-latest' && steps.cache.outputs.cache-hit == 'true' + run: | + Expand-Archive -Path ${{github.workspace}}/vcpkg_pkgs_cache.zip -DestinationPath ${{env.BUILD_DIR}}/vcpkg -Force + + - name: "[Win] Initialize vcpkg" + if: matrix.os == 'windows-latest' && steps.cache.outputs.cache-hit != 'true' uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 vcpkgDirectory: ${{env.BUILD_DIR}}/vcpkg vcpkgJsonGlob: '**/vcpkg.json' - - name: "[Win] Install dependencies" + - name: "[Win] Install vcpkg dependencies" + if: matrix.os == 'windows-latest' && steps.cache.outputs.cache-hit != 'true' + run: vcpkg install --triplet x64-windows + + - name: "[Win] Install Python requirements" if: matrix.os == 'windows-latest' - run: | - vcpkg install --triplet x64-windows - python3 -m pip install -r third_party/requirements.txt + run: python3 -m pip install -r third_party/requirements.txt - name: "[Lin] Install apt packages" if: matrix.os == 'ubuntu-latest' @@ -94,3 +109,15 @@ jobs: - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@d6bbdef45e766d081b84a2def353b0055f728d3e # v3.29.3 + + - name: "[Win] Prepare vcpkg cache" + if: matrix.os == 'windows-latest' && steps.cache.outputs.cache-hit != 'true' + run: | + Compress-Archive -Path ${{env.BUILD_DIR}}/vcpkg/packages -DestinationPath ${{github.workspace}}/vcpkg_pkgs_cache.zip -Force -CompressionLevel Fastest + + - name: "[Win] Save vcpkg cache" + if: matrix.os == 'windows-latest' && steps.cache.outputs.cache-hit != 'true' + uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: ${{github.workspace}}/vcpkg_pkgs_cache.zip + key: ${{ steps.cache.outputs.cache-primary-key }} diff --git a/.github/workflows/reusable_compatibility.yml b/.github/workflows/reusable_compatibility.yml index 60a7e0a24..5503a8110 100644 --- a/.github/workflows/reusable_compatibility.yml +++ b/.github/workflows/reusable_compatibility.yml @@ -9,7 +9,7 @@ on: tag: description: Check backward compatibility with this tag type: string - default: "v0.12.0-dev3" + default: "v1.0.0" permissions: contents: read @@ -136,7 +136,20 @@ jobs: ref: refs/tags/${{inputs.tag}} path: ${{github.workspace}}/tag_version + - name: Restore vcpkg cache + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + id: cache + with: + path: vcpkg_pkgs_cache.zip + key: vcpkg-compat-windows-latest-${{ hashFiles('tag_version/vcpkg.json') }} + + - name: Unpack vcpkg cache + if: steps.cache.outputs.cache-hit == 'true' + run: | + Expand-Archive -Path ${{github.workspace}}/vcpkg_pkgs_cache.zip -DestinationPath ${{github.workspace}}/vcpkg -Force + - name: Initialize vcpkg + if: steps.cache.outputs.cache-hit != 'true' uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 @@ -145,9 +158,9 @@ jobs: # NOTE we use vcpkg setup from "tag" version - name: Install dependencies + if: steps.cache.outputs.cache-hit != 'true' working-directory: ${{github.workspace}}/tag_version run: vcpkg install --triplet x64-windows - shell: pwsh # Specifies PowerShell as the shell for running the script. - name: Checkout latest UMF version uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 @@ -254,6 +267,18 @@ jobs: } } + - name: Prepare vcpkg cache + if: steps.cache.outputs.cache-hit != 'true' + run: | + Compress-Archive -Path ${{github.workspace}}/vcpkg/packages -DestinationPath ${{github.workspace}}/vcpkg_pkgs_cache.zip -Force -CompressionLevel Fastest + + - name: Save vcpkg cache + if: steps.cache.outputs.cache-hit != 'true' + uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: ${{github.workspace}}/vcpkg_pkgs_cache.zip + key: ${{ steps.cache.outputs.cache-primary-key }} + gpu: name: GPU Ubuntu # run only on upstream; forks will not have the HW diff --git a/.github/workflows/reusable_fast.yml b/.github/workflows/reusable_fast.yml index 63bbc85d0..3a3360468 100644 --- a/.github/workflows/reusable_fast.yml +++ b/.github/workflows/reusable_fast.yml @@ -108,7 +108,20 @@ jobs: with: fetch-depth: 0 + - name: Restore vcpkg cache + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + id: cache + with: + path: vcpkg_pkgs_cache.zip + key: vcpkg-fast-windows-latest-${{ hashFiles('vcpkg.json') }} + + - name: Unpack vcpkg cache + if: steps.cache.outputs.cache-hit == 'true' + run: | + Expand-Archive -Path ${{github.workspace}}/vcpkg_pkgs_cache.zip -DestinationPath ${{env.BUILD_DIR}}/vcpkg -Force + - name: Initialize vcpkg + if: steps.cache.outputs.cache-hit != 'true' uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 @@ -116,8 +129,8 @@ jobs: vcpkgJsonGlob: '**/vcpkg.json' - name: Install dependencies + if: steps.cache.outputs.cache-hit != 'true' run: vcpkg install --triplet x64-windows - shell: pwsh # Specifies PowerShell as the shell for running the script. - name: Configure CMake if: matrix.simple_cmake == 'OFF' @@ -164,3 +177,15 @@ jobs: run: | get-command ${{github.workspace}}/build/bin/Release/umf.dll | format-list get-command ${{github.workspace}}/build/src/proxy_lib/Release/umf_proxy.dll | format-list + + - name: Prepare vcpkg cache + if: steps.cache.outputs.cache-hit != 'true' + run: | + Compress-Archive -Path ${{env.BUILD_DIR}}/vcpkg/packages -DestinationPath ${{github.workspace}}/vcpkg_pkgs_cache.zip -Force -CompressionLevel Fastest + + - name: Save vcpkg cache + if: steps.cache.outputs.cache-hit != 'true' + uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: ${{github.workspace}}/vcpkg_pkgs_cache.zip + key: ${{ steps.cache.outputs.cache-primary-key }} diff --git a/.github/workflows/reusable_gpu.yml b/.github/workflows/reusable_gpu.yml index d7c4453c9..f0d1bcda8 100644 --- a/.github/workflows/reusable_gpu.yml +++ b/.github/workflows/reusable_gpu.yml @@ -73,8 +73,21 @@ jobs: if: matrix.os == 'Ubuntu' run: .github/scripts/get_system_info.sh - - name: "[Win] Initialize vcpkg" + - name: "[Win] Restore vcpkg cache" if: matrix.os == 'Windows' + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + id: cache + with: + path: vcpkg_pkgs_cache.zip + key: vcpkg-gpu-${{inputs.runner}}-windows-${{ hashFiles('vcpkg.json') }} + + - name: "[Win] Unpack vcpkg cache" + if: matrix.os == 'Windows' && steps.cache.outputs.cache-hit == 'true' + run: | + Expand-Archive -Path ${{github.workspace}}/vcpkg_pkgs_cache.zip -DestinationPath ${{github.workspace}}/vcpkg -Force + + - name: "[Win] Initialize vcpkg" + if: matrix.os == 'Windows' && steps.cache.outputs.cache-hit != 'true' uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: vcpkgGitCommitId: ea2a964f9303270322cf3f2d51c265ba146c422d # 1.04.2025 @@ -82,7 +95,7 @@ jobs: vcpkgJsonGlob: '**/vcpkg.json' - name: "[Win] Install dependencies" - if: matrix.os == 'Windows' + if: matrix.os == 'Windows' && steps.cache.outputs.cache-hit != 'true' run: vcpkg install --triplet x64-windows # note: disable all providers except the one being tested @@ -176,3 +189,15 @@ jobs: with: name: ${{env.COVERAGE_NAME}}-shared-${{matrix.shared_library}} path: ${{env.COVERAGE_DIR}} + + - name: "[Win] Prepare vcpkg cache" + if: matrix.os == 'Windows' && steps.cache.outputs.cache-hit != 'true' + run: | + Compress-Archive -Path ${{github.workspace}}/vcpkg/packages -DestinationPath ${{github.workspace}}/vcpkg_pkgs_cache.zip -Force -CompressionLevel Fastest + + - name: "[Win] Save vcpkg cache" + if: matrix.os == 'Windows' && steps.cache.outputs.cache-hit != 'true' + uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: ${{github.workspace}}/vcpkg_pkgs_cache.zip + key: ${{ steps.cache.outputs.cache-primary-key }} diff --git a/.github/workflows/reusable_sanitizers.yml b/.github/workflows/reusable_sanitizers.yml index 28d2088e9..0af7828ab 100644 --- a/.github/workflows/reusable_sanitizers.yml +++ b/.github/workflows/reusable_sanitizers.yml @@ -74,7 +74,8 @@ jobs: run: | ctest --output-on-failure - # TODO restore ASAN tests on Windows + # TODO: restore ASAN tests on Windows + # TODO: ... and when restored - add cache support for vcpkg packages !!! #windows-build: # env: # VCPKG_PATH: "${{github.workspace}}/build/vcpkg/packages/hwloc_x64-windows;${{github.workspace}}/build/vcpkg/packages/tbb_x64-windows;${{github.workspace}}/build/vcpkg/packages/jemalloc_x64-windows" diff --git a/ChangeLog b/ChangeLog index d498e8fd9..72b7fdec6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ -Wed Jul 16 2025 Łukasz Stolarczuk +Mon Jul 21 2025 Łukasz Stolarczuk - * Version 1.0.0-rc2 + * Version 1.0.0 The Unified Memory Framework (UMF) is a library for constructing allocators and memory pools. It also contains broadly useful abstractions and utilities for memory management. diff --git a/include/umf/memory_pool_ops.h b/include/umf/memory_pool_ops.h index e6d6736fe..4cba05319 100644 --- a/include/umf/memory_pool_ops.h +++ b/include/umf/memory_pool_ops.h @@ -36,9 +36,7 @@ typedef struct umf_memory_pool_ops_t { /// /// @brief Initializes memory pool. - /// @param providers array of memory providers that will be used for coarse-grain allocations. - /// Should contain at least one memory provider. - /// @param numProvider number of elements in the providers array + /// @param provider memory provider that will be used for coarse-grain allocations. /// @param params pool-specific params, or NULL for defaults /// @param pool [out] returns pointer to the pool /// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure. diff --git a/src/provider/provider_cuda.c b/src/provider/provider_cuda.c index d024ae0ea..983be6b55 100644 --- a/src/provider/provider_cuda.c +++ b/src/provider/provider_cuda.c @@ -12,6 +12,7 @@ #include #include +#include "provider_ctl_stats_type.h" #include "provider_cuda_internal.h" #include "utils_load_library.h" #include "utils_log.h" @@ -53,8 +54,12 @@ typedef struct cu_memory_provider_t { umf_usm_memory_type_t memory_type; size_t min_alignment; unsigned int alloc_flags; + ctl_stats_t stats; } cu_memory_provider_t; +#define CTL_PROVIDER_TYPE cu_memory_provider_t +#include "provider_ctl_stats_impl.h" + // CUDA Memory Provider settings struct typedef struct umf_cuda_memory_provider_params_t { // Handle to the CUDA context @@ -98,6 +103,9 @@ static cu_ops_t g_cu_ops; static UTIL_ONCE_FLAG cu_is_initialized = UTIL_ONCE_FLAG_INIT; static bool Init_cu_global_state_failed; +struct ctl cu_memory_ctl_root; +static UTIL_ONCE_FLAG ctl_initialized = UTIL_ONCE_FLAG_INIT; + // forward decl needed for alloc static umf_result_t cu_memory_provider_free(void *provider, void *ptr, size_t bytes); @@ -133,6 +141,10 @@ static umf_result_t cu2umf_result(CUresult result) { } } +static void initialize_cu_ctl(void) { + CTL_REGISTER_MODULE(&cu_memory_ctl_root, stats); +} + static void init_cu_global_state(void) { #ifdef _WIN32 const char *lib_name = "nvcuda.dll"; @@ -333,6 +345,7 @@ static umf_result_t cu_memory_provider_initialize(const void *params, if (!cu_provider) { return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; } + memset(cu_provider, 0, sizeof(cu_memory_provider_t)); // CUDA alloc functions doesn't allow to provide user alignment - get the // minimum one from the driver @@ -460,6 +473,8 @@ static umf_result_t cu_memory_provider_alloc(void *provider, size_t size, LOG_ERR("unsupported alignment size"); return UMF_RESULT_ERROR_INVALID_ALIGNMENT; } + + provider_ctl_stats_alloc(cu_provider, size); return umf_result; } @@ -504,7 +519,11 @@ static umf_result_t cu_memory_provider_free(void *provider, void *ptr, LOG_ERR("Failed to restore CUDA context, ret = %d", umf_result); } - return cu2umf_result(cu_result); + umf_result_t ret = cu2umf_result(cu_result); + if (ret == UMF_RESULT_SUCCESS) { + provider_ctl_stats_free(cu_provider, bytes); + } + return ret; } static umf_result_t @@ -685,6 +704,14 @@ cu_memory_provider_close_ipc_handle(void *provider, void *ptr, size_t size) { return UMF_RESULT_SUCCESS; } +static umf_result_t cu_ctl(void *provider, umf_ctl_query_source_t operationType, + const char *name, void *arg, size_t size, + umf_ctl_query_type_t query_type, va_list args) { + utils_init_once(&ctl_initialized, initialize_cu_ctl); + return ctl_query(&cu_memory_ctl_root, provider, operationType, name, + query_type, arg, size, args); +} + static umf_memory_provider_ops_t UMF_CUDA_MEMORY_PROVIDER_OPS = { .version = UMF_PROVIDER_OPS_VERSION_CURRENT, .initialize = cu_memory_provider_initialize, @@ -707,6 +734,7 @@ static umf_memory_provider_ops_t UMF_CUDA_MEMORY_PROVIDER_OPS = { .ext_put_ipc_handle = cu_memory_provider_put_ipc_handle, .ext_open_ipc_handle = cu_memory_provider_open_ipc_handle, .ext_close_ipc_handle = cu_memory_provider_close_ipc_handle, + .ext_ctl = cu_ctl, }; const umf_memory_provider_ops_t *umfCUDAMemoryProviderOps(void) { diff --git a/src/provider/provider_devdax_memory.c b/src/provider/provider_devdax_memory.c index 1f886693d..5cf1ac0fd 100644 --- a/src/provider/provider_devdax_memory.c +++ b/src/provider/provider_devdax_memory.c @@ -67,6 +67,7 @@ umf_result_t umfDevDaxMemoryProviderParamsSetProtection( #include "base_alloc_global.h" #include "coarse.h" #include "libumf.h" +#include "provider_ctl_stats_type.h" #include "utils_common.h" #include "utils_concurrency.h" #include "utils_log.h" @@ -83,8 +84,12 @@ typedef struct devdax_memory_provider_t { utils_mutex_t lock; // lock of ptr and offset unsigned protection; // combination of OS-specific protection flags coarse_t *coarse; // coarse library handle + ctl_stats_t stats; } devdax_memory_provider_t; +#define CTL_PROVIDER_TYPE devdax_memory_provider_t +#include "provider_ctl_stats_impl.h" + // DevDax Memory provider settings struct typedef struct umf_devdax_memory_provider_params_t { char *path; @@ -112,6 +117,9 @@ static __TLS devdax_last_native_error_t TLS_last_native_error; #define _UMF_DEVDAX_RESULT_ERROR_PURGE_FORCE_FAILED \ (UMF_DEVDAX_RESULT_ERROR_PURGE_FORCE_FAILED - UMF_DEVDAX_RESULT_SUCCESS) +struct ctl devdax_memory_ctl_root; +static UTIL_ONCE_FLAG ctl_initialized = UTIL_ONCE_FLAG_INIT; + static const char *Native_error_str[] = { [_UMF_DEVDAX_RESULT_SUCCESS] = "success", [_UMF_DEVDAX_RESULT_ERROR_ALLOC_FAILED] = "memory allocation failed", @@ -127,6 +135,10 @@ static void devdax_store_last_native_error(int32_t native_error, TLS_last_native_error.errno_value = errno_value; } +static void initialize_devdax_ctl(void) { + CTL_REGISTER_MODULE(&devdax_memory_ctl_root, stats); +} + static umf_result_t devdax_translate_params(const umf_devdax_memory_provider_params_t *in_params, devdax_memory_provider_t *provider) { @@ -284,7 +296,12 @@ static umf_result_t devdax_alloc(void *provider, size_t size, size_t alignment, void **resultPtr) { devdax_memory_provider_t *devdax_provider = (devdax_memory_provider_t *)provider; - return coarse_alloc(devdax_provider->coarse, size, alignment, resultPtr); + umf_result_t ret = + coarse_alloc(devdax_provider->coarse, size, alignment, resultPtr); + if (ret == UMF_RESULT_SUCCESS) { + provider_ctl_stats_alloc(devdax_provider, size); + } + return ret; } static umf_result_t devdax_get_last_native_error(void *provider, @@ -531,10 +548,23 @@ static umf_result_t devdax_close_ipc_handle(void *provider, void *ptr, return UMF_RESULT_SUCCESS; } +static umf_result_t devdax_ctl(void *provider, + umf_ctl_query_source_t operationType, + const char *name, void *arg, size_t size, + umf_ctl_query_type_t query_type, va_list args) { + utils_init_once(&ctl_initialized, initialize_devdax_ctl); + return ctl_query(&devdax_memory_ctl_root, provider, operationType, name, + query_type, arg, size, args); +} + static umf_result_t devdax_free(void *provider, void *ptr, size_t size) { devdax_memory_provider_t *devdax_provider = (devdax_memory_provider_t *)provider; - return coarse_free(devdax_provider->coarse, ptr, size); + umf_result_t ret = coarse_free(devdax_provider->coarse, ptr, size); + if (ret == UMF_RESULT_SUCCESS) { + provider_ctl_stats_free(devdax_provider, size); + } + return ret; } static umf_memory_provider_ops_t UMF_DEVDAX_MEMORY_PROVIDER_OPS = { @@ -555,7 +585,8 @@ static umf_memory_provider_ops_t UMF_DEVDAX_MEMORY_PROVIDER_OPS = { .ext_get_ipc_handle = devdax_get_ipc_handle, .ext_put_ipc_handle = devdax_put_ipc_handle, .ext_open_ipc_handle = devdax_open_ipc_handle, - .ext_close_ipc_handle = devdax_close_ipc_handle}; + .ext_close_ipc_handle = devdax_close_ipc_handle, + .ext_ctl = devdax_ctl}; const umf_memory_provider_ops_t *umfDevDaxMemoryProviderOps(void) { return &UMF_DEVDAX_MEMORY_PROVIDER_OPS; diff --git a/src/provider/provider_file_memory.c b/src/provider/provider_file_memory.c index 3304c45ee..1031993d2 100644 --- a/src/provider/provider_file_memory.c +++ b/src/provider/provider_file_memory.c @@ -74,6 +74,7 @@ umf_result_t umfFileMemoryProviderParamsSetVisibility( #include "coarse.h" #include "critnib.h" #include "libumf.h" +#include "provider_ctl_stats_type.h" #include "utils_common.h" #include "utils_concurrency.h" #include "utils_log.h" @@ -112,8 +113,12 @@ typedef struct file_memory_provider_t { critnib *fd_offset_map; coarse_t *coarse; // coarse library handle + ctl_stats_t stats; } file_memory_provider_t; +#define CTL_PROVIDER_TYPE file_memory_provider_t +#include "provider_ctl_stats_impl.h" + // File Memory Provider settings struct typedef struct umf_file_memory_provider_params_t { char *path; @@ -139,6 +144,9 @@ static __TLS file_last_native_error_t TLS_last_native_error; #define _UMF_FILE_RESULT_ERROR_PURGE_FORCE_FAILED \ (UMF_FILE_RESULT_ERROR_PURGE_FORCE_FAILED - UMF_FILE_RESULT_SUCCESS) +struct ctl file_memory_ctl_root; +static UTIL_ONCE_FLAG ctl_initialized = UTIL_ONCE_FLAG_INIT; + static const char *Native_error_str[] = { [_UMF_FILE_RESULT_SUCCESS] = "success", [_UMF_FILE_RESULT_ERROR_ALLOC_FAILED] = "memory allocation failed", @@ -152,6 +160,10 @@ static void file_store_last_native_error(int32_t native_error, TLS_last_native_error.errno_value = errno_value; } +static void initialize_file_ctl(void) { + CTL_REGISTER_MODULE(&file_memory_ctl_root, stats); +} + static umf_result_t file_translate_params(const umf_file_memory_provider_params_t *in_params, file_memory_provider_t *provider) { @@ -496,7 +508,12 @@ static umf_result_t file_alloc_aligned(file_memory_provider_t *file_provider, static umf_result_t file_alloc(void *provider, size_t size, size_t alignment, void **resultPtr) { file_memory_provider_t *file_provider = (file_memory_provider_t *)provider; - return coarse_alloc(file_provider->coarse, size, alignment, resultPtr); + umf_result_t ret = + coarse_alloc(file_provider->coarse, size, alignment, resultPtr); + if (ret == UMF_RESULT_SUCCESS) { + provider_ctl_stats_alloc(file_provider, size); + } + return ret; } static umf_result_t file_alloc_cb(void *provider, size_t size, size_t alignment, @@ -859,9 +876,22 @@ static umf_result_t file_close_ipc_handle(void *provider, void *ptr, return UMF_RESULT_SUCCESS; } +static umf_result_t file_ctl(void *provider, + umf_ctl_query_source_t operationType, + const char *name, void *arg, size_t size, + umf_ctl_query_type_t query_type, va_list args) { + utils_init_once(&ctl_initialized, initialize_file_ctl); + return ctl_query(&file_memory_ctl_root, provider, operationType, name, + query_type, arg, size, args); +} + static umf_result_t file_free(void *provider, void *ptr, size_t size) { file_memory_provider_t *file_provider = (file_memory_provider_t *)provider; - return coarse_free(file_provider->coarse, ptr, size); + umf_result_t ret = coarse_free(file_provider->coarse, ptr, size); + if (ret == UMF_RESULT_SUCCESS) { + provider_ctl_stats_free(file_provider, size); + } + return ret; } static umf_memory_provider_ops_t UMF_FILE_MEMORY_PROVIDER_OPS = { @@ -882,7 +912,8 @@ static umf_memory_provider_ops_t UMF_FILE_MEMORY_PROVIDER_OPS = { .ext_get_ipc_handle = file_get_ipc_handle, .ext_put_ipc_handle = file_put_ipc_handle, .ext_open_ipc_handle = file_open_ipc_handle, - .ext_close_ipc_handle = file_close_ipc_handle}; + .ext_close_ipc_handle = file_close_ipc_handle, + .ext_ctl = file_ctl}; const umf_memory_provider_ops_t *umfFileMemoryProviderOps(void) { return &UMF_FILE_MEMORY_PROVIDER_OPS; diff --git a/src/provider/provider_level_zero.c b/src/provider/provider_level_zero.c index 509df52d3..d5e79b244 100644 --- a/src/provider/provider_level_zero.c +++ b/src/provider/provider_level_zero.c @@ -376,9 +376,10 @@ static ze_relaxed_allocation_limits_exp_desc_t relaxed_device_allocation_desc = .pNext = NULL, .flags = ZE_RELAXED_ALLOCATION_LIMITS_EXP_FLAG_MAX_SIZE}; -static umf_result_t ze_memory_provider_alloc(void *provider, size_t size, - size_t alignment, - void **resultPtr) { +static umf_result_t ze_memory_provider_alloc_helper(void *provider, size_t size, + size_t alignment, + int update_stats, + void **resultPtr) { ze_memory_provider_t *ze_provider = (ze_memory_provider_t *)provider; ze_result_t ze_result = ZE_RESULT_SUCCESS; @@ -442,39 +443,56 @@ static umf_result_t ze_memory_provider_alloc(void *provider, size_t size, } } - provider_ctl_stats_alloc(ze_provider, size); - + if (update_stats) { + provider_ctl_stats_alloc(ze_provider, size); + } return UMF_RESULT_SUCCESS; } -static umf_result_t ze_memory_provider_free(void *provider, void *ptr, - size_t bytes) { +static umf_result_t ze_memory_provider_alloc(void *provider, size_t size, + size_t alignment, + void **resultPtr) { + return ze_memory_provider_alloc_helper(provider, size, alignment, 1, + resultPtr); +} + +static umf_result_t ze_memory_provider_free_helper(void *provider, void *ptr, + size_t bytes, + int update_stats) { if (ptr == NULL) { return UMF_RESULT_SUCCESS; } ze_memory_provider_t *ze_provider = (ze_memory_provider_t *)provider; - + umf_result_t ret; if (ze_provider->freePolicyFlags == 0) { - return ze2umf_result(g_ze_ops.zeMemFree(ze_provider->context, ptr)); - } + ret = ze2umf_result(g_ze_ops.zeMemFree(ze_provider->context, ptr)); + } else { + ze_memory_free_ext_desc_t desc = { + .stype = ZE_STRUCTURE_TYPE_MEMORY_FREE_EXT_DESC, + .pNext = NULL, + .freePolicy = ze_provider->freePolicyFlags}; - ze_memory_free_ext_desc_t desc = { - .stype = ZE_STRUCTURE_TYPE_MEMORY_FREE_EXT_DESC, - .pNext = NULL, - .freePolicy = ze_provider->freePolicyFlags}; + ret = ze2umf_result( + g_ze_ops.zeMemFreeExt(ze_provider->context, &desc, ptr)); + } - umf_result_t ret = - ze2umf_result(g_ze_ops.zeMemFreeExt(ze_provider->context, &desc, ptr)); if (ret != UMF_RESULT_SUCCESS) { return ret; } - provider_ctl_stats_free(ze_provider, bytes); + if (update_stats) { + provider_ctl_stats_free(ze_provider, bytes); + } return UMF_RESULT_SUCCESS; } +static umf_result_t ze_memory_provider_free(void *provider, void *ptr, + size_t bytes) { + return ze_memory_provider_free_helper(provider, ptr, bytes, 1); +} + static umf_result_t query_min_page_size(ze_memory_provider_t *ze_provider, size_t *min_page_size) { assert(min_page_size); @@ -482,7 +500,8 @@ static umf_result_t query_min_page_size(ze_memory_provider_t *ze_provider, LOG_DEBUG("Querying minimum page size"); void *ptr; - umf_result_t result = ze_memory_provider_alloc(ze_provider, 1, 0, &ptr); + umf_result_t result = + ze_memory_provider_alloc_helper(ze_provider, 1, 0, 0, &ptr); if (result != UMF_RESULT_SUCCESS) { return result; } @@ -494,7 +513,7 @@ static umf_result_t query_min_page_size(ze_memory_provider_t *ze_provider, *min_page_size = properties.pageSize; - ze_memory_provider_free(ze_provider, ptr, 1); + ze_memory_provider_free_helper(ze_provider, ptr, 1, 0); return ze2umf_result(ze_result); } diff --git a/test/provider_devdax_memory.cpp b/test/provider_devdax_memory.cpp index 07d64325a..01e8d62ed 100644 --- a/test/provider_devdax_memory.cpp +++ b/test/provider_devdax_memory.cpp @@ -8,6 +8,7 @@ #include #endif +#include #include #include @@ -301,6 +302,58 @@ TEST_P(umfProviderTest, free_NULL) { ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); } +TEST_P(umfProviderTest, ctl_stats) { + size_t allocated = 0, peak = 0; + umf_result_t ret = + umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, 0u); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, 0u); + + void *ptr = nullptr; + size_t size = page_size; + ret = umfMemoryProviderAlloc(provider.get(), size, 0, &ptr); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(ptr, nullptr); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, size); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, size); + + ret = umfMemoryProviderFree(provider.get(), ptr, size); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, 0u); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, size); + + ret = umfCtlExec("umf.provider.by_handle.{}.stats.peak_memory.reset", NULL, + 0, provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, 0u); +} + // other negative tests TEST_P(umfProviderTest, free_INVALID_POINTER_SIZE_GT_0) { diff --git a/test/provider_file_memory.cpp b/test/provider_file_memory.cpp index 055b4c613..1dd5324f0 100644 --- a/test/provider_file_memory.cpp +++ b/test/provider_file_memory.cpp @@ -2,6 +2,7 @@ // Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include #include #include @@ -364,6 +365,58 @@ TEST_P(FileProviderParamsDefault, free_NULL) { ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); } +TEST_P(FileProviderParamsDefault, ctl_stats) { + size_t allocated = 0, peak = 0; + umf_result_t ret = + umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, 0u); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, 0u); + + void *ptr = nullptr; + size_t size = page_size; + ret = umfMemoryProviderAlloc(provider.get(), size, page_size, &ptr); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(ptr, nullptr); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, size); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, size); + + ret = umfMemoryProviderFree(provider.get(), ptr, size); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, 0u); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, size); + + ret = umfCtlExec("umf.provider.by_handle.{}.stats.peak_memory.reset", NULL, + 0, provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, 0u); +} + // other negative tests TEST_F(test, params_null_handle) { diff --git a/test/provider_fixed_memory.cpp b/test/provider_fixed_memory.cpp index fdca92274..173f51b53 100644 --- a/test/provider_fixed_memory.cpp +++ b/test/provider_fixed_memory.cpp @@ -2,6 +2,7 @@ // Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include #include #include #include @@ -295,6 +296,58 @@ TEST_P(FixedProviderTest, purge_force_INVALID_POINTER) { verify_last_native_error(UMF_FIXED_RESULT_ERROR_PURGE_FORCE_FAILED); } +TEST_P(FixedProviderTest, ctl_stats) { + size_t allocated = 0, peak = 0; + umf_result_t ret = + umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, 0u); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, 0u); + + void *ptr = nullptr; + size_t size = page_size; + ret = umfMemoryProviderAlloc(provider.get(), size, page_size, &ptr); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(ptr, nullptr); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, size); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, size); + + ret = umfMemoryProviderFree(provider.get(), ptr, size); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, 0u); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, size); + + ret = umfCtlExec("umf.provider.by_handle.{}.stats.peak_memory.reset", NULL, + 0, provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, 0u); +} + // Params tests TEST_F(test, params_null_handle) { diff --git a/test/provider_os_memory.cpp b/test/provider_os_memory.cpp index d2eb340a3..1a4cea304 100644 --- a/test/provider_os_memory.cpp +++ b/test/provider_os_memory.cpp @@ -2,6 +2,7 @@ // Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include #include #include #include @@ -392,6 +393,58 @@ TEST_P(umfProviderTest, close_ipc_handle_wrong_visibility) { ASSERT_EQ(umf_result, UMF_RESULT_ERROR_INVALID_ARGUMENT); } +TEST_P(umfProviderTest, ctl_stats) { + size_t allocated = 0, peak = 0; + umf_result_t ret = + umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, 0u); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, 0u); + + void *ptr = nullptr; + size_t size = page_size; + ret = umfMemoryProviderAlloc(provider.get(), size, 0, &ptr); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(ptr, nullptr); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, size); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, size); + + ret = umfMemoryProviderFree(provider.get(), ptr, size); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, 0u); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, size); + + ret = umfCtlExec("umf.provider.by_handle.{}.stats.peak_memory.reset", NULL, + 0, provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider.get()); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, 0u); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(umfIpcTest); void *createOsMemoryProviderParamsShared() { diff --git a/test/providers/provider_cuda.cpp b/test/providers/provider_cuda.cpp index 4c336a836..1b448eaf0 100644 --- a/test/providers/provider_cuda.cpp +++ b/test/providers/provider_cuda.cpp @@ -9,6 +9,7 @@ #include +#include #include #include "cuda_helpers.h" @@ -278,6 +279,65 @@ TEST_P(umfCUDAProviderTest, getName) { umfMemoryProviderDestroy(provider); } +TEST_P(umfCUDAProviderTest, ctl_stats) { + umf_memory_provider_handle_t provider = nullptr; + umf_result_t ret = + umfMemoryProviderCreate(umfCUDAMemoryProviderOps(), params, &provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(provider, nullptr); + + size_t allocated = 0, peak = 0; + ret = umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, 0u); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, 0u); + + void *ptr = nullptr; + const size_t size = 1024 * 8; + ret = umfMemoryProviderAlloc(provider, size, 0, &ptr); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(ptr, nullptr); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, size); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, size); + + ret = umfMemoryProviderFree(provider, ptr, size); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, 0u); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, size); + + ret = umfCtlExec("umf.provider.by_handle.{}.stats.peak_memory.reset", NULL, + 0, provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, 0u); + + umfMemoryProviderDestroy(provider); +} + TEST_P(umfCUDAProviderTest, allocInvalidSize) { CUcontext expected_current_context = get_current_context(); // create CUDA provider diff --git a/test/providers/provider_level_zero.cpp b/test/providers/provider_level_zero.cpp index 85b7fd0b6..feb377987 100644 --- a/test/providers/provider_level_zero.cpp +++ b/test/providers/provider_level_zero.cpp @@ -9,6 +9,7 @@ #include +#include #include #include "ipcFixtures.hpp" @@ -398,6 +399,65 @@ TEST_P(umfLevelZeroProviderTest, getName) { umfMemoryProviderDestroy(provider); } +TEST_P(umfLevelZeroProviderTest, ctl_stats) { + umf_memory_provider_handle_t provider = nullptr; + umf_result_t ret = umfMemoryProviderCreate(umfLevelZeroMemoryProviderOps(), + params, &provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(provider, nullptr); + + size_t allocated = 0, peak = 0; + ret = umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, 0u); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, 0u); + + void *ptr = nullptr; + const size_t size = 1024 * 8; + ret = umfMemoryProviderAlloc(provider, size, 0, &ptr); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_NE(ptr, nullptr); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, size); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, size); + + ret = umfMemoryProviderFree(provider, ptr, size); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.allocated_memory", + &allocated, sizeof(allocated), provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(allocated, 0u); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, size); + + ret = umfCtlExec("umf.provider.by_handle.{}.stats.peak_memory.reset", NULL, + 0, provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + + ret = umfCtlGet("umf.provider.by_handle.{}.stats.peak_memory", &peak, + sizeof(peak), provider); + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); + ASSERT_EQ(peak, 0u); + + umfMemoryProviderDestroy(provider); +} + TEST_P(umfLevelZeroProviderTest, allocInvalidSize) { umf_memory_provider_handle_t provider = nullptr; umf_result_t umf_result = umfMemoryProviderCreate(