From 1200498671a7b4c4cf7d733dd2ecc7c3be5d5e0d Mon Sep 17 00:00:00 2001 From: Luna Nova Date: Sat, 20 Sep 2025 07:00:44 -0700 Subject: [PATCH] frugally-deep,rocmPackages.miopen: add regression test for .model load failure ensures frugally-deep is able to load frugally-deep .json files in its source tree https://github.com/ROCm/rocm-libraries/issues/889 --- pkgs/by-name/fr/frugally-deep/package.nix | 12 +++- .../rocm-modules/6/miopen/default.nix | 12 ++++ .../test-frugally-deep-model-loading.cpp | 55 +++++++++++++++++++ .../test-frugally-deep-model-loading.nix | 49 +++++++++++++++++ 4 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 pkgs/development/rocm-modules/6/miopen/test-frugally-deep-model-loading.cpp create mode 100644 pkgs/development/rocm-modules/6/miopen/test-frugally-deep-model-loading.nix diff --git a/pkgs/by-name/fr/frugally-deep/package.nix b/pkgs/by-name/fr/frugally-deep/package.nix index 6482993d2caf..aff222f77b68 100644 --- a/pkgs/by-name/fr/frugally-deep/package.nix +++ b/pkgs/by-name/fr/frugally-deep/package.nix @@ -8,15 +8,18 @@ functionalplus, eigen, nlohmann_json, - doctest, python3Packages, buildTests ? false, # Needs tensorflow + # for tests + doctest, + rocmPackages, }: stdenv.mkDerivation (finalAttrs: { pname = "frugally-deep"; # be careful bumping this, frugally-deep may change its model metadata format - # in ways that only fail at runtime + # in ways that only fail at runtime. MIOpen is currently the only package + # relying on this, run passthru.tests.miopen-can-load-models to check version = "0.15.24-p0"; src = fetchFromGitHub { @@ -55,6 +58,11 @@ stdenv.mkDerivation (finalAttrs: { ]; cmakeFlags = lib.optionals buildTests [ "-DFDEEP_BUILD_UNITTEST=ON" ]; + passthru.tests.miopen-can-load-models = + rocmPackages.miopen.passthru.tests.can-load-models.override + { + frugally-deep = finalAttrs.finalPackage; + }; passthru.updateScript = gitUpdater; meta = with lib; { diff --git a/pkgs/development/rocm-modules/6/miopen/default.nix b/pkgs/development/rocm-modules/6/miopen/default.nix index 3a24c267ffaf..d3d64b2605be 100644 --- a/pkgs/development/rocm-modules/6/miopen/default.nix +++ b/pkgs/development/rocm-modules/6/miopen/default.nix @@ -1,6 +1,7 @@ { lib, stdenv, + callPackage, fetchFromGitHub, fetchpatch, rocmUpdateScript, @@ -297,6 +298,17 @@ stdenv.mkDerivation (finalAttrs: { requiredSystemFeatures = [ "big-parallel" ]; + passthru.tests = { + # Ensure all .tn.model files can be loaded by whatever version of frugally-deep we have + # This is otherwise hard to verify as MIOpen will only use these models on specific, + # expensive Instinct GPUs + # If MIOpen stops embedding .tn.model files the test will also fail, and can be deleted, + # likely along with the frugally-deep dependency + can-load-models = callPackage ./test-frugally-deep-model-loading.nix { + inherit (finalAttrs) src version; + inherit frugally-deep nlohmann_json; + }; + }; passthru.updateScript = rocmUpdateScript { name = finalAttrs.pname; inherit (finalAttrs.src) owner; diff --git a/pkgs/development/rocm-modules/6/miopen/test-frugally-deep-model-loading.cpp b/pkgs/development/rocm-modules/6/miopen/test-frugally-deep-model-loading.cpp new file mode 100644 index 000000000000..6b64b8099985 --- /dev/null +++ b/pkgs/development/rocm-modules/6/miopen/test-frugally-deep-model-loading.cpp @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include + +int main() { + std::vector model_files; + std::string src_dir = std::getenv("SRC_DIR") ? std::getenv("SRC_DIR") : "."; + + // collect *tn.model files except _metadata + try { + for (const auto& entry : std::filesystem::recursive_directory_iterator(src_dir)) { + if (entry.is_regular_file()) { + std::string path = entry.path().string(); + if (path.find("tn.model") != std::string::npos && path.find("_metadata.") == std::string::npos) { + model_files.push_back(path); + } + } + } + } catch (const std::exception& e) { + std::cerr << "Error scanning directory: " << e.what() << std::endl; + return 1; + } + + if (model_files.empty()) { + std::cout << "No *.tn.model files found in " << src_dir << std::endl; + return 1; + } + + std::cout << "Found " << model_files.size() << " model files to test" << std::endl; + + int failed_count = 0; + for (const auto& model_file : model_files) { + std::cout << "Loading: " << model_file << " ... "; + std::cout.flush(); + + try { + const auto model = fdeep::load_model(model_file); + std::cout << "OK" << std::endl; + } catch (const std::exception& e) { + std::cout << "FAILED: " << e.what() << std::endl; + failed_count++; + } + } + + if (failed_count > 0) { + std::cerr << "\n" << failed_count << " out of " << model_files.size() + << " models failed to load" << std::endl; + return 1; + } + + std::cout << "\nAll " << model_files.size() << " models loaded successfully!" << std::endl; + return 0; +} diff --git a/pkgs/development/rocm-modules/6/miopen/test-frugally-deep-model-loading.nix b/pkgs/development/rocm-modules/6/miopen/test-frugally-deep-model-loading.nix new file mode 100644 index 000000000000..36cadd774a65 --- /dev/null +++ b/pkgs/development/rocm-modules/6/miopen/test-frugally-deep-model-loading.nix @@ -0,0 +1,49 @@ +{ + lib, + stdenv, + eigen, + frugally-deep, + functionalplus, + nlohmann_json, + src, + version, +}: + +stdenv.mkDerivation { + pname = "miopen-frugally-deep-model-test"; + inherit version src; + + dontConfigure = true; + dontInstall = true; + doCheck = true; + + buildPhase = '' + runHook preBuild + + $CXX -std=c++20 \ + -I${lib.getDev eigen}/include/eigen3 \ + -I${lib.getDev functionalplus}/include \ + -I${lib.getDev frugally-deep}/include \ + -I${lib.getDev nlohmann_json}/include \ + ${./test-frugally-deep-model-loading.cpp} \ + -o test_models + + runHook postBuild + ''; + + checkPhase = '' + runHook preCheck + + echo "Running model loading tests..." + SRC_DIR="${src}" ./test_models + mkdir -p $out + + runHook postCheck + ''; + + meta = { + description = "Test that frugally-deep can load MIOpen model files"; + maintainers = with lib.teams; [ rocm ]; + platforms = lib.platforms.linux; + }; +}