diff --git a/pkgs/development/cuda-modules/lib/data/cuda.nix b/pkgs/development/cuda-modules/lib/data/cuda.nix new file mode 100644 index 000000000000..0b97645c420d --- /dev/null +++ b/pkgs/development/cuda-modules/lib/data/cuda.nix @@ -0,0 +1,357 @@ +{ cudaLib, lib }: +{ + /** + All CUDA capabilities, sorted by version. + + NOTE: Since the capabilities are sorted by version and architecture/family-specific features are + appended to the minor version component, the sorted list groups capabilities by baseline feature + set. + + # Type + + ``` + allSortedCudaCapabilities :: [CudaCapability] + ``` + + # Example + + ``` + allSortedCudaCapabilities = [ + "5.0" + "5.2" + "6.0" + "6.1" + "7.0" + "7.2" + "7.5" + "8.0" + "8.6" + "8.7" + "8.9" + "9.0" + "9.0a" + "10.0" + "10.0a" + "10.0f" + "10.1" + "10.1a" + "10.1f" + "10.3" + "10.3a" + "10.3f" + ]; + ``` + */ + allSortedCudaCapabilities = lib.sort lib.versionOlder ( + lib.attrNames cudaLib.data.cudaCapabilityToInfo + ); + + /** + Mapping of CUDA micro-architecture name to capabilities belonging to that micro-architecture. + + # Type + + ``` + cudaArchNameToCapabilities :: AttrSet NonEmptyStr (NonEmptyListOf CudaCapability) + ``` + */ + cudaArchNameToCapabilities = lib.groupBy ( + cudaCapability: cudaLib.data.cudaCapabilityToInfo.${cudaCapability}.archName + ) cudaLib.data.allSortedCudaCapabilities; + + /** + Attribute set of supported CUDA capability mapped to information about that capability. + + NOTE: For more on baseline, architecture-specific, and family-specific feature sets, see + https://developer.nvidia.com/blog/nvidia-blackwell-and-nvidia-cuda-12-9-introduce-family-specific-architecture-features. + + NOTE: For information on when support for a given architecture was added, see + https://docs.nvidia.com/cuda/parallel-thread-execution/#release-notes + + NOTE: For baseline feature sets, `dontDefaultAfterCudaMajorMinorVersion` is generally set to the CUDA release + immediately prior to TensorRT removing support for that architecture. + + Many thanks to Arnon Shimoni for maintaining a list of these architectures and capabilities. + Without your work, this would have been much more difficult. + https://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/ + + # Type + + ``` + cudaCapabilityToInfo :: + AttrSet + CudaCapability + { archName :: String + , cudaCapability :: CudaCapability + , isJetson :: Bool + , isArchitectureSpecific :: Bool + , isFamilySpecific :: Bool + , minCudaMajorMinorVersion :: MajorMinorVersion + , maxCudaMajorMinorVersion :: MajorMinorVersion + , dontDefaultAfterCudaMajorMinorVersion :: Null | MajorMinorVersion + } + ``` + + `archName` + + : The name of the microarchitecture + + `cudaCapability` + + : The CUDA capability + + `isJetson` + + : Whether this capability is part of NVIDIA's line of Jetson embedded computers. This field is notable + because it tells us what architecture to build for (as Jetson devices are aarch64). + More on Jetson devices here: https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/ + NOTE: These architectures are only built upon request. + + `isArchitectureSpecific` + + : Whether this capability is an architecture-specific feature set. + NOTE: These architectures are only built upon request. + + `isFamilySpecific` + + : Whether this capability is a family-specific feature set. + NOTE: These architectures are only built upon request. + + `minCudaMajorMinorVersion` + + : The minimum (inclusive) CUDA version that supports this capability. + + `maxCudaMajorMinorVersion` + + : The maximum (exclusive) CUDA version that supports this capability. + `null` means there is no maximum. + + `dontDefaultAfterCudaMajorMinorVersion` + + : The CUDA version after which to exclude this capability from the list of default capabilities we build. + */ + cudaCapabilityToInfo = + lib.mapAttrs + ( + cudaCapability: + # Supplies default values. + { + archName, + isJetson ? false, + isArchitectureSpecific ? (lib.hasSuffix "a" cudaCapability), + isFamilySpecific ? (lib.hasSuffix "f" cudaCapability), + minCudaMajorMinorVersion, + maxCudaMajorMinorVersion ? null, + dontDefaultAfterCudaMajorMinorVersion ? null, + }: + { + inherit + archName + cudaCapability + isJetson + isArchitectureSpecific + isFamilySpecific + minCudaMajorMinorVersion + maxCudaMajorMinorVersion + dontDefaultAfterCudaMajorMinorVersion + ; + } + ) + { + # Tesla K40 + "3.5" = { + archName = "Kepler"; + minCudaMajorMinorVersion = "10.0"; + dontDefaultAfterCudaMajorMinorVersion = "11.0"; + maxCudaMajorMinorVersion = "11.8"; + }; + + # Tesla K80 + "3.7" = { + archName = "Kepler"; + minCudaMajorMinorVersion = "10.0"; + dontDefaultAfterCudaMajorMinorVersion = "11.0"; + maxCudaMajorMinorVersion = "11.8"; + }; + + # Tesla/Quadro M series + "5.0" = { + archName = "Maxwell"; + minCudaMajorMinorVersion = "10.0"; + dontDefaultAfterCudaMajorMinorVersion = "11.0"; + }; + + # Quadro M6000 , GeForce 900, GTX-970, GTX-980, GTX Titan X + "5.2" = { + archName = "Maxwell"; + minCudaMajorMinorVersion = "10.0"; + dontDefaultAfterCudaMajorMinorVersion = "11.0"; + }; + + # Quadro GP100, Tesla P100, DGX-1 (Generic Pascal) + "6.0" = { + archName = "Pascal"; + minCudaMajorMinorVersion = "10.0"; + # Removed from TensorRT 10.0, which corresponds to CUDA 12.4 release. + # https://docs.nvidia.com/deeplearning/tensorrt/archives/tensorrt-1001/support-matrix/index.html + dontDefaultAfterCudaMajorMinorVersion = "12.3"; + }; + + # GTX 1080, GTX 1070, GTX 1060, GTX 1050, GTX 1030 (GP108), GT 1010 (GP108) Titan Xp, Tesla + # P40, Tesla P4, Discrete GPU on the NVIDIA Drive PX2 + "6.1" = { + archName = "Pascal"; + minCudaMajorMinorVersion = "10.0"; + # Removed from TensorRT 10.0, which corresponds to CUDA 12.4 release. + # https://docs.nvidia.com/deeplearning/tensorrt/archives/tensorrt-1001/support-matrix/index.html + dontDefaultAfterCudaMajorMinorVersion = "12.3"; + }; + + # DGX-1 with Volta, Tesla V100, GTX 1180 (GV104), Titan V, Quadro GV100 + "7.0" = { + archName = "Volta"; + minCudaMajorMinorVersion = "10.0"; + # Removed from TensorRT 10.5, which corresponds to CUDA 12.6 release. + # https://docs.nvidia.com/deeplearning/tensorrt/archives/tensorrt-1050/support-matrix/index.html + dontDefaultAfterCudaMajorMinorVersion = "12.5"; + }; + + # Jetson AGX Xavier, Drive AGX Pegasus, Xavier NX + "7.2" = { + archName = "Volta"; + minCudaMajorMinorVersion = "10.0"; + # Note: without `cuda_compat`, maxCudaMajorMinorVersion is 11.8 + # https://docs.nvidia.com/cuda/cuda-for-tegra-appnote/index.html#deployment-considerations-for-cuda-upgrade-package + maxCudaMajorMinorVersion = "12.2"; + isJetson = true; + }; + + # GTX/RTX Turing – GTX 1660 Ti, RTX 2060, RTX 2070, RTX 2080, Titan RTX, Quadro RTX 4000, + # Quadro RTX 5000, Quadro RTX 6000, Quadro RTX 8000, Quadro T1000/T2000, Tesla T4 + "7.5" = { + archName = "Turing"; + minCudaMajorMinorVersion = "10.0"; + }; + + # NVIDIA A100 (the name “Tesla” has been dropped – GA100), NVIDIA DGX-A100 + "8.0" = { + archName = "Ampere"; + minCudaMajorMinorVersion = "11.2"; + }; + + # Tesla GA10x cards, RTX Ampere – RTX 3080, GA102 – RTX 3090, RTX A2000, A3000, RTX A4000, + # A5000, A6000, NVIDIA A40, GA106 – RTX 3060, GA104 – RTX 3070, GA107 – RTX 3050, RTX A10, RTX + # A16, RTX A40, A2 Tensor Core GPU + "8.6" = { + archName = "Ampere"; + minCudaMajorMinorVersion = "11.2"; + }; + + # Jetson AGX Orin and Drive AGX Orin only + "8.7" = { + archName = "Ampere"; + minCudaMajorMinorVersion = "11.5"; + isJetson = true; + }; + + # NVIDIA GeForce RTX 4090, RTX 4080, RTX 6000, Tesla L40 + "8.9" = { + archName = "Ada"; + minCudaMajorMinorVersion = "11.8"; + }; + + # NVIDIA H100 (GH100) + "9.0" = { + archName = "Hopper"; + minCudaMajorMinorVersion = "11.8"; + }; + + "9.0a" = { + archName = "Hopper"; + minCudaMajorMinorVersion = "12.0"; + }; + + # NVIDIA B100 + "10.0" = { + archName = "Blackwell"; + minCudaMajorMinorVersion = "12.7"; + }; + + "10.0a" = { + archName = "Blackwell"; + minCudaMajorMinorVersion = "12.7"; + }; + + "10.0f" = { + archName = "Blackwell"; + minCudaMajorMinorVersion = "12.9"; + }; + + # NVIDIA Jetson Thor Blackwell + "10.1" = { + archName = "Blackwell"; + minCudaMajorMinorVersion = "12.7"; + isJetson = true; + }; + + "10.1a" = { + archName = "Blackwell"; + minCudaMajorMinorVersion = "12.7"; + isJetson = true; + }; + + "10.1f" = { + archName = "Blackwell"; + minCudaMajorMinorVersion = "12.9"; + isJetson = true; + }; + + # NVIDIA ??? + "10.3" = { + archName = "Blackwell"; + minCudaMajorMinorVersion = "12.9"; + }; + + "10.3a" = { + archName = "Blackwell"; + minCudaMajorMinorVersion = "12.9"; + }; + + "10.3f" = { + archName = "Blackwell"; + minCudaMajorMinorVersion = "12.9"; + }; + + # NVIDIA GeForce RTX 5090 (GB202) etc. + "12.0" = { + archName = "Blackwell"; + minCudaMajorMinorVersion = "12.8"; + }; + + "12.0a" = { + archName = "Blackwell"; + minCudaMajorMinorVersion = "12.8"; + }; + + "12.0f" = { + archName = "Blackwell"; + minCudaMajorMinorVersion = "12.9"; + }; + + # NVIDIA ??? + "12.1" = { + archName = "Blackwell"; + minCudaMajorMinorVersion = "12.9"; + }; + + "12.1a" = { + archName = "Blackwell"; + minCudaMajorMinorVersion = "12.9"; + }; + + "12.1f" = { + archName = "Blackwell"; + minCudaMajorMinorVersion = "12.9"; + }; + }; +} diff --git a/pkgs/development/cuda-modules/lib/data/default.nix b/pkgs/development/cuda-modules/lib/data/default.nix new file mode 100644 index 000000000000..60924cbb4f9e --- /dev/null +++ b/pkgs/development/cuda-modules/lib/data/default.nix @@ -0,0 +1,32 @@ +{ cudaLib, lib }: +{ + # See ./cuda.nix for documentation. + inherit (import ./cuda.nix { inherit cudaLib lib; }) + allSortedCudaCapabilities + cudaArchNameToCapabilities + cudaCapabilityToInfo + ; + + # See ./nvcc.nix for documentation. + inherit (import ./nvcc.nix) + nvccCompatibilities + ; + + # See ./redist.nix for documentation. + inherit (import ./redist.nix) + redistNames + redistSystems + redistUrlPrefix + ; + + /** + The path to the CUDA packages root directory, for use with `callPackage` to create new package sets. + + # Type + + ``` + cudaPackagesPath :: Path + ``` + */ + cudaPackagesPath = ./..; +} diff --git a/pkgs/development/cuda-modules/lib/data/nvcc.nix b/pkgs/development/cuda-modules/lib/data/nvcc.nix new file mode 100644 index 000000000000..535f64b40991 --- /dev/null +++ b/pkgs/development/cuda-modules/lib/data/nvcc.nix @@ -0,0 +1,268 @@ +{ + /** + Mapping of CUDA versions to NVCC compatibilities + + Taken from + https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#host-compiler-support-policy + + NVCC performs a version check on the host compiler's major version and so newer minor versions + of the compilers listed below will be supported, but major versions falling outside the range + will not be supported. + + NOTE: These constraints don't apply to Jetson, which uses something else. + + NOTE: NVIDIA can and will add support for newer compilers even during patch releases. + E.g.: CUDA 12.2.1 maxxed out with support for Clang 15.0; 12.2.2 added support for Clang 16.0. + + NOTE: Because all platforms NVIDIA supports use GCC and Clang, we omit the architectures here. + + # Type + + ``` + nvccCompatibilities :: + AttrSet + String + { clang :: { maxMajorVersion :: String, minMajorVersion :: String } + , gcc :: { maxMajorVersion :: String, minMajorVersion :: String } + } + ``` + */ + nvccCompatibilities = { + # Our baseline + # https://docs.nvidia.com/cuda/archive/11.0/cuda-toolkit-release-notes/index.html#cuda-compiler-new-features + "11.0" = { + clang = { + maxMajorVersion = "9"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "9"; + minMajorVersion = "6"; + }; + }; + + # Added support for Clang 10 and GCC 10 + # https://docs.nvidia.com/cuda/archive/11.1.1/cuda-toolkit-release-notes/index.html#cuda-compiler-new-features + "11.1" = { + clang = { + maxMajorVersion = "10"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "10"; + minMajorVersion = "6"; + }; + }; + + # Added support for Clang 11 + # https://docs.nvidia.com/cuda/archive/11.2.2/cuda-installation-guide-linux/index.html#system-requirements + "11.2" = { + clang = { + maxMajorVersion = "11"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "10"; + minMajorVersion = "6"; + }; + }; + + # No changes from 11.2 to 11.3 + "11.3" = { + clang = { + maxMajorVersion = "11"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "10"; + minMajorVersion = "6"; + }; + }; + + # Added support for Clang 12 and GCC 11 + # https://docs.nvidia.com/cuda/archive/11.4.4/cuda-toolkit-release-notes/index.html#cuda-general-new-features + # NOTE: There is a bug in the version of GLIBC that GCC 11 uses which causes it to fail to compile some CUDA + # code. As such, we skip it for this release, and do the bump in 11.6 (skipping 11.5). + # https://forums.developer.nvidia.com/t/cuda-11-5-samples-throw-multiple-error-attribute-malloc-does-not-take-arguments/192750/15 + "11.4" = { + clang = { + maxMajorVersion = "12"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "10"; + minMajorVersion = "6"; + }; + }; + + # No changes from 11.4 to 11.5 + "11.5" = { + clang = { + maxMajorVersion = "12"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "10"; + minMajorVersion = "6"; + }; + }; + + # No changes from 11.5 to 11.6 + # However, as mentioned above, we add GCC 11 this release. + "11.6" = { + clang = { + maxMajorVersion = "12"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "11"; + minMajorVersion = "6"; + }; + }; + + # Added support for Clang 13 + # https://docs.nvidia.com/cuda/archive/11.7.1/cuda-toolkit-release-notes/index.html#cuda-compiler-new-features + "11.7" = { + clang = { + maxMajorVersion = "13"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "11"; + minMajorVersion = "6"; + }; + }; + + # Added support for Clang 14 + # https://docs.nvidia.com/cuda/archive/11.8.0/cuda-installation-guide-linux/index.html#system-requirements + "11.8" = { + clang = { + maxMajorVersion = "14"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "11"; + minMajorVersion = "6"; + }; + }; + + # Added support for GCC 12 + # https://docs.nvidia.com/cuda/archive/12.0.1/cuda-installation-guide-linux/index.html#system-requirements + "12.0" = { + clang = { + maxMajorVersion = "14"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "12"; + minMajorVersion = "6"; + }; + }; + + # Added support for Clang 15 + # https://docs.nvidia.com/cuda/archive/12.1.1/cuda-toolkit-release-notes/index.html#cuda-compilers-new-features + "12.1" = { + clang = { + maxMajorVersion = "15"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "12"; + minMajorVersion = "6"; + }; + }; + + # Added support for Clang 16 + # https://docs.nvidia.com/cuda/archive/12.2.2/cuda-installation-guide-linux/index.html#host-compiler-support-policy + "12.2" = { + clang = { + maxMajorVersion = "16"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "12"; + minMajorVersion = "6"; + }; + }; + + # No changes from 12.2 to 12.3 + # https://docs.nvidia.com/cuda/archive/12.3.2/cuda-installation-guide-linux/index.html#host-compiler-support-policy + "12.3" = { + clang = { + maxMajorVersion = "16"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "12"; + minMajorVersion = "6"; + }; + }; + + # Maximum Clang version is 17 + # Minimum GCC version is still 6, but all versions prior to GCC 7.3 are deprecated. + # Maximum GCC version is 13.2 + # https://docs.nvidia.com/cuda/archive/12.4.1/cuda-installation-guide-linux/index.html#host-compiler-support-policy + "12.4" = { + clang = { + maxMajorVersion = "17"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "13"; + minMajorVersion = "6"; + }; + }; + + # No changes from 12.4 to 12.5 + # https://docs.nvidia.com/cuda/archive/12.5.1/cuda-installation-guide-linux/index.html#host-compiler-support-policy + "12.5" = { + clang = { + maxMajorVersion = "17"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "13"; + minMajorVersion = "6"; + }; + }; + + # Maximum Clang version is 18 + # https://docs.nvidia.com/cuda/archive/12.6.0/cuda-installation-guide-linux/index.html#host-compiler-support-policy + "12.6" = { + clang = { + maxMajorVersion = "18"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "13"; + minMajorVersion = "6"; + }; + }; + + # Maximum Clang version is 19, maximum GCC version is 14 + # https://docs.nvidia.com/cuda/archive/12.8.1/cuda-installation-guide-linux/index.html#host-compiler-support-policy + "12.8" = { + clang = { + maxMajorVersion = "19"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "14"; + minMajorVersion = "6"; + }; + }; + + # No changes from 12.8 to 12.9 + # https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#host-compiler-support-policy + "12.9" = { + clang = { + maxMajorVersion = "19"; + minMajorVersion = "7"; + }; + gcc = { + maxMajorVersion = "14"; + minMajorVersion = "6"; + }; + }; + }; +} diff --git a/pkgs/development/cuda-modules/lib/data/redist.nix b/pkgs/development/cuda-modules/lib/data/redist.nix new file mode 100644 index 000000000000..52e91f81c35c --- /dev/null +++ b/pkgs/development/cuda-modules/lib/data/redist.nix @@ -0,0 +1,56 @@ +{ + /** + A list of redistributable names to use in creation of the `redistName` option type. + + # Type + + ``` + redistNames :: [String] + ``` + */ + redistNames = [ + "cublasmp" + "cuda" + "cudnn" + "cudss" + "cuquantum" + "cusolvermp" + "cusparselt" + "cutensor" + "nppplus" + "nvcomp" + # "nvidia-driver", # NOTE: Some of the earlier manifests don't follow our scheme. + "nvjpeg2000" + "nvpl" + "nvtiff" + "tensorrt" # NOTE: not truly a redist; uses different naming convention + ]; + + /** + A list of redistributable systems to use in creation of the `redistSystem` option type. + + # Type + + ``` + redistSystems :: [String] + ``` + */ + redistSystems = [ + "linux-aarch64" + "linux-all" # Taken to mean all other linux systems + "linux-sbsa" + "linux-x86_64" + "source" # Source-agnostic platform + ]; + + /** + The prefix of the URL for redistributable files. + + # Type + + ``` + redistUrlPrefix :: String + ``` + */ + redistUrlPrefix = "https://developer.download.nvidia.com/compute"; +} diff --git a/pkgs/development/cuda-modules/lib/default.nix b/pkgs/development/cuda-modules/lib/default.nix new file mode 100644 index 000000000000..6918d9ca5053 --- /dev/null +++ b/pkgs/development/cuda-modules/lib/default.nix @@ -0,0 +1,13 @@ +let + lib = import ../../../../lib; +in +lib.fixedPoints.makeExtensible (final: { + data = import ./data { + inherit lib; + cudaLib = final; + }; + utils = import ./utils { + inherit lib; + cudaLib = final; + }; +}) diff --git a/pkgs/development/cuda-modules/lib/utils/assertions.nix b/pkgs/development/cuda-modules/lib/utils/assertions.nix new file mode 100644 index 000000000000..5fc940889b7f --- /dev/null +++ b/pkgs/development/cuda-modules/lib/utils/assertions.nix @@ -0,0 +1,139 @@ +{ cudaLib, lib }: +{ + /** + Evaluate assertions and add error context to return value. + + NOTE: No guarantees are made about this function's stability. You may use it at your own risk. + + # Type + + ``` + _evaluateAssertions + :: (assertions :: List { assertion :: Bool, message :: String }) + -> Bool + ``` + */ + _evaluateAssertions = + assertions: + let + failedAssertionsString = cudaLib.utils._mkFailedAssertionsString assertions; + in + if failedAssertionsString == "" then + true + else + lib.addErrorContext "with failed assertions:${failedAssertionsString}" false; + + /** + Function to generate a string of failed assertions. + + NOTE: No guarantees are made about this function's stability. You may use it at your own risk. + + # Type + + ``` + _mkFailedAssertionsString + :: (assertions :: List { assertion :: Bool, message :: String }) + -> String + ``` + + # Inputs + + `assertions` + + : A list of assertions to evaluate + + # Examples + + :::{.example} + ## `cudaLib.utils._mkFailedAssertionsString` usage examples + + ```nix + _mkFailedAssertionsString [ + { assertion = false; message = "Assertion 1 failed"; } + { assertion = true; message = "Assertion 2 failed"; } + ] + => "\n- Assertion 1 failed" + ``` + + ```nix + _mkFailedAssertionsString [ + { assertion = false; message = "Assertion 1 failed"; } + { assertion = false; message = "Assertion 2 failed"; } + ] + => "\n- Assertion 1 failed\n- Assertion 2 failed" + ``` + ::: + */ + _mkFailedAssertionsString = lib.foldl' ( + failedAssertionsString: + { assertion, message }: + failedAssertionsString + lib.optionalString (!assertion) ("\n- " + message) + ) ""; + + /** + Utility function to generate assertions for missing packages. + + Used to mark a package as unsupported if any of its required packages are missing (null). + + Expects a set of attributes. + + Most commonly used in overrides files on a callPackage-provided attribute set of packages. + + NOTE: We typically use platfromAssertions instead of brokenAssertions because the presence of packages set to null + means evaluation will fail if package attributes are accessed without checking for null first. OfBorg evaluation + sets allowBroken to true, which means we can't rely on brokenAssertions to prevent evaluation of a package with + missing dependencies. + + NOTE: No guarantees are made about this function's stability. You may use it at your own risk. + + # Type + + ``` + _mkMissingPackagesAssertions + :: (attrs :: AttrSet) + -> (assertions :: List { assertion :: Bool, message :: String }) + ``` + + # Inputs + + `attrs` + + : The attributes to check for null + + # Examples + + :::{.example} + ## `cudaLib.utils._mkMissingPackagesAssertions` usage examples + + ```nix + { + lib, + libcal ? null, + libcublas, + utils, + }: + let + inherit (lib.attrsets) recursiveUpdate; + inherit (cudaLib.utils) _mkMissingPackagesAssertions; + in + prevAttrs: { + passthru = prevAttrs.passthru or { } // { + platformAssertions = + prevAttrs.passthru.platformAssertions or [ ] + ++ _mkMissingPackagesAssertions { inherit libcal; }; + }; + } + ``` + ::: + */ + _mkMissingPackagesAssertions = lib.flip lib.pipe [ + # Take the attributes that are null. + (lib.filterAttrs (_: value: value == null)) + lib.attrNames + # Map them to assertions. + (lib.map (name: { + message = "${name} is available"; + assertion = false; + })) + ]; +} diff --git a/pkgs/development/cuda-modules/lib/utils/cuda.nix b/pkgs/development/cuda-modules/lib/utils/cuda.nix new file mode 100644 index 000000000000..e372fda0d1b5 --- /dev/null +++ b/pkgs/development/cuda-modules/lib/utils/cuda.nix @@ -0,0 +1,129 @@ +{ lib }: +{ + /** + Returns whether a capability should be built by default for a particular CUDA version. + + Capabilities built by default are baseline, non-Jetson capabilities with relatively recent CUDA support. + + NOTE: No guarantees are made about this function's stability. You may use it at your own risk. + + # Type + + ``` + _cudaCapabilityIsDefault + :: (cudaMajorMinorVersion :: Version) + -> (cudaCapabilityInfo :: CudaCapabilityInfo) + -> Bool + ``` + + # Inputs + + `cudaMajorMinorVersion` + + : The CUDA version to check + + `cudaCapabilityInfo` + + : The capability information to check + */ + _cudaCapabilityIsDefault = + cudaMajorMinorVersion: cudaCapabilityInfo: + let + recentCapability = + cudaCapabilityInfo.dontDefaultAfterCudaMajorMinorVersion == null + || lib.versionAtLeast cudaCapabilityInfo.dontDefaultAfterCudaMajorMinorVersion cudaMajorMinorVersion; + in + recentCapability + && !cudaCapabilityInfo.isJetson + && !cudaCapabilityInfo.isArchitectureSpecific + && !cudaCapabilityInfo.isFamilySpecific; + + /** + Returns whether a capability is supported for a particular CUDA version. + + NOTE: No guarantees are made about this function's stability. You may use it at your own risk. + + # Type + + ``` + _cudaCapabilityIsSupported + :: (cudaMajorMinorVersion :: Version) + -> (cudaCapabilityInfo :: CudaCapabilityInfo) + -> Bool + ``` + + # Inputs + + `cudaMajorMinorVersion` + + : The CUDA version to check + + `cudaCapabilityInfo` + + : The capability information to check + */ + _cudaCapabilityIsSupported = + cudaMajorMinorVersion: cudaCapabilityInfo: + let + lowerBoundSatisfied = lib.versionAtLeast cudaMajorMinorVersion cudaCapabilityInfo.minCudaMajorMinorVersion; + upperBoundSatisfied = + cudaCapabilityInfo.maxCudaMajorMinorVersion == null + || lib.versionAtLeast cudaCapabilityInfo.maxCudaMajorMinorVersion cudaMajorMinorVersion; + in + lowerBoundSatisfied && upperBoundSatisfied; + + /** + Generates a CUDA variant name from a version. + + NOTE: No guarantees are made about this function's stability. You may use it at your own risk. + + # Type + + ``` + _mkCudaVariant :: (version :: String) -> String + ``` + + # Inputs + + `version` + + : The version string + + # Examples + + :::{.example} + ## `cudaLib.utils._mkCudaVariant` usage examples + + ```nix + _mkCudaVariant "11.0" + => "cuda11" + ``` + ::: + */ + _mkCudaVariant = version: "cuda${lib.versions.major version}"; + + /** + A predicate which, given a package, returns true if the package has a free license or one of NVIDIA's licenses. + + This function is intended to be provided as `config.allowUnfreePredicate` when `import`-ing Nixpkgs. + + # Type + + ``` + allowUnfreeCudaPredicate :: (package :: Package) -> Bool + ``` + */ + allowUnfreeCudaPredicate = + package: + lib.all ( + license: + license.free + || lib.elem license.shortName [ + "CUDA EULA" + "cuDNN EULA" + "cuSPARSELt EULA" + "cuTENSOR EULA" + "NVidia OptiX EULA" + ] + ) (lib.toList package.meta.license); +} diff --git a/pkgs/development/cuda-modules/lib/utils/default.nix b/pkgs/development/cuda-modules/lib/utils/default.nix new file mode 100644 index 000000000000..ee9ace015fae --- /dev/null +++ b/pkgs/development/cuda-modules/lib/utils/default.nix @@ -0,0 +1,49 @@ +{ cudaLib, lib }: +{ + # See ./assertions.nix for documentation. + inherit (import ./assertions.nix { inherit cudaLib lib; }) + _evaluateAssertions + _mkFailedAssertionsString + _mkMissingPackagesAssertions + ; + + # See ./cuda.nix for documentation. + inherit (import ./cuda.nix { inherit lib; }) + _cudaCapabilityIsDefault + _cudaCapabilityIsSupported + _mkCudaVariant + allowUnfreeCudaPredicate + ; + + # See ./meta.nix for documentation. + inherit (import ./meta.nix { inherit cudaLib lib; }) + _mkMetaBadPlatforms + _mkMetaBroken + ; + + # See ./redist.nix for documentation. + inherit (import ./redist.nix { inherit cudaLib lib; }) + _redistSystemIsSupported + getNixSystems + getRedistSystem + mkRedistUrl + ; + + # See ./strings.nix for documentation. + inherit (import ./strings.nix { inherit cudaLib lib; }) + dotsToUnderscores + dropDots + formatCapabilities + mkCmakeCudaArchitecturesString + mkGencodeFlag + mkRealArchitecture + mkVersionedName + mkVirtualArchitecture + ; + + # See ./versions.nix for documentation. + inherit (import ./versions.nix { inherit cudaLib lib; }) + majorMinorPatch + trimComponents + ; +} diff --git a/pkgs/development/cuda-modules/lib/utils/meta.nix b/pkgs/development/cuda-modules/lib/utils/meta.nix new file mode 100644 index 000000000000..327d4ae97d95 --- /dev/null +++ b/pkgs/development/cuda-modules/lib/utils/meta.nix @@ -0,0 +1,71 @@ +{ cudaLib, lib }: +{ + /** + Returns a list of bad platforms for a given package if assertsions in `finalAttrs.passthru.platformAssertions` + fail, optionally logging evaluation warnings for each reason. + + NOTE: No guarantees are made about this function's stability. You may use it at your own risk. + + NOTE: This function requires `finalAttrs.passthru.platformAssertions` to be a list of assertions and + `finalAttrs.finalPackage.name` and `finalAttrs.finalPackage.stdenv` to be available. + + # Type + + ``` + _mkMetaBadPlatforms :: (warn :: Bool) -> (finalAttrs :: AttrSet) -> List String + ``` + */ + _mkMetaBadPlatforms = + warn: finalAttrs: + let + failedAssertionsString = cudaLib.utils._mkFailedAssertionsString finalAttrs.passthru.platformAssertions; + hasFailedAssertions = failedAssertionsString != ""; + finalStdenv = finalAttrs.finalPackage.stdenv; + in + lib.warnIf (warn && hasFailedAssertions) + "Package ${finalAttrs.finalPackage.name} is unsupported on this platform due to the following failed assertions:${failedAssertionsString}" + ( + lib.optionals hasFailedAssertions ( + lib.unique [ + finalStdenv.buildPlatform.system + finalStdenv.hostPlatform.system + finalStdenv.targetPlatform.system + ] + ) + ); + + /** + Returns a boolean indicating whether the package is broken as a result of `finalAttrs.passthru.brokenAssertions`, + optionally logging evaluation warnings for each reason. + + NOTE: No guarantees are made about this function's stability. You may use it at your own risk. + + NOTE: This function requires `finalAttrs.passthru.brokenAssertions` to be a list of assertions and + `finalAttrs.finalPackage.name` to be available. + + # Type + + ``` + _mkMetaBroken :: (warn :: Bool) -> (finalAttrs :: AttrSet) -> Bool + ``` + + # Inputs + + `warn` + + : A boolean indicating whether to log warnings + + `finalAttrs` + + : The final attributes of the package + */ + _mkMetaBroken = + warn: finalAttrs: + let + failedAssertionsString = cudaLib.utils._mkFailedAssertionsString finalAttrs.passthru.brokenAssertions; + hasFailedAssertions = failedAssertionsString != ""; + in + lib.warnIf (warn && hasFailedAssertions) + "Package ${finalAttrs.finalPackage.name} is marked as broken due to the following failed assertions:${failedAssertionsString}" + hasFailedAssertions; +} diff --git a/pkgs/development/cuda-modules/lib/utils/redist.nix b/pkgs/development/cuda-modules/lib/utils/redist.nix new file mode 100644 index 000000000000..b9cd2a3b1e0d --- /dev/null +++ b/pkgs/development/cuda-modules/lib/utils/redist.nix @@ -0,0 +1,196 @@ +{ cudaLib, lib }: +{ + /** + Returns a boolean indicating whether the provided redist system is supported by any of the provided redist systems. + + NOTE: No guarantees are made about this function's stability. You may use it at your own risk. + + # Type + + ``` + _redistSystemIsSupported + :: (redistSystem :: RedistSystem) + -> (redistSystems :: List RedistSystem) + -> Bool + ``` + + # Inputs + + `redistSystem` + + : The redist system to check + + `redistSystems` + + : The list of redist systems to check against + + # Examples + + :::{.example} + ## `cudaLib.utils._redistSystemIsSupported` usage examples + + ```nix + _redistSystemIsSupported "linux-x86_64" [ "linux-x86_64" ] + => true + ``` + + ```nix + _redistSystemIsSupported "linux-x86_64" [ "linux-aarch64" ] + => false + ``` + + ```nix + _redistSystemIsSupported "linux-x86_64" [ "linux-aarch64" "linux-x86_64" ] + => true + ``` + + ```nix + _redistSystemIsSupported "linux-x86_64" [ "linux-aarch64" "linux-all" ] + => true + ``` + ::: + */ + _redistSystemIsSupported = + redistSystem: redistSystems: + lib.findFirst ( + redistSystem': + redistSystem' == redistSystem || redistSystem' == "linux-all" || redistSystem' == "source" + ) null redistSystems != null; + + /** + Maps a NVIDIA redistributable system to Nix systems. + + NOTE: This function returns a list of systems because the redistributable systems `"linux-all"` and `"source"` can + be built on multiple systems. + + NOTE: This function *will* be called by unsupported systems because `cudaPackages` is evaluated on all systems. As + such, we need to handle unsupported systems gracefully. + + # Type + + ``` + getNixSystems :: (redistSystem :: RedistSystem) -> [String] + ``` + + # Inputs + + `redistSystem` + + : The NVIDIA redistributable system + + # Examples + + :::{.example} + ## `cudaLib.utils.getNixSystems` usage examples + + ```nix + getNixSystems "linux-sbsa" + => [ "aarch64-linux" ] + ``` + + ```nix + getNixSystems "linux-aarch64" + => [ "aarch64-linux" ] + ``` + ::: + */ + getNixSystems = + redistSystem: + if redistSystem == "linux-x86_64" then + [ "x86_64-linux" ] + else if redistSystem == "linux-sbsa" || redistSystem == "linux-aarch64" then + [ "aarch64-linux" ] + else if redistSystem == "linux-all" || redistSystem == "source" then + [ + "aarch64-linux" + "x86_64-linux" + ] + else + [ ]; + + /** + Maps a Nix system to a NVIDIA redistributable system. + + NOTE: We swap out the default `linux-sbsa` redist (for server-grade ARM chips) with the `linux-aarch64` redist + (which is for Jetson devices) if we're building any Jetson devices. Since both are based on aarch64, we can only + have one or the other, otherwise there's an ambiguity as to which should be used. + + NOTE: This function *will* be called by unsupported systems because `cudaPackages` is evaluated on all systems. As + such, we need to handle unsupported systems gracefully. + + # Type + + ``` + getRedistSystem :: (hasJetsonCudaCapability :: Bool) -> (nixSystem :: String) -> String + ``` + + # Inputs + + `hasJetsonCudaCapability` + + : If configured for a Jetson device + + `nixSystem` + + : The Nix system + + # Examples + + :::{.example} + ## `cudaLib.utils.getRedistSystem` usage examples + + ```nix + getRedistSystem true "aarch64-linux" + => "linux-aarch64" + ``` + + ```nix + getRedistSystem false "aarch64-linux" + => "linux-sbsa" + ``` + ::: + */ + getRedistSystem = + hasJetsonCudaCapability: nixSystem: + if nixSystem == "x86_64-linux" then + "linux-x86_64" + else if nixSystem == "aarch64-linux" then + if hasJetsonCudaCapability then "linux-aarch64" else "linux-sbsa" + else + "unsupported"; + + /** + Function to generate a URL for something in the redistributable tree. + + # Type + + ``` + mkRedistUrl :: (redistName :: RedistName) -> (relativePath :: NonEmptyStr) -> RedistUrl + ``` + + # Inputs + + `redistName` + + : The name of the redistributable + + `relativePath` + + : The relative path to a file in the redistributable tree + */ + mkRedistUrl = + redistName: relativePath: + lib.concatStringsSep "/" ( + [ cudaLib.data.redistUrlPrefix ] + ++ ( + if redistName != "tensorrt" then + [ + redistName + "redist" + ] + else + [ "machine-learning" ] + ) + ++ [ relativePath ] + ); +} diff --git a/pkgs/development/cuda-modules/lib/utils/strings.nix b/pkgs/development/cuda-modules/lib/utils/strings.nix new file mode 100644 index 000000000000..47a71b395f4f --- /dev/null +++ b/pkgs/development/cuda-modules/lib/utils/strings.nix @@ -0,0 +1,379 @@ +{ cudaLib, lib }: +{ + /** + Replaces dots in a string with underscores. + + # Type + + ``` + dotsToUnderscores :: (str :: String) -> String + ``` + + # Inputs + + `str` + + : The string for which dots shall be replaced by underscores + + # Examples + + :::{.example} + ## `cudaLib.utils.dotsToUnderscores` usage examples + + ```nix + dotsToUnderscores "1.2.3" + => "1_2_3" + ``` + ::: + */ + dotsToUnderscores = lib.replaceStrings [ "." ] [ "_" ]; + + /** + Removes the dots from a string. + + # Type + + ``` + dropDots :: (str :: String) -> String + ``` + + # Inputs + + `str` + + : The string to remove dots from + + # Examples + + :::{.example} + ## `cudaLib.utils.dropDots` usage examples + + ```nix + dropDots "1.2.3" + => "123" + ``` + ::: + */ + dropDots = lib.replaceStrings [ "." ] [ "" ]; + + /** + Produces an attribute set of useful data and functionality for packaging CUDA software within Nixpkgs. + + # Type + + ``` + formatCapabilities + :: { cudaCapabilityToInfo :: AttrSet CudaCapability CudaCapabilityInfo + , cudaCapabilities :: List CudaCapability + , cudaForwardCompat :: Bool + } + -> { cudaCapabilities :: List CudaCapability + , cudaForwardCompat :: Bool + , gencode :: List String + , realArches :: List String + , virtualArches :: List String + , archNames :: List String + , arches :: List String + , gencodeString :: String + , cmakeCudaArchitecturesString :: String + } + ``` + + # Inputs + + `cudaCapabilityToInfo` + + : A mapping of CUDA capabilities to their information + + `cudaCapabilities` + + : A list of CUDA capabilities to use + + `cudaForwardCompat` + + : A boolean indicating whether to include the forward compatibility gencode (+PTX) to support future GPU + generations + */ + formatCapabilities = + { + cudaCapabilityToInfo, + cudaCapabilities, + cudaForwardCompat, + }: + let + /** + The real architectures for the given CUDA capabilities. + + # Type + + ``` + realArches :: List String + ``` + */ + realArches = lib.map cudaLib.utils.mkRealArchitecture cudaCapabilities; + + /** + The virtual architectures for the given CUDA capabilities. + + These are typically used for forward compatibility, when trying to support an architecture newer than the CUDA + version allows. + + # Type + + ``` + virtualArches :: List String + ``` + */ + virtualArches = lib.map cudaLib.utils.mkVirtualArchitecture cudaCapabilities; + + /** + The gencode flags for the given CUDA capabilities. + + # Type + + ``` + gencode :: List String + ``` + */ + gencode = + let + base = lib.map (cudaLib.utils.mkGencodeFlag "sm") cudaCapabilities; + forward = cudaLib.utils.mkGencodeFlag "compute" (lib.last cudaCapabilities); + in + base ++ lib.optionals cudaForwardCompat [ forward ]; + in + { + inherit + cudaCapabilities + cudaForwardCompat + gencode + realArches + virtualArches + ; + + /** + The architecture names for the given CUDA capabilities. + + # Type + + ``` + archNames :: List String + ``` + */ + # E.g. [ "Ampere" "Turing" ] + archNames = lib.pipe cudaCapabilities [ + (lib.map (cudaCapability: cudaCapabilityToInfo.${cudaCapability}.archName)) + lib.unique + lib.naturalSort + ]; + + /** + The architectures for the given CUDA capabilities, including both real and virtual architectures. + + When `cudaForwardCompat` is enabled, the last architecture in the list is used as the forward compatibility architecture. + + # Type + + ``` + arches :: List String + ``` + */ + # E.g. [ "sm_75" "sm_86" "compute_86" ] + arches = realArches ++ lib.optionals cudaForwardCompat [ (lib.last virtualArches) ]; + + /** + The CMake-compatible CUDA architectures string for the given CUDA capabilities. + + # Type + + ``` + cmakeCudaArchitecturesString :: String + ``` + */ + cmakeCudaArchitecturesString = cudaLib.utils.mkCmakeCudaArchitecturesString cudaCapabilities; + + /** + The gencode string for the given CUDA capabilities. + + # Type + + ``` + gencodeString :: String + ``` + */ + gencodeString = lib.concatStringsSep " " gencode; + }; + + /** + Produces a CMake-compatible CUDA architecture string from a list of CUDA capabilities. + + # Type + + ``` + mkCmakeCudaArchitecturesString :: (cudaCapabilities :: List String) -> String + ``` + + # Inputs + + `cudaCapabilities` + + : The CUDA capabilities to convert + + # Examples + + :::{.example} + ## `cudaLib.utils.mkCmakeCudaArchitecturesString` usage examples + + ```nix + mkCmakeCudaArchitecturesString [ "8.9" "10.0a" ] + => "89;100a" + ``` + ::: + */ + mkCmakeCudaArchitecturesString = lib.concatMapStringsSep ";" cudaLib.utils.dropDots; + + /** + Produces a gencode flag from a CUDA capability. + + # Type + + ``` + mkGencodeFlag :: (archPrefix :: String) -> (cudaCapability :: String) -> String + ``` + + # Inputs + + `archPrefix` + + : The architecture prefix to use for the `code` field + + `cudaCapability` + + : The CUDA capability to convert + + # Examples + + :::{.example} + ## `cudaLib.utils.mkGencodeFlag` usage examples + + ```nix + mkGencodeFlag "sm" "8.9" + => "-gencode=arch=compute_89,code=sm_89" + ``` + + ```nix + mkGencodeFlag "compute" "10.0a" + => "-gencode=arch=compute_100a,code=compute_100a" + ``` + ::: + */ + mkGencodeFlag = + archPrefix: cudaCapability: + let + cap = cudaLib.utils.dropDots cudaCapability; + in + "-gencode=arch=compute_${cap},code=${archPrefix}_${cap}"; + + /** + Produces a real architecture string from a CUDA capability. + + # Type + + ``` + mkRealArchitecture :: (cudaCapability :: String) -> String + ``` + + # Inputs + + `cudaCapability` + + : The CUDA capability to convert + + # Examples + + :::{.example} + ## `cudaLib.utils.mkRealArchitecture` usage examples + + ```nix + mkRealArchitecture "8.9" + => "sm_89" + ``` + + ```nix + mkRealArchitecture "10.0a" + => "sm_100a" + ``` + ::: + */ + mkRealArchitecture = cudaCapability: "sm_" + cudaLib.utils.dropDots cudaCapability; + + /** + Create a versioned attribute name from a version by replacing dots with underscores. + + # Type + + ``` + mkVersionedName :: (name :: String) -> (version :: Version) -> String + ``` + + # Inputs + + `name` + + : The name to use + + `version` + + : The version to use + + # Examples + + :::{.example} + ## `cudaLib.utils.mkVersionedName` usage examples + + ```nix + mkVersionedName "hello" "1.2.3" + => "hello_1_2_3" + ``` + + ```nix + mkVersionedName "cudaPackages" "12.8" + => "cudaPackages_12_8" + ``` + ::: + */ + mkVersionedName = name: version: "${name}_${cudaLib.utils.dotsToUnderscores version}"; + + /** + Produces a virtual architecture string from a CUDA capability. + + # Type + + ``` + mkVirtualArchitecture :: (cudaCapability :: String) -> String + ``` + + # Inputs + + `cudaCapability` + + : The CUDA capability to convert + + # Examples + + :::{.example} + ## `cudaLib.utils.mkVirtualArchitecture` usage examples + + ```nix + mkVirtualArchitecture "8.9" + => "compute_89" + ``` + + ```nix + mkVirtualArchitecture "10.0a" + => "compute_100a" + ``` + ::: + */ + mkVirtualArchitecture = cudaCapability: "compute_" + cudaLib.utils.dropDots cudaCapability; +} diff --git a/pkgs/development/cuda-modules/lib/utils/versions.nix b/pkgs/development/cuda-modules/lib/utils/versions.nix new file mode 100644 index 000000000000..976ad65b2b65 --- /dev/null +++ b/pkgs/development/cuda-modules/lib/utils/versions.nix @@ -0,0 +1,76 @@ +{ cudaLib, lib }: +{ + /** + Extracts the major, minor, and patch version from a string. + + # Type + + ``` + majorMinorPatch :: (version :: String) -> String + ``` + + # Inputs + + `version` + + : The version string + + # Examples + + :::{.example} + ## `cudaLib.utils.majorMinorPatch` usage examples + + ```nix + majorMinorPatch "11.0.3.4" + => "11.0.3" + ``` + ::: + */ + majorMinorPatch = cudaLib.utils.trimComponents 3; + + /** + Get a version string with no more than than the specified number of components. + + # Type + + ``` + trimComponents :: (numComponents :: Integer) -> (version :: String) -> String + ``` + + # Inputs + + `numComponents` + : A positive integer corresponding to the maximum number of components to keep + + `version` + : A version string + + # Examples + + :::{.example} + ## `cudaLib.utils.trimComponents` usage examples + + ```nix + trimComponents 1 "1.2.3.4" + => "1" + ``` + + ```nix + trimComponents 3 "1.2.3.4" + => "1.2.3" + ``` + + ```nix + trimComponents 9 "1.2.3.4" + => "1.2.3.4" + ``` + ::: + */ + trimComponents = + n: v: + lib.pipe v [ + lib.splitVersion + (lib.take n) + (lib.concatStringsSep ".") + ]; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 76949cbd03f0..59d64e99c884 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -2719,6 +2719,8 @@ with pkgs; cron = isc-cron; + cudaLib = import ../development/cuda-modules/lib; + cudaPackages_11_0 = callPackage ./cuda-packages.nix { cudaMajorMinorVersion = "11.0"; }; cudaPackages_11_1 = callPackage ./cuda-packages.nix { cudaMajorMinorVersion = "11.1"; }; cudaPackages_11_2 = callPackage ./cuda-packages.nix { cudaMajorMinorVersion = "11.2"; };