commit 266da6d4befe348f44af09eda244d57b292dc285 Author: Tarry Singh Date: Mon Jan 2 14:28:25 2023 +0000 Add initial Bazel build configuration, async runtime implementation, and core MLIR dialect definitions for ZML. diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 0000000..e69de29 diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 0000000..f09b01b --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,79 @@ +module( + name = "zml", +) + +new_git_repository = use_repo_rule("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository") + +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "hermetic_cc_toolchain", version = "3.1.0") +bazel_dep(name = "patchelf", version = "0.18.0") +bazel_dep(name = "platforms", version = "0.0.10") +bazel_dep(name = "rules_cc", version = "0.0.9") +bazel_dep(name = "rules_pkg", version = "1.0.1") +bazel_dep(name = "rules_proto", version = "6.0.2") + +bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True) + +bazel_dep(name = "aspect_bazel_lib", version = "2.8.1.1") +bazel_lib_toolchains = use_extension("@aspect_bazel_lib//lib:extensions.bzl", "toolchains", dev_dependency = True) +use_repo(bazel_lib_toolchains, "jq_toolchains") + +toolchains = use_extension("@hermetic_cc_toolchain//toolchain:ext.bzl", "toolchains") +use_repo(toolchains, "zig_sdk") + +bazel_dep(name = "rules_zig", version = "20240913.0-1957d05") +zig = use_extension("@rules_zig//zig:extensions.bzl", "zig") +zig.index(file = "//bazel:zig_index.json") +zig.toolchain(zig_version = "0.14.0-dev.363+c3faae6bf") +zig.mirrors(urls = [ + "https://mirror.zml.ai/zig", +]) +use_repo(zig, "zig_toolchains") + +register_toolchains("@rules_zig//zig/target:all") +register_toolchains("@zig_toolchains//:all") +register_toolchains( + "@zig_sdk//toolchain:linux_amd64_gnu.2.31", + "@zig_sdk//toolchain:linux_arm64_gnu.2.31", +) + +cpu = use_extension("//runtimes/cpu:cpu.bzl", "cpu_pjrt_plugin") +use_repo(cpu, "libpjrt_cpu_darwin_arm64", "libpjrt_cpu_linux_amd64") + +cuda = use_extension("//runtimes/cuda:cuda.bzl", "cuda_packages") +use_repo(cuda, "libpjrt_cuda") + +rocm = use_extension("//runtimes/rocm:rocm.bzl", "rocm_packages") +use_repo(rocm, "libpjrt_rocm") + +tpu = use_extension("//runtimes/tpu:tpu.bzl", "tpu_packages") +use_repo(tpu, "libpjrt_tpu") + +zls = use_extension("//third_party/zls:zls.bzl", "repo") +use_repo(zls, "zls_aarch64-macos", "zls_x86_64-linux") + +register_toolchains("//third_party/zls:all") + +bazel_dep(name = "libxev", version = "20240910.0-a2d9b31") +bazel_dep(name = "llvm-raw", version = "20240823.0-f142f8a") + +llvm = use_extension("@llvm-raw//utils/bazel:extension.bzl", "llvm") +llvm.configure( + targets = [ + "AArch64", + "X86", + "NVPTX", + ], +) +use_repo(llvm, "llvm-project") + +bazel_dep(name = "stablehlo", version = "20240829.0-54aa1a5") +bazel_dep(name = "xla", version = "20240902.0-d18cd64") + +tsl = use_extension("@xla//:tsl.bzl", "tsl") +use_repo(tsl, "tsl") + +bazel_dep(name = "zigcoro", version = "20240829.0-fc1db29") +bazel_dep(name = "sentencepiece", version = "20240618.0-d7ace0a") +bazel_dep(name = "zig-protobuf", version = "20240722.0-c644d11") +bazel_dep(name = "zig-yaml", version = "20240903.0-83d5fdf") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock new file mode 100644 index 0000000..ee6947a --- /dev/null +++ b/MODULE.bazel.lock @@ -0,0 +1,1305 @@ +{ + "lockFileVersion": 11, + "registryFileHashes": { + "https://bazel-registry.zml.ai/modules/abseil-cpp/20210324.2/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/abseil-cpp/20211102.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/abseil-cpp/20230125.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/abseil-cpp/20230802.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/abseil-cpp/20240116.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/apple_support/1.11.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/apple_support/1.5.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/aspect_bazel_lib/2.8.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/bazel_features/1.1.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/bazel_features/1.11.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/bazel_features/1.3.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/bazel_features/1.4.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/bazel_skylib/1.0.3/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/bazel_skylib/1.1.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/bazel_skylib/1.2.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/bazel_skylib/1.2.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/bazel_skylib/1.3.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/bazel_skylib/1.4.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/bazel_skylib/1.4.2/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/bazel_skylib/1.5.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/bazel_skylib/1.6.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/bazel_skylib/1.7.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/buildifier_prebuilt/6.4.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/buildozer/7.1.2/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/google_benchmark/1.8.2/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/googletest/1.11.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/googletest/1.14.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/hermetic_cc_toolchain/3.1.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/libpfm/4.11.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/nlohmann_json/3.6.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/patchelf/0.18.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/platforms/0.0.10/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/platforms/0.0.4/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/platforms/0.0.5/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/platforms/0.0.6/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/platforms/0.0.7/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/platforms/0.0.8/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/platforms/0.0.9/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/protobuf/21.7/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/protobuf/3.19.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/protobuf/3.19.6/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/pybind11_bazel/2.11.1.bzl.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/pybind11_bazel/2.11.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/re2/2023-09-01/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/re2/2024-02-01/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_apple/3.2.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_cc/0.0.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_cc/0.0.2/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_cc/0.0.6/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_cc/0.0.8/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_cc/0.0.9/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_java/4.0.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_java/6.3.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_java/7.3.2/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_java/7.6.5/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_jvm_external/4.4.2/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_jvm_external/5.2/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_license/0.0.3/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_license/0.0.4/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_license/0.0.7/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_license/0.0.8/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_pkg/0.7.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_pkg/0.9.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_pkg/1.0.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_proto/4.0.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_proto/6.0.2/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_python/0.10.2/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_python/0.22.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_python/0.25.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_python/0.29.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_python/0.31.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_python/0.4.0/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/rules_swift/1.15.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/stardoc/0.5.1/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/stardoc/0.5.3/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/stardoc/0.6.2/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/zlib/1.2.11/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/zlib/1.2.12/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/zlib/1.2.13/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "not found", + "https://bazel-registry.zml.ai/modules/zstd/1.5.6/MODULE.bazel": "not found", + "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", + "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", + "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", + "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.0/MODULE.bazel": "98dc378d64c12a4e4741ad3362f87fb737ee6a0886b2d90c3cdbb4d93ea3e0bf", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.0/source.json": "251927429731bd37831facad38ddfc83b8f6f680f819e1d4d35e811b30479d5b", + "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896", + "https://bcr.bazel.build/modules/apple_support/1.11.1/source.json": "c797537544f4b76d46d12f488456529d7372b6ccff249c82fca50ce0a665957f", + "https://bcr.bazel.build/modules/apple_support/1.5.0/MODULE.bazel": "50341a62efbc483e8a2a6aec30994a58749bd7b885e18dd96aa8c33031e558ef", + "https://bcr.bazel.build/modules/aspect_bazel_lib/2.8.1/MODULE.bazel": "812d2dd42f65dca362152101fbec418029cc8fd34cbad1a2fde905383d705838", + "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", + "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", + "https://bcr.bazel.build/modules/bazel_features/1.11.0/source.json": "c9320aa53cd1c441d24bd6b716da087ad7e4ff0d9742a9884587596edfe53015", + "https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9", + "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", + "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", + "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", + "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", + "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", + "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953", + "https://bcr.bazel.build/modules/buildifier_prebuilt/6.4.0/MODULE.bazel": "37389c6b5a40c59410b4226d3bb54b08637f393d66e2fa57925c6fcf68e64bf4", + "https://bcr.bazel.build/modules/buildifier_prebuilt/6.4.0/source.json": "83eb01b197ed0b392f797860c9da5ed1bf95f4d0ded994d694a3d44731275916", + "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", + "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", + "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", + "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", + "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", + "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/source.json": "41e9e129f80d8c8bf103a7acc337b76e54fad1214ac0a7084bf24f4cd924b8b4", + "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", + "https://bcr.bazel.build/modules/hermetic_cc_toolchain/3.1.0/MODULE.bazel": "ea4b3a25a9417a7db57a8a2f9ebdee91d679823c6274b482b817ed128d81c594", + "https://bcr.bazel.build/modules/hermetic_cc_toolchain/3.1.0/source.json": "9d1df0459caefdf41052d360469922a73e219f67c8ce4da0628cc604469822b9", + "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", + "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74", + "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9", + "https://bcr.bazel.build/modules/patchelf/0.18.0/MODULE.bazel": "15a6beff7e828d585c5bd0f9f93589df117b5594e9d19e43096c77de58b9ae5f", + "https://bcr.bazel.build/modules/patchelf/0.18.0/source.json": "57caf6bcaa5ba515c6fb1c2eacee00735afbeb1ffacb34a57553fb139c8e4333", + "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", + "https://bcr.bazel.build/modules/platforms/0.0.10/source.json": "f22828ff4cf021a6b577f1bf6341cb9dcd7965092a439f64fc1bb3b7a5ae4bd5", + "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", + "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", + "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", + "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", + "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", + "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", + "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", + "https://bcr.bazel.build/modules/protobuf/21.7/source.json": "bbe500720421e582ff2d18b0802464205138c06056f443184de39fbb8187b09b", + "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", + "https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1.bzl.1/MODULE.bazel": "1ef2994c097ee88f8f7ae8fbf991aaefb0603b2540fe575eca14943bc9f220a6", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1.bzl.1/source.json": "d8f5b2ebc186b90c6112f92f43d86359dda2c3649c754d9680fd668f8dd28a79", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", + "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", + "https://bcr.bazel.build/modules/re2/2024-02-01/MODULE.bazel": "5ed922cb8b6c110e30969695e73bd0d3159576bf17ce8ee2443a7d07bf500551", + "https://bcr.bazel.build/modules/re2/2024-02-01/source.json": "0b108d5e9836cb66815fbbb70e4395eab52dc29dd2c39a9785f01d6661a8f37e", + "https://bcr.bazel.build/modules/rules_apple/3.2.1/MODULE.bazel": "55f19b572fdb4a4bd5a1c2231b60c663f8b4e3146769062b2bdeba72226c74b7", + "https://bcr.bazel.build/modules/rules_apple/3.2.1/source.json": "b7e8aa85c5fcd9dfec8ea62642b7e93ca161a03b2c403ae05872813f5dfeb7be", + "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", + "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", + "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", + "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", + "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", + "https://bcr.bazel.build/modules/rules_cc/0.0.9/source.json": "1f1ba6fea244b616de4a554a0f4983c91a9301640c8fe0dd1d410254115c8430", + "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", + "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", + "https://bcr.bazel.build/modules/rules_java/6.3.0/MODULE.bazel": "a97c7678c19f236a956ad260d59c86e10a463badb7eb2eda787490f4c969b963", + "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2", + "https://bcr.bazel.build/modules/rules_java/7.6.5/MODULE.bazel": "481164be5e02e4cab6e77a36927683263be56b7e36fef918b458d7a8a1ebadb1", + "https://bcr.bazel.build/modules/rules_java/7.6.5/source.json": "a805b889531d1690e3c72a7a7e47a870d00323186a9904b36af83aa3d053ee8d", + "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", + "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", + "https://bcr.bazel.build/modules/rules_jvm_external/5.2/source.json": "10572111995bc349ce31c78f74b3c147f6b3233975c7fa5eff9211f6db0d34d9", + "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", + "https://bcr.bazel.build/modules/rules_license/0.0.4/MODULE.bazel": "6a88dd22800cf1f9f79ba32cacad0d3a423ed28efa2c2ed5582eaa78dd3ac1e5", + "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", + "https://bcr.bazel.build/modules/rules_license/0.0.8/MODULE.bazel": "5669c6fe49b5134dbf534db681ad3d67a2d49cfc197e4a95f1ca2fd7f3aebe96", + "https://bcr.bazel.build/modules/rules_license/0.0.8/source.json": "ccfd3964cd0cd1739202efb8dbf9a06baab490e61e174b2ad4790f9c4e610beb", + "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", + "https://bcr.bazel.build/modules/rules_pkg/0.9.1/MODULE.bazel": "af00144208c4be503bc920d043ba3284fb37385b3f6160b4a4daf4df80b4b823", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", + "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", + "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", + "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483", + "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", + "https://bcr.bazel.build/modules/rules_proto/6.0.2/source.json": "17a2e195f56cb28d6bbf763e49973d13890487c6945311ed141e196fb660426d", + "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", + "https://bcr.bazel.build/modules/rules_python/0.22.1/MODULE.bazel": "26114f0c0b5e93018c0c066d6673f1a2c3737c7e90af95eff30cfee38d0bbac7", + "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", + "https://bcr.bazel.build/modules/rules_python/0.29.0/MODULE.bazel": "2ac8cd70524b4b9ec49a0b8284c79e4cd86199296f82f6e0d5da3f783d660c82", + "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", + "https://bcr.bazel.build/modules/rules_python/0.31.0/source.json": "a41c836d4065888eef4377f2f27b6eea0fedb9b5adb1bab1970437373fe90dc7", + "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", + "https://bcr.bazel.build/modules/rules_swift/1.15.1/MODULE.bazel": "7031d3e5221b54dfee3901d221f10f54a8b0f2a64d4616de7879bcf83fe8d85d", + "https://bcr.bazel.build/modules/rules_swift/1.15.1/source.json": "6472a4607d0a2f39eeb7daae78054b995aba593caad99aa64561f631fcf93a63", + "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", + "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", + "https://bcr.bazel.build/modules/stardoc/0.6.2/MODULE.bazel": "7060193196395f5dd668eda046ccbeacebfd98efc77fed418dbe2b82ffaa39fd", + "https://bcr.bazel.build/modules/stardoc/0.6.2/source.json": "d2ff8063b63b4a85e65fe595c4290f99717434fa9f95b4748a79a7d04dfed349", + "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", + "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/source.json": "f1ef7d3f9e0e26d4b23d1c39b5f5de71f584dd7d1b4ef83d9bbba6ec7a6a6459", + "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", + "https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27", + "https://bcr.bazel.build/modules/zlib/1.2.13/MODULE.bazel": "aa6deb1b83c18ffecd940c4119aff9567cd0a671d7bba756741cb2ef043a29d5", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d", + "https://bcr.bazel.build/modules/zstd/1.5.6/MODULE.bazel": "471ebe7d3cdd8c6469390fcf623eb4779ff55fbee0a87f1dc57a1def468b96d4", + "https://bcr.bazel.build/modules/zstd/1.5.6/source.json": "02010c3333fc89b44fe861db049968decb6e688411f7f9d4f6791d74f9adfb51" + }, + "selectedYankedVersions": {}, + "moduleExtensions": { + "@@apple_support~//crosstool:setup.bzl%apple_cc_configure_extension": { + "general": { + "bzlTransitiveDigest": "hDHJiBbKme6a+N8oiSQcVnU1v5B7tHMjJaAzS6GFfPc=", + "usagesDigest": "atH8xayh8CVhGZG9cm/kh7fV7XwOYgQy6Zhe1AzBH3g=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "local_config_apple_cc": { + "bzlFile": "@@apple_support~//crosstool:setup.bzl", + "ruleClassName": "_apple_cc_autoconf", + "attributes": {} + }, + "local_config_apple_cc_toolchains": { + "bzlFile": "@@apple_support~//crosstool:setup.bzl", + "ruleClassName": "_apple_cc_autoconf_toolchains", + "attributes": {} + } + }, + "recordedRepoMappingEntries": [ + [ + "apple_support~", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@aspect_bazel_lib~//lib:extensions.bzl%toolchains": { + "general": { + "bzlTransitiveDigest": "p8GR5EeSAP5RvoQ0821nQQ9nelAyTrNoUULFFBUdGlU=", + "usagesDigest": "JTRHwJCDIFLoz4veHZ+G6HnnCkU60EauNsYpX/JQlYc=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "expand_template_windows_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:expand_template_toolchain.bzl", + "ruleClassName": "expand_template_platform_repo", + "attributes": { + "platform": "windows_amd64" + } + }, + "copy_to_directory_windows_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_to_directory_toolchain.bzl", + "ruleClassName": "copy_to_directory_platform_repo", + "attributes": { + "platform": "windows_amd64" + } + }, + "jq_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:jq_toolchain.bzl", + "ruleClassName": "jq_platform_repo", + "attributes": { + "platform": "darwin_amd64", + "version": "1.7" + } + }, + "copy_to_directory_freebsd_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_to_directory_toolchain.bzl", + "ruleClassName": "copy_to_directory_platform_repo", + "attributes": { + "platform": "freebsd_amd64" + } + }, + "expand_template_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:expand_template_toolchain.bzl", + "ruleClassName": "expand_template_platform_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "jq_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:jq_toolchain.bzl", + "ruleClassName": "jq_platform_repo", + "attributes": { + "platform": "linux_arm64", + "version": "1.7" + } + }, + "coreutils_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:coreutils_toolchain.bzl", + "ruleClassName": "coreutils_platform_repo", + "attributes": { + "platform": "darwin_arm64", + "version": "0.0.26" + } + }, + "copy_to_directory_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_to_directory_toolchain.bzl", + "ruleClassName": "copy_to_directory_platform_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "bsd_tar_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:tar_toolchain.bzl", + "ruleClassName": "bsdtar_binary_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "copy_directory_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_directory_toolchain.bzl", + "ruleClassName": "copy_directory_platform_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "coreutils_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:coreutils_toolchain.bzl", + "ruleClassName": "coreutils_platform_repo", + "attributes": { + "platform": "darwin_amd64", + "version": "0.0.26" + } + }, + "coreutils_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:coreutils_toolchain.bzl", + "ruleClassName": "coreutils_platform_repo", + "attributes": { + "platform": "linux_arm64", + "version": "0.0.26" + } + }, + "zstd_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:zstd_toolchain.bzl", + "ruleClassName": "zstd_binary_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "yq_linux_s390x": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_platform_repo", + "attributes": { + "platform": "linux_s390x", + "version": "4.25.2" + } + }, + "yq": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_host_alias_repo", + "attributes": {} + }, + "expand_template_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:expand_template_toolchain.bzl", + "ruleClassName": "expand_template_platform_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "copy_directory_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_directory_toolchain.bzl", + "ruleClassName": "copy_directory_platform_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "jq_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:jq_toolchain.bzl", + "ruleClassName": "jq_platform_repo", + "attributes": { + "platform": "darwin_arm64", + "version": "1.7" + } + }, + "yq_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_platform_repo", + "attributes": { + "platform": "darwin_amd64", + "version": "4.25.2" + } + }, + "copy_directory_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_directory_toolchain.bzl", + "ruleClassName": "copy_directory_platform_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "expand_template_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:expand_template_toolchain.bzl", + "ruleClassName": "expand_template_toolchains_repo", + "attributes": { + "user_repository_name": "expand_template" + } + }, + "bats_assert": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "sha256": "98ca3b685f8b8993e48ec057565e6e2abcc541034ed5b0e81f191505682037fd", + "urls": [ + "https://github.com/bats-core/bats-assert/archive/v2.1.0.tar.gz" + ], + "strip_prefix": "bats-assert-2.1.0", + "build_file_content": "load(\"@aspect_bazel_lib//lib:copy_to_directory.bzl\", \"copy_to_directory\")\n\ncopy_to_directory(\n name = \"assert\",\n hardlink = \"on\",\n srcs = glob([\n \"src/**\",\n \"load.bash\",\n ]),\n out = \"bats-assert\",\n visibility = [\"//visibility:public\"]\n)\n" + } + }, + "copy_to_directory_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_to_directory_toolchain.bzl", + "ruleClassName": "copy_to_directory_platform_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "zstd_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:zstd_toolchain.bzl", + "ruleClassName": "zstd_binary_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "bsd_tar_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:tar_toolchain.bzl", + "ruleClassName": "bsdtar_binary_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "yq_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_toolchains_repo", + "attributes": { + "user_repository_name": "yq" + } + }, + "zstd_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:zstd_toolchain.bzl", + "ruleClassName": "zstd_binary_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "bats_support": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "sha256": "7815237aafeb42ddcc1b8c698fc5808026d33317d8701d5ec2396e9634e2918f", + "urls": [ + "https://github.com/bats-core/bats-support/archive/v0.3.0.tar.gz" + ], + "strip_prefix": "bats-support-0.3.0", + "build_file_content": "load(\"@aspect_bazel_lib//lib:copy_to_directory.bzl\", \"copy_to_directory\")\n\ncopy_to_directory(\n name = \"support\",\n hardlink = \"on\",\n srcs = glob([\n \"src/**\",\n \"load.bash\",\n ]),\n out = \"bats-support\",\n visibility = [\"//visibility:public\"]\n)\n" + } + }, + "bsd_tar_windows_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:tar_toolchain.bzl", + "ruleClassName": "bsdtar_binary_repo", + "attributes": { + "platform": "windows_amd64" + } + }, + "jq": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:jq_toolchain.bzl", + "ruleClassName": "jq_host_alias_repo", + "attributes": {} + }, + "expand_template_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:expand_template_toolchain.bzl", + "ruleClassName": "expand_template_platform_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "bsd_tar_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:tar_toolchain.bzl", + "ruleClassName": "bsdtar_binary_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "copy_to_directory_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_to_directory_toolchain.bzl", + "ruleClassName": "copy_to_directory_platform_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "coreutils_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:coreutils_toolchain.bzl", + "ruleClassName": "coreutils_platform_repo", + "attributes": { + "platform": "linux_amd64", + "version": "0.0.26" + } + }, + "copy_directory_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_directory_toolchain.bzl", + "ruleClassName": "copy_directory_toolchains_repo", + "attributes": { + "user_repository_name": "copy_directory" + } + }, + "yq_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_platform_repo", + "attributes": { + "platform": "linux_amd64", + "version": "4.25.2" + } + }, + "copy_to_directory_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_to_directory_toolchain.bzl", + "ruleClassName": "copy_to_directory_platform_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "coreutils_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:coreutils_toolchain.bzl", + "ruleClassName": "coreutils_toolchains_repo", + "attributes": { + "user_repository_name": "coreutils" + } + }, + "copy_directory_freebsd_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_directory_toolchain.bzl", + "ruleClassName": "copy_directory_platform_repo", + "attributes": { + "platform": "freebsd_amd64" + } + }, + "zstd_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:zstd_toolchain.bzl", + "ruleClassName": "zstd_binary_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "zstd_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:zstd_toolchain.bzl", + "ruleClassName": "zstd_toolchains_repo", + "attributes": { + "user_repository_name": "zstd" + } + }, + "bats_file": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "sha256": "9b69043241f3af1c2d251f89b4fcafa5df3f05e97b89db18d7c9bdf5731bb27a", + "urls": [ + "https://github.com/bats-core/bats-file/archive/v0.4.0.tar.gz" + ], + "strip_prefix": "bats-file-0.4.0", + "build_file_content": "load(\"@aspect_bazel_lib//lib:copy_to_directory.bzl\", \"copy_to_directory\")\n\ncopy_to_directory(\n name = \"file\",\n hardlink = \"on\",\n srcs = glob([\n \"src/**\",\n \"load.bash\",\n ]),\n out = \"bats-file\",\n visibility = [\"//visibility:public\"]\n)\n" + } + }, + "expand_template_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:expand_template_toolchain.bzl", + "ruleClassName": "expand_template_platform_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "jq_linux_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:jq_toolchain.bzl", + "ruleClassName": "jq_platform_repo", + "attributes": { + "platform": "linux_amd64", + "version": "1.7" + } + }, + "bsd_tar_darwin_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:tar_toolchain.bzl", + "ruleClassName": "bsdtar_binary_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "bsd_tar_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:tar_toolchain.bzl", + "ruleClassName": "tar_toolchains_repo", + "attributes": { + "user_repository_name": "bsd_tar" + } + }, + "bats_toolchains": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "sha256": "a1a9f7875aa4b6a9480ca384d5865f1ccf1b0b1faead6b47aa47d79709a5c5fd", + "urls": [ + "https://github.com/bats-core/bats-core/archive/v1.10.0.tar.gz" + ], + "strip_prefix": "bats-core-1.10.0", + "build_file_content": "load(\"@local_config_platform//:constraints.bzl\", \"HOST_CONSTRAINTS\")\nload(\"@aspect_bazel_lib//lib/private:bats_toolchain.bzl\", \"bats_toolchain\")\nload(\"@aspect_bazel_lib//lib:copy_to_directory.bzl\", \"copy_to_directory\")\n\ncopy_to_directory(\n name = \"core\",\n hardlink = \"on\",\n srcs = glob([\n \"lib/**\",\n \"libexec/**\"\n ]) + [\"bin/bats\"],\n out = \"bats-core\",\n)\n\nbats_toolchain(\n name = \"toolchain\",\n core = \":core\",\n libraries = [\"@bats_support//:support\", \"@bats_assert//:assert\", \"@bats_file//:file\"]\n)\n\ntoolchain(\n name = \"bats_toolchain\",\n exec_compatible_with = HOST_CONSTRAINTS,\n toolchain = \":toolchain\",\n toolchain_type = \"@aspect_bazel_lib//lib:bats_toolchain_type\",\n)\n" + } + }, + "yq_windows_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_platform_repo", + "attributes": { + "platform": "windows_amd64", + "version": "4.25.2" + } + }, + "jq_windows_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:jq_toolchain.bzl", + "ruleClassName": "jq_platform_repo", + "attributes": { + "platform": "windows_amd64", + "version": "1.7" + } + }, + "expand_template_freebsd_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:expand_template_toolchain.bzl", + "ruleClassName": "expand_template_platform_repo", + "attributes": { + "platform": "freebsd_amd64" + } + }, + "yq_linux_ppc64le": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_platform_repo", + "attributes": { + "platform": "linux_ppc64le", + "version": "4.25.2" + } + }, + "copy_to_directory_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_to_directory_toolchain.bzl", + "ruleClassName": "copy_to_directory_toolchains_repo", + "attributes": { + "user_repository_name": "copy_to_directory" + } + }, + "jq_toolchains": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:jq_toolchain.bzl", + "ruleClassName": "jq_toolchains_repo", + "attributes": { + "user_repository_name": "jq" + } + }, + "copy_directory_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_directory_toolchain.bzl", + "ruleClassName": "copy_directory_platform_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "copy_directory_windows_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:copy_directory_toolchain.bzl", + "ruleClassName": "copy_directory_platform_repo", + "attributes": { + "platform": "windows_amd64" + } + }, + "yq_darwin_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_platform_repo", + "attributes": { + "platform": "darwin_arm64", + "version": "4.25.2" + } + }, + "coreutils_windows_amd64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:coreutils_toolchain.bzl", + "ruleClassName": "coreutils_platform_repo", + "attributes": { + "platform": "windows_amd64", + "version": "0.0.26" + } + }, + "yq_linux_arm64": { + "bzlFile": "@@aspect_bazel_lib~//lib/private:yq_toolchain.bzl", + "ruleClassName": "yq_platform_repo", + "attributes": { + "platform": "linux_arm64", + "version": "4.25.2" + } + } + }, + "recordedRepoMappingEntries": [ + [ + "aspect_bazel_lib~", + "aspect_bazel_lib", + "aspect_bazel_lib~" + ], + [ + "aspect_bazel_lib~", + "bazel_skylib", + "bazel_skylib~" + ], + [ + "aspect_bazel_lib~", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@buildifier_prebuilt~//:defs.bzl%buildifier_prebuilt_deps_extension": { + "general": { + "bzlTransitiveDigest": "RaNT6gZicQa6HpONHOm8ejwF7zVAk4fIUHrbuHme7z4=", + "usagesDigest": "nThSTPRdiQbhDFl8FRM2nsKJftWMtPBQHrp/mdk716w=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "buildozer_darwin_amd64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildozer-darwin-amd64" + ], + "downloaded_file_path": "buildozer", + "executable": true, + "sha256": "d29e347ecd6b5673d72cb1a8de05bf1b06178dd229ff5eb67fad5100c840cc8e" + } + }, + "buildifier_linux_amd64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildifier-linux-amd64" + ], + "downloaded_file_path": "buildifier", + "executable": true, + "sha256": "be63db12899f48600bad94051123b1fd7b5251e7661b9168582ce52396132e92" + } + }, + "buildozer_darwin_arm64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildozer-darwin-arm64" + ], + "downloaded_file_path": "buildozer", + "executable": true, + "sha256": "9b9e71bdbec5e7223871e913b65d12f6d8fa026684daf991f00e52ed36a6978d" + } + }, + "buildozer_linux_amd64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildozer-linux-amd64" + ], + "downloaded_file_path": "buildozer", + "executable": true, + "sha256": "8dfd6345da4e9042daa738d7fdf34f699c5dfce4632f7207956fceedd8494119" + } + }, + "buildozer_windows_amd64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildozer-windows-amd64.exe" + ], + "downloaded_file_path": "buildozer.exe", + "executable": true, + "sha256": "e7f05bf847f7c3689dd28926460ce6e1097ae97380ac8e6ae7147b7b706ba19b" + } + }, + "buildozer_linux_arm64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildozer-linux-arm64" + ], + "downloaded_file_path": "buildozer", + "executable": true, + "sha256": "6559558fded658c8fa7432a9d011f7c4dcbac6b738feae73d2d5c352e5f605fa" + } + }, + "buildifier_windows_amd64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildifier-windows-amd64.exe" + ], + "downloaded_file_path": "buildifier.exe", + "executable": true, + "sha256": "da8372f35e34b65fb6d997844d041013bb841e55f58b54d596d35e49680fe13c" + } + }, + "buildifier_prebuilt_toolchains": { + "bzlFile": "@@buildifier_prebuilt~//:defs.bzl", + "ruleClassName": "_buildifier_toolchain_setup", + "attributes": { + "assets_json": "[{\"arch\":\"amd64\",\"name\":\"buildifier\",\"platform\":\"darwin\",\"sha256\":\"eeb47b2de27f60efe549348b183fac24eae80f1479e8b06cac0799c486df5bed\",\"version\":\"v6.4.0\"},{\"arch\":\"arm64\",\"name\":\"buildifier\",\"platform\":\"darwin\",\"sha256\":\"fa07ba0d20165917ca4cc7609f9b19a8a4392898148b7babdf6bb2a7dd963f05\",\"version\":\"v6.4.0\"},{\"arch\":\"amd64\",\"name\":\"buildifier\",\"platform\":\"linux\",\"sha256\":\"be63db12899f48600bad94051123b1fd7b5251e7661b9168582ce52396132e92\",\"version\":\"v6.4.0\"},{\"arch\":\"arm64\",\"name\":\"buildifier\",\"platform\":\"linux\",\"sha256\":\"18540fc10f86190f87485eb86963e603e41fa022f88a2d1b0cf52ff252b5e1dd\",\"version\":\"v6.4.0\"},{\"arch\":\"amd64\",\"name\":\"buildifier\",\"platform\":\"windows\",\"sha256\":\"da8372f35e34b65fb6d997844d041013bb841e55f58b54d596d35e49680fe13c\",\"version\":\"v6.4.0\"},{\"arch\":\"amd64\",\"name\":\"buildozer\",\"platform\":\"darwin\",\"sha256\":\"d29e347ecd6b5673d72cb1a8de05bf1b06178dd229ff5eb67fad5100c840cc8e\",\"version\":\"v6.4.0\"},{\"arch\":\"arm64\",\"name\":\"buildozer\",\"platform\":\"darwin\",\"sha256\":\"9b9e71bdbec5e7223871e913b65d12f6d8fa026684daf991f00e52ed36a6978d\",\"version\":\"v6.4.0\"},{\"arch\":\"amd64\",\"name\":\"buildozer\",\"platform\":\"linux\",\"sha256\":\"8dfd6345da4e9042daa738d7fdf34f699c5dfce4632f7207956fceedd8494119\",\"version\":\"v6.4.0\"},{\"arch\":\"arm64\",\"name\":\"buildozer\",\"platform\":\"linux\",\"sha256\":\"6559558fded658c8fa7432a9d011f7c4dcbac6b738feae73d2d5c352e5f605fa\",\"version\":\"v6.4.0\"},{\"arch\":\"amd64\",\"name\":\"buildozer\",\"platform\":\"windows\",\"sha256\":\"e7f05bf847f7c3689dd28926460ce6e1097ae97380ac8e6ae7147b7b706ba19b\",\"version\":\"v6.4.0\"}]" + } + }, + "buildifier_darwin_amd64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildifier-darwin-amd64" + ], + "downloaded_file_path": "buildifier", + "executable": true, + "sha256": "eeb47b2de27f60efe549348b183fac24eae80f1479e8b06cac0799c486df5bed" + } + }, + "buildifier_darwin_arm64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildifier-darwin-arm64" + ], + "downloaded_file_path": "buildifier", + "executable": true, + "sha256": "fa07ba0d20165917ca4cc7609f9b19a8a4392898148b7babdf6bb2a7dd963f05" + } + }, + "buildifier_linux_arm64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "urls": [ + "https://github.com/bazelbuild/buildtools/releases/download/v6.4.0/buildifier-linux-arm64" + ], + "downloaded_file_path": "buildifier", + "executable": true, + "sha256": "18540fc10f86190f87485eb86963e603e41fa022f88a2d1b0cf52ff252b5e1dd" + } + } + }, + "recordedRepoMappingEntries": [ + [ + "buildifier_prebuilt~", + "bazel_skylib", + "bazel_skylib~" + ], + [ + "buildifier_prebuilt~", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@hermetic_cc_toolchain~//toolchain:ext.bzl%toolchains": { + "general": { + "bzlTransitiveDigest": "YrUOAIuZsxXEx+Q8Bh4BooEu9qcrrOJRxaoC368wqAs=", + "usagesDigest": "EoOqmoW16SGIu0l1zbP8oSGHkhceATca/trgf094fVo=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "zig_sdk": { + "bzlFile": "@@hermetic_cc_toolchain~//toolchain:defs.bzl", + "ruleClassName": "zig_repository", + "attributes": { + "version": "0.12.0", + "url_formats": [ + "https://mirror.bazel.build/ziglang.org/download/{version}/zig-{host_platform}-{version}.{_ext}", + "https://ziglang.org/download/{version}/zig-{host_platform}-{version}.{_ext}" + ], + "host_platform_sha256": { + "linux-aarch64": "754f1029484079b7e0ca3b913a0a2f2a6afd5a28990cb224fe8845e72f09de63", + "linux-x86_64": "c7ae866b8a76a568e2d5cfd31fe89cdb629bdd161fdd5018b29a4a0a17045cad", + "macos-aarch64": "294e224c14fd0822cfb15a35cf39aa14bd9967867999bf8bdfe3db7ddec2a27f", + "macos-x86_64": "4d411bf413e7667821324da248e8589278180dbc197f4f282b7dbb599a689311", + "windows-aarch64": "04c6b92689241ca7a8a59b5f12d2ca2820c09d5043c3c4808b7e93e41c7bf97b", + "windows-x86_64": "2199eb4c2000ddb1fba85ba78f1fcf9c1fb8b3e57658f6a627a8e513131893f5" + }, + "host_platform_ext": { + "linux-aarch64": "tar.xz", + "linux-x86_64": "tar.xz", + "macos-aarch64": "tar.xz", + "macos-x86_64": "tar.xz", + "windows-x86_64": "zip" + } + } + } + }, + "recordedRepoMappingEntries": [ + [ + "hermetic_cc_toolchain~", + "bazel_tools", + "bazel_tools" + ], + [ + "hermetic_cc_toolchain~", + "hermetic_cc_toolchain", + "hermetic_cc_toolchain~" + ] + ] + } + }, + "@@platforms//host:extension.bzl%host_platform": { + "general": { + "bzlTransitiveDigest": "WewbYICdNVp22bzUQafEVMzMIpBnNjJ3zqKlUOCDIGc=", + "usagesDigest": "V1R2Y2oMxKNfx2WCWpSCaUV1WefW1o8HZGm3v1vHgY4=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "host_platform": { + "bzlFile": "@@platforms//host:extension.bzl", + "ruleClassName": "host_platform_repo", + "attributes": {} + } + }, + "recordedRepoMappingEntries": [] + } + }, + "@@rules_python~//python/extensions:python.bzl%python": { + "general": { + "bzlTransitiveDigest": "uFBdNKDewkX8DPVvKoPEcW0b3dXtksiE7SShRkuCA3E=", + "usagesDigest": "fQEsnAYwqRJT7/lTBAe+NllONXk6f/Tc57oiPxLG8SI=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": { + "RULES_PYTHON_BZLMOD_DEBUG": null + }, + "generatedRepoSpecs": { + "python_3_11_s390x-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "49520e3ff494708020f306e30b0964f079170be83e956be4504f850557378a22", + "patches": [], + "platform": "s390x-unknown-linux-gnu", + "python_version": "3.11.7", + "release_filename": "20240107/cpython-3.11.7+20240107-s390x-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7+20240107-s390x-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_11_host": { + "bzlFile": "@@rules_python~//python/private:toolchains_repo.bzl", + "ruleClassName": "host_toolchain", + "attributes": { + "python_version": "3.11.7", + "user_repository_name": "python_3_11", + "platforms": [ + "aarch64-apple-darwin", + "aarch64-unknown-linux-gnu", + "ppc64le-unknown-linux-gnu", + "s390x-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-unknown-linux-gnu" + ] + } + }, + "python_3_11": { + "bzlFile": "@@rules_python~//python/private:toolchains_repo.bzl", + "ruleClassName": "toolchain_aliases", + "attributes": { + "python_version": "3.11.7", + "user_repository_name": "python_3_11", + "platforms": [ + "aarch64-apple-darwin", + "aarch64-unknown-linux-gnu", + "ppc64le-unknown-linux-gnu", + "s390x-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-unknown-linux-gnu" + ] + } + }, + "python_3_11_aarch64-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "b102eaf865eb715aa98a8a2ef19037b6cc3ae7dfd4a632802650f29de635aa13", + "patches": [], + "platform": "aarch64-unknown-linux-gnu", + "python_version": "3.11.7", + "release_filename": "20240107/cpython-3.11.7+20240107-aarch64-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7+20240107-aarch64-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_11_aarch64-apple-darwin": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "b042c966920cf8465385ca3522986b12d745151a72c060991088977ca36d3883", + "patches": [], + "platform": "aarch64-apple-darwin", + "python_version": "3.11.7", + "release_filename": "20240107/cpython-3.11.7+20240107-aarch64-apple-darwin-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7+20240107-aarch64-apple-darwin-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_11_ppc64le-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "b44e1b74afe75c7b19143413632c4386708ae229117f8f950c2094e9681d34c7", + "patches": [], + "platform": "ppc64le-unknown-linux-gnu", + "python_version": "3.11.7", + "release_filename": "20240107/cpython-3.11.7+20240107-ppc64le-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7+20240107-ppc64le-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_11_x86_64-apple-darwin": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "a0e615eef1fafdc742da0008425a9030b7ea68a4ae4e73ac557ef27b112836d4", + "patches": [], + "platform": "x86_64-apple-darwin", + "python_version": "3.11.7", + "release_filename": "20240107/cpython-3.11.7+20240107-x86_64-apple-darwin-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7+20240107-x86_64-apple-darwin-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "pythons_hub": { + "bzlFile": "@@rules_python~//python/private/bzlmod:pythons_hub.bzl", + "ruleClassName": "hub_repo", + "attributes": { + "default_python_version": "3.11", + "toolchain_prefixes": [ + "_0000_python_3_11_" + ], + "toolchain_python_versions": [ + "3.11" + ], + "toolchain_set_python_version_constraints": [ + "False" + ], + "toolchain_user_repository_names": [ + "python_3_11" + ] + } + }, + "python_versions": { + "bzlFile": "@@rules_python~//python/private:toolchains_repo.bzl", + "ruleClassName": "multi_toolchain_aliases", + "attributes": { + "python_versions": { + "3.11": "python_3_11" + } + } + }, + "python_3_11_x86_64-pc-windows-msvc": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "67077e6fa918e4f4fd60ba169820b00be7c390c497bf9bc9cab2c255ea8e6f3e", + "patches": [], + "platform": "x86_64-pc-windows-msvc", + "python_version": "3.11.7", + "release_filename": "20240107/cpython-3.11.7+20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7+20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_11_x86_64-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "4a51ce60007a6facf64e5495f4cf322e311ba9f39a8cd3f3e4c026eae488e140", + "patches": [], + "platform": "x86_64-unknown-linux-gnu", + "python_version": "3.11.7", + "release_filename": "20240107/cpython-3.11.7+20240107-x86_64-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7+20240107-x86_64-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_python~", + "bazel_skylib", + "bazel_skylib~" + ], + [ + "rules_python~", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_python~//python/private/bzlmod:internal_deps.bzl%internal_deps": { + "general": { + "bzlTransitiveDigest": "ZKHEOaFX4G/WohTzMTV688TfCsSfLvbwBC2ma87N24w=", + "usagesDigest": "4Fj9JSpEDoJSLPRSbvSTol2bTL7baZjuA3k9U7kG/1k=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "pypi__wheel": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/b8/8b/31273bf66016be6ad22bb7345c37ff350276cfd46e389a0c2ac5da9d9073/wheel-0.41.2-py3-none-any.whl", + "sha256": "75909db2664838d015e3d9139004ee16711748a52c8f336b52882266540215d8", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__click": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", + "sha256": "ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__importlib_metadata": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/cc/37/db7ba97e676af155f5fcb1a35466f446eadc9104e25b83366e8088c9c926/importlib_metadata-6.8.0-py3-none-any.whl", + "sha256": "3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pyproject_hooks": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/d5/ea/9ae603de7fbb3df820b23a70f6aff92bf8c7770043254ad8d2dc9d6bcba4/pyproject_hooks-1.0.0-py3-none-any.whl", + "sha256": "283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pep517": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/ee/2f/ef63e64e9429111e73d3d6cbee80591672d16f2725e648ebc52096f3d323/pep517-0.13.0-py3-none-any.whl", + "sha256": "4ba4446d80aed5b5eac6509ade100bff3e7943a8489de249654a5ae9b33ee35b", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__packaging": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/ab/c3/57f0601a2d4fe15de7a553c00adbc901425661bf048f2a22dfc500caf121/packaging-23.1-py3-none-any.whl", + "sha256": "994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pip_tools": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/e8/df/47e6267c6b5cdae867adbdd84b437393e6202ce4322de0a5e0b92960e1d6/pip_tools-7.3.0-py3-none-any.whl", + "sha256": "8717693288720a8c6ebd07149c93ab0be1fced0b5191df9e9decd3263e20d85e", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__setuptools": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/4f/ab/0bcfebdfc3bfa8554b2b2c97a555569c4c1ebc74ea288741ea8326c51906/setuptools-68.1.2-py3-none-any.whl", + "sha256": "3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__zipp": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/8c/08/d3006317aefe25ea79d3b76c9650afabaf6d63d1c8443b236e7405447503/zipp-3.16.2-py3-none-any.whl", + "sha256": "679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__colorama": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", + "sha256": "4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__build": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/58/91/17b00d5fac63d3dca605f1b8269ba3c65e98059e1fd99d00283e42a454f0/build-0.10.0-py3-none-any.whl", + "sha256": "af266720050a66c893a6096a2f410989eeac74ff9a68ba194b3f6473e8e26171", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "rules_python_internal": { + "bzlFile": "@@rules_python~//python/private:internal_config_repo.bzl", + "ruleClassName": "internal_config_repo", + "attributes": {} + }, + "pypi__pip": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/50/c2/e06851e8cc28dcad7c155f4753da8833ac06a5c704c109313b8d5a62968a/pip-23.2.1-py3-none-any.whl", + "sha256": "7ccf472345f20d35bdc9d1841ff5f313260c2c33fe417f48c30ac46cccabf5be", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__installer": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/e5/ca/1172b6638d52f2d6caa2dd262ec4c811ba59eee96d54a7701930726bce18/installer-0.7.0-py3-none-any.whl", + "sha256": "05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__more_itertools": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/5a/cb/6dce742ea14e47d6f565589e859ad225f2a5de576d7696e0623b784e226b/more_itertools-10.1.0-py3-none-any.whl", + "sha256": "64e0735fcfdc6f3464ea133afe8ea4483b1c5fe3a3d69852e6503b43a0b222e6", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__tomli": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", + "sha256": "939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_python~", + "bazel_tools", + "bazel_tools" + ] + ] + } + } + } +} diff --git a/async/BUILD.bazel b/async/BUILD.bazel new file mode 100644 index 0000000..d7ac4a5 --- /dev/null +++ b/async/BUILD.bazel @@ -0,0 +1,11 @@ +load("@rules_zig//zig:defs.bzl", "zig_library") + +zig_library( + name = "async", + main = "async.zig", + visibility = ["//visibility:public"], + deps = [ + "@zigcoro//:libcoro", + "@libxev//:xev", + ], +) diff --git a/async/async.zig b/async/async.zig new file mode 100644 index 0000000..ae77cf4 --- /dev/null +++ b/async/async.zig @@ -0,0 +1,400 @@ +const std = @import("std"); +const xev = @import("xev"); +const libcoro = @import("libcoro"); +const aio = libcoro.asyncio; + +/// Normalize from a real tuple to a generic tuple. This is needed because +/// real tuples are reifed tuples are not the same. +fn NormalizedTuple(comptime T: type) type { + const ti = @typeInfo(T).Struct; + var types: [ti.fields.len]type = undefined; + inline for (ti.fields, 0..) |field, i| { + types[i] = field.type; + } + return std.meta.Tuple(&types); +} + +pub fn FnSignature(comptime func: anytype, comptime argsT: ?type) type { + return struct { + pub const FuncT = if (@TypeOf(func) == type) func else @TypeOf(func); + pub const ArgsT = blk: { + if (@typeInfo(FuncT).Fn.params.len == 0) { + break :blk @TypeOf(.{}); + } + break :blk argsT orelse std.meta.ArgsTuple(FuncT); + }; + pub const ReturnT = @TypeOf(@call(.auto, func, @as(ArgsT, undefined))); + pub const ReturnPayloadT = blk: { + break :blk switch (@typeInfo(ReturnT)) { + .ErrorUnion => |u| u.payload, + else => ReturnT, + }; + }; + pub const ReturnErrorSet: ?type = blk: { + break :blk switch (@typeInfo(ReturnT)) { + .ErrorUnion => |u| u.error_set, + else => null, + }; + }; + }; +} + +pub fn Frame(comptime func: anytype) type { + const Signature = FnSignature(func, null); + return FrameEx(func, Signature.ArgsT); +} + +pub fn FrameEx(comptime func: anytype, comptime argsT: type) type { + return FrameExx(func, argsT); +} + +fn FrameExx(comptime func: anytype, comptime argsT: type) type { + return struct { + const Self = @This(); + const Signature = FnSignature(func, argsT); + const FrameT = libcoro.FrameT(func, .{ .ArgsT = Signature.ArgsT }); + + inner: FrameT, + + pub fn await_(self: *Self) Signature.ReturnT { + defer { + self.inner.deinit(); + self.* = undefined; + } + return libcoro.xawait(self.inner); + } + + fn from(other: anytype) !Self { + return .{ .inner = FrameT.wrap(other.frame()) }; + } + }; +} + +pub fn async_(comptime func: anytype, args: anytype) !FrameEx(func, @TypeOf(args)) { + const frame = try aio.xasync(func, args, null); + return FrameEx(func, @TypeOf(args)).from(frame); +} + +pub fn call(comptime func: anytype, args: std.meta.ArgsTuple(@TypeOf(func))) @TypeOf(callGeneric(func, args)) { + return callGeneric(func, args); +} + +pub fn callGeneric(comptime func: anytype, args: anytype) FnSignature(func, @TypeOf(args)).ReturnT { + const Signature = FnSignature(func, @TypeOf(args)); + + const TaskT = struct { + const Self = @This(); + + _task: xev.ThreadPool.Task = .{ .callback = &Self.run }, + + notif: Notification, + args: *const Signature.ArgsT, + result: Signature.ReturnT = undefined, + + pub fn run(task_: *xev.ThreadPool.Task) void { + const task: *Self = @alignCast(@fieldParentPtr("_task", task_)); + task.result = @call(.auto, func, task.args.*); + task.notif.notify() catch @panic("Unable to notify"); + } + }; + + var newtask: TaskT = .{ + .notif = Notification.init() catch @panic("Notification.init failed"), + .args = &args, + }; + defer newtask.notif.deinit(); + + AsyncThread.current.thread_pool.schedule(xev.ThreadPool.Batch.from(&newtask._task)); + newtask.notif.wait() catch @panic("Unable to wait for notification"); + return newtask.result; +} + +pub fn tick() void { + AsyncThread.current.executor.exec.tick(); +} + +pub fn sleep(ms: u64) !void { + try aio.sleep(AsyncThread.current.executor, ms); +} + +pub const Notification = struct { + inner: aio.AsyncNotification, + + pub fn init() !Notification { + return .{ + .inner = aio.AsyncNotification.init(AsyncThread.current.executor, try xev.Async.init()), + }; + } + + pub fn notify(self: *Notification) !void { + try self.inner.notif.notify(); + } + + pub fn wait(self: *Notification) !void { + try self.inner.wait(); + } + + pub fn deinit(self: *Notification) void { + self.inner.notif.deinit(); + self.* = undefined; + } +}; + +pub const AsyncThread = struct { + threadlocal var current: AsyncThread = undefined; + + executor: *aio.Executor, + loop: *xev.Loop, + thread_pool: *xev.ThreadPool, + + pub fn main(allocator: std.mem.Allocator, comptime func: anytype, args: anytype) !FnSignature(func, NormalizedTuple(@TypeOf(args))).ReturnPayloadT { + const Signature = FnSignature(func, NormalizedTuple(@TypeOf(args))); + + var thread_pool = xev.ThreadPool.init(.{}); + defer { + thread_pool.shutdown(); + thread_pool.deinit(); + } + + var loop = try xev.Loop.init(.{ + .thread_pool = &thread_pool, + }); + defer loop.deinit(); + + var executor = aio.Executor.init(&loop); + + AsyncThread.current = .{ + .executor = &executor, + .loop = &loop, + .thread_pool = &thread_pool, + }; + + aio.initEnv(.{ + .stack_allocator = allocator, + .default_stack_size = 16 * 1024 * 1024, + }); + + if (Signature.ReturnErrorSet) |_| { + return try aio.run(&executor, func, args, null); + } else { + return aio.run(&executor, func, args, null); + } + } +}; + +pub fn StdIn() !File { + return File.init(std.io.getStdIn()) catch @panic("Unable to open stdin"); +} + +pub fn StdOut() File { + return File.init(std.io.getStdOut()) catch @panic("Unable to open stdout"); +} + +pub fn StdErr() File { + return File.init(std.io.getStdErr()) catch @panic("Unable to open stderr"); +} + +pub const File = struct { + pub const SeekError = FnSignature(File.seekTo, null).ReturnErrorSet.? || FnSignature(File.seekBy, null).ReturnErrorSet.?; + pub const GetSeekPosError = SeekError || FnSignature(File.stat, null).ReturnErrorSet.?; + pub const Reader = std.io.GenericReader(File, FnSignature(File.read, null).ReturnErrorSet.?, File.read); + pub const Writer = std.io.GenericWriter(File, FnSignature(File.write, null).ReturnErrorSet.?, File.write); + pub const SeekableStream = std.io.SeekableStream( + File, + SeekError, + GetSeekPosError, + seekTo, + seekBy, + getPos, + getEndPos, + ); + + inner: aio.File, + + fn asFile(self: File) std.fs.File { + return .{ .handle = self.inner.file.fd }; + } + + pub fn init(file_: std.fs.File) !File { + return .{ .inner = aio.File.init(AsyncThread.current.executor, try xev.File.init(file_)) }; + } + + pub fn fromFd(fd: std.fs.File.Handle) !File { + return .{ .inner = aio.File.init(AsyncThread.current.executor, try xev.File.initFd(fd)) }; + } + + pub fn open(path: []const u8, flags: std.fs.File.OpenFlags) !File { + return init(try call(std.fs.Dir.openFile, .{ std.fs.cwd(), path, flags })); + } + + pub fn read(self: File, buf: []u8) !usize { + // NOTE(Corentin): Early return is required to avoid error with xev on Linux with io_uring backend. + if (buf.len == 0) return 0; + + return self.inner.read(.{ .slice = buf }) catch |err| switch (err) { + // NOTE(Corentin): read shouldn't return an error on EOF, but a read length of 0 instead. This is to be iso with std.fs.File. + error.EOF => 0, + else => err, + }; + } + + pub fn pread(self: File, buf: []u8, offset: u64) !usize { + // NOTE(Corentin): Early return is required to avoid error with xev on Linux with io_uring backend. + if (buf.len == 0) return 0; + + return self.inner.pread(.{ .slice = buf }, offset) catch |err| switch (err) { + // NOTE(Corentin): pread shouldn't return an error on EOF, but a read length of 0 instead. This is to be iso with std.fs.File. + error.EOF => 0, + else => err, + }; + } + + pub fn write(self: File, buf: []const u8) !usize { + return self.inner.write(.{ .slice = buf }); + } + + pub fn pwrite(self: File, buf: []const u8, offset: u64) !usize { + return self.inner.pwrite(.{ .slice = buf }, offset); + } + + pub fn close(self: File) !void { + return self.inner.close(); + } + + pub fn reader(self: File) Reader { + return .{ .context = self }; + } + + pub fn seekableStream(file: File) SeekableStream { + return .{ .context = file }; + } + + pub fn writer(self: File) Writer { + return .{ .context = self }; + } + + pub fn stat(self: File) !std.fs.File.Stat { + return try call(std.fs.File.stat, .{self.asFile()}); + } + + pub fn seekBy(self: File, offset: i64) !void { + try call(std.fs.File.seekBy, .{ self.asFile(), offset }); + } + + pub fn seekTo(self: File, offset: u64) !void { + try call(std.fs.File.seekTo, .{ self.asFile(), offset }); + } + + pub fn getPos(self: File) !u64 { + return try call(std.fs.File.getPos, .{self.asFile()}); + } + + pub fn getEndPos(self: File) !u64 { + return try call(std.fs.File.getEndPos, .{self.asFile()}); + } +}; + +pub const Socket = struct { + pub const TCP = struct { + pub const Reader = std.io.GenericReader(TCP, FnSignature(TCP.read, null).ReturnErrorSet.?, TCP.read); + pub const Writer = std.io.GenericWriter(TCP, FnSignature(TCP.write, null).ReturnErrorSet.?, TCP.write); + + inner: aio.TCP, + + pub fn init(addr: std.net.Address) !TCP { + return .{ .inner = aio.TCP.init(AsyncThread.current.executor, try xev.TCP.init(addr)) }; + } + + pub fn deinit(self: *TCP) void { + self.inner.shutdown(); + } + + pub fn connect(self: *TCP, addr: std.net.Address) !void { + return self.inner.connect(addr); + } + + pub fn read(self: *TCP, buf: []u8) !usize { + return self.inner.read(.{ .slice = buf }); + } + + pub fn write(self: *TCP, buf: []const u8) !usize { + return self.inner.write(.{ .slice = buf }); + } + + pub fn close(self: *TCP) !void { + defer self.* = undefined; + return self.inner.close(); + } + + pub fn reader(self: File) Reader { + return .{ .context = self }; + } + + pub fn writer(self: File) Writer { + return .{ .context = self }; + } + }; + + pub const UDP = struct { + pub const Reader = std.io.GenericReader(UDP, FnSignature(UDP.read, null).ReturnErrorSet.?, UDP.read); + pub const WriterContext = struct { + file: UDP, + addr: std.net.Address, + }; + pub const Writer = std.io.GenericWriter(WriterContext, FnSignature(UDP.write, null).ReturnErrorSet.?, struct { + fn call(self: WriterContext, buf: []const u8) !usize { + return self.file.write(self.addr, buf); + } + }.call); + + inner: aio.UDP, + + pub fn init(addr: std.net.Address) !UDP { + return .{ .inner = aio.UDP.init(AsyncThread.current.executor, try xev.UDP.init(addr)) }; + } + + pub fn read(self: UDP, buf: []u8) !usize { + return self.inner.read(.{ .slice = buf }); + } + + pub fn write(self: UDP, addr: std.net.Address, buf: []const u8) !usize { + return self.inner.write(addr, .{ .slice = buf }); + } + + pub fn close(self: *UDP) !void { + defer self.* = undefined; + return self.inner.close(); + } + + pub fn reader(self: File) Reader { + return .{ .context = self }; + } + + pub fn writer(self: File, addr: std.net.Address) Writer { + return .{ + .context = .{ + .file = self, + .addr = addr, + }, + }; + } + }; +}; + +pub const Mutex = struct { + const VoidChannel = libcoro.Channel(void, .{ .capacity = 1 }); + + inner: VoidChannel, + + pub fn init() Mutex { + return .{ .inner = VoidChannel.init(&AsyncThread.current.executor.exec) }; + } + + pub fn lock(self: *Mutex) !void { + try self.inner.send({}); + } + + pub fn unlock(self: *Mutex) void { + _ = self.inner.recv(); + } +}; diff --git a/bazel/BUILD.bazel b/bazel/BUILD.bazel new file mode 100644 index 0000000..e69de29 diff --git a/bazel/cc_import.bzl b/bazel/cc_import.bzl new file mode 100644 index 0000000..92cb014 --- /dev/null +++ b/bazel/cc_import.bzl @@ -0,0 +1,96 @@ +load("@bazel_tools//tools/build_defs/cc:cc_import.bzl", _cc_import = "cc_import") +load(":patchelf.bzl", "patchelf") + +def _cc_import_runfiles_impl(ctx): + runfiles = ctx.runfiles(files = ctx.files.data) + transitive_runfiles_list = [] + if ctx.attr.static_library: + transitive_runfiles_list.append(ctx.attr.static_library[DefaultInfo].default_runfiles) + if ctx.attr.pic_static_library: + transitive_runfiles_list.append(ctx.attr.pic_static_library[DefaultInfo].default_runfiles) + if ctx.attr.shared_library: + transitive_runfiles_list.append(ctx.attr.shared_library[DefaultInfo].default_runfiles) + if ctx.attr.interface_library: + transitive_runfiles_list.append(ctx.attr.interface_library[DefaultInfo].default_runfiles) + for dep in ctx.attr.deps: + transitive_runfiles_list.append(dep[DefaultInfo].default_runfiles) + + for maybe_runfiles in transitive_runfiles_list: + if maybe_runfiles: + runfiles = runfiles.merge(maybe_runfiles) + + default_info = DefaultInfo(runfiles = runfiles) + return [ctx.attr.src[CcInfo], default_info] + +_cc_import_runfiles = rule( + implementation = _cc_import_runfiles_impl, + attrs = { + "src": attr.label(providers = [CcInfo]), + "static_library": attr.label(allow_single_file = [".a", ".lib"]), + "pic_static_library": attr.label(allow_single_file = [".pic.a", ".pic.lib"]), + "shared_library": attr.label(allow_single_file = True), + "interface_library": attr.label(allow_single_file = [".ifso", ".tbd", ".lib", ".so", ".dylib"]), + "data": attr.label_list(allow_files = True), + "deps": attr.label_list(), + }, +) + +def cc_import( + name, + static_library = None, + pic_static_library = None, + shared_library = None, + interface_library = None, + data = None, + deps = None, + visibility = None, + soname = None, + add_needed = None, + remove_needed = None, + replace_needed = None, + **kwargs): + if shared_library and (soname or add_needed or remove_needed or replace_needed): + patched_name = "{}_patchelf".format(name) + patchelf( + name = patched_name, + shared_library = shared_library, + soname = soname, + add_needed = add_needed, + remove_needed = remove_needed, + replace_needed = replace_needed, + ) + shared_library = ":" + patched_name + if data: + _cc_import( + name = name + "_no_runfiles", + static_library = static_library, + pic_static_library = pic_static_library, + shared_library = shared_library, + interface_library = interface_library, + data = data, + deps = deps, + **kwargs + ) + _cc_import_runfiles( + name = name, + src = ":{}_no_runfiles".format(name), + static_library = static_library, + pic_static_library = pic_static_library, + shared_library = shared_library, + interface_library = interface_library, + data = data, + deps = deps, + visibility = visibility, + ) + else: + _cc_import( + name = name, + static_library = static_library, + pic_static_library = pic_static_library, + shared_library = shared_library, + interface_library = interface_library, + data = data, + deps = deps, + visibility = visibility, + **kwargs + ) diff --git a/bazel/http_deb_archive.bzl b/bazel/http_deb_archive.bzl new file mode 100644 index 0000000..f847e6f --- /dev/null +++ b/bazel/http_deb_archive.bzl @@ -0,0 +1,45 @@ +load( + "@bazel_tools//tools/build_defs/repo:utils.bzl", + "get_auth", + "patch", + "workspace_and_buildfile", +) + +def _http_deb_archive_impl(rctx): + if rctx.attr.build_file and rctx.attr.build_file_content: + fail("Only one of build_file and build_file_content can be provided.") + download_info = rctx.download_and_extract( + url = rctx.attr.urls, + output = "tmp", + sha256 = rctx.attr.sha256, + type = "deb", + stripPrefix = "", + canonical_id = " ".join(rctx.attr.urls), + auth = get_auth(rctx, rctx.attr.urls), + ) + + for ext in ["gz", "xz", "zst"]: + data = "tmp/data.tar.{}".format(ext) + if rctx.path(data).exists: + rctx.extract( + archive = data, + output = "", + stripPrefix = rctx.attr.strip_prefix, + ) + rctx.delete("tmp") + break + workspace_and_buildfile(rctx) + patch(rctx) + +http_deb_archive = repository_rule( + _http_deb_archive_impl, + attrs = { + "urls": attr.string_list(mandatory = True), + "sha256": attr.string(mandatory = True), + "strip_prefix": attr.string(), + "build_file": attr.label(allow_single_file = True), + "build_file_content": attr.string(), + "workspace_file": attr.label(allow_single_file = True), + "workspace_file_content": attr.string(), + }, +) diff --git a/bazel/huggingface.bzl b/bazel/huggingface.bzl new file mode 100644 index 0000000..11eb0a7 --- /dev/null +++ b/bazel/huggingface.bzl @@ -0,0 +1,173 @@ +load( + "@bazel_tools//tools/build_defs/repo:utils.bzl", + "patch", + "workspace_and_buildfile", +) + +TREE_URL_TEMPLATE = "https://huggingface.co/api/models/{model}/tree/{commit}/{path}" +RAW_FILE_URL_REMPLATE = "https://huggingface.co/{model}/raw/{commit}/{path}" +LFS_FILE_URL_TEMPLATE = "https://huggingface.co/{model}/resolve/{commit}/{path}" + +def _glob(rctx, str, patterns): + cmd = "\n".join([ + """[[ "{str}" = {pattern} ]] && exit 0""".format(str = str, pattern = pattern) + for pattern in patterns + ] + ["exit 1"]) + return rctx.execute(["bash", "-c", cmd]).return_code == 0 + +def _ls(rctx, headers, path): + url = TREE_URL_TEMPLATE.format( + model = rctx.attr.model, + commit = rctx.attr.commit, + path = path, + ) + rctx.download(url, path + ".index.json", headers = headers) + ret = json.decode(rctx.read(path + ".index.json")) + rctx.delete(path + ".index.json") + return ret + +def _get_token_via_env(rctx): + return rctx.getenv("HUGGINGFACE_TOKEN") + +def _get_token_via_file(rctx): + p = rctx.path(rctx.getenv("HOME") + "/.cache/huggingface/token") + if p.exists: + return rctx.read(p) + +def _get_token_via_git_credentials(rctx): + input = """\ +protocol=https +host=huggingface.co + +""" + res = rctx.execute(["bash", "-c", "echo '{}' | git credential fill".format(input)]) + if res.return_code != 0: + return None + for line in res.stdout.split("\n"): + if line.startswith("password="): + return line[len("password="):] + return None + +def _get_token(rctx): + t = _get_token_via_env(rctx) or \ + _get_token_via_file(rctx) or \ + _get_token_via_git_credentials(rctx) + if t: + return t.strip() + +def _huggingface_repository_impl(rctx): + headers = { + "Accept": "application/json", + "Accept-Encoding": "gzip, deflate", + } + + token = _get_token(rctx) + if token: + headers["Authorization"] = "Bearer " + token + + includes = rctx.attr.includes + excludes = rctx.attr.excludes + stack = [""] + downloads = [] + + for _ in range(9999999): + if (not stack): + break + path = stack.pop() + for entry in _ls(rctx, headers, path): + if entry["type"] == "directory": + stack.append(entry["path"]) + elif entry["type"] == "file": + if (excludes and _glob(rctx, entry["path"], excludes)): + continue + if (not includes or _glob(rctx, entry["path"], includes)): + tpl = RAW_FILE_URL_REMPLATE + if ("lfs" in entry): + tpl = LFS_FILE_URL_TEMPLATE + url = tpl.format( + model = rctx.attr.model, + commit = rctx.attr.commit, + path = entry["path"], + ) + downloads.append(rctx.download( + url = url, + output = entry["path"], + canonical_id = entry["oid"], + headers = headers, + block = False, + )) + + for download in downloads: + download.wait() + + workspace_and_buildfile(rctx) + patch(rctx) + +huggingface_repository = repository_rule( + implementation = _huggingface_repository_impl, + attrs = { + "model": attr.string(mandatory = True), + "commit": attr.string(mandatory = True), + "includes": attr.string_list(default = []), + "excludes": attr.string_list(default = []), + "patches": attr.label_list(), + "patch_tool": attr.string(default = ""), + "patch_args": attr.string_list(default = ["-p0"]), + "patch_cmds": attr.string_list(default = []), + "patch_cmds_win": attr.string_list(default = []), + "build_file": attr.label(allow_single_file = True), + "build_file_content": attr.string(), + "workspace_file": attr.label(allow_single_file = True), + "workspace_file_content": attr.string(), + }, +) + +def _huggingface_impl(mctx): + for mod in mctx.modules: + for model in mod.tags.model: + huggingface_repository( + name = model.name, + model = model.model, + commit = model.commit, + includes = model.includes, + excludes = model.excludes, + patches = model.patches, + patch_tool = model.patch_tool, + patch_args = model.patch_args, + patch_cmds = model.patch_cmds, + patch_cmds_win = model.patch_cmds_win, + build_file = model.build_file, + build_file_content = model.build_file_content, + workspace_file = model.workspace_file, + workspace_file_content = model.workspace_file_content, + ) + + return mctx.extension_metadata( + reproducible = True, + root_module_direct_deps = "all", + root_module_direct_dev_deps = [], + ) + +huggingface = module_extension( + implementation = _huggingface_impl, + tag_classes = { + "model": tag_class( + attrs = { + "name": attr.string(mandatory = True), + "model": attr.string(mandatory = True), + "commit": attr.string(mandatory = True), + "includes": attr.string_list(default = []), + "excludes": attr.string_list(default = []), + "patches": attr.label_list(), + "patch_tool": attr.string(default = ""), + "patch_args": attr.string_list(default = ["-p0"]), + "patch_cmds": attr.string_list(default = []), + "patch_cmds_win": attr.string_list(default = []), + "build_file": attr.label(allow_single_file = True), + "build_file_content": attr.string(), + "workspace_file": attr.label(allow_single_file = True), + "workspace_file_content": attr.string(), + }, + ), + }, +) diff --git a/bazel/patchelf.bzl b/bazel/patchelf.bzl new file mode 100644 index 0000000..244dbf6 --- /dev/null +++ b/bazel/patchelf.bzl @@ -0,0 +1,58 @@ +def _render_kv(e): + return e + +def _patchelf_impl(ctx): + output_name = ctx.file.shared_library.basename + if ctx.attr.soname: + output_name = ctx.attr.soname + output = ctx.actions.declare_file("{}/{}".format(ctx.attr.name, output_name)) + + commands = [ + "set -e", + 'cp -f "$2" "$3"', + 'chmod +w "$3"', + ] + + if ctx.attr.soname: + commands.append('"$1" --set-soname "{}" "$3"'.format(ctx.attr.soname)) + if ctx.attr.remove_needed: + for v in ctx.attr.remove_needed: + commands.append('"$1" --remove-needed "{}" "$3"'.format(v)) + if ctx.attr.add_needed: + for v in ctx.attr.add_needed: + commands.append('"$1" --add-needed "{}" "$3"'.format(v)) + + if ctx.attr.replace_needed: + for k, v in ctx.attr.replace_needed.items(): + commands.append('"$1" --replace-needed "{}" "{}" "$3"'.format(k, v)) + + ctx.actions.run_shell( + inputs = [ctx.file.shared_library], + outputs = [output], + arguments = [ctx.executable._patchelf.path, ctx.file.shared_library.path, output.path], + command = "\n".join(commands), + tools = [ctx.executable._patchelf], + ) + + return [ + DefaultInfo( + files = depset([output]), + ), + ] + +patchelf = rule( + implementation = _patchelf_impl, + attrs = { + "shared_library": attr.label(allow_single_file = True, mandatory = True), + "soname": attr.string(), + "add_needed": attr.string_list(), + "remove_needed": attr.string_list(), + "replace_needed": attr.string_dict(), + "_patchelf": attr.label( + default = "@patchelf", + allow_single_file = True, + executable = True, + cfg = "exec", + ), + }, +) diff --git a/bazel/zig.bzl b/bazel/zig.bzl new file mode 100644 index 0000000..f6de39a --- /dev/null +++ b/bazel/zig.bzl @@ -0,0 +1,39 @@ +load("@rules_zig//zig:defs.bzl", "BINARY_KIND", "zig_binary") + +def zig_cc_binary(name, args = None, env = None, data = [], deps = [], visibility = None, **kwargs): + zig_binary( + name = "{}_lib".format(name), + kind = BINARY_KIND.static_lib, + deps = deps + [ + "@rules_zig//zig/lib:libc", + ], + **kwargs + ) + native.cc_binary( + name = name, + args = args, + env = env, + data = data, + deps = [":{}_lib".format(name)], + visibility = visibility, + ) + +def zig_cc_test(name, env = None, data = [], deps = [], test_runner = None, visibility = None, **kwargs): + zig_binary( + name = "{}_test_lib".format(name), + kind = BINARY_KIND.test_lib, + test_runner = test_runner, + data = data, + deps = deps + [ + "@rules_zig//zig/lib:libc", + ], + **kwargs + ) + native.cc_test( + name = name, + env = env, + data = data, + deps = [":{}_test_lib".format(name)], + visibility = visibility, + linkstatic = True, + ) diff --git a/bazel/zig_index.json b/bazel/zig_index.json new file mode 100644 index 0000000..4c37b61 --- /dev/null +++ b/bazel/zig_index.json @@ -0,0 +1,1090 @@ +{ + "master": { + "version": "0.14.0-dev.363+c3faae6bf", + "date": "2024-07-18", + "docs": "https://ziglang.org/documentation/master/", + "stdDocs": "https://ziglang.org/documentation/master/std/", + "src": { + "tarball": "https://ziglang.org/builds/zig-0.14.0-dev.363+c3faae6bf.tar.xz", + "shasum": "55b48780575ee86668fe9e8119abcc0831d3ce93f5f848b7a9b610155c1a865e", + "size": "17272356" + }, + "bootstrap": { + "tarball": "https://ziglang.org/builds/zig-bootstrap-0.14.0-dev.363+c3faae6bf.tar.xz", + "shasum": "65cd278494293ff953561194607c4b7e9b96908aa903c7a8421f4e8014a6345b", + "size": "46507328" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/builds/zig-macos-x86_64-0.14.0-dev.363+c3faae6bf.tar.xz", + "shasum": "256b09afa6a4e0cd5c4f8497ef3625ba9b01de2b75f57b728337bc1de4681c9c", + "size": "48937384" + }, + "aarch64-macos": { + "tarball": "https://ziglang.org/builds/zig-macos-aarch64-0.14.0-dev.363+c3faae6bf.tar.xz", + "shasum": "cd9f563150b1adb7306912b5acff9b00e39ef283075a42b95186f39bda656862", + "size": "44960052" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/builds/zig-linux-x86_64-0.14.0-dev.363+c3faae6bf.tar.xz", + "shasum": "98ce531beaac0e683713ec1843023b8aa81a318686472ff13f2c075f0362bf0a", + "size": "47164832" + }, + "aarch64-linux": { + "tarball": "https://ziglang.org/builds/zig-linux-aarch64-0.14.0-dev.363+c3faae6bf.tar.xz", + "shasum": "81e1c06740c017ad8aa3df451c544da17a2e23440c1e695954b8c4b612243af0", + "size": "43190732" + }, + "armv7a-linux": { + "tarball": "https://ziglang.org/builds/zig-linux-armv7a-0.14.0-dev.363+c3faae6bf.tar.xz", + "shasum": "cda6c3f2b51355c3f117814c13962c9fd65d9ba02f5981d45ea83c135b9019b6", + "size": "44096460" + }, + "riscv64-linux": { + "tarball": "https://ziglang.org/builds/zig-linux-riscv64-0.14.0-dev.363+c3faae6bf.tar.xz", + "shasum": "aa488f1763ff65a910c8f6bdedc5ff8b9a05225d8b29a1446e3c0e0cb7bff683", + "size": "45637416" + }, + "powerpc64le-linux": { + "tarball": "https://ziglang.org/builds/zig-linux-powerpc64le-0.14.0-dev.363+c3faae6bf.tar.xz", + "shasum": "8e9f715b53edf8d8b8c0d9dcc173a1faafdb3b659cebe4435d19d2b2ef24eda9", + "size": "46654844" + }, + "x86-linux": { + "tarball": "https://ziglang.org/builds/zig-linux-x86-0.14.0-dev.363+c3faae6bf.tar.xz", + "shasum": "4633ce74826903cf019f390956726c434a5b032f06931aa085e0b22194b55bb5", + "size": "52144844" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/builds/zig-windows-x86_64-0.14.0-dev.363+c3faae6bf.zip", + "shasum": "44a26238f1757723f54e9b5d4d08b508be8ebdfad9442218d0f2a3ae61f032a5", + "size": "79857623" + }, + "aarch64-windows": { + "tarball": "https://ziglang.org/builds/zig-windows-aarch64-0.14.0-dev.363+c3faae6bf.zip", + "shasum": "8214699c48b5753d127f9632fbb78432fdfa1dd5715ff73106469b339bb641ef", + "size": "75829556" + }, + "x86-windows": { + "tarball": "https://ziglang.org/builds/zig-windows-x86-0.14.0-dev.363+c3faae6bf.zip", + "shasum": "86be63cb2017f23371da631980b27ab6aa4a43b5d4ed96fd08f1311584d779a9", + "size": "83972311" + } + }, + "0.13.0": { + "date": "2024-06-07", + "docs": "https://ziglang.org/documentation/0.13.0/", + "stdDocs": "https://ziglang.org/documentation/0.13.0/std/", + "notes": "https://ziglang.org/download/0.13.0/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.13.0/zig-0.13.0.tar.xz", + "shasum": "06c73596beeccb71cc073805bdb9c0e05764128f16478fa53bf17dfabc1d4318", + "size": "17220728" + }, + "bootstrap": { + "tarball": "https://ziglang.org/download/0.13.0/zig-bootstrap-0.13.0.tar.xz", + "shasum": "cd446c084b5da7bc42e8ad9b4e1c910a957f2bf3f82bcc02888102cd0827c139", + "size": "46440356" + }, + "x86_64-freebsd": { + "tarball": "https://ziglang.org/download/0.13.0/zig-freebsd-x86_64-0.13.0.tar.xz", + "shasum": "adc1ffc9be56533b2f1c7191f9e435ad55db00414ff2829d951ef63d95aaad8c", + "size": "47177744" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.13.0/zig-macos-x86_64-0.13.0.tar.xz", + "shasum": "8b06ed1091b2269b700b3b07f8e3be3b833000841bae5aa6a09b1a8b4773effd", + "size": "48857012" + }, + "aarch64-macos": { + "tarball": "https://ziglang.org/download/0.13.0/zig-macos-aarch64-0.13.0.tar.xz", + "shasum": "46fae219656545dfaf4dce12fb4e8685cec5b51d721beee9389ab4194d43394c", + "size": "44892040" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.13.0/zig-linux-x86_64-0.13.0.tar.xz", + "shasum": "d45312e61ebcc48032b77bc4cf7fd6915c11fa16e4aad116b66c9468211230ea", + "size": "47082308" + }, + "aarch64-linux": { + "tarball": "https://ziglang.org/download/0.13.0/zig-linux-aarch64-0.13.0.tar.xz", + "shasum": "041ac42323837eb5624068acd8b00cd5777dac4cf91179e8dad7a7e90dd0c556", + "size": "43090688" + }, + "armv7a-linux": { + "tarball": "https://ziglang.org/download/0.13.0/zig-linux-armv7a-0.13.0.tar.xz", + "shasum": "4b0550239c2cd884cc03ddeb2b9934708f4b073ad59a96fccbfe09f7e4f54233", + "size": "43998916" + }, + "riscv64-linux": { + "tarball": "https://ziglang.org/download/0.13.0/zig-linux-riscv64-0.13.0.tar.xz", + "shasum": "9f7f3c685894ff80f43eaf3cad1598f4844ac46f4308374237c7f912f7907bb3", + "size": "45540956" + }, + "powerpc64le-linux": { + "tarball": "https://ziglang.org/download/0.13.0/zig-linux-powerpc64le-0.13.0.tar.xz", + "shasum": "6a467622448e830e8f85d20cabed151498af2b0a62f87b8c083b2fe127e60417", + "size": "46574596" + }, + "x86-linux": { + "tarball": "https://ziglang.org/download/0.13.0/zig-linux-x86-0.13.0.tar.xz", + "shasum": "876159cc1e15efb571e61843b39a2327f8925951d48b9a7a03048c36f72180f7", + "size": "52062336" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.13.0/zig-windows-x86_64-0.13.0.zip", + "shasum": "d859994725ef9402381e557c60bb57497215682e355204d754ee3df75ee3c158", + "size": "79163968" + }, + "aarch64-windows": { + "tarball": "https://ziglang.org/download/0.13.0/zig-windows-aarch64-0.13.0.zip", + "shasum": "95ff88427af7ba2b4f312f45d2377ce7a033e5e3c620c8caaa396a9aba20efda", + "size": "75119033" + }, + "x86-windows": { + "tarball": "https://ziglang.org/download/0.13.0/zig-windows-x86-0.13.0.zip", + "shasum": "eb3d533c3cf868bff7e74455dc005d18fd836c42e50b27106b31e9fec6dffc4a", + "size": "83274739" + } + }, + "0.12.1": { + "date": "2024-06-08", + "docs": "https://ziglang.org/documentation/0.12.1/", + "stdDocs": "https://ziglang.org/documentation/0.12.1/std/", + "src": { + "tarball": "https://ziglang.org/download/0.12.1/zig-0.12.1.tar.xz", + "shasum": "cca0bf5686fe1a15405bd535661811fac7663f81664d2204ea4590ce49a6e9ba", + "size": "17110932" + }, + "bootstrap": { + "tarball": "https://ziglang.org/download/0.12.1/zig-bootstrap-0.12.1.tar.xz", + "shasum": "e533e2cb6ef60edda0ae3f2ca5c6504557db6e985e3c3a80159beb32279ed341", + "size": "45542004" + }, + "x86_64-freebsd": { + "tarball": "https://ziglang.org/download/0.12.1/zig-freebsd-x86_64-0.12.1.tar.xz", + "shasum": "30eaa28fa7bc21d01f88528d75ae4b392ae4970406675d5ac712a4937a605123", + "size": "45590080" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.12.1/zig-macos-x86_64-0.12.1.tar.xz", + "shasum": "68f309c6e431d56eb42648d7fe86e8028a23464d401a467831e27c26f1a8d9c9", + "size": "47202232" + }, + "aarch64-macos": { + "tarball": "https://ziglang.org/download/0.12.1/zig-macos-aarch64-0.12.1.tar.xz", + "shasum": "6587860dbbc070e1ee069e1a3d18ced83b7ba7a80bf67b2c57caf7c9ce5208b1", + "size": "43451512" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.12.1/zig-linux-x86_64-0.12.1.tar.xz", + "shasum": "8860fc9725c2d9297a63008f853e9b11e3c5a2441217f99c1e3104cc6fa4a443", + "size": "45512024" + }, + "aarch64-linux": { + "tarball": "https://ziglang.org/download/0.12.1/zig-linux-aarch64-0.12.1.tar.xz", + "shasum": "27d4fef393e8d8b5f3b1d19f4dd43bfdb469b4ed17bbc4c2283c1b1fe650ef7f", + "size": "41867324" + }, + "armv7a-linux": { + "tarball": "https://ziglang.org/download/0.12.1/zig-linux-armv7a-0.12.1.tar.xz", + "shasum": "27493c922fd1454137ed6cbe6b6bec00352838fcd32e6e74f4f9187011816157", + "size": "42665508" + }, + "riscv64-linux": { + "tarball": "https://ziglang.org/download/0.12.1/zig-linux-riscv64-0.12.1.tar.xz", + "shasum": "463511a863acc16911cff6801de97623e6de296aab7b15dcda5f6fd078b400b5", + "size": "43932908" + }, + "powerpc64le-linux": { + "tarball": "https://ziglang.org/download/0.12.1/zig-linux-powerpc64le-0.12.1.tar.xz", + "shasum": "462d6f10350f3c5d6fc4c9d6cfdede93d69d0103af026889a15f65c5de791d39", + "size": "45227716" + }, + "x86-linux": { + "tarball": "https://ziglang.org/download/0.12.1/zig-linux-x86-0.12.1.tar.xz", + "shasum": "c36ac019ca0fc3167e50d17e2affd3d072a06c519761737d0639adfdf2dcfddd", + "size": "50555428" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.12.1/zig-windows-x86_64-0.12.1.zip", + "shasum": "52459b147c2de4d7c28f6b1a4b3d571c114e96836bf8e31c953a7d2f5e94251c", + "size": "76470574" + }, + "aarch64-windows": { + "tarball": "https://ziglang.org/download/0.12.1/zig-windows-aarch64-0.12.1.zip", + "shasum": "e1286114a11be4695a6ad5cf0ba6a0e5f489bb3b029a5237de93598133f0c13a", + "size": "72998386" + }, + "x86-windows": { + "tarball": "https://ziglang.org/download/0.12.1/zig-windows-x86-0.12.1.zip", + "shasum": "4f0cc9258527e7b8bcf742772b3069122086a5cd857b38a1c08002462ac81f80", + "size": "80979711" + } + }, + "0.12.0": { + "date": "2024-04-20", + "docs": "https://ziglang.org/documentation/0.12.0/", + "stdDocs": "https://ziglang.org/documentation/0.12.0/std/", + "notes": "https://ziglang.org/download/0.12.0/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.12.0/zig-0.12.0.tar.xz", + "shasum": "a6744ef84b6716f976dad923075b2f54dc4f785f200ae6c8ea07997bd9d9bd9a", + "size": "17099152" + }, + "bootstrap": { + "tarball": "https://ziglang.org/download/0.12.0/zig-bootstrap-0.12.0.tar.xz", + "shasum": "3efc643d56421fa68072af94d5512cb71c61acf1c32512f77c0b4590bff63187", + "size": "45527312" + }, + "x86_64-freebsd": { + "tarball": "https://ziglang.org/download/0.12.0/zig-freebsd-x86_64-0.12.0.tar.xz", + "shasum": "bd49957d1157850b337ee1cf3c00af83585cff98e1ebc3c524a267e7422a2d7b", + "size": "45578364" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.12.0/zig-macos-x86_64-0.12.0.tar.xz", + "shasum": "4d411bf413e7667821324da248e8589278180dbc197f4f282b7dbb599a689311", + "size": "47185720" + }, + "aarch64-macos": { + "tarball": "https://ziglang.org/download/0.12.0/zig-macos-aarch64-0.12.0.tar.xz", + "shasum": "294e224c14fd0822cfb15a35cf39aa14bd9967867999bf8bdfe3db7ddec2a27f", + "size": "43447724" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.12.0/zig-linux-x86_64-0.12.0.tar.xz", + "shasum": "c7ae866b8a76a568e2d5cfd31fe89cdb629bdd161fdd5018b29a4a0a17045cad", + "size": "45480516" + }, + "aarch64-linux": { + "tarball": "https://ziglang.org/download/0.12.0/zig-linux-aarch64-0.12.0.tar.xz", + "shasum": "754f1029484079b7e0ca3b913a0a2f2a6afd5a28990cb224fe8845e72f09de63", + "size": "41849060" + }, + "armv7a-linux": { + "tarball": "https://ziglang.org/download/0.12.0/zig-linux-armv7a-0.12.0.tar.xz", + "shasum": "b48221f4c64416d257f0f9f77d8727dccf7de92aeabe59744ee6e70d650a97bc", + "size": "42638808" + }, + "riscv64-linux": { + "tarball": "https://ziglang.org/download/0.12.0/zig-linux-riscv64-0.12.0.tar.xz", + "shasum": "bb2d1a78b01595a9c00ffd2e12ab46e32f8b6798f76aec643ff78e5b4f5c5afd", + "size": "43917444" + }, + "powerpc64le-linux": { + "tarball": "https://ziglang.org/download/0.12.0/zig-linux-powerpc64le-0.12.0.tar.xz", + "shasum": "9218beecfb9250e9eff863f58f987dca7077e3258dd263c40269086127f9679b", + "size": "45216736" + }, + "x86-linux": { + "tarball": "https://ziglang.org/download/0.12.0/zig-linux-x86-0.12.0.tar.xz", + "shasum": "fb752fceb88749a80d625a6efdb23bea8208962b5150d6d14c92d20efda629a5", + "size": "50498940" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.12.0/zig-windows-x86_64-0.12.0.zip", + "shasum": "2199eb4c2000ddb1fba85ba78f1fcf9c1fb8b3e57658f6a627a8e513131893f5", + "size": "76442958" + }, + "aarch64-windows": { + "tarball": "https://ziglang.org/download/0.12.0/zig-windows-aarch64-0.12.0.zip", + "shasum": "04c6b92689241ca7a8a59b5f12d2ca2820c09d5043c3c4808b7e93e41c7bf97b", + "size": "72976876" + }, + "x86-windows": { + "tarball": "https://ziglang.org/download/0.12.0/zig-windows-x86-0.12.0.zip", + "shasum": "497dc9fd415cadf948872f137d6cc0870507488f79db9547b8f2adb73cda9981", + "size": "80950440" + } + }, + "0.11.0": { + "date": "2023-08-04", + "docs": "https://ziglang.org/documentation/0.11.0/", + "stdDocs": "https://ziglang.org/documentation/0.11.0/std/", + "notes": "https://ziglang.org/download/0.11.0/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.11.0/zig-0.11.0.tar.xz", + "shasum": "72014e700e50c0d3528cef3adf80b76b26ab27730133e8202716a187a799e951", + "size": "15275316" + }, + "bootstrap": { + "tarball": "https://ziglang.org/download/0.11.0/zig-bootstrap-0.11.0.tar.xz", + "shasum": "38dd9e17433c7ce5687c48fa0a757462cbfcbe75d9d5087d14ebbe00efd21fdc", + "size": "43227592" + }, + "x86_64-freebsd": { + "tarball": "https://ziglang.org/download/0.11.0/zig-freebsd-x86_64-0.11.0.tar.xz", + "shasum": "ea430327f9178377b79264a1d492868dcff056cd76d43a6fb00719203749e958", + "size": "46432140" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.11.0/zig-macos-x86_64-0.11.0.tar.xz", + "shasum": "1c1c6b9a906b42baae73656e24e108fd8444bb50b6e8fd03e9e7a3f8b5f05686", + "size": "47189164" + }, + "aarch64-macos": { + "tarball": "https://ziglang.org/download/0.11.0/zig-macos-aarch64-0.11.0.tar.xz", + "shasum": "c6ebf927bb13a707d74267474a9f553274e64906fd21bf1c75a20bde8cadf7b2", + "size": "43855096" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.11.0/zig-linux-x86_64-0.11.0.tar.xz", + "shasum": "2d00e789fec4f71790a6e7bf83ff91d564943c5ee843c5fd966efc474b423047", + "size": "44961892" + }, + "aarch64-linux": { + "tarball": "https://ziglang.org/download/0.11.0/zig-linux-aarch64-0.11.0.tar.xz", + "shasum": "956eb095d8ba44ac6ebd27f7c9956e47d92937c103bf754745d0a39cdaa5d4c6", + "size": "41492432" + }, + "armv7a-linux": { + "tarball": "https://ziglang.org/download/0.11.0/zig-linux-armv7a-0.11.0.tar.xz", + "shasum": "aebe8bbeca39f13f9b7304465f9aee01ab005d243836bd40f4ec808093dccc9b", + "size": "42240664" + }, + "riscv64-linux": { + "tarball": "https://ziglang.org/download/0.11.0/zig-linux-riscv64-0.11.0.tar.xz", + "shasum": "24a478937eddb507e96d60bd4da00de9092b3f0920190eb45c4c99c946b00ed5", + "size": "43532324" + }, + "powerpc64le-linux": { + "tarball": "https://ziglang.org/download/0.11.0/zig-linux-powerpc64le-0.11.0.tar.xz", + "shasum": "75260e87325e820a278cf9e74f130c7b3d84c0b5197afb2e3c85eff3fcedd48d", + "size": "44656184" + }, + "powerpc-linux": { + "tarball": "https://ziglang.org/download/0.11.0/zig-linux-powerpc-0.11.0.tar.xz", + "shasum": "70a5f9668a66fb2a91a7c3488b15bcb568e1f9f44b95cd10075c138ad8c42864", + "size": "44539972" + }, + "x86-linux": { + "tarball": "https://ziglang.org/download/0.11.0/zig-linux-x86-0.11.0.tar.xz", + "shasum": "7b0dc3e0e070ae0e0d2240b1892af6a1f9faac3516cae24e57f7a0e7b04662a8", + "size": "49824456" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.11.0/zig-windows-x86_64-0.11.0.zip", + "shasum": "142caa3b804d86b4752556c9b6b039b7517a08afa3af842645c7e2dcd125f652", + "size": "77216743" + }, + "aarch64-windows": { + "tarball": "https://ziglang.org/download/0.11.0/zig-windows-aarch64-0.11.0.zip", + "shasum": "5d4bd13db5ecb0ddc749231e00f125c1d31087d708e9ff9b45c4f4e13e48c661", + "size": "73883137" + }, + "x86-windows": { + "tarball": "https://ziglang.org/download/0.11.0/zig-windows-x86-0.11.0.zip", + "shasum": "e72b362897f28c671633e650aa05289f2e62b154efcca977094456c8dac3aefa", + "size": "81576961" + } + }, + "0.10.1": { + "date": "2023-01-19", + "docs": "https://ziglang.org/documentation/0.10.1/", + "stdDocs": "https://ziglang.org/documentation/0.10.1/std/", + "notes": "https://ziglang.org/download/0.10.1/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.10.1/zig-0.10.1.tar.xz", + "shasum": "69459bc804333df077d441ef052ffa143d53012b655a51f04cfef1414c04168c", + "size": "15143112" + }, + "bootstrap": { + "tarball": "https://ziglang.org/download/0.10.1/zig-bootstrap-0.10.1.tar.xz", + "shasum": "9f5781210b9be8f832553d160851635780f9bd71816065351ab29cfd8968f5e9", + "size": "43971816" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.10.1/zig-macos-x86_64-0.10.1.tar.xz", + "shasum": "02483550b89d2a3070c2ed003357fd6e6a3059707b8ee3fbc0c67f83ca898437", + "size": "45119596" + }, + "aarch64-macos": { + "tarball": "https://ziglang.org/download/0.10.1/zig-macos-aarch64-0.10.1.tar.xz", + "shasum": "b9b00477ec5fa1f1b89f35a7d2a58688e019910ab80a65eac2a7417162737656", + "size": "40517896" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.10.1/zig-linux-x86_64-0.10.1.tar.xz", + "shasum": "6699f0e7293081b42428f32c9d9c983854094bd15fee5489f12c4cf4518cc380", + "size": "44085596" + }, + "aarch64-linux": { + "tarball": "https://ziglang.org/download/0.10.1/zig-linux-aarch64-0.10.1.tar.xz", + "shasum": "db0761664f5f22aa5bbd7442a1617dd696c076d5717ddefcc9d8b95278f71f5d", + "size": "40321280" + }, + "riscv64-linux": { + "tarball": "https://ziglang.org/download/0.10.1/zig-linux-riscv64-0.10.1.tar.xz", + "shasum": "9db5b59a5112b8beb995094ba800e88b0060e9cf7cfadf4dc3e666c9010dc77b", + "size": "42196008" + }, + "i386-linux": { + "tarball": "https://ziglang.org/download/0.10.1/zig-linux-i386-0.10.1.tar.xz", + "shasum": "8c710ca5966b127b0ee3efba7310601ee57aab3dd6052a082ebc446c5efb2316", + "size": "48367388" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.10.1/zig-windows-x86_64-0.10.1.zip", + "shasum": "5768004e5e274c7969c3892e891596e51c5df2b422d798865471e05049988125", + "size": "73259729" + }, + "aarch64-windows": { + "tarball": "https://ziglang.org/download/0.10.1/zig-windows-aarch64-0.10.1.zip", + "shasum": "ece93b0d77b2ab03c40db99ef7ccbc63e0b6bd658af12b97898960f621305428", + "size": "69417459" + } + }, + "0.10.0": { + "date": "2022-10-31", + "docs": "https://ziglang.org/documentation/0.10.0/", + "stdDocs": "https://ziglang.org/documentation/0.10.0/std/", + "notes": "https://ziglang.org/download/0.10.0/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.10.0/zig-0.10.0.tar.xz", + "shasum": "d8409f7aafc624770dcd050c8fa7e62578be8e6a10956bca3c86e8531c64c136", + "size": "14530912" + }, + "bootstrap": { + "tarball": "https://ziglang.org/download/0.10.0/zig-bootstrap-0.10.0.tar.xz", + "shasum": "c13dc70c4ff4c09f749adc0d473cbd3942991dd4d1bd2d860fbf257d8c1bbabf", + "size": "45625516" + }, + "x86_64-freebsd": { + "tarball": "https://ziglang.org/download/0.10.0/zig-freebsd-x86_64-0.10.0.tar.xz", + "shasum": "dd77afa2a8676afbf39f7d6068eda81b0723afd728642adaac43cb2106253d65", + "size": "44056504" + }, + "aarch64-linux": { + "tarball": "https://ziglang.org/download/0.10.0/zig-linux-aarch64-0.10.0.tar.xz", + "shasum": "09ef50c8be73380799804169197820ee78760723b0430fa823f56ed42b06ea0f", + "size": "40387688" + }, + "armv7a-linux": { + "tarball": "https://ziglang.org/download/0.10.0/zig-linux-armv7a-0.10.0.tar.xz", + "shasum": "7201b2e89cd7cc2dde95d39485fd7d5641ba67dc6a9a58c036cb4c308d2e82de", + "size": "50805936" + }, + "i386-linux": { + "tarball": "https://ziglang.org/download/0.10.0/zig-linux-i386-0.10.0.tar.xz", + "shasum": "dac8134f1328c50269f3e50b334298ec7916cb3b0ef76927703ddd1c96fd0115", + "size": "48451732" + }, + "riscv64-linux": { + "tarball": "https://ziglang.org/download/0.10.0/zig-linux-riscv64-0.10.0.tar.xz", + "shasum": "2a126f3401a7a7efc4b454f0a85c133db1af5a9dfee117f172213b7cbd47bfba", + "size": "42272968" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.10.0/zig-linux-x86_64-0.10.0.tar.xz", + "shasum": "631ec7bcb649cd6795abe40df044d2473b59b44e10be689c15632a0458ddea55", + "size": "44142400" + }, + "aarch64-macos": { + "tarball": "https://ziglang.org/download/0.10.0/zig-macos-aarch64-0.10.0.tar.xz", + "shasum": "02f7a7839b6a1e127eeae22ea72c87603fb7298c58bc35822a951479d53c7557", + "size": "40602664" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.10.0/zig-macos-x86_64-0.10.0.tar.xz", + "shasum": "3a22cb6c4749884156a94ea9b60f3a28cf4e098a69f08c18fbca81c733ebfeda", + "size": "45175104" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.10.0/zig-windows-x86_64-0.10.0.zip", + "shasum": "a66e2ff555c6e48781de1bcb0662ef28ee4b88af3af2a577f7b1950e430897ee", + "size": "73181558" + }, + "aarch64-windows": { + "tarball": "https://ziglang.org/download/0.10.0/zig-windows-aarch64-0.10.0.zip", + "shasum": "1bbda8d123d44f3ae4fa90d0da04b1e9093c3f9ddae3429a4abece1e1c0bf19a", + "size": "69332389" + } + }, + "0.9.1": { + "date": "2022-02-14", + "docs": "https://ziglang.org/documentation/0.9.1/", + "stdDocs": "https://ziglang.org/documentation/0.9.1/std/", + "notes": "https://ziglang.org/download/0.9.1/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.9.1/zig-0.9.1.tar.xz", + "shasum": "38cf4e84481f5facc766ba72783e7462e08d6d29a5d47e3b75c8ee3142485210", + "size": "13940828" + }, + "bootstrap": { + "tarball": "https://ziglang.org/download/0.9.1/zig-bootstrap-0.9.1.tar.xz", + "shasum": "0a8e221c71860d8975c15662b3ed3bd863e81c4fe383455a596e5e0e490d6109", + "size": "42488812" + }, + "x86_64-freebsd": { + "tarball": "https://ziglang.org/download/0.9.1/zig-freebsd-x86_64-0.9.1.tar.xz", + "shasum": "4e06009bd3ede34b72757eec1b5b291b30aa0d5046dadd16ecb6b34a02411254", + "size": "39028848" + }, + "aarch64-linux": { + "tarball": "https://ziglang.org/download/0.9.1/zig-linux-aarch64-0.9.1.tar.xz", + "shasum": "5d99a39cded1870a3fa95d4de4ce68ac2610cca440336cfd252ffdddc2b90e66", + "size": "37034860" + }, + "armv7a-linux": { + "tarball": "https://ziglang.org/download/0.9.1/zig-linux-armv7a-0.9.1.tar.xz", + "shasum": "6de64456cb4757a555816611ea697f86fba7681d8da3e1863fa726a417de49be", + "size": "37974652" + }, + "i386-linux": { + "tarball": "https://ziglang.org/download/0.9.1/zig-linux-i386-0.9.1.tar.xz", + "shasum": "e776844fecd2e62fc40d94718891057a1dbca1816ff6013369e9a38c874374ca", + "size": "44969172" + }, + "riscv64-linux": { + "tarball": "https://ziglang.org/download/0.9.1/zig-linux-riscv64-0.9.1.tar.xz", + "shasum": "208dea53662c2c52777bd9e3076115d2126a4f71aed7f2ff3b8fe224dc3881aa", + "size": "39390868" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.9.1/zig-linux-x86_64-0.9.1.tar.xz", + "shasum": "be8da632c1d3273f766b69244d80669fe4f5e27798654681d77c992f17c237d7", + "size": "41011464" + }, + "aarch64-macos": { + "tarball": "https://ziglang.org/download/0.9.1/zig-macos-aarch64-0.9.1.tar.xz", + "shasum": "8c473082b4f0f819f1da05de2dbd0c1e891dff7d85d2c12b6ee876887d438287", + "size": "38995640" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.9.1/zig-macos-x86_64-0.9.1.tar.xz", + "shasum": "2d94984972d67292b55c1eb1c00de46580e9916575d083003546e9a01166754c", + "size": "43713044" + }, + "i386-windows": { + "tarball": "https://ziglang.org/download/0.9.1/zig-windows-i386-0.9.1.zip", + "shasum": "74a640ed459914b96bcc572183a8db687bed0af08c30d2ea2f8eba03ae930f69", + "size": "67929868" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.9.1/zig-windows-x86_64-0.9.1.zip", + "shasum": "443da53387d6ae8ba6bac4b3b90e9fef4ecbe545e1c5fa3a89485c36f5c0e3a2", + "size": "65047697" + }, + "aarch64-windows": { + "tarball": "https://ziglang.org/download/0.9.1/zig-windows-aarch64-0.9.1.zip", + "shasum": "621bf95f54dc3ff71466c5faae67479419951d7489e40e87fd26d195825fb842", + "size": "61478151" + } + }, + "0.9.0": { + "date": "2021-12-20", + "docs": "https://ziglang.org/documentation/0.9.0/", + "stdDocs": "https://ziglang.org/documentation/0.9.0/std/", + "notes": "https://ziglang.org/download/0.9.0/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.9.0/zig-0.9.0.tar.xz", + "shasum": "cd1be83b12f8269cc5965e59877b49fdd8fa638efb6995ac61eb4cea36a2e381", + "size": "13928772" + }, + "bootstrap": { + "tarball": "https://ziglang.org/download/0.9.0/zig-bootstrap-0.9.0.tar.xz", + "shasum": "16b0bdf0bc0a5ed1e0950e08481413d806192e06443a512347526647b2baeabc", + "size": "42557736" + }, + "x86_64-freebsd": { + "tarball": "https://ziglang.org/download/0.9.0/zig-freebsd-x86_64-0.9.0.tar.xz", + "shasum": "c95afe679b7cc4110dc2ecd3606c83a699718b7a958d6627f74c20886333e194", + "size": "41293236" + }, + "aarch64-linux": { + "tarball": "https://ziglang.org/download/0.9.0/zig-linux-aarch64-0.9.0.tar.xz", + "shasum": "1524fedfdbade2dbc9bae1ed98ad38fa7f2114c9a3e94da0d652573c75efbc5a", + "size": "40008396" + }, + "armv7a-linux": { + "tarball": "https://ziglang.org/download/0.9.0/zig-linux-armv7a-0.9.0.tar.xz", + "shasum": "50225dee6e6448a63ee96383a34d9fe3bba34ae8da1a0c8619bde2cdfc1df87d", + "size": "41196876" + }, + "i386-linux": { + "tarball": "https://ziglang.org/download/0.9.0/zig-linux-i386-0.9.0.tar.xz", + "shasum": "b0dcf688349268c883292acdd55eaa3c13d73b9146e4b990fad95b84a2ac528b", + "size": "47408656" + }, + "riscv64-linux": { + "tarball": "https://ziglang.org/download/0.9.0/zig-linux-riscv64-0.9.0.tar.xz", + "shasum": "85466de07504767ed37f59782672ad41bbdf43d6480fafd07f45543278b07620", + "size": "44171420" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.9.0/zig-linux-x86_64-0.9.0.tar.xz", + "shasum": "5c55344a877d557fb1b28939785474eb7f4f2f327aab55293998f501f7869fa6", + "size": "43420796" + }, + "aarch64-macos": { + "tarball": "https://ziglang.org/download/0.9.0/zig-macos-aarch64-0.9.0.tar.xz", + "shasum": "3991c70594d61d09fb4b316157a7c1d87b1d4ec159e7a5ecd11169ff74cad832", + "size": "39013392" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.9.0/zig-macos-x86_64-0.9.0.tar.xz", + "shasum": "c5280eeec4d6e5ea5ce5b448dc9a7c4bdd85ecfed4c1b96aa0835e48b36eccf0", + "size": "43764596" + }, + "i386-windows": { + "tarball": "https://ziglang.org/download/0.9.0/zig-windows-i386-0.9.0.zip", + "shasum": "bb839434afc75092015cf4c33319d31463c18512bc01dd719aedf5dcbc368466", + "size": "67946715" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.9.0/zig-windows-x86_64-0.9.0.zip", + "shasum": "084ea2646850aaf068234b0f1a92b914ed629be47075e835f8a67d55c21d880e", + "size": "65045849" + }, + "aarch64-windows": { + "tarball": "https://ziglang.org/download/0.9.0/zig-windows-aarch64-0.9.0.zip", + "shasum": "f9018725e3fb2e8992b17c67034726971156eb190685018a9ac8c3a9f7a22340", + "size": "61461921" + } + }, + "0.8.1": { + "date": "2021-09-06", + "docs": "https://ziglang.org/documentation/0.8.1/", + "stdDocs": "https://ziglang.org/documentation/0.8.1/std/", + "notes": "https://ziglang.org/download/0.8.1/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.8.1/zig-0.8.1.tar.xz", + "shasum": "8c428e14a0a89cb7a15a6768424a37442292858cdb695e2eb503fa3c7bf47f1a", + "size": "12650228" + }, + "bootstrap": { + "tarball": "https://ziglang.org/download/0.8.1/zig-bootstrap-0.8.1.tar.xz", + "shasum": "fa1239247f830ecd51c42537043f5220e4d1dfefdc54356fa419616a0efb3902", + "size": "43613464" + }, + "x86_64-freebsd": { + "tarball": "https://ziglang.org/download/0.8.1/zig-freebsd-x86_64-0.8.1.tar.xz", + "shasum": "fc4f6478bcf3a9fce1b8ef677a91694f476dd35be6d6c9c4f44a8b76eedbe176", + "size": "39150924" + }, + "aarch64-linux": { + "tarball": "https://ziglang.org/download/0.8.1/zig-linux-aarch64-0.8.1.tar.xz", + "shasum": "2166dc9f2d8df387e8b4122883bb979d739281e1ff3f3d5483fec3a23b957510", + "size": "37605932" + }, + "armv7a-linux": { + "tarball": "https://ziglang.org/download/0.8.1/zig-linux-armv7a-0.8.1.tar.xz", + "shasum": "5ba58141805e2519f38cf8e715933cbf059f4f3dade92c71838cce341045de05", + "size": "39185876" + }, + "i386-linux": { + "tarball": "https://ziglang.org/download/0.8.1/zig-linux-i386-0.8.1.tar.xz", + "shasum": "2f3e84f30492b5f1c5f97cecc0166f07a8a8d50c5f85dbb3a6ef2a4ee6f915e6", + "size": "44782932" + }, + "riscv64-linux": { + "tarball": "https://ziglang.org/download/0.8.1/zig-linux-riscv64-0.8.1.tar.xz", + "shasum": "4adfaf147b025917c03367462fe5018aaa9edbc6439ef9cd0da2b074ae960554", + "size": "41234480" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.8.1/zig-linux-x86_64-0.8.1.tar.xz", + "shasum": "6c032fc61b5d77a3f3cf781730fa549f8f059ffdb3b3f6ad1c2994d2b2d87983", + "size": "41250060" + }, + "aarch64-macos": { + "tarball": "https://ziglang.org/download/0.8.1/zig-macos-aarch64-0.8.1.tar.xz", + "shasum": "5351297e3b8408213514b29c0a938002c5cf9f97eee28c2f32920e1227fd8423", + "size": "35340712" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.8.1/zig-macos-x86_64-0.8.1.tar.xz", + "shasum": "16b0e1defe4c1807f2e128f72863124bffdd906cefb21043c34b673bf85cd57f", + "size": "39946200" + }, + "i386-windows": { + "tarball": "https://ziglang.org/download/0.8.1/zig-windows-i386-0.8.1.zip", + "shasum": "099605051eb0452a947c8eab8fbbc7e43833c8376d267e94e41131c289a1c535", + "size": "64152358" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.8.1/zig-windows-x86_64-0.8.1.zip", + "shasum": "43573db14cd238f7111d6bdf37492d363f11ecd1eba802567a172f277d003926", + "size": "61897838" + } + }, + "0.8.0": { + "date": "2021-06-04", + "docs": "https://ziglang.org/documentation/0.8.0/", + "stdDocs": "https://ziglang.org/documentation/0.8.0/std/", + "notes": "https://ziglang.org/download/0.8.0/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.8.0/zig-0.8.0.tar.xz", + "shasum": "03a828d00c06b2e3bb8b7ff706997fd76bf32503b08d759756155b6e8c981e77", + "size": "12614896" + }, + "bootstrap": { + "tarball": "https://ziglang.org/download/0.8.0/zig-bootstrap-0.8.0.tar.xz", + "shasum": "10600bc9c01f92e343f40d6ecc0ad05d67d27c3e382bce75524c0639cd8ca178", + "size": "43574248" + }, + "x86_64-freebsd": { + "tarball": "https://ziglang.org/download/0.8.0/zig-freebsd-x86_64-0.8.0.tar.xz", + "shasum": "0d3ccc436c8c0f50fd55462f72f8492d98723c7218ffc2a8a1831967d81b4bdc", + "size": "39125332" + }, + "aarch64-linux": { + "tarball": "https://ziglang.org/download/0.8.0/zig-linux-aarch64-0.8.0.tar.xz", + "shasum": "ee204ca2c2037952cf3f8b10c609373a08a291efa4af7b3c73be0f2b27720470", + "size": "37575428" + }, + "armv7a-linux": { + "tarball": "https://ziglang.org/download/0.8.0/zig-linux-armv7a-0.8.0.tar.xz", + "shasum": "d00b8bd97b79f45d6f5da956983bafeaa082e6c2ae8c6e1c6d4faa22fa29b320", + "size": "38884212" + }, + "i386-linux": { + "tarball": "https://ziglang.org/download/0.8.0/zig-linux-i386-0.8.0.tar.xz", + "shasum": "96e43ee6ed81c3c63401f456bd1c58ee6d42373a43cb324f5cf4974ca0998865", + "size": "42136032" + }, + "riscv64-linux": { + "tarball": "https://ziglang.org/download/0.8.0/zig-linux-riscv64-0.8.0.tar.xz", + "shasum": "75997527a78cdab64c40c43d9df39c01c4cdb557bb3992a869838371a204cfea", + "size": "40016268" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.8.0/zig-linux-x86_64-0.8.0.tar.xz", + "shasum": "502625d3da3ae595c5f44a809a87714320b7a40e6dff4a895b5fa7df3391d01e", + "size": "41211184" + }, + "aarch64-macos": { + "tarball": "https://ziglang.org/download/0.8.0/zig-macos-aarch64-0.8.0.tar.xz", + "shasum": "b32d13f66d0e1ff740b3326d66a469ee6baddbd7211fa111c066d3bd57683111", + "size": "35292180" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.8.0/zig-macos-x86_64-0.8.0.tar.xz", + "shasum": "279f9360b5cb23103f0395dc4d3d0d30626e699b1b4be55e98fd985b62bc6fbe", + "size": "39969312" + }, + "i386-windows": { + "tarball": "https://ziglang.org/download/0.8.0/zig-windows-i386-0.8.0.zip", + "shasum": "b6ec9aa6cd6f3872fcb30d43ff411802d82008a0c4142ee49e208a09b2c1c5fe", + "size": "61507213" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.8.0/zig-windows-x86_64-0.8.0.zip", + "shasum": "8580fbbf3afb72e9b495c7f8aeac752a03475ae0bbcf5d787f3775c7e1f4f807", + "size": "61766193" + } + }, + "0.7.1": { + "date": "2020-12-13", + "docs": "https://ziglang.org/documentation/0.7.1/", + "stdDocs": "https://ziglang.org/documentation/0.7.1/std/", + "notes": "https://ziglang.org/download/0.7.1/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.7.1/zig-0.7.1.tar.xz", + "shasum": "2db3b944ab368d955b48743d9f7c963b8f96de1a441ba5a35e197237cc6dae44", + "size": "10711824" + }, + "bootstrap": { + "tarball": "https://ziglang.org/download/0.7.1/zig-bootstrap-0.7.1.tar.xz", + "shasum": "040f27c1fae4b0cac0a2782aecdb691f6a2f8e89db6a6ed35024c31c304fd9b2", + "size": "40232612" + }, + "x86_64-freebsd": { + "tarball": "https://ziglang.org/download/0.7.1/zig-freebsd-x86_64-0.7.1.tar.xz", + "shasum": "e73c1dca35791a3183fdd5ecde0443ebbe180942efceafe651886034fb8def09", + "size": "39066808" + }, + "aarch64-linux": { + "tarball": "https://ziglang.org/download/0.7.1/zig-linux-aarch64-0.7.1.tar.xz", + "shasum": "48ec90eba407e4587ddef7eecef25fec7e13587eb98e3b83c5f2f5fff2a5cbe7", + "size": "33780552" + }, + "armv7a-linux": { + "tarball": "https://ziglang.org/download/0.7.1/zig-linux-armv7a-0.7.1.tar.xz", + "shasum": "5a0662e07b4c4968665e1f97558f8591f6facec45d2e0ff5715e661743107ceb", + "size": "35813504" + }, + "i386-linux": { + "tarball": "https://ziglang.org/download/0.7.1/zig-linux-i386-0.7.1.tar.xz", + "shasum": "4882e052e5f83690bd0334bb4fc1702b5403cb3a3d2aa63fd7d6043d8afecba3", + "size": "39230912" + }, + "riscv64-linux": { + "tarball": "https://ziglang.org/download/0.7.1/zig-linux-riscv64-0.7.1.tar.xz", + "shasum": "187294bfd35983348c3fe042901b42e67e7e36ab7f77a5f969d21c0051f4d21f", + "size": "37454812" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.7.1/zig-linux-x86_64-0.7.1.tar.xz", + "shasum": "18c7b9b200600f8bcde1cd8d7f1f578cbc3676241ce36d771937ce19a8159b8d", + "size": "37848176" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.7.1/zig-macos-x86_64-0.7.1.tar.xz", + "shasum": "845cb17562978af0cf67e3993f4e33330525eaf01ead9386df9105111e3bc519", + "size": "36211076" + }, + "i386-windows": { + "tarball": "https://ziglang.org/download/0.7.1/zig-windows-i386-0.7.1.zip", + "shasum": "a1b9a7421e13153e07fd2e2c93ff29aad64d83105b8fcdafa633dbe689caf1c0", + "size": "54374983" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.7.1/zig-windows-x86_64-0.7.1.zip", + "shasum": "4818a8a65b4672bc52c0ae7f14d014e0eb8caf10f12c0745176820384cea296a", + "size": "54909997" + } + }, + "0.7.0": { + "date": "2020-11-08", + "docs": "https://ziglang.org/documentation/0.7.0/", + "stdDocs": "https://ziglang.org/documentation/0.7.0/std/", + "notes": "https://ziglang.org/download/0.7.0/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.7.0/zig-0.7.0.tar.xz", + "shasum": "0efd2cf6c3b05723db80e9cf193bc55150bba84ca41f855a90f53fc756445f83", + "size": "10683920" + }, + "bootstrap": { + "tarball": "https://ziglang.org/download/0.7.0/zig-bootstrap-0.7.0.tar.xz", + "shasum": "f073beaf5c53c8c57c0d374cbfcb332ef92ad703173edba0d9e0f2ed28401b72", + "size": "40200436" + }, + "x86_64-freebsd": { + "tarball": "https://ziglang.org/download/0.7.0/zig-freebsd-x86_64-0.7.0.tar.xz", + "shasum": "a0c926272ee4ae720034b4a6a1dc98399d76156dd84182554740f0ca8a41fc99", + "size": "34798992" + }, + "aarch64-linux": { + "tarball": "https://ziglang.org/download/0.7.0/zig-linux-aarch64-0.7.0.tar.xz", + "shasum": "f89933bac87d44be82325754ff88423020c81c7032a6fc41cfeb81e982eeab9b", + "size": "33096140" + }, + "armv7a-linux": { + "tarball": "https://ziglang.org/download/0.7.0/zig-linux-armv7a-0.7.0.tar.xz", + "shasum": "011c267e25a96ee160505a560c441daa045359a9d50e13ab1bada9d75c95db2d", + "size": "35157584" + }, + "i386-linux": { + "tarball": "https://ziglang.org/download/0.7.0/zig-linux-i386-0.7.0.tar.xz", + "shasum": "4bb2072cd363bcb1cbeb4872ff5cbc1f683b02d0cc1f90c46e3ea7422ce53222", + "size": "38530596" + }, + "riscv64-linux": { + "tarball": "https://ziglang.org/download/0.7.0/zig-linux-riscv64-0.7.0.tar.xz", + "shasum": "40dff81faa6f232ac40abbf88b9371f3cc932b6e09c423b94387c9ea580cb7be", + "size": "36759992" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.7.0/zig-linux-x86_64-0.7.0.tar.xz", + "shasum": "e619b1c6094c095b932767f527aee2507f847ea981513ff8a08aab0fd730e0ac", + "size": "37154432" + }, + "aarch64-macos": { + "tarball": "https://ziglang.org/download/0.7.0/zig-macos-aarch64-0.7.0.tar.xz", + "shasum": "338238035734db74ea4f30e500a4893bf741d38305c10952d5e39fa05bdb057d", + "size": "33739424" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.7.0/zig-macos-x86_64-0.7.0.tar.xz", + "shasum": "94063f9a311cbbf7a2e0a12295e09437182cf950f18cb0eb30ea9893f3677f24", + "size": "35258328" + }, + "i386-windows": { + "tarball": "https://ziglang.org/download/0.7.0/zig-windows-i386-0.7.0.zip", + "shasum": "b1e520aacbfbd645ff3521b3eb4d44166d9a0288b8725e4b001f8b50a425eb2e", + "size": "53390517" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.7.0/zig-windows-x86_64-0.7.0.zip", + "shasum": "965f56c0a36f9cda2125e3a348bc654f7f155e2804c3667d231775ec228f8553", + "size": "53943784" + } + }, + "0.6.0": { + "date": "2020-04-13", + "docs": "https://ziglang.org/documentation/0.6.0/", + "stdDocs": "https://ziglang.org/documentation/0.6.0/std/", + "notes": "https://ziglang.org/download/0.6.0/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.6.0/zig-0.6.0.tar.xz", + "shasum": "5d167dc19354282dd35dd17b38e99e1763713b9be8a4ba9e9e69284e059e7204", + "size": "10349552" + }, + "bootstrap": { + "tarball": "https://ziglang.org/download/0.6.0/zig-bootstrap-0.6.0.tar.xz", + "shasum": "5e0e4dc878b3dd0c1852a442b174f0732e8c07869a8fcd226b71a93b89b381ab", + "size": "38469948" + }, + "x86_64-freebsd": { + "tarball": "https://ziglang.org/download/0.6.0/zig-freebsd-x86_64-0.6.0.tar.xz", + "shasum": "190ff79c1eb56805a315d7c7a51082e32f62926250c0702b36760c225e1634a3", + "size": "36974604" + }, + "aarch64-linux": { + "tarball": "https://ziglang.org/download/0.6.0/zig-linux-aarch64-0.6.0.tar.xz", + "shasum": "e7520efd42cfa02be48c2e430d08fe1f3cbb999d21d9f0d3ffd0febb976b2f41", + "size": "37090044" + }, + "armv6kz-linux": { + "tarball": "https://ziglang.org/download/0.6.0/zig-linux-armv6kz-0.6.0.tar.xz", + "shasum": "36b6493b3fed43eb1f0000e765798ad31a6bb7d7fd3f553ac1c3761dbc919b82", + "size": "39133452" + }, + "armv7a-linux": { + "tarball": "https://ziglang.org/download/0.6.0/zig-linux-armv7a-0.6.0.tar.xz", + "shasum": "946969abe357def95ca9cbbfcebfcf2d90cf967bcd3f48ee87662e32d91d8f35", + "size": "39143748" + }, + "i386-linux": { + "tarball": "https://ziglang.org/download/0.6.0/zig-linux-i386-0.6.0.tar.xz", + "shasum": "a97a2f9ae21575743cdd763c1917d49400d83fc562ef64582b18bade43eb24ce", + "size": "44877640" + }, + "riscv64-linux": { + "tarball": "https://ziglang.org/download/0.6.0/zig-linux-riscv64-0.6.0.tar.xz", + "shasum": "68ddee43f7503c8ae5f26a921f3602c34719a02ed2241f528c0b8b888cc14b38", + "size": "41993144" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.6.0/zig-linux-x86_64-0.6.0.tar.xz", + "shasum": "08fd3c757963630645441c2772362e9c2294020c44f14fce1b89f45de0dc1253", + "size": "44766320" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.6.0/zig-macos-x86_64-0.6.0.tar.xz", + "shasum": "17270360e87ddc49f737e760047b2fac49f1570a824a306119b1194ac4093895", + "size": "42573184" + }, + "i386-windows": { + "tarball": "https://ziglang.org/download/0.6.0/zig-windows-i386-0.6.0.zip", + "shasum": "3b0a02618743e92175990dc6d1a787bb95ff62c4cda016f1c14c7786f575f8ca", + "size": "60446431" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.6.0/zig-windows-x86_64-0.6.0.zip", + "shasum": "c3b897832523e1026e10b2d8d55d7f895185c0a27a63681f3a23219c3f1c38f4", + "size": "49065511" + } + }, + "0.5.0": { + "date": "2019-09-30", + "docs": "https://ziglang.org/documentation/0.5.0/", + "notes": "https://ziglang.org/download/0.5.0/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.5.0/zig-0.5.0.tar.xz", + "shasum": "55ae16960f152bcb9cf98b4f8570902d0e559a141abf927f0d3555b7cc838a31", + "size": "10956132" + }, + "x86_64-freebsd": { + "tarball": "https://ziglang.org/download/0.5.0/zig-freebsd-x86_64-0.5.0.tar.xz", + "shasum": "9e1f4d36c3d584c0aa01f20eb4cd0a0eef3eee5af23e483b8414de55feab6ab6", + "size": "33650744" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.5.0/zig-macos-x86_64-0.5.0.tar.xz", + "shasum": "28702cc05745c7c0bd450487d5f4091bf0a1ad279b35eb9a640ce3e3a15b300d", + "size": "37898664" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.5.0/zig-windows-x86_64-0.5.0.zip", + "shasum": "58141323db8d84a5af62746be5f9140bc161ee760ef33dc91a887bf9ac021976", + "size": "44871804" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.5.0/zig-linux-x86_64-0.5.0.tar.xz", + "shasum": "43e8f8a8b8556edd373ddf9c1ef3ca6cf852d4d09fe07d5736d12fefedd2b4f7", + "size": "40895068" + } + }, + "0.4.0": { + "date": "2019-04-08", + "docs": "https://ziglang.org/documentation/0.4.0/", + "notes": "https://ziglang.org/download/0.4.0/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.4.0/zig-0.4.0.tar.xz", + "shasum": "fec1f3f6b359a3d942e0a7f9157b3b30cde83927627a0e1ea95c54de3c526cfc", + "size": "5348776" + }, + "x86_64-freebsd": { + "tarball": "https://ziglang.org/download/0.4.0/zig-freebsd-x86_64-0.4.0.tar.xz", + "shasum": "3d557c91ac36d8262eb1733bb5f261c95944f9b635e43386e3d00a3272818c30", + "size": "27269672" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.4.0/zig-macos-x86_64-0.4.0.tar.xz", + "shasum": "67c932982484d017c5111e54af9f33f15e8e05c6bc5346a55e04052159c964a8", + "size": "30841504" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.4.0/zig-windows-x86_64-0.4.0.zip", + "shasum": "fbc3dd205e064c263063f69f600bedb18e3d0aa2efa747a63ef6cafb6d73f127", + "size": "35800101" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.4.0/zig-linux-x86_64-0.4.0.tar.xz", + "shasum": "fb1954e2fb556a01f8079a08130e88f70084e08978ff853bb2b1986d8c39d84e", + "size": "32876100" + } + }, + "0.3.0": { + "date": "2018-09-28", + "docs": "https://ziglang.org/documentation/0.3.0/", + "notes": "https://ziglang.org/download/0.3.0/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.3.0/zig-0.3.0.tar.xz", + "shasum": "d70af604f3a8622f3393d93abb3e056bf60351e32d121e6fa4fe03d8d41e1f5a", + "size": "2335592" + }, + "x86_64-macos": { + "tarball": "https://ziglang.org/download/0.3.0/zig-macos-x86_64-0.3.0.tar.xz", + "shasum": "19dec1f1943ab7be26823376d466f7e456143deb34e17502778a949034dc2e7e", + "size": "23712696" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.3.0/zig-windows-x86_64-0.3.0.zip", + "shasum": "bb568c03950958f8bb3472139c3ab5ed74547c8c694ab50f404c202faf51baf4", + "size": "22524425" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.3.0/zig-linux-x86_64-0.3.0.tar.xz", + "shasum": "b378d0aae30cb54f28494e7bc4efbc9bfb6326f47bfb302e8b5287af777b2f3c", + "size": "25209304" + } + }, + "0.2.0": { + "date": "2018-03-15", + "docs": "https://ziglang.org/documentation/0.2.0/", + "notes": "https://ziglang.org/download/0.2.0/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.2.0/zig-0.2.0.tar.xz", + "shasum": "29c9beb172737f4d5019b88ceae829ae8bc6512fb4386cfbf895ae2b42aa6965", + "size": "1940832" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.2.0/zig-win64-0.2.0.zip", + "shasum": "4f8a2979941a1f081ec8e545cca0b72608c0db1c5a3fd377a94db40649dcd3d4", + "size": "21076274" + }, + "x86_64-linux": { + "tarball": "https://ziglang.org/download/0.2.0/zig-linux-x86_64-0.2.0.tar.xz", + "shasum": "209c6fb745d42474c0a73d6f291c7ae3a38b6a1b6b641eea285a7f840cc1a890", + "size": "22551928" + } + }, + "0.1.1": { + "date": "2017-10-17", + "docs": "https://ziglang.org/documentation/0.1.1/", + "notes": "https://ziglang.org/download/0.1.1/release-notes.html", + "src": { + "tarball": "https://ziglang.org/download/0.1.1/zig-0.1.1.tar.xz", + "shasum": "ffca0cfb263485287e19cc997b08701fcd5f24b700345bcdc3dd8074f5a104e0", + "size": "1659716" + }, + "x86_64-windows": { + "tarball": "https://ziglang.org/download/0.1.1/zig-win64-0.1.1.zip", + "shasum": "6fc88bef531af7e567fe30bf60da1487b86833cbee84c7a2f3e317030aa5b660", + "size": "19757776" + } + } +} diff --git a/bazel/zig_proto_library.bzl b/bazel/zig_proto_library.bzl new file mode 100644 index 0000000..99c0831 --- /dev/null +++ b/bazel/zig_proto_library.bzl @@ -0,0 +1,109 @@ +"""Starlark implementation of zig_proto_library""" + +load("@rules_proto//proto:defs.bzl", "proto_common") +load( + "@rules_zig//zig/private/providers:zig_module_info.bzl", + "ZigModuleInfo", + "zig_module_info", +) + +def _zig_proto_library_impl(ctx): + if len(ctx.attr.deps) != 1: + fail("zig_proto_library '{}' requires exactly one 'deps'".format(ctx.label.name)) + + (dep,) = ctx.attr.deps + + # the aspect already generated for us the Zig module + # we just change the import name to make it match what the user chose. + module = dep[ZigModuleInfo] + import_name = ctx.attr.import_name or ctx.label.name + + if import_name: + keys = ["canonical_name", "cdeps", "copts", "deps", "extra_srcs", "linkopts", "main", "srcs"] + args = {k: getattr(module, k) for k in keys} + args["name"] = import_name + module = zig_module_info(**args) + return [module] + +def zig_proto_library_aspect_impl(target, ctx): + """ + For each `.proto` in the given target dependencies, + generate a `.pb.zig` file, and a `zig_module` to import it. + """ + toolchain = ctx.attr._zig_proto_toolchain[proto_common.ProtoLangToolchainInfo] + proto_info = target[ProtoInfo] + + # assert len(proto_info.direct_sources) == 1, "Can only compile .proto files one by one" + (proto_src,) = proto_info.direct_sources + pb_zig_name = proto_src.basename[:-len(".proto")] + ".pb.zig" + zig_src = ctx.actions.declare_file(pb_zig_name, sibling = proto_src) + + ctx.actions.run + proto_common.compile( + ctx.actions, + proto_info = proto_info, + proto_lang_toolchain_info = toolchain, + generated_files = [zig_src], + ) + + zig_proto_modules = [p[ZigModuleInfo] for p in ctx.rule.attr.deps] + import_name = get_import_name(target, proto_src) + + module = zig_module_info( + name = import_name, + canonical_name = str(target.label), + main = zig_src, + srcs = [], + extra_srcs = [], + copts = [], + linkopts = [], + deps = [toolchain.runtime[ZigModuleInfo]] + zig_proto_modules, + cdeps = [], + ) + return [module] + +def get_import_name(target, proto_src): + """ + When the Zig protoc plugin is generating .pb.zig files, + it generates import names based on the path received from protoc. + We need to create Zig modules with the same name. + """ + name = str(target.label) + + # special handling of builtin types + if "com_google_protobuf//:" in name: + name = "google_protobuf_" + proto_src.basename + else: + name = name.rsplit("//")[-1] + name = name.rsplit("//")[-1] + return name.replace(".", "_").replace(":", "_").replace("/", "_") + +zig_proto_library_aspect = aspect( + attrs = { + "_zig_proto_toolchain": attr.label( + default = "@zig-protobuf//:zig_toolchain", + providers = [proto_common.ProtoLangToolchainInfo], + ), + }, + implementation = zig_proto_library_aspect_impl, + provides = [ZigModuleInfo], + attr_aspects = ["deps"], +) + +zig_proto_library = rule( + doc = """ + Converts a single `proto_library` into a zig module. + """, + implementation = _zig_proto_library_impl, + attrs = { + "deps": attr.label_list( + aspects = [zig_proto_library_aspect], + providers = [ProtoInfo], + ), + "import_name": attr.string( + doc = "The import name of the Zig module.", + default = "", + ), + }, + provides = [ZigModuleInfo], +) diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..e69de29 diff --git a/mlir/BUILD.bazel b/mlir/BUILD.bazel new file mode 100644 index 0000000..93968e8 --- /dev/null +++ b/mlir/BUILD.bazel @@ -0,0 +1,39 @@ +load("@rules_zig//zig:defs.bzl", "zig_library") +load("//bazel:zig.bzl", "zig_cc_test") + +cc_library( + name = "mlirx", + srcs = ["mlirx.cc"], + hdrs = ["mlirx.h"], + includes = ["."], + deps = [ + "@llvm-project//mlir:CAPIIR", + ], +) + +cc_library( + name = "c", + hdrs = ["c.h"], + visibility = ["//mlir:__subpackages__"], + deps = [ + "@llvm-project//mlir:CAPIArith", + "@llvm-project//mlir:CAPIIR", + "@llvm-project//mlir:CAPIMath", + "@llvm-project//mlir:CAPITransforms", + ], +) + +zig_library( + name = "mlir", + main = "mlir.zig", + visibility = ["//visibility:public"], + deps = [ + ":c", + ":mlirx", + ], +) + +zig_cc_test( + name = "test", + deps = [":mlir"], +) diff --git a/mlir/c.h b/mlir/c.h new file mode 100644 index 0000000..014666a --- /dev/null +++ b/mlir/c.h @@ -0,0 +1,8 @@ +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/mlir/dialects/BUILD.bazel b/mlir/dialects/BUILD.bazel new file mode 100644 index 0000000..847e60a --- /dev/null +++ b/mlir/dialects/BUILD.bazel @@ -0,0 +1,41 @@ +load("@rules_zig//zig:defs.bzl", "zig_library") +load("//bazel:zig.bzl", "zig_cc_test") + +zig_library( + name = "dialects", + srcs = [ + "arith.zig", + "func.zig", + "math.zig", + "tensor.zig", + ], + import_name = "mlir/dialects", + main = "dialects.zig", + visibility = ["//visibility:public"], + deps = [ + ":stablehlo", + "//mlir", + ], +) + +zig_cc_test( + name = "test", + deps = [":dialects"], +) + +zig_library( + name = "stablehlo", + import_name = "mlir/dialects/stablehlo", + main = "stablehlo.zig", + visibility = ["//mlir/dialects:__subpackages__"], + deps = [ + "//mlir", + "//mlir:c", + "@stablehlo//:stablehlo_capi", + ], +) + +zig_cc_test( + name = "stablehlo_test", + deps = [":stablehlo"], +) diff --git a/mlir/dialects/arith.zig b/mlir/dialects/arith.zig new file mode 100644 index 0000000..2c9e945 --- /dev/null +++ b/mlir/dialects/arith.zig @@ -0,0 +1,109 @@ +const std = @import("std"); +const mlir = @import("mlir"); + +pub fn constant(ctx: mlir.Context, value: mlir.Attribute, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "arith.constant", .{ + .attributes = &.{ + .{ "value", value }, + }, + .result_type_inference = true, + .location = location, + }); +} + +fn binary_fn(comptime op_name: [:0]const u8) fn (mlir.Context, mlir.Value, mlir.Value, mlir.Location) mlir.Operation { + return struct { + pub fn call(ctx: mlir.Context, lhs: mlir.Value, rhs: mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, op_name, .{ + .operands = &.{ lhs, rhs }, + .result_type_inference = true, + .location = location, + }); + } + }.call; +} + +fn cast_fn(comptime op_name: [:0]const u8) fn (mlir.Context, mlir.Value, mlir.Type, mlir.Location) mlir.Operation { + return struct { + pub fn call(ctx: mlir.Context, value: mlir.Value, new_type: mlir.Type, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, op_name, .{ + .operands = &.{value}, + .results = &.{new_type}, + .location = location, + }); + } + }.call; +} + +pub const addi = binary_fn("arith.addi"); +pub const addf = binary_fn("arith.addf"); +pub const subi = binary_fn("arith.subi"); +pub const subf = binary_fn("arith.subf"); +pub const muli = binary_fn("arith.muli"); +pub const mulf = binary_fn("arith.mulf"); +pub const divsi = binary_fn("arith.divsi"); +pub const divui = binary_fn("arith.divui"); +pub const divf = binary_fn("arith.divf"); +pub const extsi = cast_fn("arith.extsi"); +pub const extui = cast_fn("arith.extui"); +pub const extf = cast_fn("arith.extf"); +pub const trunci = cast_fn("arith.trunci"); +pub const truncf = cast_fn("arith.truncf"); +pub const fptosi = cast_fn("arith.fptosi"); +pub const fptoui = cast_fn("arith.fptoui"); +pub const sitofp = cast_fn("arith.sitofp"); +pub const uitofp = cast_fn("arith.uitofp"); + +pub const CmpIPredicate = enum { + eq, + ne, + slt, + sle, + sgt, + sge, + ult, + ule, + ugt, + uge, +}; + +pub fn cmpi(ctx: mlir.Context, predicate: CmpIPredicate, lhs: mlir.Value, rhs: mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "arith.cmpi", .{ + .operands = &.{ lhs, rhs }, + .result_type_inference = true, + .attributes = &.{ + .{ "predicate", mlir.IntegerAttribute(.i64).init(ctx, @intFromEnum(predicate)).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub const CmpFPredicate = enum { + false, + oeq, + ogt, + oge, + olt, + ole, + one, + ord, + ueq, + ugt, + uge, + ult, + ule, + une, + uno, + true, +}; + +pub fn cmpf(ctx: mlir.Context, predicate: CmpFPredicate, lhs: mlir.Value, rhs: mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "arith.cmpf", .{ + .operands = &.{ lhs, rhs }, + .result_type_inference = true, + .attributes = &.{ + .{ "predicate", mlir.IntegerAttribute(.i64).init(ctx, @intFromEnum(predicate)).as(mlir.Attribute).? }, + }, + .location = location, + }); +} diff --git a/mlir/dialects/dialects.zig b/mlir/dialects/dialects.zig new file mode 100644 index 0000000..1da34b7 --- /dev/null +++ b/mlir/dialects/dialects.zig @@ -0,0 +1,11 @@ +const std = @import("std"); + +pub const arith = @import("arith.zig"); +pub const func = @import("func.zig"); +pub const math = @import("math.zig"); +pub const tensor = @import("tensor.zig"); +pub const stablehlo = @import("mlir/dialects/stablehlo"); + +test { + std.testing.refAllDecls(@This()); +} diff --git a/mlir/dialects/func.zig b/mlir/dialects/func.zig new file mode 100644 index 0000000..4f2feb0 --- /dev/null +++ b/mlir/dialects/func.zig @@ -0,0 +1,45 @@ +const std = @import("std"); +const mlir = @import("mlir"); + +pub fn func( + ctx: mlir.Context, + args: struct { + sym_name: [:0]const u8, + args: []const mlir.Type, + arg_attrs: []const mlir.Attribute = &.{}, + results: []const mlir.Type, + block: mlir.Block, + location: mlir.Location, + }, +) mlir.Operation { + const AttrTuple = struct { [:0]const u8, mlir.Attribute }; + var attrs_tuple_buffer = std.BoundedArray(AttrTuple, 3){}; + attrs_tuple_buffer.appendAssumeCapacity(.{ "sym_name", mlir.StringAttribute.init(ctx, args.sym_name).as(mlir.Attribute).? }); + attrs_tuple_buffer.appendAssumeCapacity(.{ "function_type", mlir.TypeAttribute.init((mlir.FunctionType.init(ctx, args.args, args.results) catch unreachable).as(mlir.Type).?).as(mlir.Attribute).? }); + if (args.arg_attrs.len > 0) { + attrs_tuple_buffer.appendAssumeCapacity(.{ "arg_attrs", mlir.ArrayAttribute.init(ctx, args.arg_attrs).as(mlir.Attribute).? }); + } + return mlir.Operation.make(ctx, "func.func", .{ + .blocks = &.{args.block}, + .attributes = attrs_tuple_buffer.constSlice(), + .location = args.location, + }); +} + +pub fn call(ctx: mlir.Context, name: [:0]const u8, values: []const mlir.Value, results: []const mlir.Type, loc: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "func.call", .{ + .variadic_operands = &.{values}, + .results = results, + .verify = true, + .attributes = &.{.{ "callee", mlir.FlatSymbolRefAttribute.init(ctx, name).as(mlir.Attribute).? }}, + .location = loc, + }); +} + +pub fn return_(ctx: mlir.Context, values: []const mlir.Value, loc: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "func.return", .{ + .operands = values, + .verify = false, + .location = loc, + }); +} diff --git a/mlir/dialects/math.zig b/mlir/dialects/math.zig new file mode 100644 index 0000000..766f40c --- /dev/null +++ b/mlir/dialects/math.zig @@ -0,0 +1,35 @@ +const std = @import("std"); +const mlir = @import("mlir"); + +const namespace = "math"; + +fn unary_fn(comptime op_name: [:0]const u8) type { + return struct { + pub fn call(ctx: mlir.Context, value: mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, namespace ++ "." ++ op_name, .{ + .operands = &.{value}, + .results = &.{}, + .location = location, + }); + } + }; +} + +fn binary_fn(comptime op_name: [:0]const u8) type { + return struct { + pub fn call(ctx: mlir.Context, lhs: mlir.Value, rhs: mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, namespace ++ "." ++ op_name, .{ + .operands = &.{ lhs, rhs }, + .results = &.{}, + .location = location, + }); + } + }; +} + +pub const ipowi = binary_fn("ipowi").call; +pub const fpowi = binary_fn("fpowi").call; +pub const tanh = unary_fn("tanh").call; +pub const sqrt = unary_fn("sqrt").call; +pub const exp = unary_fn("exp").call; +pub const log = unary_fn("log").call; diff --git a/mlir/dialects/stablehlo.zig b/mlir/dialects/stablehlo.zig new file mode 100644 index 0000000..03a8011 --- /dev/null +++ b/mlir/dialects/stablehlo.zig @@ -0,0 +1,1330 @@ +const std = @import("std"); + +const c = @import("c"); +const mlir = @import("mlir"); + +pub const abs = functors.unary_fn("stablehlo.abs").call; +pub const cosine = functors.unary_fn("stablehlo.cosine").call; +pub const sine = functors.unary_fn("stablehlo.sine").call; +pub const exponential = functors.unary_fn("stablehlo.exponential").call; +pub const exponential_minus_one = functors.unary_fn("stablehlo.exponential_minus_one").call; +pub const floor = functors.unary_fn("stablehlo.floor").call; +pub const log = functors.unary_fn("stablehlo.log").call; +pub const log_plus_one = functors.unary_fn("stablehlo.log_plus_one").call; +pub const not = functors.unary_fn("stablehlo.not").call; +pub const negate = functors.unary_fn("stablehlo.negate").call; +pub const sqrt = functors.unary_fn("stablehlo.sqrt").call; +pub const tanh = functors.unary_fn("stablehlo.tanh").call; +pub const cbrt = functors.unary_fn("stablehlo.cbrt").call; +pub const ceil = functors.unary_fn("stablehlo.ceil").call; +pub const rsqrt = functors.unary_fn("stablehlo.rsqrt").call; +pub const count_leading_zeros = functors.unary_fn("stablehlo.count_leading_zeros").call; +pub const is_finite = functors.unary_fn("stablehlo.is_finite").call; +pub const logistic = functors.unary_fn("stablehlo.logistic").call; +pub const popcnt = functors.unary_fn("stablehlo.popcnt").call; +pub const sign = functors.unary_fn("stablehlo.sign").call; +pub const real = functors.unary_fn("stablehlo.real").call; +pub const imag = functors.unary_fn("stablehlo.imag").call; + +pub const add = functors.binary_fn("stablehlo.add").call; +pub const multiply = functors.binary_fn("stablehlo.multiply").call; +pub const divide = functors.binary_fn("stablehlo.divide").call; +pub const subtract = functors.binary_fn("stablehlo.subtract").call; +pub const or_ = functors.binary_fn("stablehlo.or").call; +pub const xor = functors.binary_fn("stablehlo.xor").call; +pub const and_ = functors.binary_fn("stablehlo.and").call; +pub const atan2 = functors.binary_fn("stablehlo.atan2").call; +pub const maximum = functors.binary_fn("stablehlo.maximum").call; +pub const minimum = functors.binary_fn("stablehlo.minimum").call; +pub const power = functors.binary_fn("stablehlo.power").call; +pub const remainder = functors.binary_fn("stablehlo.remainder").call; +pub const shift_left = functors.binary_fn("stablehlo.shift_left").call; +pub const shift_right_arithmetic = functors.binary_fn("stablehlo.shift_right_arithmetic").call; +pub const shift_right_logical = functors.binary_fn("stablehlo.shift_right_logical").call; +pub const complex = functors.binary_fn("stablehlo.complex").call; + +const functors = struct { + fn unary_fn(comptime op_name: [:0]const u8) type { + return struct { + pub fn call(ctx: mlir.Context, value: mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, op_name, .{ + .operands = &.{value}, + .result_type_inference = true, + .location = location, + }); + } + }; + } + + pub fn binary_fn(comptime op_name: [:0]const u8) type { + return struct { + pub fn call(ctx: mlir.Context, lhs: mlir.Value, rhs: mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, op_name, .{ + .operands = &.{ lhs, rhs }, + .result_type_inference = true, + .location = location, + }); + } + }; + } +}; + +pub fn return_(ctx: mlir.Context, value: mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.return", .{ + .variadic_operands = &.{&.{value}}, + .verify = false, + .location = location, + }); +} + +pub fn returns_(ctx: mlir.Context, values: []const mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.return", .{ + .variadic_operands = &.{values}, + .verify = false, + .location = location, + }); +} + +pub fn bitcast_convert(ctx: mlir.Context, value: mlir.Value, result_type: mlir.Type, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.bitcast_convert", .{ + .operands = &.{value}, + .results = &.{result_type}, + .location = location, + }); +} + +pub fn cholesky(ctx: mlir.Context, value: mlir.Value, lower: bool, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.cholesky", .{ + .operands = &.{value}, + .result_type_inference = true, + .attributes = &.{ + .{ "lower", mlir.IntegerAttribute(.i1).init(ctx, @intCast(@intFromBool(lower))).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn clamp(ctx: mlir.Context, min: mlir.Value, value: mlir.Value, max: mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.clamp", .{ + .operands = &.{ min, value, max }, + .result_type_inference = true, + .location = location, + }); +} + +/// General matrix multiplication "a la Einstein sum" +/// Note: stablehlo doesn't do type inference for dot_general +pub fn dot_general(ctx: mlir.Context, lhs: mlir.Value, rhs: mlir.Value, result_type: mlir.Type, location: mlir.Location, opts: struct { + lhs_batching_dimensions: []const i64, + rhs_batching_dimensions: []const i64, + lhs_contracting_dimensions: []const i64, + rhs_contracting_dimensions: []const i64, + precision: []const PrecisionAttribute.Precision, +}) mlir.Operation { + var maxPrecisions: [10]mlir.Attribute = undefined; + for (opts.precision, 0..) |p, i| { + maxPrecisions[i] = PrecisionAttribute.init(ctx, p).as(mlir.Attribute).?; + } + + return mlir.Operation.make(ctx, "stablehlo.dot_general", .{ + .operands = &.{ lhs, rhs }, + .results = &.{result_type}, + .attributes = &.{ + .{ + "dot_dimension_numbers", DotDimensionNumbersAttribute.init(ctx, .{ + .lhs_batching_dimensions = opts.lhs_batching_dimensions, + .rhs_batching_dimensions = opts.rhs_batching_dimensions, + .lhs_contracting_dimensions = opts.lhs_contracting_dimensions, + .rhs_contracting_dimensions = opts.rhs_contracting_dimensions, + }).as(mlir.Attribute).?, + }, + .{ "precision_config", mlir.ArrayAttribute.init(ctx, maxPrecisions[0..opts.precision.len]).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn constant( + ctx: mlir.Context, + result_type: mlir.RankedTensorType, + elem_type: mlir.DenseElementsAttributeTypes, + raw_bytes: []const u8, + location: mlir.Location, +) mlir.Operation { + const attribute = switch (elem_type) { + inline else => |dt| mlir.DenseIntOrFPElementsAttribute(dt).init(result_type.as(mlir.Type).?, raw_bytes).as(mlir.Attribute).?, + }; + + return mlir.Operation.make(ctx, "stablehlo.constant", .{ + .operands = &.{}, + .results = &.{result_type.as(mlir.Type).?}, + .attributes = &.{.{ "value", attribute }}, + .location = location, + }); +} + +pub fn convert(ctx: mlir.Context, value: mlir.Value, result_type: mlir.Type, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.convert", .{ + .operands = &.{value}, + .results = &.{result_type}, + .location = location, + }); +} + +pub fn broadcast_in_dim(ctx: mlir.Context, operand: mlir.Value, dims: []const i64, result_type: mlir.Type, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.broadcast_in_dim", .{ + .operands = &.{operand}, + .results = &.{result_type}, + .attributes = &.{ + .{ "broadcast_dimensions", mlir.DenseArrayAttribute(.i64).init(ctx, dims).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn transpose(ctx: mlir.Context, value: mlir.Value, result_type: mlir.Type, location: mlir.Location, opts: struct { permutation: []const i64 }) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.transpose", .{ + .operands = &.{value}, + .results = &.{result_type}, + .attributes = &.{ + .{ "permutation", mlir.DenseArrayAttribute(.i64).init(ctx, opts.permutation).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn slice(ctx: mlir.Context, operand: mlir.Value, start_indices: []const i64, limit_indices: []const i64, strides: []const i64, result_type: mlir.Type, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.slice", .{ + .operands = &.{operand}, + .results = &.{result_type}, + .attributes = &.{ + .{ "start_indices", mlir.DenseArrayAttribute(.i64).init(ctx, start_indices).as(mlir.Attribute).? }, + .{ "limit_indices", mlir.DenseArrayAttribute(.i64).init(ctx, limit_indices).as(mlir.Attribute).? }, + .{ "strides", mlir.DenseArrayAttribute(.i64).init(ctx, strides).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn concatenate(ctx: mlir.Context, inputs: []const mlir.Value, dimension: i64, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.concatenate", .{ + .operands = inputs, + .result_type_inference = true, + .attributes = &.{ + .{ "dimension", mlir.IntegerAttribute(.i64).init(ctx, dimension).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn reshape(ctx: mlir.Context, value: mlir.Value, result_type: mlir.RankedTensorType, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.reshape", .{ + .operands = &.{value}, + .results = &.{result_type.as(mlir.Type).?}, + .location = location, + }); +} + +pub fn select(ctx: mlir.Context, condition: mlir.Value, then: mlir.Value, else_: mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.select", .{ + .operands = &.{ condition, then, else_ }, + .results = &.{then.getType()}, + .location = location, + }); +} + +pub fn gather( + ctx: mlir.Context, + value: mlir.Value, + indices: mlir.Value, + slice_sizes: []const i64, + location: mlir.Location, + args: struct { + offset_dims: []const i64, + collapsed_slice_dims: []const i64, + operand_batching_dims: []const i64, + start_indices_batching_dims: []const i64, + start_index_map: []const i64, + index_vector_dim: i64, + indices_are_sorted: bool = false, + }, +) mlir.Operation { + return mlir.Operation.make( + ctx, + "stablehlo.gather", + .{ + .operands = &.{ value, indices }, + .result_type_inference = true, + .attributes = &.{ + .{ "dimension_numbers", GatherDimensionNumbersAttribute.init( + ctx, + args.offset_dims, + args.collapsed_slice_dims, + args.operand_batching_dims, + args.start_indices_batching_dims, + args.start_index_map, + args.index_vector_dim, + ).as(mlir.Attribute).? }, + .{ "slice_sizes", mlir.DenseArrayAttribute(.i64).init(ctx, slice_sizes).as(mlir.Attribute).? }, + .{ "indices_are_sorted", mlir.BoolAttribute.init(ctx, args.indices_are_sorted).as(mlir.Attribute).? }, + }, + .location = location, + }, + ); +} + +pub const ScatterArgs = struct { + update_window_dims: []const i64, + inserted_window_dims: []const i64, + scatter_dims_to_operand_dims: []const i64, + index_vector_dim: i64, + indices_are_sorted: bool = false, + unique_indices: bool = false, +}; + +fn elementTypeOrSelf(typ: mlir.Type) mlir.Type { + return if (typ.as(mlir.ShapedType)) |shaped| { + return shaped.elementType(); + } else typ; +} + +pub fn scatter( + ctx: mlir.Context, + // inputs + inputs: []const mlir.Value, + scatter_indices: mlir.Value, + updates: []const mlir.Value, + // input functions + update_ctx: anytype, // for update_fn + update_fn: fn (anytype, mlir.Context, []const mlir.Value, []const mlir.Value) mlir.Operation, + // attributes + args: struct { + update_window_dims: []const i64, + inserted_window_dims: []const i64, + input_batching_dims: []const i64, + scatter_indices_batching_dims: []const i64, + scatter_dims_to_operand_dims: []const i64, + index_vector_dim: i64, + indices_are_sorted: bool = false, + unique_indices: bool = false, + }, + // zml loc + location: mlir.Location, +) mlir.Operation { + // create block for update_fn + const MaxBlockArguments = 32; // TODO(rene): where does this 32 come from? + // taken from reduce + + const block_n_args = inputs.len * 2; // TODO(rene): is this correct? yes, passes tests: block_inputs plus block_accumulators = inputs + const locations = ([_]mlir.Location{mlir.Location.unknown(ctx)} ** MaxBlockArguments)[0..block_n_args]; + var scatter_elem_types: [MaxBlockArguments]mlir.Type = undefined; + for (inputs, 0..) |input, i| { + const arg_type = mlir.RankedTensorType.init(&.{}, elementTypeOrSelf(input.getType())).as(mlir.Type).?; + scatter_elem_types[i] = arg_type; + scatter_elem_types[inputs.len + i] = arg_type; + } + + var block = mlir.Block.open(scatter_elem_types[0..block_n_args], locations) catch unreachable; + { + defer block.close(); + var block_inputs: [MaxBlockArguments / 2]mlir.Value = undefined; + var block_accs: [MaxBlockArguments / 2]mlir.Value = undefined; + for (0..inputs.len) |i| { + block_inputs[i] = block.argument(i); + block_accs[i] = block.argument(inputs.len + i); + } + _ = update_fn(update_ctx, ctx, block_inputs[0..inputs.len], block_accs[0..inputs.len]); + } + return mlir.Operation.make( + ctx, + "stablehlo.scatter", + .{ + .variadic_operands = &.{ inputs, &.{scatter_indices}, updates }, + // .blocks = &.{block}, + .block = block, + .attributes = &.{ + .{ "scatter_dimension_numbers", ScatterDimensionNumbersAttribute.init( + ctx, + args.update_window_dims, + args.inserted_window_dims, + args.input_batching_dims, + args.scatter_indices_batching_dims, + args.scatter_dims_to_operand_dims, + args.index_vector_dim, + ).as(mlir.Attribute).? }, + .{ "indices_are_sorted", mlir.BoolAttribute.init(ctx, args.indices_are_sorted).as(mlir.Attribute).? }, + .{ "unique_indices", mlir.BoolAttribute.init(ctx, args.unique_indices).as(mlir.Attribute).? }, + }, + .result_type_inference = true, + .location = location, + }, + ); +} + +pub fn iota(ctx: mlir.Context, dimension: i64, result_type: mlir.Type, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.iota", .{ + .operands = &.{}, + .results = &.{result_type}, + .attributes = &.{ + .{ "iota_dimension", mlir.IntegerAttribute(.i64).init(ctx, dimension).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn reverse(ctx: mlir.Context, operand: mlir.Value, dimensions: []const i64, location: mlir.Location) mlir.Operation { + const result_type = operand.getType(); + return mlir.Operation.make(ctx, "stablehlo.reverse", .{ + .operands = &.{operand}, + .results = &.{result_type}, + .attributes = &.{ + .{ "dimensions", mlir.DenseArrayAttribute(.i64).init(ctx, dimensions).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn reverseMany(ctx: mlir.Context, operand: mlir.Value, dimensions: []const i64, location: mlir.Location) mlir.Operation { + const result_type = operand.getType(); + return mlir.Operation.make(ctx, "stablehlo.reverse", .{ + .operands = &.{operand}, + .results = &.{result_type}, + .attributes = &.{ + .{ "dimensions", mlir.DenseArrayAttribute(.i64).init(ctx, dimensions).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn compare(ctx: mlir.Context, lhs: mlir.Value, rhs: mlir.Value, comparison_direction: ComparisonDirection, compare_type: CompareType, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.compare", .{ + .operands = &.{ lhs, rhs }, + .result_type_inference = true, + .attributes = &.{ + .{ "comparison_direction", comparison_direction.as(mlir.Attribute).? }, + .{ "compare_type", compare_type.as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn reduce( + ctx: mlir.Context, + inputs: []const mlir.Value, + init_values: []const mlir.Value, + dimensions: []const i64, + blkctx: anytype, + blkfn: fn (anytype, mlir.Context, []const mlir.Value, []const mlir.Value) mlir.Operation, + location: mlir.Location, +) mlir.Operation { + const MaxBlockArguments = 32; + + const block_n_args = inputs.len + init_values.len; + const locations = ([_]mlir.Location{mlir.Location.unknown(ctx)} ** MaxBlockArguments)[0..block_n_args]; + var reduce_elem_types: [MaxBlockArguments]mlir.Type = undefined; + for (inputs, 0..) |input, i| { + const arg_type = mlir.RankedTensorType.init(&.{}, elementTypeOrSelf(input.getType())).as(mlir.Type).?; + reduce_elem_types[i] = arg_type; + reduce_elem_types[inputs.len + i] = arg_type; + } + var block = mlir.Block.open(reduce_elem_types[0..block_n_args], locations) catch unreachable; + { + defer block.close(); + + var block_inputs: [MaxBlockArguments / 2]mlir.Value = undefined; + var block_accs: [MaxBlockArguments / 2]mlir.Value = undefined; + for (0..inputs.len) |i| { + block_inputs[i] = block.argument(i); + block_accs[i] = block.argument(inputs.len + i); + } + _ = blkfn(blkctx, ctx, block_inputs[0..inputs.len], block_accs[0..init_values.len]); + } + + return mlir.Operation.make(ctx, "stablehlo.reduce", .{ + .variadic_operands = &.{ inputs, init_values }, + .result_type_inference = true, + .block = block, + .attributes = &.{ + .{ "dimensions", mlir.DenseArrayAttribute(.i64).init(ctx, dimensions).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub const ReduceWindowOpts = struct { + window_dimensions: []const i64, + window_strides: []const i64, + base_dilations: []const i64, + window_dilations: []const i64, + padding_values: []const i64, + padding_shape: []const i64, +}; + +// pub fn reduce_window( +// ctx: mlir.Context, +// inputs: []const mlir.Value, +// init_values: []const mlir.Value, +// opts: ReduceWindowOpts, +// blkctx: anytype, +// blkfn: fn (anytype, mlir.Context, []const mlir.Value, []const mlir.Value) mlir.Operation, +// location: mlir.Location, +// ) mlir.Operation { +// // TODO: move to ops.zig, and refactor similar to `reduce` +// const MaxBlockArguments = 32; + +// const block_n_args = inputs.len + init_values.len; +// const locations = ([_]mlir.Location{mlir.Location.unknown(ctx)} ** MaxBlockArguments)[0..block_n_args]; +// var reduce_elem_types: [MaxBlockArguments]mlir.Type = undefined; +// for (inputs, 0..) |input, i| { +// const arg_type = mlir.RankedTensorType.init(&.{}, elementTypeOrSelf(input.getType())).as(mlir.Type).?; +// reduce_elem_types[i] = arg_type; +// reduce_elem_types[inputs.len + i] = arg_type; +// } +// const module = @import("../module.zig"); +// const comp = module.getCompilationContext(); +// var block = comp.openBlock(reduce_elem_types[0..block_n_args], locations) catch unreachable; +// { +// defer comp.closeBlock(block); + +// var block_inputs: [MaxBlockArguments / 2]mlir.Value = undefined; +// var block_accs: [MaxBlockArguments / 2]mlir.Value = undefined; +// for (0..inputs.len) |i| { +// block_inputs[i] = block.argument(i); +// block_accs[i] = block.argument(inputs.len + i); +// } +// _ = blkfn(blkctx, ctx, block_inputs[0..inputs.len], block_accs[0..init_values.len]); +// } + +// const pad_shape = mlir.RankedTensorType.init(opts.padding_shape, DataType.i64.mlirType(ctx)).as(mlir.Type).?; +// return mlir.Operation.make(ctx, "stablehlo.reduce_window", .{ +// .variadic_operands = &.{ inputs, init_values }, +// .result_type_inference = true, +// .blocks = &.{block}, +// .attributes = &.{ +// .{ "window_dimensions", mlir.DenseArrayAttribute(.i64).init(ctx, opts.window_dimensions).as(mlir.Attribute).? }, +// .{ "window_strides", mlir.DenseArrayAttribute(.i64).init(ctx, opts.window_strides).as(mlir.Attribute).? }, +// .{ "base_dilations", mlir.DenseArrayAttribute(.i64).init(ctx, opts.base_dilations).as(mlir.Attribute).? }, +// .{ "window_dilations", mlir.DenseArrayAttribute(.i64).init(ctx, opts.window_dilations).as(mlir.Attribute).? }, +// .{ "padding", mlir.DenseIntOrFPElementsAttribute(.i64).init(pad_shape, std.mem.sliceAsBytes(opts.padding_values)).as(mlir.Attribute).? }, +// }, +// .location = location, +// }); +// } + +pub fn sort( + ctx: mlir.Context, + inputs: []const mlir.Value, + dimension: i64, + is_stable: bool, + blkctx: anytype, + compfn: fn (anytype, mlir.Context, []const mlir.Value) mlir.Operation, + location: mlir.Location, +) mlir.Operation { + const MaxBlockArguments = 32; + + const locations = ([_]mlir.Location{mlir.Location.unknown(ctx)} ** MaxBlockArguments)[0 .. inputs.len * 2]; + var sort_elem_types: [MaxBlockArguments]mlir.Type = undefined; + for (inputs, 0..) |input, i| { + const arg_type = mlir.RankedTensorType.init(&.{}, elementTypeOrSelf(input.getType())).as(mlir.Type).?; + sort_elem_types[i * 2] = arg_type; + sort_elem_types[i * 2 + 1] = arg_type; + } + var block = mlir.Block.init(sort_elem_types[0 .. inputs.len * 2], locations) catch unreachable; + + var block_inputs: [MaxBlockArguments]mlir.Value = undefined; + for (0..inputs.len * 2) |i| { + block_inputs[i] = block.argument(i); + } + _ = compfn(blkctx, ctx, block_inputs[0 .. inputs.len * 2]); + + return mlir.Operation.make(ctx, "stablehlo.sort", .{ + .variadic_operands = &.{inputs}, + .result_type_inference = true, + .block = block, + .attributes = &.{ + .{ "dimension", mlir.IntegerAttribute(.i64).init(ctx, dimension).as(mlir.Attribute).? }, + .{ "is_stable", mlir.BoolAttribute.init(ctx, is_stable).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn dynamicSlice(ctx: mlir.Context, operand: mlir.Value, new_dims: []const i64, start_indices: []const mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.dynamic_slice", .{ + .variadic_operands = &.{ &.{operand}, start_indices }, + .result_type_inference = true, + .attributes = &.{ + .{ "slice_sizes", mlir.DenseArrayAttribute(.i64).init(ctx, new_dims).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn round_nearest_afz(ctx: mlir.Context, value: mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.round_nearest_afz", .{ + .operands = &.{value}, + .result_type_inference = true, + .location = location, + }); +} + +pub fn round_nearest_even(ctx: mlir.Context, value: mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.round_nearest_even", .{ + .operands = &.{value}, + .result_type_inference = true, + .location = location, + }); +} + +pub const PadOpts = struct { + low: []const i64, + high: []const i64, + interior: ?[]const i64, +}; + +pub fn pad(ctx: mlir.Context, value: mlir.Value, padding_value: mlir.Value, opts: PadOpts, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.pad", .{ + .operands = &.{ value, padding_value }, + .result_type_inference = true, + .attributes = &.{ + .{ "edge_padding_low", mlir.DenseArrayAttribute(.i64).init(ctx, opts.low).as(mlir.Attribute).? }, + .{ "edge_padding_high", mlir.DenseArrayAttribute(.i64).init(ctx, opts.high).as(mlir.Attribute).? }, + .{ "interior_padding", mlir.DenseArrayAttribute(.i64).init(ctx, opts.interior.?).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub const TriangularSolveOpts = struct { + left_side: bool, + lower: bool, + unit_diagonal: bool, + transpose_a: Transpose.Type, +}; + +pub fn triangular_solve(ctx: mlir.Context, value: mlir.Value, other: mlir.Value, location: mlir.Location, opts: TriangularSolveOpts) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.triangular_solve", .{ + .operands = &.{ value, other }, + .result_type_inference = true, + .attributes = &.{ + .{ "left_side", mlir.IntegerAttribute(.i1).init(ctx, @intCast(@intFromBool(opts.left_side))).as(mlir.Attribute).? }, + .{ "lower", mlir.IntegerAttribute(.i1).init(ctx, @intCast(@intFromBool(opts.lower))).as(mlir.Attribute).? }, + .{ "unit_diagonal", mlir.IntegerAttribute(.i1).init(ctx, @intCast(@intFromBool(opts.unit_diagonal))).as(mlir.Attribute).? }, + .{ "transpose_a", Transpose.init(ctx, opts.transpose_a).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub const FftOpts = struct { + kind: FftType.Type, + length: []const i64, +}; + +pub fn fft(ctx: mlir.Context, value: mlir.Value, location: mlir.Location, opts: FftOpts) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.fft", .{ + .operands = &.{value}, + .result_type_inference = true, + .attributes = &.{ + .{ "fft_type", FftType.init(ctx, opts.kind).as(mlir.Attribute).? }, + .{ "fft_length", mlir.DenseArrayAttribute(.i64).init(ctx, opts.length).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn rng(ctx: mlir.Context, a: mlir.Value, b: mlir.Value, shape: mlir.Value, rng_distribution: RngDistribution.Type, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.rng", .{ + .operands = &.{ a, b, shape }, + .result_type_inference = true, + .attributes = &.{ + .{ "rng_distribution", RngDistribution.init(ctx, rng_distribution).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn rng_bit_generator(ctx: mlir.Context, rng_algorithm: RngAlgorithm.Type, initial_state: mlir.Value, res_state_type: mlir.Type, res_type: mlir.Type, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.rng_bit_generator", .{ + .operands = &.{initial_state}, + .results = &.{ res_state_type, res_type }, + .attributes = &.{ + .{ "rng_algorithm", RngAlgorithm.init(ctx, rng_algorithm).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn reduce_precision(ctx: mlir.Context, value: mlir.Value, exponent_bits: i32, mantissa_bits: i32, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.reduce_precision", .{ + .operands = &.{value}, + .result_type_inference = true, + .attributes = &.{ + .{ "exponent_bits", mlir.IntegerAttribute(.i32).init(ctx, exponent_bits).as(mlir.Attribute).? }, + .{ "mantissa_bits", mlir.IntegerAttribute(.i32).init(ctx, mantissa_bits).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub fn dynamic_update_slice(ctx: mlir.Context, operand: mlir.Value, update: mlir.Value, start_indices: []const mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.dynamic_update_slice", .{ + .variadic_operands = &.{ &.{operand}, &.{update}, start_indices }, + .result_type_inference = true, + .location = location, + }); +} + +pub fn tuple(ctx: mlir.Context, values: []const mlir.Value, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.tuple", .{ + .operands = values, + .result_type_inference = true, + .location = location, + }); +} + +pub fn get_tuple_element(ctx: mlir.Context, tuple_value: mlir.Value, index: i64, location: mlir.Location) mlir.Operation { + return mlir.Operation.make(ctx, "stablehlo.get_tuple_element", .{ + .operands = &.{tuple_value}, + .result_type_inference = true, + .attributes = &.{ + .{ "index", mlir.IntegerAttribute(.i32).init(ctx, index).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub const ConvolutionOpts = struct { + window_strides: []const i64, + pad_value: []const i64, + pad_shape: []const i64 = &.{}, + lhs_dilation: []const i64, + rhs_dilation: []const i64, + window_reversal: []const bool, + input_batch_dimension: i64, + input_feature_dimension: i64, + input_spatial_dimensions: []const i64, + kernel_input_feature_dimension: i64, + kernel_output_feature_dimension: i64, + kernel_spatial_dimensions: []const i64, + output_batch_dimension: i64, + output_feature_dimension: i64, + output_spatial_dimensions: []const i64, + feature_group_count: i64, + batch_group_count: i64, + precision_config: []const PrecisionAttribute.Precision = &.{}, +}; + +pub fn convolution( + ctx: mlir.Context, + lhs: mlir.Value, + rhs: mlir.Value, + opts: ConvolutionOpts, + res_type: mlir.Type, + location: mlir.Location, +) mlir.Operation { + var max_precisions: [2]mlir.Attribute = undefined; + for (opts.precision_config, 0..) |p, i| { + max_precisions[i] = PrecisionAttribute.init(ctx, p).as(mlir.Attribute).?; + } + var window_reversal: [3]i32 = undefined; + for (opts.window_reversal, 0..) |w, i| { + window_reversal[i] = @intCast(@intFromBool(w)); + } + const pad_type = mlir.IntegerType(.i64).init(ctx).as(mlir.Type).?; + const pad_shape = mlir.RankedTensorType.init(opts.pad_shape, pad_type).as(mlir.Type).?; + return mlir.Operation.make(ctx, "stablehlo.convolution", .{ + .operands = &.{ lhs, rhs }, + .results = &.{res_type}, + .attributes = &.{ + .{ "window_strides", mlir.DenseArrayAttribute(.i64).init(ctx, opts.window_strides).as(mlir.Attribute).? }, + .{ "padding", mlir.DenseIntOrFPElementsAttribute(.i64).init(pad_shape, std.mem.sliceAsBytes(opts.pad_value)).as(mlir.Attribute).? }, + .{ "lhs_dilation", mlir.DenseArrayAttribute(.i64).init(ctx, opts.lhs_dilation).as(mlir.Attribute).? }, + .{ "rhs_dilation", mlir.DenseArrayAttribute(.i64).init(ctx, opts.rhs_dilation).as(mlir.Attribute).? }, + .{ "window_reversal", mlir.DenseArrayAttribute(.bool).init(ctx, window_reversal[0..opts.window_reversal.len]).as(mlir.Attribute).? }, + .{ + "dimension_numbers", ConvDimensionNumbersAttribute.init(ctx, .{ + .input_batch_dimension = opts.input_batch_dimension, + .input_feature_dimension = opts.input_feature_dimension, + .input_spatial_dimensions = opts.input_spatial_dimensions, + .kernel_input_feature_dimension = opts.kernel_input_feature_dimension, + .kernel_output_feature_dimension = opts.kernel_output_feature_dimension, + .kernel_spatial_dimensions = opts.kernel_spatial_dimensions, + .output_batch_dimension = opts.output_batch_dimension, + .output_feature_dimension = opts.output_feature_dimension, + .output_spatial_dimensions = opts.output_spatial_dimensions, + }).as(mlir.Attribute).?, + }, + .{ "feature_group_count", mlir.IntegerAttribute(.i64).init(ctx, opts.feature_group_count).as(mlir.Attribute).? }, + .{ "batch_group_count", mlir.IntegerAttribute(.i64).init(ctx, opts.batch_group_count).as(mlir.Attribute).? }, + .{ "precision_config", mlir.ArrayAttribute.init(ctx, &max_precisions).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub const CustomCallOpts = struct { + call_target_name: [:0]const u8, + has_side_effect: bool, + backend_config: [:0]const u8 = &.{}, + api_version: i32, + output_operand_aliases: []const i64, +}; + +pub fn custom_call(ctx: mlir.Context, inputs: []const mlir.Value, opts: CustomCallOpts, res_types: []const mlir.Type, location: mlir.Location) mlir.Operation { + var buffer: [1024]u8 = undefined; + var fba = std.heap.FixedBufferAllocator.init(&buffer); + const allocator = fba.allocator(); + + const output_operand_aliases = allocator.alloc(mlir.Attribute, opts.output_operand_aliases.len) catch unreachable; + for (opts.output_operand_aliases, 0..) |alias, i| { + output_operand_aliases[i] = OutputOperandAliasAttribute.init(ctx, &.{}, alias, &.{}).as(mlir.Attribute).?; + } + + return mlir.Operation.make(ctx, "stablehlo.custom_call", .{ + .operands = inputs, + .results = res_types, + .attributes = &.{ + .{ "api_version", mlir.IntegerAttribute(.i32).init(ctx, opts.api_version).as(mlir.Attribute).? }, + .{ "call_target_name", mlir.StringAttribute.init(ctx, opts.call_target_name).as(mlir.Attribute).? }, + .{ "has_side_effect", mlir.BoolAttribute.init(ctx, opts.has_side_effect).as(mlir.Attribute).? }, + .{ "backend_config", mlir.StringAttribute.init(ctx, opts.backend_config).as(mlir.Attribute).? }, + .{ "output_operand_aliases", mlir.ArrayAttribute.init(ctx, output_operand_aliases).as(mlir.Attribute).? }, + }, + .location = location, + }); +} + +pub const DotDimensionNumbersAttribute = struct { + _inner: c.MlirAttribute, + + pub usingnamespace mlir.MlirHelpers(DotDimensionNumbersAttribute, .{ + .is_a_fn = c.stablehloAttributeIsADotDimensionNumbers, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = DotDimensionNumbersAttribute; + + pub fn init(ctx: mlir.Context, args: struct { + lhs_batching_dimensions: []const i64, + rhs_batching_dimensions: []const i64, + lhs_contracting_dimensions: []const i64, + rhs_contracting_dimensions: []const i64, + }) Self { + return Self.wrap( + c.stablehloDotDimensionNumbersGet( + ctx.inner(), + @intCast(args.lhs_batching_dimensions.len), + args.lhs_batching_dimensions.ptr, + @intCast(args.rhs_batching_dimensions.len), + args.rhs_batching_dimensions.ptr, + @intCast(args.lhs_contracting_dimensions.len), + args.lhs_contracting_dimensions.ptr, + @intCast(args.rhs_contracting_dimensions.len), + args.rhs_contracting_dimensions.ptr, + ), + ); + } + + pub fn getLhsBatchingDimensionsSize(self: Self) usize { + return @intCast(c.stablehloDotDimensionNumbersGetLhsBatchingDimensionsSize(self.inner())); + } + + pub fn getLhsBatchingDimensionsElem(self: Self, pos: usize) i64 { + return c.stablehloDotDimensionNumbersGetLhsBatchingDimensionsElem(self.inner(), @intCast(pos)); + } + + pub fn getRhsBatchingDimensionsSize(self: Self) usize { + return @intCast(c.stablehloDotDimensionNumbersGetRhsBatchingDimensionsSize(self.inner())); + } + + pub fn getRhsBatchingDimensionsElem(self: Self, pos: usize) i64 { + return c.stablehloDotDimensionNumbersGetRhsBatchingDimensionsElem(self.inner(), @intCast(pos)); + } + + pub fn getLhsContractingDimensionsSize(self: Self) usize { + return @intCast(c.stablehloDotDimensionNumbersGetLhsContractingDimensionsSize(self.inner())); + } + + pub fn getLhsContractingDimensionsElem(self: Self, pos: usize) i64 { + return c.stablehloDotDimensionNumbersGetLhsContractingDimensionsElem(self.inner(), @intCast(pos)); + } + + pub fn getRhsContractingDimensionsSize(self: Self) usize { + return @intCast(c.stablehloDotDimensionNumbersGetRhsContractingDimensionsSize(self.inner())); + } + + pub fn getRhsContractingDimensionsElem(self: Self, pos: usize) i64 { + return c.stablehloDotDimensionNumbersGetRhsContractingDimensionsElem(self.inner(), @intCast(pos)); + } +}; + +pub const GatherDimensionNumbersAttribute = struct { + _inner: c.MlirAttribute, + + pub usingnamespace mlir.MlirHelpers(GatherDimensionNumbersAttribute, .{ + .is_a_fn = c.stablehloAttributeIsAGatherDimensionNumbers, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = GatherDimensionNumbersAttribute; + + pub fn init( + ctx: mlir.Context, + offset_dims: []const i64, + collapsed_slice_dims: []const i64, + operand_batching_dims: []const i64, + start_indices_batching_dims: []const i64, + start_index_map: []const i64, + index_vector_dim: i64, + ) Self { + return Self.wrap( + c.stablehloGatherDimensionNumbersGet( + ctx.inner(), + @intCast(offset_dims.len), + offset_dims.ptr, + @intCast(collapsed_slice_dims.len), + collapsed_slice_dims.ptr, + @intCast(operand_batching_dims.len), + operand_batching_dims.ptr, + @intCast(start_indices_batching_dims.len), + start_indices_batching_dims.ptr, + @intCast(start_index_map.len), + start_index_map.ptr, + index_vector_dim, + ), + ); + } + + pub fn getOffsetDimsSize(self: Self) usize { + return @intCast(c.stablehloGatherDimensionNumbersGetOffsetDimsSize(self.inner())); + } + + pub fn getOffsetDimsElem(self: Self, pos: usize) i64 { + return c.stablehloGatherDimensionNumbersGetOffsetDimsElem(self.inner(), @intCast(pos)); + } + + pub fn getCollapsedSliceDimsSize(self: Self) usize { + return @intCast(c.stablehloGatherDimensionNumbersGetCollapsedSliceDimsSize(self.inner())); + } + + pub fn getCollapsedSliceDimsElem(self: Self, pos: usize) i64 { + return c.stablehloGatherDimensionNumbersGetCollapsedSliceDimsElem(self.inner(), @intCast(pos)); + } + + pub fn getStartIndexMapSize(self: Self) usize { + return @intCast(c.stablehloGatherDimensionNumbersGetStartIndexMapSize(self.inner())); + } + + pub fn getOperandBatchingDimsSize(self: Self) usize { + return @intCast(c.stablehloGatherDimensionNumbersGetOperandBatchingDimsSize(self.inner())); + } + + pub fn getOperandBatchingDimsElem(self: Self, pos: usize) i64 { + return c.stablehloGatherDimensionNumbersGetOperandBatchingDimsElem(self.inner(), @intCast(pos)); + } + + pub fn getStartIndicesBatchingDimsSize(self: Self) usize { + return @intCast(c.stablehloGatherDimensionNumbersGetStartIndicesBatchingDimsSize(self.inner())); + } + + pub fn getStartIndicesBatchingDimsElem(self: Self, pos: usize) i64 { + return c.stablehloGatherDimensionNumbersGetStartIndicesBatchingDimsElem(self.inner(), @intCast(pos)); + } + + pub fn getStartIndexMapElem(self: Self, pos: usize) i64 { + return c.stablehloGatherDimensionNumbersGetStartIndexMapElem(self.inner(), @intCast(pos)); + } + + pub fn getIndexVectorDim(self: Self) usize { + return @intCast(c.stablehloGatherDimensionNumbersGetIndexVectorDim(self.inner())); + } +}; + +pub const ConvDimensionNumbersAttribute = struct { + _inner: c.MlirAttribute, + + pub usingnamespace mlir.MlirHelpers(ConvDimensionNumbersAttribute, .{ + .is_a_fn = c.stablehloAttributeIsAConvDimensionNumbers, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = ConvDimensionNumbersAttribute; + + pub fn init(ctx: mlir.Context, args: struct { + input_batch_dimension: i64, + input_feature_dimension: i64, + input_spatial_dimensions: []const i64, + kernel_input_feature_dimension: i64, + kernel_output_feature_dimension: i64, + kernel_spatial_dimensions: []const i64, + output_batch_dimension: i64, + output_feature_dimension: i64, + output_spatial_dimensions: []const i64, + }) Self { + return Self.wrap( + c.stablehloConvDimensionNumbersGet( + ctx.inner(), + args.input_batch_dimension, + args.input_feature_dimension, + @intCast(args.input_spatial_dimensions.len), + args.input_spatial_dimensions.ptr, + args.kernel_input_feature_dimension, + args.kernel_output_feature_dimension, + @intCast(args.kernel_spatial_dimensions.len), + args.kernel_spatial_dimensions.ptr, + args.output_batch_dimension, + args.output_feature_dimension, + @intCast(args.output_spatial_dimensions.len), + args.output_spatial_dimensions.ptr, + ), + ); + } + + pub fn getInputBatchDimension(self: Self) i64 { + return c.stablehloConvDimensionNumbersGetInputBatchDimension(self.inner()); + } + + pub fn getInputFeatureDimension(self: Self) i64 { + return c.stablehloConvDimensionNumbersGetInputFeatureDimension(self.inner()); + } + + pub fn getInputSpatialDimensionsSize(self: Self) usize { + return @intCast(c.stablehloConvDimensionNumbersGetInputSpatialDimensionsSize(self.inner())); + } + + pub fn getInputSpatialDimensionsElem(self: Self, pos: usize) i64 { + return c.stablehloConvDimensionNumbersGetInputSpatialDimensionsElem(self.inner(), @intCast(pos)); + } + + pub fn getKernelInputFeatureDimension(self: Self) i64 { + return c.stablehloConvDimensionNumbersGetKernelInputFeatureDimension(self.inner()); + } + + pub fn getKernelOutputFeatureDimension(self: Self) i64 { + return c.stablehloConvDimensionNumbersGetKernelOutputFeatureDimension(self.inner()); + } + + pub fn getKernelSpatialDimensionsSize(self: Self) usize { + return @intCast(c.stablehloConvDimensionNumbersGetKernelSpatialDimensionsSize(self.inner())); + } + + pub fn getKernelSpatialDimensionsElem(self: Self, pos: usize) i64 { + return c.stablehloConvDimensionNumbersGetKernelSpatialDimensionsElem(self.inner(), @intCast(pos)); + } + + pub fn getOutputBatchDimension(self: Self) i64 { + return c.stablehloConvDimensionNumbersGetOutputBatchDimension(self.inner()); + } + + pub fn getOutputFeatureDimension(self: Self) i64 { + return c.stablehloConvDimensionNumbersGetOutputFeatureDimension(self.inner()); + } + + pub fn getOutputSpatialDimensionsSize(self: Self) usize { + return @intCast(c.stablehloConvDimensionNumbersGetOutputSpatialDimensionsSize(self.inner())); + } + + pub fn getOutputSpatialDimensionsElem(self: Self, pos: usize) i64 { + return c.stablehloConvDimensionNumbersGetOutputSpatialDimensionsElem(self.inner(), @intCast(pos)); + } +}; + +pub const OutputOperandAliasAttribute = struct { + _inner: c.MlirAttribute, + + pub usingnamespace mlir.MlirHelpers(OutputOperandAliasAttribute, .{ + .is_a_fn = c.stablehloAttributeIsAOutputOperandAlias, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + + pub fn init( + ctx: mlir.Context, + output_tuple_indices: []const i64, + operand_index: i64, + operand_tuple_indices: []const i64, + ) OutputOperandAliasAttribute { + return OutputOperandAliasAttribute.wrap(c.stablehloOutputOperandAliasGet( + ctx.inner(), + @intCast(output_tuple_indices.len), + output_tuple_indices.ptr, + @intCast(operand_index), + @intCast(operand_tuple_indices.len), + operand_tuple_indices.ptr, + )); + } +}; + +pub const ScatterDimensionNumbersAttribute = struct { + _inner: c.MlirAttribute, + + pub usingnamespace mlir.MlirHelpers(ScatterDimensionNumbersAttribute, .{ + .is_a_fn = c.stablehloAttributeIsAScatterDimensionNumbers, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = ScatterDimensionNumbersAttribute; + + pub fn init( + ctx: mlir.Context, + update_window_dims: []const i64, + inserted_window_dims: []const i64, + input_batching_dims: []const i64, + scatter_indices_batching_dims: []const i64, + scatter_dims_to_operand_dims: []const i64, + index_vector_dim: i64, + ) Self { + return Self.wrap( + c.stablehloScatterDimensionNumbersGet( + ctx.inner(), + @intCast(update_window_dims.len), + update_window_dims.ptr, + @intCast(inserted_window_dims.len), + inserted_window_dims.ptr, + @intCast(input_batching_dims.len), + input_batching_dims.ptr, + @intCast(scatter_indices_batching_dims.len), + scatter_indices_batching_dims.ptr, + @intCast(scatter_dims_to_operand_dims.len), + scatter_dims_to_operand_dims.ptr, + index_vector_dim, + ), + ); + } + + pub fn getUpdateWindowDimsSize(self: Self) usize { + return @intCast(c.stablehloScatterDimensionNumbersGetUpdateWindowDimsSize(self.inner())); + } + + pub fn getUpdateWindowDimsElem(self: Self, pos: usize) i64 { + return c.stablehloScatterDimensionNumbersGetUpdateWindowDimsElem(self.inner(), @intCast(pos)); + } + + pub fn getInsertedWindowDimsSize(self: Self) usize { + return @intCast(c.stablehloScatterDimensionNumbersGetInsertedWindowDimsSize(self.inner())); + } + + pub fn getInsertedWindowDimsElem(self: Self, pos: usize) i64 { + return c.stablehloScatterDimensionNumbersGetInsertedWindowDimsElem(self.inner(), @intCast(pos)); + } + + pub fn getInputBatchingDimsSize(self: Self) usize { + return @intCast(c.stablehloScatterDimensionNumbersGetInputBatchingDimsSize(self.inner())); + } + + pub fn getInputBatchingDimsElem(self: Self, pos: usize) i64 { + return c.stablehloScatterDimensionNumbersGetInputBatchingDimsElem(self.inner(), @intCast(pos)); + } + + pub fn getScatterIndicesBatchingDimsSize(self: Self) usize { + return @intCast(c.stablehloScatterDimensionNumbersGetScatterIndicesBatchingDimsSize(self.inner())); + } + + pub fn getScatterIndicesBatchingDimsElem(self: Self, pos: usize) i64 { + return c.stablehloScatterDimensionNumbersGetScatterIndicesBatchingDimsElem(self.inner(), @intCast(pos)); + } + + pub fn getIndexVectorDim(self: Self) i64 { + // There really is "Scatter" missing in the function name + return c.stablehloDimensionNumbersGetIndexVectorDim(self.inner()); + } +}; + +pub const PrecisionAttribute = struct { + _inner: c.MlirAttribute, + + pub usingnamespace mlir.MlirHelpers(PrecisionAttribute, .{ + .is_a_fn = c.stablehloAttributeIsAPrecisionAttr, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = PrecisionAttribute; + + pub const Precision = enum { + DEFAULT, + HIGH, + HIGHEST, + }; + + pub fn init(ctx: mlir.Context, value: Precision) Self { + return Self.wrap(c.stablehloPrecisionAttrGet(ctx.inner(), mlir.stringRef(@tagName(value)))); + } + + pub fn getValue(self: Self) Precision { + const value = mlir.fromStringRef(c.stablehloPrecisionAttrGetValue(self.inner())); + return std.meta.stringToEnum(Precision, value) orelse unreachable; + } +}; + +pub const ComparisonDirection = struct { + _inner: c.MlirAttribute, + + pub usingnamespace mlir.MlirHelpers(ComparisonDirection, .{ + .is_a_fn = c.stablehloAttributeIsAComparisonDirectionAttr, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = ComparisonDirection; + + pub const Direction = enum { + EQ, + NE, + GE, + GT, + LE, + LT, + }; + + pub fn init(ctx: mlir.Context, value: Direction) Self { + return Self.wrap(c.stablehloComparisonDirectionAttrGet(ctx.inner(), mlir.stringRef(@tagName(value)))); + } + + pub fn getValue(self: Self) Direction { + const value = mlir.fromStringRef(c.stablehloComparisonDirectionAttrGetValue(self.inner())); + return std.meta.stringToEnum(Direction, value) orelse unreachable; + } +}; + +pub const CompareType = struct { + _inner: c.MlirAttribute, + + pub usingnamespace mlir.MlirHelpers(CompareType, .{ + .is_a_fn = c.stablehloAttributeIsAComparisonTypeAttr, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = CompareType; + + pub const Type = enum { + SIGNED, + UNSIGNED, + FLOAT, + TOTALORDER, + }; + + pub fn init(ctx: mlir.Context, value: Type) Self { + return Self.wrap(c.stablehloComparisonTypeAttrGet(ctx.inner(), mlir.stringRef(@tagName(value)))); + } + + pub fn getValue(self: Self) Type { + const value = mlir.fromStringRef(c.stablehloComparisonTypeAttrGetValue(self.inner())); + return std.meta.stringToEnum(Type, value) orelse unreachable; + } +}; + +pub const Transpose = struct { + _inner: c.MlirAttribute, + + pub usingnamespace mlir.MlirHelpers(Transpose, .{ + .is_a_fn = c.stablehloAttributeIsATransposeAttr, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = Transpose; + + pub const Type = enum { + NO_TRANSPOSE, + TRANSPOSE, + ADJOINT, + }; + + pub fn init(ctx: mlir.Context, value: Type) Self { + return Self.wrap(c.stablehloTransposeAttrGet(ctx.inner(), mlir.stringRef(@tagName(value)))); + } + + pub fn getValue(self: Self) Type { + const value = mlir.fromStringRef(c.stablehloTransposeAttrGetValue(self.inner())); + return std.meta.stringToEnum(Type, value) orelse unreachable; + } +}; + +pub const FftType = struct { + _inner: c.MlirAttribute, + + pub usingnamespace mlir.MlirHelpers(FftType, .{ + .is_a_fn = c.stablehloAttributeIsAFftTypeAttr, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = FftType; + + pub const Type = enum { + FFT, + IFFT, + RFFT, + IRFFT, + }; + + pub fn init(ctx: mlir.Context, value: Type) Self { + return Self.wrap(c.stablehloFftTypeAttrGet(ctx.inner(), mlir.stringRef(@tagName(value)))); + } + + pub fn getValue(self: Self) Type { + const value = mlir.fromStringRef(c.stablehloFftTypeAttrGetValue(self.inner())); + return std.meta.stringToEnum(Type, value) orelse unreachable; + } +}; + +pub const RngDistribution = struct { + _inner: c.MlirAttribute, + + pub usingnamespace mlir.MlirHelpers(RngDistribution, .{ + .is_a_fn = c.stablehloAttributeIsARngDistributionAttr, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = RngDistribution; + + pub const Type = enum { + UNIFORM, + NORMAL, + }; + + pub fn init(ctx: mlir.Context, value: Type) Self { + return Self.wrap(c.stablehloRngDistributionAttrGet(ctx.inner(), mlir.stringRef(@tagName(value)))); + } + + pub fn getValue(self: Self) Type { + const value = mlir.fromStringRef(c.stablehloRngDistributionAttrGetValue(self.inner())); + return std.meta.stringToEnum(Type, value) orelse unreachable; + } +}; + +pub const RngAlgorithm = struct { + _inner: c.MlirAttribute, + + pub usingnamespace mlir.MlirHelpers(RngAlgorithm, .{ + .is_a_fn = c.stablehloAttributeIsARngAlgorithmAttr, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = RngAlgorithm; + + pub const Type = enum { + DEFAULT, + THREE_FRY, + PHILOX, + }; + + pub fn init(ctx: mlir.Context, value: Type) Self { + return Self.wrap(c.stablehloRngAlgorithmAttrGet(ctx.inner(), mlir.stringRef(@tagName(value)))); + } + + pub fn getValue(self: Self) Type { + const value = mlir.fromStringRef(c.stablehloRngAlgorithmAttrGetValue(self.inner())); + return std.meta.stringToEnum(Type, value) orelse unreachable; + } +}; diff --git a/mlir/dialects/tensor.zig b/mlir/dialects/tensor.zig new file mode 100644 index 0000000..8d7de34 --- /dev/null +++ b/mlir/dialects/tensor.zig @@ -0,0 +1,36 @@ +const std = @import("std"); +const mlir = @import("mlir"); + +pub fn empty(ctx: mlir.Context, args: struct { + result: mlir.Type, + location: mlir.Location, +}) mlir.Operation { + return mlir.Operation.make(ctx, "tensor.empty", .{ + .results = &.{args.result}, + .location = args.location, + }); +} + +pub fn splat(ctx: mlir.Context, args: struct { + value: mlir.Value, + result: mlir.Type, + location: mlir.Location, +}) mlir.Operation { + return mlir.Operation.make(ctx, "tensor.splat", .{ + .operands = &.{args.value}, + .results = &.{args.result}, + .location = args.location, + }); +} + +pub fn cast(ctx: mlir.Context, args: struct { + source: mlir.Value, + dest: mlir.Type, + location: mlir.Location, +}) mlir.Operation { + return mlir.Operation.make(ctx, "tensor.cast", .{ + .operands = &.{args.source}, + .results = &.{args.dest}, + .location = args.location, + }); +} diff --git a/mlir/mlir.zig b/mlir/mlir.zig new file mode 100644 index 0000000..6eda578 --- /dev/null +++ b/mlir/mlir.zig @@ -0,0 +1,1933 @@ +const builtin = @import("builtin"); +const std = @import("std"); + +const c = @import("c"); + +test { + std.testing.refAllDecls(@This()); +} + +const Error = error{ + /// Invalid Mlir was created. + InvalidMlir, + /// Another Mlir error. Check the log for more context. + MlirUnexpected, + /// A resource/executor was not found. + NotFound, + OutOfMemory, +}; + +pub inline fn stringRef(str: []const u8) c.MlirStringRef { + return .{ .data = str.ptr, .length = str.len }; +} + +pub inline fn fromStringRef(str: c.MlirStringRef) []const u8 { + // Note: mlir.StringRef need not to be null terminated. + return str.data[0..str.length]; +} + +pub fn registerPasses(comptime passes: []const u8) void { + @field(c, "mlirRegister" ++ passes ++ "Passes")(); +} + +fn successOr(res: c.MlirLogicalResult, err: anytype) !void { + return if (res.value == 0) err; +} + +pub fn MlirTypeMethods(comptime InnerT: type) type { + return struct { + is_null_fn: ?fn (InnerT) callconv(.C) bool = null, + is_a_fn: ?fn (InnerT) callconv(.C) bool = null, + equal_fn: ?fn (InnerT, InnerT) callconv(.C) bool = null, + dump_fn: ?fn (InnerT) callconv(.C) void = null, + deinit_fn: ?fn (InnerT) callconv(.C) void = null, + }; +} + +/// Alternative to MlirWrapperType +pub const MlirStrCallback = fn (c.MlirStringRef, ?*anyopaque) callconv(.C) void; + +fn MlirHelpersMethods(comptime OuterT: type) type { + switch (@typeInfo(OuterT)) { + .Struct => |info| { + if (info.fields.len != 1) @compileError("Mlir wrapper type can only wrap one Mlir value. Received: " ++ @typeName(OuterT)); + }, + else => @compileError("MlirHelpersMethods is only available on an Mlir wrapper struct. Received: " ++ @typeName(OuterT)), + } + + return struct { + pub const InnerT = std.meta.FieldType(OuterT, ._inner); + comptime { + std.debug.assert(@sizeOf(InnerT) == @sizeOf(OuterT)); + } + + is_null_fn: ?fn (InnerT) callconv(.C) bool = null, + is_a_fn: ?fn (InnerT) callconv(.C) bool = null, + equal_fn: ?fn (InnerT, InnerT) callconv(.C) bool = null, + deinit_fn: ?fn (InnerT) callconv(.C) void = null, + dump_fn: ?fn (InnerT) callconv(.C) void = null, + print_fn: ?fn (InnerT, ?*const MlirStrCallback, ?*anyopaque) callconv(.C) void = null, + }; +} + +pub fn MlirHelpers(comptime OuterT: type, comptime methods: MlirHelpersMethods(OuterT)) type { + const InnerT = @TypeOf(methods).InnerT; + return struct { + pub const Methods = methods; + + pub inline fn wrap(raw: InnerT) OuterT { + return .{ ._inner = raw }; + } + + pub inline fn inner(self: OuterT) InnerT { + return self._inner; + } + + pub inline fn innerPtr(self: *OuterT) *InnerT { + return &self._inner; + } + + pub inline fn is_a(self: OuterT, comptime otherT: type) bool { + if (otherT.Methods.is_a_fn) |is_a_fn| { + return is_a_fn(self.inner()); + } + return false; + } + + pub inline fn as(self: OuterT, comptime OtherT: type) ?OtherT { + if (OtherT.Methods.is_a_fn) |is_a_fn| { + return if (is_a_fn(self.inner())) OtherT.wrap(self.inner()) else null; + } + // if the other type doesn't have an is_a_fn, try. + return OtherT.wrap(self.inner()); + } + + pub usingnamespace if (Methods.is_null_fn) |is_null| struct { + pub inline fn wrapOr(raw: InnerT) ?OuterT { + return if (is_null(raw)) null else OuterT.wrap(raw); + } + } else struct {}; + + pub usingnamespace if (Methods.equal_fn) |equal| struct { + pub inline fn eql(self: OuterT, other: OuterT) bool { + return equal(self.inner(), other.inner()); + } + } else struct {}; + + pub usingnamespace if (Methods.deinit_fn) |_deinit| struct { + pub inline fn deinit(self: *OuterT) void { + _deinit(self.inner()); + self.* = undefined; + } + } else struct {}; + + pub usingnamespace if (Methods.dump_fn) |_dump| struct { + pub inline fn dump(self: OuterT) void { + return _dump(self.inner()); + } + } else struct {}; + + pub usingnamespace if (Methods.print_fn) |print| struct { + pub fn format( + self: OuterT, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, + ) !void { + _ = fmt; + _ = options; + + const Writer = struct { + writer: @TypeOf(writer), + err: ?@TypeOf(writer).Error = null, + fn printCallback(mlir_str: c.MlirStringRef, opaque_ctx: ?*anyopaque) callconv(.C) void { + var ctx: *@This() = @alignCast(@ptrCast(opaque_ctx)); + if (ctx.err) |_| return; + _ = ctx.writer.write(mlir_str.data[0..mlir_str.length]) catch |err| { + ctx.err = err; + return; + }; + } + }; + + var context: Writer = .{ .writer = writer }; + print(self.inner(), &Writer.printCallback, &context); + if (context.err) |err| return err; + } + } else struct {}; + }; +} + +pub const Registry = struct { + _inner: c.MlirDialectRegistry, + pub usingnamespace MlirHelpers(Registry, .{ + .is_null_fn = c.mlirDialectRegistryIsNull, + .deinit_fn = c.mlirDialectRegistryDestroy, + }); + const Self = Registry; + + pub fn init() !Self { + return Self.wrapOr(c.mlirDialectRegistryCreate()) orelse Error.MlirUnexpected; + } +}; + +pub const Context = struct { + _inner: c.MlirContext, + pub usingnamespace MlirHelpers(Context, .{ + .is_null_fn = c.mlirContextIsNull, + .deinit_fn = c.mlirContextDestroy, + }); + const Self = Context; + + pub fn init() !Self { + return Self.wrapOr(c.mlirContextCreate()) orelse Error.MlirUnexpected; + } + + pub fn initWithRegistry(registry: Registry, threadingEnabled: bool) !Self { + return Self.wrapOr( + c.mlirContextCreateWithRegistry(registry.inner(), threadingEnabled), + ) orelse Error.InvalidMlir; + } + + pub fn setMultiThreading(self: *Self, enabled: bool) void { + c.mlirContextEnableMultithreading(self.inner(), enabled); + } + + pub fn appendDialectRegistry(self: *Self, registry: Registry) void { + c.mlirContextAppendDialectRegistry(self.inner(), registry.inner()); + } + + pub fn loadAllAvailableDialects(self: *Self) void { + c.mlirContextLoadAllAvailableDialects(self.inner()); + } + + pub fn numRegisteredDialects(self: Self) usize { + return @intCast(c.mlirContextGetNumRegisteredDialects(self.inner())); + } + + pub fn numLoadedDialects(self: Self) usize { + return @intCast(c.mlirContextGetNumLoadedDialects(self.inner())); + } + + pub fn isRegisteredOperation(self: Self, op: [:0]const u8) bool { + return c.mlirContextIsRegisteredOperation(self.inner(), stringRef(op)); + } + + pub fn location(self: Self, src: std.builtin.SourceLocation) Location { + return Location.fromSrc(self, src); + } +}; + +pub const Module = struct { + _inner: c.MlirModule, + pub usingnamespace MlirHelpers(Module, .{ + .is_null_fn = c.mlirModuleIsNull, + .deinit_fn = c.mlirModuleDestroy, + }); + const Self = Module; + + pub fn init(loc: Location) Self { + return Self.wrap(c.mlirModuleCreateEmpty(loc.inner())); + } + + pub fn parse(ctx: Context, source: [:0]const u8) !Module { + return Module.wrapOr( + c.mlirModuleCreateParse(ctx.inner(), stringRef(source)), + ) orelse Error.InvalidMlir; + } + + pub fn fromOperation(operation: Operation) Module { + return Module.wrap(c.mlirModuleFromOperation(operation.inner())); + } + + pub fn context(self: Module) Context { + return Context.wrap(c.mlirModuleGetContext(self.inner())); + } + + pub fn getBody(self: Module) Block { + return Block.wrap(c.mlirModuleGetBody(self.inner())); + } + + pub fn op(self: Module) Operation { + return Operation.wrap(c.mlirModuleGetOperation(self.inner())); + } +}; + +pub const PassManager = struct { + _inner: c.MlirPassManager, + + pub usingnamespace MlirHelpers(PassManager, .{ + .is_null_fn = c.mlirPassManagerIsNull, + .deinit_fn = c.mlirPassManagerDestroy, + }); + const Self = PassManager; + + pub fn init(ctx: Context) !Self { + return Self.wrapOr( + c.mlirPassManagerCreate(ctx.inner()), + ) orelse Error.MlirUnexpected; + } + + pub fn initOnOperation(ctx: Context, op: [:0]const u8) !Self { + return Self.wrapOr( + c.mlirPassManagerCreateOnOperation(ctx.inner(), stringRef(op)), + ) orelse Error.MlirUnexpected; + } + + pub fn asOpPassManager(self: Self) OpPassManager { + return OpPassManager.wrap(c.mlirPassManagerGetAsOpPassManager(self.inner())); + } + + pub fn enableIRPrinting(self: *Self) void { + c.mlirPassManagerEnableIRPrinting(self.inner()); + } + + pub fn runOnOp(self: *Self, op: Operation) error{InvalidMlir}!void { + if (c.mlirPassManagerRunOnOp(self.inner(), op.inner()).value == 0) { + return Error.InvalidMlir; + } + } +}; + +fn _mlir_passpipeline_error(err: c.MlirStringRef, ctx: ?*anyopaque) callconv(.C) void { + _ = ctx; + std.debug.print(">>ERROR: {s}\n", .{err.data}); +} + +pub const OpPassManager = struct { + _inner: c.MlirOpPassManager, + pub usingnamespace MlirHelpers(OpPassManager, .{}); + + pub fn addPipeline(self: *OpPassManager, pipeline: [:0]const u8) error{OutOfMemory}!void { + if (c.mlirOpPassManagerAddPipeline( + self.inner(), + stringRef(pipeline), + &_mlir_passpipeline_error, + null, + ).value == 0) { + return Error.OutOfMemory; + } + } +}; + +pub const Identifier = struct { + _inner: c.MlirIdentifier, + pub usingnamespace MlirHelpers(Identifier, .{}); + const Self = Identifier; + + pub fn get(ctx: Context, str_: [:0]const u8) Self { + return Self.wrap(c.mlirIdentifierGet(ctx.inner(), stringRef(str_))); + } + + pub fn context(self: Self) Context { + return Context.wrap(c.mlirIdentifierGetContext(self.inner())); + } + + pub fn str(self: Self) []const u8 { + return fromStringRef(c.mlirIdentifierStr(self.inner())); + } + + pub fn equals(self: Self, other: Self) bool { + return c.mlirIdentifierEqual(self.inner(), other.inner()); + } +}; + +pub const Attribute = struct { + _inner: c.MlirAttribute, + pub usingnamespace MlirHelpers(Attribute, .{ + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = Attribute; + + pub fn parse(ctx: Context, attr: [:0]const u8) !Attribute { + return Attribute.wrapOr( + c.mlirAttributeParseGet(ctx.inner(), stringRef(attr)), + ) orelse Error.InvalidMlir; + } + + pub fn getNull() Self { + return Self.wrap(c.mlirAttributeGetNull()); + } +}; + +pub const NamedAttribute = struct { + _inner: c.MlirNamedAttribute, + pub usingnamespace MlirHelpers(NamedAttribute, .{}); + const Self = NamedAttribute; + + pub fn init(name: Identifier, attr: Attribute) Self { + return Self.wrap(.{ + .name = name.inner(), + .attribute = attr.inner(), + }); + } +}; + +pub const StringAttribute = struct { + _inner: c.MlirAttribute, + pub usingnamespace MlirHelpers(StringAttribute, .{ + .is_a_fn = c.mlirAttributeIsAString, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = StringAttribute; + + pub fn init(ctx: Context, str: []const u8) Self { + return Self.wrap(c.mlirStringAttrGet(ctx.inner(), stringRef(str))); + } + + pub fn value(self: Self) []const u8 { + return fromStringRef(c.mlirStringAttrGetValue(self.inner())); + } +}; + +pub const UnitAttribute = struct { + _inner: c.MlirAttribute, + pub usingnamespace MlirHelpers(UnitAttribute, .{ + .is_a_fn = c.mlirAttributeIsAUnit, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = UnitAttribute; + + pub fn init(ctx: Context) Self { + return Self.wrap(c.mlirUnitAttrGet(ctx.inner())); + } +}; + +pub const BoolAttribute = struct { + _inner: c.MlirAttribute, + pub usingnamespace MlirHelpers(BoolAttribute, .{ + .is_a_fn = c.mlirAttributeIsABool, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = BoolAttribute; + + pub fn init(ctx: Context, value_: bool) Self { + return Self.wrap(c.mlirBoolAttrGet(ctx.inner(), if (value_) 1 else 0)); + } + + pub fn value(self: Self) bool { + return c.mlirBoolAttrGetValue(self.inner()); + } +}; + +pub const TypeAttribute = struct { + _inner: c.MlirAttribute, + pub usingnamespace MlirHelpers(TypeAttribute, .{ + .is_a_fn = c.mlirAttributeIsAType, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = TypeAttribute; + + pub fn init(type_: Type) Self { + return Self.wrap(c.mlirTypeAttrGet(type_.inner())); + } + + pub fn typ(self: Self) Type { + return Type.wrap(c.mlirAttributeGetType(self.inner())); + } +}; + +pub const ArrayAttribute = struct { + _inner: c.MlirAttribute, + pub usingnamespace MlirHelpers(ArrayAttribute, .{ + .is_a_fn = c.mlirAttributeIsAArray, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Self = ArrayAttribute; + + pub fn init(ctx: Context, attrs: []const Attribute) Self { + return Self.wrap(c.mlirArrayAttrGet(ctx.inner(), @intCast(attrs.len), @ptrCast(attrs.ptr))); + } + + pub fn size(self: Self) usize { + return @intCast(c.mlirArrayAttrGetNumElements(self.inner())); + } + + pub fn get(self: Self, index: usize) Attribute { + return Attribute.wrap(c.mlirArrayAttrGetElement(self.inner(), @intCast(index))); + } +}; + +pub fn IntegerAttribute(comptime it: IntegerTypes) type { + const ZigType, const getter = comptime switch (it) { + .i1, .i4, .i8, .i16, .i32, .i64 => .{ u64, c.mlirIntegerAttrGetValueInt }, + .si4, .si8, .si16, .si32, .si64 => .{ u64, c.mlirIntegerAttrGetValueSInt }, + .u4, .u8, .u16, .u32, .u64 => .{ u64, c.mlirIntegerAttrGetValueUInt }, + .unknown => @compileError("IntegerAttribute(unknown)"), + }; + + return struct { + _inner: c.MlirAttribute, + pub usingnamespace MlirHelpers(@This(), .{ + .is_a_fn = c.mlirAttributeIsAInteger, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + pub const IntegerTypeType = IntegerType(it); + const IntAttr = @This(); + + pub fn init(ctx: Context, value: i64) IntAttr { + return IntAttr.wrap(c.mlirIntegerAttrGet( + IntegerType(it).init(ctx).inner(), + value, + )); + } + + pub fn get(value: IntAttr) ZigType { + return @intCast(getter(value.inner())); + } + }; +} + +pub fn FloatAttribute(comptime ft: FloatTypes) type { + return struct { + _inner: c.MlirAttribute, + pub usingnamespace MlirHelpers(@This(), .{ + .is_a_fn = c.mlirAttributeIsAFloat, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const FloatAttr = @This(); + pub fn init(ctx: Context, value: f64) FloatAttr { + return FloatAttr.wrap(c.mlirFloatAttrDoubleGet( + ctx.inner(), + FloatType(ft).init(ctx).inner(), + value, + )); + } + + pub fn get(value: FloatAttr) f64 { + return c.mlirFloatAttrGetValueDouble(value.inner()); + } + }; +} + +pub const DenseArrayTypes = enum { + bool, + i8, + i16, + i32, + i64, + f32, + f64, +}; + +pub fn DenseArrayAttribute(comptime dt: DenseArrayTypes) type { + const Config = switch (dt) { + .bool => .{ i32, c.mlirAttributeIsADenseBoolArray, c.mlirDenseBoolArrayGet, c.mlirDenseBoolArrayGetElement }, + .i8 => .{ i8, c.mlirAttributeIsADenseI8Array, c.mlirDenseI8ArrayGet, c.mlirDenseI8ArrayGetElement }, + .i16 => .{ i16, c.mlirAttributeIsADenseI16Array, c.mlirDenseI16ArrayGet, c.mlirDenseI16ArrayGetElement }, + .i32 => .{ i32, c.mlirAttributeIsADenseI32Array, c.mlirDenseI32ArrayGet, c.mlirDenseI32ArrayGetElement }, + .i64 => .{ i64, c.mlirAttributeIsADenseI64Array, c.mlirDenseI64ArrayGet, c.mlirDenseI64ArrayGetElement }, + .f32 => .{ f32, c.mlirAttributeIsADenseF32Array, c.mlirDenseF32ArrayGet, c.mlirDenseF32ArrayGetElement }, + .f64 => .{ f64, c.mlirAttributeIsADenseF64Array, c.mlirDenseF64ArrayGet, c.mlirDenseF64ArrayGetElement }, + }; + + return struct { + _inner: c.MlirAttribute, + pub usingnamespace MlirHelpers(@This(), .{ + .is_a_fn = Config[1], + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + const Attr = @This(); + const ElementType = dt; + const ElementTypeZig = Config[0]; + + pub fn init(ctx: Context, values: []const ElementTypeZig) Attr { + const get_fn = Config[2]; + return Attr.wrap(get_fn(ctx.inner(), @intCast(values.len), @ptrCast(values.ptr))); + } + + pub fn get(self: Attr, pos: usize) ElementTypeZig { + const get_element_fn = Config[3]; + return get_element_fn(self.inner(), @intCast(pos)); + } + + pub fn len(self: Attr) usize { + return @intCast(c.mlirDenseArrayGetNumElements(self.inner())); + } + + pub usingnamespace switch (dt) { + .bool, .i64 => struct { + const DenseArray = DenseArrayAttribute(switch (dt) { + .bool => .bool, + .i64 => .i64, + else => @compileError("DenseArrayAttribute: unreachable"), + }); + + pub fn toElements(self: Attr) DenseArray { + return DenseArray.wrap(c.mlirDenseArrayToElements(self.inner())); + } + }, + else => struct {}, + }; + }; +} + +pub const DenseElementsAttributeTypes = enum { + bool, + i8, + i16, + i32, + i64, + u8, + u16, + u32, + u64, + bf16, + f16, + f32, + f64, +}; + +pub fn DenseIntOrFPElementsAttribute(comptime dt: DenseElementsAttributeTypes) type { + const ZigInDataType, const ZigOutDataType, const initFn, const getValue = switch (dt) { + .bool => .{ i32, bool, c.mlirDenseElementsAttrBoolGet, c.mlirDenseElementsAttrGetBoolValue }, + .i8 => .{ i8, i8, c.mlirDenseElementsAttrInt8Get, c.mlirDenseElementsAttrGetInt8Value }, + .i16 => .{ i16, i16, c.mlirDenseElementsAttrInt16Get, c.mlirDenseElementsAttrGetInt16Value }, + .i32 => .{ i32, i32, c.mlirDenseElementsAttrInt32Get, c.mlirDenseElementsAttrGetInt32Value }, + .i64 => .{ i64, i64, c.mlirDenseElementsAttrInt64Get, c.mlirDenseElementsAttrGetInt64Value }, + .u8 => .{ u8, u8, c.mlirDenseElementsAttrUInt8Get, c.mlirDenseElementsAttrGetUInt8Value }, + .u16 => .{ u16, u16, c.mlirDenseElementsAttrUInt16Get, c.mlirDenseElementsAttrGetUInt16Value }, + .u32 => .{ u32, u32, c.mlirDenseElementsAttrUInt32Get, c.mlirDenseElementsAttrGetUInt32Value }, + .u64 => .{ u64, u64, c.mlirDenseElementsAttrUInt64Get, c.mlirDenseElementsAttrGetUInt64Value }, + .bf16 => .{ u16, f32, c.mlirDenseElementsAttrBFloat16Get, c.mlirDenseElementsAttrGetFloatValue }, + .f16 => .{ f16, f32, c.mlirDenseElementsAttrFloat16Get, c.mlirDenseElementsAttrGetFloatValue }, + .f32 => .{ f32, f32, c.mlirDenseElementsAttrFloatGet, c.mlirDenseElementsAttrGetFloatValue }, + .f64 => .{ f64, f64, c.mlirDenseElementsAttrDoubleGet, c.mlirDenseElementsAttrGetDoubleValue }, + }; + + return struct { + _inner: c.MlirAttribute, + const Attr = @This(); + pub usingnamespace MlirHelpers(Attr, .{ + .is_a_fn = c.mlirAttributeIsADenseElements, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + + pub fn init(shaped_type: Type, raw_values: []const u8) Attr { + const values = std.mem.bytesAsSlice(ZigInDataType, raw_values); + return Attr.wrap(initFn(shaped_type.inner(), @intCast(values.len), @ptrCast(@alignCast(values.ptr)))); + } + + pub fn get(self: Attr, pos: usize) ZigOutDataType { + return getValue(self.inner(), @intCast(pos)); + } + }; +} + +pub const FlatSymbolRefAttribute = struct { + _inner: c.MlirAttribute, + pub usingnamespace MlirHelpers(FlatSymbolRefAttribute, .{ + .is_a_fn = c.mlirAttributeIsAFlatSymbolRef, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + + const Self = FlatSymbolRefAttribute; + + pub fn init(ctx: Context, str: [:0]const u8) Self { + return Self.wrap(c.mlirFlatSymbolRefAttrGet(ctx.inner(), stringRef(str))); + } + + pub fn value(self: Self) []const u8 { + return fromStringRef(c.mlirFlatSymbolRefAttrGetValue(self.inner())); + } +}; + +pub const OperationState = struct { + _inner: c.MlirOperationState, + pub usingnamespace MlirHelpers( + OperationState, + .{}, + ); + + const Self = OperationState; + + pub fn init(name: [:0]const u8, loc: Location) Self { + return Self.wrap(c.mlirOperationStateGet(stringRef(name), loc.inner())); + } + + pub fn addResult(self: *Self, type_: Type) void { + c.mlirOperationStateAddResults(self.innerPtr(), 1, &[_]c.MlirType{type_.inner()}); + } + + pub fn addResults(self: *Self, types: []const Type) void { + c.mlirOperationStateAddResults(self.innerPtr(), @intCast(types.len), @ptrCast(types.ptr)); + } + + pub fn addOperand(self: *Self, value: Value) void { + c.mlirOperationStateAddOperands(self.innerPtr(), 1, &[_]c.MlirValue{value.inner()}); + } + + pub fn addOperands(self: *Self, values: []const Value) void { + c.mlirOperationStateAddOperands(self.innerPtr(), @intCast(values.len), @ptrCast(values.ptr)); + } + + pub fn addRegion(self: *Self, region: *Region) void { + c.mlirOperationStateAddOwnedRegions(self.innerPtr(), 1, &[_]c.MlirRegion{region.inner()}); + } + + pub fn addRegions(self: *Self, regions: []const Region) void { + c.mlirOperationStateAddOwnedRegions(self.innerPtr(), @intCast(regions.len), @ptrCast(regions.ptr)); + } + + // pub fn addSuccessor(self: *Self, successor: Operation) void { + // c.mlirOperationStateAddSuccessors(self.innerPtr(), 1, &[_]c.MlirOperation{successor.inner()}); + // } + + pub fn addAttribute(self: *Self, ctx: Context, name: [:0]const u8, attr: Attribute) void { + c.mlirOperationStateAddAttributes(self.innerPtr(), 1, @ptrCast(&.{ + .{ + .name = Identifier.get(ctx, name).inner(), + .attribute = attr.inner(), + }, + })); + } + + pub fn addAttributeRaw(self: *Self, name: Identifier, attr: Attribute) void { + c.mlirOperationStateAddAttributes(self.innerPtr(), 1, @ptrCast(&.{ + .{ + .name = name.inner(), + .attribute = attr.inner(), + }, + })); + } + + pub fn addAttributes(self: *Self, attributes: []const NamedAttribute) void { + c.mlirOperationStateAddAttributes(self.innerPtr(), @intCast(attributes.len), @ptrCast(attributes.ptr)); + } + + pub fn resultTypeInference(self: *Self, enabled: bool) void { + self.innerPtr().enableResultTypeInference = enabled; + } +}; + +pub const DictionaryAttribute = struct { + _inner: c.MlirAttribute, + pub usingnamespace MlirHelpers(DictionaryAttribute, .{ + .is_a_fn = c.mlirAttributeIsADictionary, + .is_null_fn = c.mlirAttributeIsNull, + .dump_fn = c.mlirAttributeDump, + .equal_fn = c.mlirAttributeEqual, + }); + + const Self = DictionaryAttribute; + + pub fn init(ctx: Context, attributes: []const NamedAttribute) Self { + return Self.wrap(c.mlirDictionaryAttrGet(ctx.inner(), @intCast(attributes.len), @ptrCast(attributes.ptr))); + } + + pub fn size(self: Self) usize { + return @intCast(c.mlirDictionaryAttrGetNumElements(self.inner())); + } + + pub fn get(self: Self, pos: usize) NamedAttribute { + return NamedAttribute.wrap(c.mlirDictionaryAttrGetElement(self.inner(), @intCast(pos))); + } + + // pub fn getByName(self: Self, name: [:0]const u8) ?NamedAttribute { + // return NamedAttribute.wrapOr(c.mlirDictionaryAttrGetElementByName(self.inner(), name)); + // } +}; + +pub const Operation = struct { + const Self = Operation; + _inner: c.MlirOperation, + + pub usingnamespace MlirHelpers( + Operation, + .{ + .is_null_fn = c.mlirOperationIsNull, + .deinit_fn = c.mlirOperationDestroy, + .dump_fn = c.mlirOperationDump, + .equal_fn = c.mlirOperationEqual, + }, + ); + + pub fn init(state: *OperationState) !Self { + return Self.wrapOr( + c.mlirOperationCreate(state.innerPtr()), + ) orelse Error.InvalidMlir; + } + + pub fn make(ctx: Context, op_name: [:0]const u8, args: struct { + pub const AttrTuple = struct { [:0]const u8, Attribute }; + + operands: ?[]const Value = null, + variadic_operands: ?[]const []const Value = null, + results: ?[]const Type = null, + variadic_results: ?[]const []const Type = null, + result_type_inference: ?bool = null, + n_regions: usize = 0, + attributes: ?[]const AttrTuple = null, + blocks: ?[]const Block = null, + verify: bool = true, + location: Location, + }) Self { + var state = OperationState.init(op_name, args.location); + std.debug.assert(!(args.operands != null and args.variadic_operands != null)); + if (args.operands) |operands| { + state.addOperands(operands); + } else if (args.variadic_operands) |operands_segments| { + for (operands_segments) |operands| { + state.addOperands(operands); + } + } + if (args.result_type_inference) |enable| { + state.resultTypeInference(enable); + } + std.debug.assert(!(args.results != null and args.variadic_results != null)); + if (args.results) |results| { + state.addResults(results); + } else if (args.variadic_results) |result_segments| { + for (result_segments) |results| { + state.addResults(results); + } + } + for (0..args.n_regions) |_| { + var region_ = Region.init() catch { + @panic("Failed to create MLIR region"); + }; + state.addRegion(®ion_); + } + if (args.attributes) |attrs| { + for (attrs) |attr| { + state.addAttributeRaw( + Identifier.get(ctx, attr[0]), + attr[1], + ); + } + } + if (args.blocks) |blocks_| { + for (blocks_) |block_| { + var region_ = Region.init() catch { + @panic("Failed to create MLIR region"); + }; + region_.appendBlock(block_); + state.addRegion(®ion_); + } + } + + const new_op = Operation.init(&state) catch { + @panic("Failed to create MLIR operation"); + }; + if (args.verify and new_op.verify() == false) { + std.log.err("Failed to verify MLIR operation:\n{}", .{new_op.mlirFormatter(.{ .debug_info = true })}); + @panic("Failed to verify MLIR operation"); + } + return new_op; + } + + pub fn initParse(ctx: Context, str: [:0]const u8) !Self { + return Self.wrapOr( + c.mlirOperationCreateParse(ctx.inner(), stringRef(str), stringRef("pouet")), + ) orelse Error.InvalidMlir; + } + + pub fn clone(self: Self) !Self { + return Self.wrapOr( + c.mlirOperationClone(self.inner()), + ) orelse Error.InvalidMlir; + } + + pub fn name(self: Self) Identifier { + return Identifier.wrap(c.mlirOperationGetName(self.inner())); + } + + pub fn removeFromParent(self: *Self) void { + c.mlirOperationRemoveFromParent(self.inner()); + } + + pub fn numOperands(self: Self) usize { + return @intCast(c.mlirOperationGetNumOperands(self.inner())); + } + + pub fn operand(self: Self, index: usize) Value { + return Value.wrap(c.mlirOperationGetOperand(self.inner(), @intCast(index))); + } + + pub fn setOperand(self: *Self, index: usize, value: Value) void { + c.mlirOperationSetOperand(self.inner(), @intCast(index), value.inner()); + } + + pub fn numResults(self: Self) usize { + return @intCast(c.mlirOperationGetNumResults(self.inner())); + } + + pub fn result(self: Self, index: usize) Value { + return Value.wrap(c.mlirOperationGetResult(self.inner(), @intCast(index))); + } + + pub fn nextInBlock(self: Self) Self { + return Self.wrap(c.mlirOperationGetNextInBlock(self.inner())); + } + + // pub fn previousInBlock(self: Self) Self { + // return Self.wrap(c.mlirOperationGetPrevInBlock(self.inner())); + // } + + pub fn block(self: Self) ?Block { + return Block.wrapOr(c.mlirOperationGetBlock(self.inner())); + } + + pub fn parent(self: Self) ?Self { + return Self.wrapOr(c.mlirOperationGetParentOperation(self.inner())); + } + + pub fn region(self: Self, index: usize) Region { + return Region.wrap(c.mlirOperationGetRegion(self.inner(), @intCast(index))); + } + + pub fn context(self: Self) Context { + return Context.wrap(c.mlirOperationGetContext(self.inner())); + } + + pub fn writeBytecode(self: Self, writer: anytype) void { + var writer_context = .{ .writer = writer }; + const WriterContext = @TypeOf(writer_context); + + c.mlirOperationWriteBytecode( + self.inner(), + (struct { + pub fn callback(str: c.MlirStringRef, ctx_: ?*anyopaque) callconv(.C) void { + const inner_writer_context: *WriterContext = @ptrCast(@alignCast(ctx_)); + _ = inner_writer_context.writer.write(str.data[0..str.length]) catch unreachable; + } + }).callback, + &writer_context, + ); + } + + pub fn writeBytecodeWithConfig(self: Self, writer: anytype, config: struct { + desiredEmitedVersion: ?i64 = null, + }) !void { + const cfg = c.mlirBytecodeWriterConfigCreate(); + defer c.mlirBytecodeWriterConfigDestroy(cfg); + if (config.desiredEmitedVersion) |v| { + c.mlirBytecodeWriterConfigDesiredEmitVersion(cfg, v); + } + + var writer_context = .{ .writer = writer }; + const WriterContext = @TypeOf(writer_context); + + try successOr(c.mlirOperationWriteBytecodeWithConfig( + self.inner(), + cfg, + (struct { + pub fn callback(str: c.MlirStringRef, ctx_: ?*anyopaque) callconv(.C) void { + const inner_writer_context: *WriterContext = @ptrCast(@alignCast(ctx_)); + _ = inner_writer_context.writer.write(str.data[0..str.length]) catch unreachable; + } + }).callback, + &writer_context, + ), error.InvalidMlirBytecodeVersion); + } + + /// Enable a full dump of the IR. + /// Usage `std.log.debug("{}", .{ module.op().mlirFormatter(.{}) }); + pub fn mlirFormatter(self: Operation, flags: OpPrintingFlags) MlirFormatter { + return .{ .op = self, .flags = flags }; + } + + const MlirFormatter = struct { + op: Operation, + flags: OpPrintingFlags, + + pub fn format(self: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { + _ = fmt; + _ = options; + self.op.print(writer, self.flags); + } + }; + + pub fn print(self: Self, writer: anytype, flags: OpPrintingFlags) void { + const pflags = flags.create(); + defer c.mlirOpPrintingFlagsDestroy(pflags); + + var writer_context = .{ .writer = writer }; + const WriterContext = @TypeOf(writer_context); + c.mlirOperationPrintWithFlags( + self.inner(), + pflags, + (struct { + pub fn callback(str: c.MlirStringRef, ctx_: ?*anyopaque) callconv(.C) void { + const inner_writer_context: *WriterContext = @ptrCast(@alignCast(ctx_)); + _ = inner_writer_context.writer.write(str.data[0..str.length]) catch unreachable; + } + }).callback, + &writer_context, + ); + } + + pub fn verify(self: Self) bool { + return c.mlirOperationVerify(self.inner()); + } + + pub fn getLocation(self: Self) Location { + return Location.wrap(c.mlirOperationGetLocation(self.inner())); + } + + pub const WalkOrder = enum(c.MlirWalkOrder) { + pre_order = c.MlirWalkPreOrder, + post_order = c.MlirWalkPostOrder, + }; + + pub const WalkResult = enum(c.MlirWalkResult) { + advance = c.MlirWalkResultAdvance, + interrupt = c.MlirWalkResultInterrupt, + skip = c.MlirWalkResultSkip, + }; + + pub fn walk(self: Self, order: WalkOrder, ctx: anytype, walkfn: fn (ctx: anytype, op: Operation) WalkResult) void { + var inner_ctx = .{ .ctx = ctx }; + const ContextType = @TypeOf(inner_ctx); + + c.mlirOperationWalk( + self.inner(), + (struct { + pub fn callback(op: c.MlirOperation, ctx_: ?*anyopaque) callconv(.C) c.MlirWalkResult { + const inner_ctx_: *ContextType = @ptrCast(@alignCast(ctx_)); + return @intFromEnum(walkfn(inner_ctx_.ctx, Operation.wrap(op))); + } + }).callback, + &inner_ctx, + @intFromEnum(order), + ); + } + + pub fn getAttribute(self: Self, pos: usize) NamedAttribute { + return NamedAttribute.wrap(c.mlirOperationGetAttribute(self.inner(), @intCast(pos))); + } + + pub fn getAttributeByName(self: Self, name_: [:0]const u8) ?Attribute { + return Attribute.wrapOr(c.mlirOperationGetAttributeByName(self.inner(), stringRef(name_))); + } + + pub fn setAttributeByName(self: Self, name_: [:0]const u8, attr: Attribute) void { + c.mlirOperationSetAttributeByName(self.inner(), stringRef(name_), attr.inner()); + } + + pub fn removeAttributeByName(self: Self, name_: [:0]const u8) bool { + return c.mlirOperationRemoveAttributeByName(self.inner(), stringRef(name_)); + } +}; + +pub const OpPrintingFlags = struct { + elide_large_elements_attrs: ?usize = null, + debug_info: bool = false, + debug_info_pretty_form: bool = false, + print_generic_op_form: bool = false, + use_local_scope: bool = false, + assume_verified: bool = false, + + pub fn create(self: OpPrintingFlags) c.MlirOpPrintingFlags { + const pflags = c.mlirOpPrintingFlagsCreate(); + if (self.elide_large_elements_attrs) |v| { + c.mlirOpPrintingFlagsElideLargeElementsAttrs(pflags, @intCast(v)); + } + c.mlirOpPrintingFlagsEnableDebugInfo(pflags, self.debug_info, self.debug_info_pretty_form); + if (self.print_generic_op_form) { + c.mlirOpPrintingFlagsPrintGenericOpForm(pflags); + } + if (self.use_local_scope) { + c.mlirOpPrintingFlagsUseLocalScope(pflags); + } + if (self.assume_verified) { + c.mlirOpPrintingFlagsAssumeVerified(pflags); + } + return pflags; + } +}; + +pub const OpOperand = struct { + _inner: c.MlirOpOperand, + pub usingnamespace MlirHelpers(OpOperand, .{ + .is_null_fn = c.mlirOpOperandIsNull, + }); + + const Self = OpOperand; + + pub fn owner(self: Self) Operation { + return Operation.wrap(c.mlirOpOperandGetOwner(self.inner())); + } + + pub fn number(self: Self) usize { + return @intCast(c.mlirOpOperandGetOperandNumber(self.inner())); + } + + pub fn nextUse(self: Self) ?Self { + return Self.wrapOr( + c.mlirOpOperandGetNextUse(self.inner()), + ); + } +}; + +pub const Region = struct { + _inner: c.MlirRegion, + pub usingnamespace MlirHelpers(Region, .{ + .is_null_fn = c.mlirRegionIsNull, + .deinit_fn = c.mlirRegionDestroy, + .equal_fn = c.mlirRegionEqual, + }); + + const Self = Region; + + pub fn init() !Self { + return Self.wrapOr( + c.mlirRegionCreate(), + ) orelse Error.InvalidMlir; + } + + pub fn appendBlock(self: *Self, block: Block) void { + c.mlirRegionAppendOwnedBlock(self.inner(), block.inner()); + } + + pub fn insertBlock(self: *Self, index: isize, block: Block) void { + c.mlirRegionInsertOwnedBlock(self.inner(), index, block.inner()); + } + + pub fn insertBlockBefore(self: *Self, reference: Block, block: Block) void { + c.mlirRegionInsertOwnedBlockBefore(self.inner(), reference.inner(), block.inner()); + } + + pub fn insertBlockAfter(self: *Self, reference: Block, block: Block) void { + c.mlirRegionInsertOwnedBlockAfter(self.inner(), reference.inner(), block.inner()); + } + + pub fn firstBlock(self: Self) Block { + return Block.wrap(c.mlirRegionGetFirstBlock(self.inner())); + } +}; + +pub const Value = struct { + _inner: c.MlirValue, + + pub usingnamespace MlirHelpers(Value, .{ + .is_null_fn = c.mlirValueIsNull, + .equal_fn = c.mlirValueEqual, + .dump_fn = c.mlirValueDump, + .print_fn = c.mlirValuePrint, + }); + + pub fn getType(val: Value) Type { + return Type.wrap(c.mlirValueGetType(val.inner())); + } + + pub fn setType(val: *Value, typ: Type) void { + c.mlirValueSetType(val.inner(), typ.inner()); + } + + pub fn firstUse(val: Value) OpOperand { + return OpOperand.wrap(c.mlirValueGetFirstUse(val.inner())); + } + + pub fn replaceAllUsesWith(val: Value, with: Value) void { + c.mlirValueReplaceAllUsesOfWith(val.inner(), with.inner()); + } + + pub fn owner(val: Value) Operation { + return Operation.wrap(c.mlirOpResultGetOwner(val.inner())); + } + + pub fn isABlockArgument(val: Value) bool { + return c.mlirValueIsABlockArgument(val.inner()); + } + + pub fn isAOpResult(val: Value) bool { + return c.mlirValueIsAOpResult(val.inner()); + } + + pub const Kind = enum { + unknown, + block_argument, + op_result, + }; + + pub fn kind(val: Value) Kind { + if (val.isAOpResult()) { + return .op_result; + } + if (val.isABlockArgument()) { + return .block_argument; + } + return .unknown; + } +}; + +pub const Type = struct { + _inner: c.MlirType, + + pub usingnamespace MlirHelpers(Type, .{ + .is_null_fn = c.mlirTypeIsNull, + .dump_fn = c.mlirTypeDump, + .equal_fn = c.mlirTypeEqual, + .print_fn = c.mlirTypePrint, + }); + + pub fn parse(ctx: Context, str: [:0]const u8) !Type { + return Type.wrapOr( + c.mlirTypeParseGet(ctx.inner(), stringRef(str)), + ) orelse Error.InvalidMlir; + } +}; + +pub const IntegerTypes = enum { + i1, + i4, + i8, + i16, + i32, + i64, + si4, + si8, + si16, + si32, + si64, + u4, + u8, + u16, + u32, + u64, + + unknown, +}; + +pub fn IntegerType(comptime it: IntegerTypes) type { + const Config = switch (it) { + .i1 => .{ 1, c.mlirIntegerTypeGet, c.mlirIntegerTypeIsSignless }, + .i4 => .{ 4, c.mlirIntegerTypeGet, c.mlirIntegerTypeIsSignless }, + .i8 => .{ 8, c.mlirIntegerTypeGet, c.mlirIntegerTypeIsSignless }, + .i16 => .{ 16, c.mlirIntegerTypeGet, c.mlirIntegerTypeIsSignless }, + .i32 => .{ 32, c.mlirIntegerTypeGet, c.mlirIntegerTypeIsSignless }, + .i64 => .{ 64, c.mlirIntegerTypeGet, c.mlirIntegerTypeIsSignless }, + .si4 => .{ 4, c.mlirIntegerTypeSignedGet, c.mlirIntegerTypeIsSigned }, + .si8 => .{ 8, c.mlirIntegerTypeSignedGet, c.mlirIntegerTypeIsSigned }, + .si16 => .{ 16, c.mlirIntegerTypeSignedGet, c.mlirIntegerTypeIsSigned }, + .si32 => .{ 32, c.mlirIntegerTypeSignedGet, c.mlirIntegerTypeIsSigned }, + .si64 => .{ 64, c.mlirIntegerTypeSignedGet, c.mlirIntegerTypeIsSigned }, + .u4 => .{ 4, c.mlirIntegerTypeUnsignedGet, c.mlirIntegerTypeIsUnsigned }, + .u8 => .{ 8, c.mlirIntegerTypeUnsignedGet, c.mlirIntegerTypeIsUnsigned }, + .u16 => .{ 16, c.mlirIntegerTypeUnsignedGet, c.mlirIntegerTypeIsUnsigned }, + .u32 => .{ 32, c.mlirIntegerTypeUnsignedGet, c.mlirIntegerTypeIsUnsigned }, + .u64 => .{ 64, c.mlirIntegerTypeUnsignedGet, c.mlirIntegerTypeIsUnsigned }, + .unknown => .{ 0, null, null }, + }; + + return struct { + _inner: c.MlirType, + + const Int = @This(); + pub usingnamespace MlirHelpers(Int, .{ + .is_a_fn = switch (it) { + .unknown => c.mlirTypeIsAInteger, + else => typeIsAIntegerExact, + }, + .is_null_fn = c.mlirTypeIsNull, + .dump_fn = c.mlirTypeDump, + .equal_fn = c.mlirTypeEqual, + }); + const IntegerTypeType = it; + + fn typeIsAIntegerExact(typ: c.MlirType) callconv(.C) bool { + const bit_width = Config[0]; + const is_sign = Config[2]; + return c.mlirTypeIsAInteger(typ) and (c.mlirIntegerTypeGetWidth(typ) == bit_width) and is_sign(typ); + } + pub usingnamespace if (it != .unknown) struct { + pub const BitWidth = Config[0]; + + pub fn init(ctx: Context) Int { + const type_get = Config[1]; + return Int.wrap(type_get(ctx.inner(), BitWidth)); + } + } else struct {}; + }; +} + +pub const FloatTypes = enum { + f8e4m3b11fnuz, + f8e4m3fn, + f8e4m3fnuz, + f8e5m2, + f8e5m2fnuz, + bf16, + f16, + f32, + f64, + + unknown, +}; + +pub fn FloatType(comptime ft: FloatTypes) type { + const Config = switch (ft) { + .f8e4m3b11fnuz => .{ c.mlirTypeIsAFloat8E4M3B11FNUZ, c.mlirFloat8E4M3B11FNUZTypeGet }, + .f8e4m3fn => .{ c.mlirTypeIsAFloat8E4M3FN, c.mlirFloat8E4M3FNTypeGet }, + .f8e4m3fnuz => .{ c.mlirTypeIsAFloat8E4M3FNUZ, c.mlirFloat8E4M3FNUZTypeGet }, + .f8e5m2 => .{ c.mlirTypeIsAFloat8E5M2, c.mlirFloat8E5M2TypeGet }, + .f8e5m2fnuz => .{ c.mlirTypeIsAFloat8E5M2FNUZ, c.mlirFloat8E5M2FNUZTypeGet }, + .bf16 => .{ c.mlirTypeIsABF16, c.mlirBF16TypeGet }, + .f16 => .{ c.mlirTypeIsAF16, c.mlirF16TypeGet }, + .f32 => .{ c.mlirTypeIsAF32, c.mlirF32TypeGet }, + .f64 => .{ c.mlirTypeIsAF64, c.mlirF64TypeGet }, + .unknown => .{ null, null }, + }; + + return struct { + _inner: c.MlirType, + const Float = @This(); + pub usingnamespace MlirHelpers(Float, .{ + .is_a_fn = switch (ft) { + .unknown => typeIsAUnknownFloat, + else => Config[0], + }, + .is_null_fn = c.mlirTypeIsNull, + .dump_fn = c.mlirTypeDump, + .equal_fn = c.mlirTypeEqual, + }); + + pub usingnamespace if (ft != .unknown) struct { + pub const FloatTypeType = ft; + + pub fn init(ctx: Context) Float { + const type_get = Config[1]; + return Float.wrap(type_get(ctx.inner())); + } + } else struct {}; + + fn typeIsAUnknownFloat(typ: c.MlirType) callconv(.C) bool { + const is_a_fns = .{ + c.mlirTypeIsABF16, + c.mlirTypeIsAF16, + c.mlirTypeIsAF32, + c.mlirTypeIsF64, + }; + inline for (is_a_fns) |is_a_fn| { + if (is_a_fn(typ)) { + return true; + } + } + return false; + } + }; +} + +pub const ComplexTypes = enum { + c64, + c128, + + unknown, +}; + +pub fn ComplexType(comptime ct: ComplexTypes) type { + return struct { + _inner: c.MlirType, + const Complex = @This(); + + fn mlirC64TypeGet(ctx: c.MlirContext) callconv(.C) c.MlirType { + return c.mlirComplexTypeGet(c.mlirF32TypeGet(ctx)); + } + + fn mlirC128TypeGet(ctx: c.MlirContext) callconv(.C) c.MlirType { + return c.mlirComplexTypeGet(c.mlirF64TypeGet(ctx)); + } + + fn mlirTypeIsAC64(typ: c.MlirType) callconv(.C) bool { + const element_type: c.MlirType = c.mlirComplexTypeGetElementType(typ); + return c.mlirTypeIsAF32(element_type); + } + + fn mlirTypeIsAC128(typ: c.MlirType) callconv(.C) bool { + const element_type: c.MlirType = c.mlirComplexTypeGetElementType(typ); + return c.mlirTypeIsAF64(element_type); + } + + const Config = switch (ct) { + .c64 => .{ mlirTypeIsAC64, mlirC64TypeGet }, + .c128 => .{ mlirTypeIsAC128, mlirC128TypeGet }, + .unknown => .{ c.mlirTypeIsAComplex, null }, + }; + + fn typeIsAUnknownComplex(typ: c.MlirType) callconv(.C) bool { + return c.mlirTypeIsAComplex(typ); + } + + pub usingnamespace MlirHelpers(@This(), .{ + .is_a_fn = Config[0], + .is_null_fn = c.mlirTypeIsNull, + .dump_fn = c.mlirTypeDump, + .equal_fn = c.mlirTypeEqual, + }); + + pub usingnamespace if (ct != .unknown) struct { + pub const ComplexTypeType = ct; + + pub fn init(ctx: Context) Complex { + const type_get = Config[1]; + return Complex.wrap(type_get(ctx.inner())); + } + } else struct {}; + }; +} + +pub const TupleType = struct { + _inner: c.MlirType, + pub usingnamespace MlirHelpers(TupleType, .{ + .is_a_fn = c.mlirTypeIsATuple, + .is_null_fn = c.mlirTypeIsNull, + .dump_fn = c.mlirTypeDump, + .equal_fn = c.mlirTypeEqual, + }); + + const Self = TupleType; + + pub fn init(ctx: Context, elements: []const Type) !Self { + return Self.wrapOr(c.mlirTupleTypeGet( + ctx.inner(), + @intCast(elements.len), + @ptrCast(elements.ptr), + )) orelse Error.InvalidMlir; + } + + pub fn getNumTypes(self: Self) usize { + return @intCast(c.mlirTupleTypeGetNumTypes(self.inner())); + } + + pub fn getElementType(self: Self, index: usize) Type { + return Type.wrap(c.mlirTupleTypeGetType(self.inner(), @intCast(index))); + } +}; + +pub const FunctionType = struct { + _inner: c.MlirType, + pub usingnamespace MlirHelpers(FunctionType, .{ + .is_a_fn = c.mlirTypeIsAFunction, + .is_null_fn = c.mlirTypeIsNull, + .dump_fn = c.mlirTypeDump, + .equal_fn = c.mlirTypeEqual, + }); + + const Self = FunctionType; + + pub fn init(ctx: Context, args: []const Type, results: []const Type) !Self { + return Self.wrapOr(c.mlirFunctionTypeGet( + ctx.inner(), + @intCast(args.len), + @ptrCast(args.ptr), + @intCast(results.len), + @ptrCast(results.ptr), + )) orelse Error.InvalidMlir; + } +}; + +pub const RankedTensorType = struct { + _inner: c.MlirType, + pub usingnamespace MlirHelpers(RankedTensorType, .{ + .is_a_fn = c.mlirTypeIsARankedTensor, + .is_null_fn = c.mlirTypeIsNull, + .dump_fn = c.mlirTypeDump, + .equal_fn = c.mlirTypeEqual, + .print_fn = c.mlirTypePrint, + }); + + pub fn init(dimensions: []const i64, elemType: Type) RankedTensorType { + return RankedTensorType.wrap( + c.mlirRankedTensorTypeGet( + @intCast(dimensions.len), + @ptrCast(dimensions.ptr), + elemType.inner(), + c.mlirAttributeGetNull(), + ), + ); + } + + pub fn getElementType(self: RankedTensorType) Type { + return Type.wrap(c.mlirShapedTypeGetElementType(self.inner())); + } + + pub fn getRank(self: RankedTensorType) usize { + return @intCast(c.mlirShapedTypeGetRank(self.inner())); + } + + pub fn getDimension(self: RankedTensorType, dim: usize) i64 { + return c.mlirShapedTypeGetDimSize(self.inner(), @intCast(dim)); + } +}; + +pub const Dialect = struct { + _inner: c.MlirDialect, + pub usingnamespace MlirHelpers(Dialect, .{ + .equal_fn = c.mlirDialectEqual, + .is_null_fn = c.mlirDialectIsNull, + }); + + const Self = Dialect; + + pub fn getContext(self: Self) Context { + return Context.wrap(c.mlirDialectGetContext(self.inner())); + } + + pub fn getNamespace(self: Self) []const u8 { + return fromStringRef(c.mlirDialectGetNamespace(self.inner())); + } +}; + +pub const DialectHandle = struct { + _inner: c.MlirDialectHandle, + pub usingnamespace MlirHelpers( + DialectHandle, + .{}, + ); + + pub fn getNamespace(self: DialectHandle) []const u8 { + return fromStringRef(c.mlirDialectHandleGetNamespace(self.inner())); + } + + pub fn insertDialect(self: DialectHandle, registry: Registry) void { + c.mlirDialectHandleInsertDialect(self.inner(), registry.inner()); + } + + pub fn registerDialect(self: DialectHandle, ctx: Context) void { + c.mlirDialectHandleRegisterDialect(self.inner(), ctx.inner()); + } + + pub fn loadDialect(self: DialectHandle, ctx: Context) Dialect { + return Dialect.wrap(c.mlirDialectHandleLoadDialect(self.inner(), ctx.inner())); + } + + pub fn fromString(comptime namespace: []const u8) DialectHandle { + return DialectHandle.wrap(@field(c, "mlirGetDialectHandle__" ++ namespace ++ "__")()); + } +}; + +// pub const AnyQuantizedType = MlirWrapperType(c.MlirType, .{ +// .is_a_fn = c.mlirTypeIsAAnyQuantizedType, +// .is_null_fn = c.mlirTypeIsNull, +// .dump_fn = c.mlirTypeDump, +// .equal_fn = c.mlirTypeEqual, +// }, struct { +// const Self = AnyQuantizedType; + +// pub fn init( +// flags: quant.QuantizationFlags, +// storageType: Type, +// expressedType: Type, +// storageTypeMin: i64, +// storageTypeMax: i64, +// ) Self { +// return Self.wrap(c.mlirAnyQuantizedTypeGet( +// @intCast(@intFromEnum(flags)), +// storageType.inner(), +// expressedType.inner(), +// storageTypeMin, +// storageTypeMax, +// )); +// } + +// pub fn getExpressedType(self: Self) Type { +// return Type.wrap(c.mlirQuantizedTypeGetExpressedType(self.inner())); +// } + +// pub fn getFlags(self: Self) quant.QuantizationFlags { +// return @enumFromInt(c.mlirQuantizedTypeGetFlags(self.inner())); +// } + +// pub fn isSigned(self: Self) bool { +// return c.mlirQuantizedTypeIsSigned(self.inner()); +// } + +// pub fn getStorageType(self: Self) Type { +// return Type.wrap(c.mlirQuantizedTypeGetStorageType(self.inner())); +// } + +// pub fn getStorageTypeMin(self: Self) i64 { +// return c.mlirQuantizedTypeGetStorageTypeMin(self.inner()); +// } + +// pub fn getStorageTypeMax(self: Self) i64 { +// return c.mlirQuantizedTypeGetStorageTypeMax(self.inner()); +// } + +// pub fn getStorageTypeIntegralWidth(self: Self) c_uint { +// return c.mlirQuantizedTypeGetStorageTypeIntegralWidth(self.inner()); +// } + +// pub fn getQuantizedElementType(self: Self) Type { +// return Type.wrap(c.mlirQuantizedTypeGetQuantizedElementType(self.inner())); +// } +// }); + +// pub const UniformQuantizedType = MlirWrapperType(c.MlirType, .{ +// .is_a_fn = c.mlirTypeIsAUniformQuantizedType, +// .is_null_fn = c.mlirTypeIsNull, +// .dump_fn = c.mlirTypeDump, +// .equal_fn = c.mlirTypeEqual, +// }, struct { +// const Self = AnyQuantizedType; + +// pub fn init( +// flags: quant.QuantizationFlags, +// storageType: Type, +// expressedType: Type, +// scale: f64, +// zeroPoint: i64, +// storageTypeMin: i64, +// storageTypeMax: i64, +// ) Self { +// return Self.wrap(c.mlirUniformQuantizedTypeGet( +// @intCast(@intFromEnum(flags)), +// storageType.inner(), +// expressedType.inner(), +// scale, +// zeroPoint, +// storageTypeMin, +// storageTypeMax, +// )); +// } + +// pub fn getExpressedType(self: Self) Type { +// return Type.wrap(c.mlirQuantizedTypeGetExpressedType(self.inner())); +// } + +// pub fn getFlags(self: Self) quant.QuantizationFlags { +// return @enumFromInt(c.mlirQuantizedTypeGetFlags(self.inner())); +// } + +// pub fn isSigned(self: Self) bool { +// return c.mlirQuantizedTypeIsSigned(self.inner()); +// } + +// pub fn getStorageType(self: Self) Type { +// return Type.wrap(c.mlirQuantizedTypeGetStorageType(self.inner())); +// } + +// pub fn getStorageTypeMin(self: Self) i64 { +// return c.mlirQuantizedTypeGetStorageTypeMin(self.inner()); +// } + +// pub fn getStorageTypeMax(self: Self) i64 { +// return c.mlirQuantizedTypeGetStorageTypeMax(self.inner()); +// } + +// pub fn getStorageTypeIntegralWidth(self: Self) c_uint { +// return c.mlirQuantizedTypeGetStorageTypeIntegralWidth(self.inner()); +// } + +// pub fn getQuantizedElementType(self: Self) Type { +// return Type.wrap(c.mlirQuantizedTypeGetQuantizedElementType(self.inner())); +// } + +// pub fn getScale(self: Self) f64 { +// return c.mlirUniformQuantizedTypeGetScale(self.inner()); +// } + +// pub fn getZeroPoint(self: Self) i64 { +// return c.mlirUniformQuantizedTypeGetZeroPoint(self.inner()); +// } + +// pub fn isFixedPoint(self: Self) bool { +// return c.mlirUniformQuantizedTypeIsFixedPoint(self.inner()); +// } +// }); + +// pub const QuantizedPerAxisType = MlirWrapperType(c.MlirType, .{ +// .is_a_fn = c.mlirTypeIsAUniformQuantizedPerAxisType, +// .is_null_fn = c.mlirTypeIsNull, +// .dump_fn = c.mlirTypeDump, +// .equal_fn = c.mlirTypeEqual, +// }, struct { +// const Self = AnyQuantizedType; + +// pub fn init( +// flags: quant.QuantizationFlags, +// storageType: Type, +// expressedType: Type, +// nDims: usize, +// scales: []f64, +// zeroPoints: []i64, +// quantizedDimension: i32, +// storageTypeMin: i64, +// storageTypeMax: i64, +// ) Self { +// std.debug.assert(scales.len == nDims); +// std.debug.assert(zeroPoints.len == nDims); +// return Self.wrap(c.mlirUniformQuantizedPerAxisTypeGet( +// @intCast(@intFromEnum(flags)), +// storageType.inner(), +// expressedType.inner(), +// @intCast(nDims), +// scales.ptr, +// zeroPoints.ptr, +// quantizedDimension, +// storageTypeMin, +// storageTypeMax, +// )); +// } + +// pub fn getExpressedType(self: Self) Type { +// return Type.wrap(c.mlirQuantizedTypeGetExpressedType(self.inner())); +// } + +// pub fn getFlags(self: Self) quant.QuantizationFlags { +// return @enumFromInt(c.mlirQuantizedTypeGetFlags(self.inner())); +// } + +// pub fn isSigned(self: Self) bool { +// return c.mlirQuantizedTypeIsSigned(self.inner()); +// } + +// pub fn getStorageType(self: Self) Type { +// return Type.wrap(c.mlirQuantizedTypeGetStorageType(self.inner())); +// } + +// pub fn getStorageTypeMin(self: Self) i64 { +// return c.mlirQuantizedTypeGetStorageTypeMin(self.inner()); +// } + +// pub fn getStorageTypeMax(self: Self) i64 { +// return c.mlirQuantizedTypeGetStorageTypeMax(self.inner()); +// } + +// pub fn getStorageTypeIntegralWidth(self: Self) c_uint { +// return c.mlirQuantizedTypeGetStorageTypeIntegralWidth(self.inner()); +// } + +// pub fn getQuantizedElementType(self: Self) Type { +// return Type.wrap(c.mlirQuantizedTypeGetQuantizedElementType(self.inner())); +// } + +// pub fn getNumDims(self: Self) usize { +// return @intCast(c.mlirUniformQuantizedPerAxisTypeGetNumDims(self.inner())); +// } + +// pub fn getScale(self: Self) f64 { +// return @intCast(c.mlirUniformQuantizedPerAxisTypeGetScale(self.inner())); +// } + +// pub fn getZeroPoint(self: Self, pos: usize) i64 { +// return c.mlirUniformQuantizedPerAxisTypeGetZeroPoint(self.inner(), @intCast(pos)); +// } + +// pub fn getQuantizedDimension(self: Self) i32 { +// return c.mlirUniformQuantizedPerAxisTypeGetQuantizedDimension(self.inner()); +// } + +// pub fn isFixedPoint(self: Self) bool { +// return c.mlirUniformQuantizedPerAxisTypeIsFixedPoint(self.inner()); +// } +// }); + +// pub const CalibratedQuantizedType = MlirWrapperType(c.MlirType, .{ +// .is_a_fn = c.mlirTypeIsACalibratedQuantizedType, +// .is_null_fn = c.mlirTypeIsNull, +// .dump_fn = c.mlirTypeDump, +// .equal_fn = c.mlirTypeEqual, +// }, struct { +// const Self = AnyQuantizedType; + +// pub fn init(expressedType: Type, min: f64, max: f64) Self { +// return Self.wrap(c.mlirCalibratedQuantizedTypeGet(expressedType.inner(), min, max)); +// } + +// pub fn getExpressedType(self: Self) Type { +// return Type.wrap(c.mlirQuantizedTypeGetExpressedType(self.inner())); +// } + +// pub fn getFlags(self: Self) quant.QuantizationFlags { +// return @enumFromInt(c.mlirQuantizedTypeGetFlags(self.inner())); +// } + +// pub fn isSigned(self: Self) bool { +// return c.mlirQuantizedTypeIsSigned(self.inner()); +// } + +// pub fn getStorageType(self: Self) Type { +// return Type.wrap(c.mlirQuantizedTypeGetStorageType(self.inner())); +// } + +// pub fn getStorageTypeMin(self: Self) i64 { +// return c.mlirQuantizedTypeGetStorageTypeMin(self.inner()); +// } + +// pub fn getStorageTypeMax(self: Self) i64 { +// return c.mlirQuantizedTypeGetStorageTypeMax(self.inner()); +// } + +// pub fn getStorageTypeIntegralWidth(self: Self) c_uint { +// return c.mlirQuantizedTypeGetStorageTypeIntegralWidth(self.inner()); +// } + +// pub fn getQuantizedElementType(self: Self) Type { +// return Type.wrap(c.mlirQuantizedTypeGetQuantizedElementType(self.inner())); +// } + +// pub fn getMin(self: Self) f64 { +// return c.mlirCalibratedQuantizedTypeGetMin(self.inner()); +// } + +// pub fn getMax(self: Self) f64 { +// return c.mlirCalibratedQuantizedTypeGetMax(self.inner()); +// } +// }); + +pub const ShapedType = struct { + _inner: c.MlirType, + pub usingnamespace MlirHelpers(ShapedType, .{ + .is_a_fn = c.mlirTypeIsAShaped, + .is_null_fn = c.mlirTypeIsNull, + .dump_fn = c.mlirTypeDump, + .equal_fn = c.mlirTypeEqual, + }); + const Self = ShapedType; + + pub fn rank(self: Self) usize { + return @intCast(c.mlirShapedTypeGetRank(self.inner())); + } + + pub fn elementType(self: Self) Type { + return Type.wrap(c.mlirShapedTypeGetElementType(self.inner())); + } + + pub fn dimension(self: Self, dim: usize) usize { + return @intCast(c.mlirShapedTypeGetDimSize(self.inner(), @intCast(dim))); + } +}; + +pub const Location = struct { + _inner: c.MlirLocation, + + pub usingnamespace MlirHelpers(Location, .{ + .is_null_fn = c.mlirLocationIsNull, + .equal_fn = c.mlirLocationEqual, + .print_fn = c.mlirLocationPrint, + }); + + pub fn fromSrc(ctx: Context, src: std.builtin.SourceLocation) Location { + return Location.wrap(c.mlirLocationFileLineColGet( + ctx.inner(), + stringRef(src.file), + @intCast(src.line), + @intCast(src.column), + )); + } + + pub fn fileLineCol(ctx: Context, file: []const u8, line: usize, column: usize) Location { + return Location.wrap(c.mlirLocationFileLineColGet( + ctx.inner(), + stringRef(file), + @intCast(line), + @intCast(column), + )); + } + + pub fn callSite(callee: Location, caller: Location) Location { + return Location.wrap(c.mlirLocationCallSiteGet(callee.inner(), caller.inner())); + } + + pub fn fused(ctx: Context, locations: []const Location, metadata: Attribute) Location { + return Location.wrap(c.mlirLocationFusedGet( + ctx.inner(), + @intCast(locations.len), + @ptrCast(locations.ptr), + metadata.inner(), + )); + } + + pub fn named(loc: Location, ctx: Context, loc_name: [:0]const u8) Location { + return Location.wrap(c.mlirLocationNameGet(ctx.inner(), stringRef(loc_name), loc.inner())); + } + + pub fn namedFmt(loc: Location, ctx: Context, comptime fmt: [:0]const u8, args: anytype) Location { + var buf: [256]u8 = undefined; + var stream = std.io.fixedBufferStream(&buf); + std.fmt.format(stream.writer(), fmt, args) catch { + buf[256 - 3 ..].* = "...".*; + }; + return loc.named(ctx, @ptrCast(stream.getWritten())); + } + + pub fn unknown(ctx: Context) Location { + return Location.wrap(c.mlirLocationUnknownGet(ctx.inner())); + } +}; + +pub const Block = struct { + _inner: c.MlirBlock, + pub usingnamespace MlirHelpers(Block, .{ + .is_null_fn = c.mlirBlockIsNull, + .deinit_fn = c.mlirBlockDestroy, + .equal_fn = c.mlirBlockEqual, + }); + + pub fn init(args: []const Type, locs: []const Location) !Block { + const block = Block.wrapOr( + c.mlirBlockCreate(@intCast(args.len), @ptrCast(args.ptr), @ptrCast(locs.ptr)), + ); + return block orelse error.InvalidMlir; + } + + pub fn argument(self: Block, index: usize) Value { + return Value.wrap(c.mlirBlockGetArgument(self.inner(), @intCast(index))); + } + + pub fn numArguments(self: Block) usize { + return @intCast(c.mlirBlockGetNumArguments(self.inner())); + } + + pub fn addArgument(self: *Block, typ: Type, loc: Location) Value { + return Value.wrap(c.mlirBlockAddArgument(self.inner(), typ.inner(), loc.inner())); + } + + pub fn insertArgument(self: *Block, index: usize, typ: Type, loc: Location) Value { + return Value.wrap(c.mlirBlockInsertArgument(self.inner(), @intCast(index), typ.inner(), loc.inner())); + } + + pub fn equals(self: Block, other: Block) bool { + return c.mlirBlockEqual(self.inner(), other.inner()); + } + + pub fn appendOperation(self: Block, op: Operation) void { + c.mlirBlockAppendOwnedOperation(self.inner(), op.inner()); + } + + pub fn appendOperations(self: *Block, ops: []const Operation) void { + for (ops) |op| { + c.mlirBlockAppendOwnedOperation(self.inner(), op.inner()); + } + } + + pub fn addOperationsRecursive(block: *Block, op_or_result: anytype) void { + const op: Operation = switch (@TypeOf(op_or_result)) { + Operation => op_or_result, + Value => if (op_or_result.kind() == .op_result) op_or_result.owner() else return, + else => |t| @compileError("can either be an operation or a value, not " ++ @typeName(t)), + }; + if (op.block()) |prev_block| { + std.debug.assert(prev_block.equals(block.*)); + return; + } + for (0..op.numOperands()) |i| { + block.addOperationsRecursive(op.operand(i)); + } + block.appendOperation(op); + } +}; diff --git a/mlir/mlirx.cc b/mlir/mlirx.cc new file mode 100644 index 0000000..f5fd45f --- /dev/null +++ b/mlir/mlirx.cc @@ -0,0 +1,27 @@ +#include "mlir/IR/Attributes.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/CAPI/IR.h" +#include "mlir/CAPI/Support.h" +#include "mlirx.h" + +namespace mlirx { + + static mlir::Attribute ArrayToElements(mlir::Attribute attr) { + if (auto array = attr.dyn_cast()) { + return mlir::DenseIntElementsAttr::get( + mlir::RankedTensorType::get(array.size(), array.getElementType()), + array.asArrayRef()); + } + if (auto array = attr.dyn_cast()) { + return mlir::DenseIntElementsAttr::get( + mlir::RankedTensorType::get(array.size(), array.getElementType()), + array.asArrayRef()); + } + return attr; + } + +} + +MlirAttribute mlirDenseArrayToElements(MlirAttribute attr) { + return wrap(mlirx::ArrayToElements(unwrap(attr))); +} diff --git a/mlir/mlirx.h b/mlir/mlirx.h new file mode 100644 index 0000000..9946477 --- /dev/null +++ b/mlir/mlirx.h @@ -0,0 +1,16 @@ +#ifndef MLIRX_CC_H +#define MLIRX_CC_H + +#include "mlir-c/IR.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MLIR_CAPI_EXPORTED MlirAttribute mlirDenseArrayToElements(MlirAttribute attr); + +#ifdef __cplusplus +} +#endif + +#endif // MLIRX_CC_H diff --git a/pjrt/BUILD.bazel b/pjrt/BUILD.bazel new file mode 100644 index 0000000..4882d87 --- /dev/null +++ b/pjrt/BUILD.bazel @@ -0,0 +1,30 @@ +load("@rules_zig//zig:defs.bzl", "zig_library") +load("//bazel:zig_proto_library.bzl", "zig_proto_library") + +cc_library( + name = "dlfcn", + hdrs = ["dlfcn.h"], +) + +zig_library( + name = "pjrt", + srcs = ["profiler.zig"], + main = "pjrt.zig", + visibility = ["//visibility:public"], + deps = [ + ":profiler_options_proto", + "//runtimes", + "@xla//xla/pjrt/c:pjrt_c_api_gpu_extension_hdrs", + "@xla//xla/pjrt/c:pjrt_c_api_hdrs", + "@xla//xla/pjrt/c:pjrt_c_api_profiler_extension_hdrs", + ] + select({ + "@platforms//os:linux": [":dlfcn"], + "//conditions:default": [], + }), +) + +zig_proto_library( + name = "profiler_options_proto", + import_name = "//tsl:profiler_options_proto", + deps = ["@tsl//tsl/profiler/protobuf:profiler_options_proto"], +) diff --git a/pjrt/dlfcn.h b/pjrt/dlfcn.h new file mode 100644 index 0000000..9e446a2 --- /dev/null +++ b/pjrt/dlfcn.h @@ -0,0 +1 @@ +#include diff --git a/pjrt/pjrt.zig b/pjrt/pjrt.zig new file mode 100644 index 0000000..14d040d --- /dev/null +++ b/pjrt/pjrt.zig @@ -0,0 +1,886 @@ +const builtin = @import("builtin"); +const std = @import("std"); + +const c = @import("c"); + +const log = std.log.scoped(.pjrt); + +pub const Profiler = @import("profiler.zig").Profiler; + +test { + std.testing.refAllDecls(@This()); +} + +// We could calculate it like PJRT does, but it turns out that some of those +// were wrong in PJRT itself [1], which gets propagated to binary plugins. In +// order to mirror that, we just the value as computed by PJRT itself, through +// comptime reflection. We could make the argument to remove that one day since +// [1] has been fixed. The problem is that this problem could happen again in +// as the way PJRT does it is not very robust. +// +// 1. https://github.com/openxla/xla/issues/10032 +fn pjrtStructSize(comptime T: type) usize { + // unsafe on purpose, we want this to fail if that ever changes + const typedef_name = comptime blk: { + const needle = ".struct_"; + const idx = std.mem.indexOf(u8, @typeName(T), needle).?; + break :blk @typeName(T)[idx + needle.len ..]; + }; + return @field(c, typedef_name ++ "_STRUCT_SIZE"); +} + +inline fn pjrtStruct(v: anytype) @TypeOf(v) { + var ret = v; + ret.struct_size = pjrtStructSize(@TypeOf(v)); + return ret; +} + +pub const ApiError = error{ + Cancelled, + Unknown, + InvalidArgument, + DeadlineExceeded, + NotFound, + AlreadyExists, + PermissionDenied, + ResourceExhausted, + FailedPrecondition, + Aborted, + OutOfRange, + Unimplemented, + Internal, + Unavailable, + DataLoss, + Unauthenticated, +}; + +fn InnerMixin(comptime innerT: type) type { + return struct { + fn inner(self: anytype) *innerT { + return @ptrCast(@constCast(@alignCast(self))); + } + }; +} + +pub const Api = struct { + pub const Version = struct { + major: i64, + minor: i64, + }; + + const Funcs = std.meta.FieldEnum(c.PJRT_Api); + + inner: c.PJRT_Api, + + pub fn loadFrom(library: []const u8) !*const Api { + var lib: std.DynLib = switch (builtin.os.tag) { + .linux => blk: { + const library_c = try std.posix.toPosixPath(library); + break :blk .{ + .inner = .{ + .handle = c.dlopen(&library_c, c.RTLD_LAZY | c.RTLD_LOCAL | c.RTLD_NODELETE) orelse { + return error.FileNotFound; + }, + }, + }; + }, + else => try std.DynLib.open(library), + }; + const DynGetPjrtApi = lib.lookup(*const fn () callconv(.C) *const Api, "GetPjrtApi") orelse { + std.debug.panic("Unable to find GetPjrtApi symbol in library: {s}", .{library}); + }; + + const api = DynGetPjrtApi(); + log.info("Loaded library: {s}", .{library}); + _ = api.call(.PJRT_Plugin_Initialize, .{}) catch unreachable; + + return api; + } + + fn CallFnArgType(comptime func: Funcs) type { + const fti = @typeInfo(std.meta.FieldType(c.PJRT_Api, func)); + const fn_ptr = @typeInfo(fti.Optional.child); + const fn_type_info = @typeInfo(fn_ptr.Pointer.child); + const arg_array_type_info = @typeInfo(fn_type_info.Fn.params[0].type.?); + return arg_array_type_info.Pointer.child; + } + + inline fn call(self: *const Api, comptime method: Funcs, arg: CallFnArgType(method)) ApiError!@TypeOf(arg) { + var ret = pjrtStruct(arg); + const fn_ptr = @field(&self.inner, @tagName(method)).?; + const result = fn_ptr(&ret); + if (@TypeOf(result) == void) { + return ret; + } + + if (result) |pjrt_c_error| { + const pjrt_error: *Error = @ptrCast(pjrt_c_error); + log.err("[{s}] {s}", .{ @tagName(method), pjrt_error.getMessage(self) }); + return pjrt_error.getCode(self).toApiError(); + } + + return ret; + } + + pub fn lookupExtension(self: *const Api, comptime ExtensionT: type, ext_id: c_int) ?*const ExtensionT { + var cur: [*c]const c.PJRT_Extension_Base = @alignCast(@ptrCast(self.inner.extension_start)); + while (cur != null) : (cur = cur.*.next) { + if (cur.*.type == ext_id) { + return @alignCast(@ptrCast(cur)); + } + } + + return null; + } + + pub inline fn version(self: *const Api) Version { + return .{ + .major = @intCast(self.inner.pjrt_api_version.major_version), + .minor = @intCast(self.inner.pjrt_api_version.minor_version), + }; + } +}; + +pub const ErrorCode = enum(c.PJRT_Error_Code) { + cancelled = c.PJRT_Error_Code_CANCELLED, + unknown = c.PJRT_Error_Code_UNKNOWN, + invalid_argument = c.PJRT_Error_Code_INVALID_ARGUMENT, + deadline_exceeded = c.PJRT_Error_Code_DEADLINE_EXCEEDED, + not_found = c.PJRT_Error_Code_NOT_FOUND, + already_exists = c.PJRT_Error_Code_ALREADY_EXISTS, + permission_denied = c.PJRT_Error_Code_PERMISSION_DENIED, + resource_exhausted = c.PJRT_Error_Code_RESOURCE_EXHAUSTED, + failed_precondition = c.PJRT_Error_Code_FAILED_PRECONDITION, + aborted = c.PJRT_Error_Code_ABORTED, + out_of_range = c.PJRT_Error_Code_OUT_OF_RANGE, + unimplemented = c.PJRT_Error_Code_UNIMPLEMENTED, + internal = c.PJRT_Error_Code_INTERNAL, + unavailable = c.PJRT_Error_Code_UNAVAILABLE, + data_loss = c.PJRT_Error_Code_DATA_LOSS, + unauthenticated = c.PJRT_Error_Code_UNAUTHENTICATED, + + pub fn toApiError(code: ErrorCode) ApiError { + return switch (code) { + .cancelled => error.Cancelled, + .unknown => error.Unknown, + .invalid_argument => error.InvalidArgument, + .deadline_exceeded => error.DeadlineExceeded, + .not_found => error.NotFound, + .already_exists => error.AlreadyExists, + .permission_denied => error.PermissionDenied, + .resource_exhausted => error.ResourceExhausted, + .failed_precondition => error.FailedPrecondition, + .aborted => error.Aborted, + .out_of_range => error.OutOfRange, + .unimplemented => error.Unimplemented, + .internal => error.Internal, + .unavailable => error.Unavailable, + .data_loss => error.DataLoss, + .unauthenticated => error.Unauthenticated, + }; + } +}; + +pub const Error = opaque { + pub fn deinit(self: *Error, api: *const Api) void { + _ = api.call(.PJRT_Error_Destroy, .{ + .@"error" = @ptrCast(self), + }) catch unreachable; + } + + pub fn getCode(self: *Error, api: *const Api) ErrorCode { + const ret = api.call(.PJRT_Error_GetCode, .{ + .@"error" = @ptrCast(self), + }) catch unreachable; + return @enumFromInt(ret.code); + } + + pub fn getMessage(self: *Error, api: *const Api) []const u8 { + const ret = api.call(.PJRT_Error_Message, .{ + .@"error" = @ptrCast(self), + }) catch unreachable; + return ret.message[0..ret.message_size]; + } +}; + +pub const ClientInitError = error{LoadingFailed} || ApiError; + +pub const Client = opaque { + const inner = InnerMixin(c.PJRT_Client).inner; + + pub const ProgramFormat = enum { + hlo, + mlir, + }; + + pub fn init(api: *const Api, create_options: []const NamedValue) ClientInitError!*Client { + // log.info("Loaded PJRT runtime plugin: {s}", .{api.Platform}); + const ret = try api.call(.PJRT_Client_Create, .{ + .create_options = @ptrCast(create_options.ptr), + .num_options = create_options.len, + .kv_get_callback = null, + .kv_put_callback = null, + .kv_put_user_arg = null, + .kv_get_user_arg = null, + }); + return @ptrCast(ret.client.?); + } + + pub fn deinit(self: *Client, api: *const Api) void { + _ = api.call(.PJRT_Client_Destroy, .{ + .client = self.inner(), + }) catch {}; + } + + pub fn getPlatformName(self: *const Client, api: *const Api) []const u8 { + const ret = api.call(.PJRT_Client_PlatformName, .{ + .client = self.inner(), + }) catch unreachable; + return ret.platform_name[0..ret.platform_name_size]; + } + + pub fn getDevices(self: *const Client, api: *const Api) []const *Device { + const ret = api.call(.PJRT_Client_Devices, .{ + .client = self.inner(), + }) catch unreachable; + return @ptrCast(ret.devices[0..ret.num_devices]); + } + + pub fn getAddressableDevices(self: *const Client, api: *const Api) []const *Device { + const ret = api.call(.PJRT_Client_AddressableDevices, .{ + .client = self.inner(), + }) catch unreachable; + return @ptrCast(ret.addressable_devices[0..ret.num_addressable_devices]); + } + + pub const CompileArgs = struct { + bytecode: []const u8, + bytecode_format: ProgramFormat, + compile_options_pb: []const u8, + }; + + pub fn compile(self: *const Client, api: *const Api, args: CompileArgs) ApiError!*LoadedExecutable { + const bytecode_format_ = @tagName(args.bytecode_format); + const ret = try api.call(.PJRT_Client_Compile, .{ + .program = &pjrtStruct(c.PJRT_Program{ + .code = @ptrCast(@constCast(args.bytecode.ptr)), + .code_size = args.bytecode.len, + .format = @ptrCast(@constCast(bytecode_format_.ptr)), + .format_size = bytecode_format_.len, + }), + .compile_options = @ptrCast(@constCast(args.compile_options_pb.ptr)), + .compile_options_size = args.compile_options_pb.len, + .client = self.inner(), + }); + return @ptrCast(ret.executable.?); + } + + pub const BufferFromHostBufferArgs = struct { + data: []const u8, + buffer_type: BufferType, + dims: []const i64, + byte_strides: ?[]const i64, + device: *const Device, + host_buffer_semantics: HostBufferSemantics, + }; + + pub fn bufferFromHostBuffer(self: *const Client, api: *const Api, args: BufferFromHostBufferArgs) ApiError!struct { *Buffer, *Event } { + const ret = try api.call(.PJRT_Client_BufferFromHostBuffer, .{ + .client = self.inner(), + .data = @ptrCast(@constCast(args.data.ptr)), + .type = @intFromEnum(args.buffer_type), + .dims = @ptrCast(@constCast(args.dims.ptr)), + .num_dims = args.dims.len, + .byte_strides = if (args.byte_strides) |bs| @ptrCast(@constCast(bs.ptr)) else null, + .num_byte_strides = if (args.byte_strides) |bs| bs.len else 0, + .host_buffer_semantics = @intFromEnum(args.host_buffer_semantics), + .device = @ptrCast(@constCast(args.device)), + .memory = null, // TODO + .device_layout = null, // TODO + .done_with_host_buffer = null, + .buffer = null, + }); + return .{ + @ptrCast(ret.buffer.?), + @ptrCast(ret.done_with_host_buffer.?), + }; + } + + /// Returns the Profiler for this API. + /// Not all platform have a profiling api, for those the profiler object will do nothing. + /// Platforms with known profiler extensions: cuda, xpu + pub fn getProfiler(self: *const Client, api: *const Api, options: Profiler.Options) Profiler { + if (api.version().minor >= 45) { + if (api.lookupExtension(c.PJRT_Profiler_Extension, c.PJRT_Extension_Type_Profiler)) |ext| { + return Profiler.init(ext.profiler_api.*, options); + } + } + log.warn("No profiler found for platform: {}", .{self}); + return Profiler.init(null, options); + } + + // pub fn getGpuCustomCallRegistry(self: *const Client, api: *const Api) ?*GpuCustomCallRegistry { + // if (api.lookupExtension(c.PJRT_Gpu_Custom_Call, c.PJRT_Extension_Type_Gpu_Custom_Call)) |ext| { + // return .{ .custom_call_register = ext.custom_call.? }; + // } + // log.warn("No Gpu Custom Call registry found for platform: {}", .{self}); + // return null; + // } + + pub fn deserializeAndLoad(self: *const Client, api: *const Api, bytes: []const u8) ApiError!*LoadedExecutable { + const ret = try api.call(.PJRT_Executable_DeserializeAndLoad, .{ + .client = self.inner(), + .serialized_executable = bytes.ptr, + .serialized_executable_size = bytes.len, + }); + return @ptrCast(ret.loaded_executable.?); + } + + pub const CreateViewOfDeviceBufferArgs = struct { + data: []const u8, + dims: []const i64, + element_type: BufferType, + layout: MemoryLayout, + device: *const Device, + on_delete_callback: ?*const fn (device_buffer_ptr: ?*anyopaque, ctx: ?*anyopaque) callconv(.C) void = null, + on_delete_callback_arg: ?*anyopaque = null, + stream: ?isize = null, + }; + + pub fn createViewOfDeviceBuffer(self: *const Client, api: *const Api, args: CreateViewOfDeviceBufferArgs) ApiError!*Buffer { + const layout = args.layout.toCStruct(); + const ret = try api.call(.PJRT_Client_CreateViewOfDeviceBuffer, .{ + .client = self.inner(), + .device_buffer_ptr = @ptrCast(@constCast(args.data.ptr)), + .dims = args.dims.ptr, + .num_dims = args.dims.len, + .element_type = @intFromEnum(args.element_type), + .layout = @ptrCast(@constCast(&layout)), + .device = @ptrCast(@constCast(args.device)), + .on_delete_callback = args.on_delete_callback, + .on_delete_callback_arg = args.on_delete_callback_arg, + .stream = if (args.stream) |stream| stream else 0, + }); + return @ptrCast(ret.buffer.?); + } +}; + +// // pub const CustomCallSignature = *const fn (*anyopaque, **anyopaque, [*c]const u8, usize) callconv(.C) void; + +// // pub const GpuCustomCallRegistry = struct { +// // custom_call_register: *const c.PJRT_Gpu_Register_Custom_Call, + +// // pub fn registerCustomCall(self: GpuCustomCallRegistry, api: *const Api, api_version: usize, name: []const u8, func: CustomCallSignature) ApiError!void { +// // var ret = pjrtStruct(c.PJRT_Gpu_Register_Custom_Call_Args{ +// // .function_name = name.ptr, +// // .function_name_size = name.len, +// // .api_version = @intCast(api_version), +// // .custom_call_function = @ptrCast(@constCast(func)), +// // }); +// // const result = self.custom_call_register(&ret); +// // if (result) |pjrt_c_error| { +// // const pjrt_error = .{ .inner = pjrt_c_error }; +// // log.err("{s}", .{pjrt_error.getMessage(api)}); +// // return pjrt_error.getCode().toApiError(); +// // } +// // } +// // }; + +// // const OldPjrtExtension = extern struct { +// // type: c.PJRT_Extension_Type, +// // next: [*]OldPjrtExtension, +// // }; + +pub const Device = opaque { + const inner = InnerMixin(c.PJRT_Device).inner; + + pub fn getDescription(self: *const Device, api: *const Api) *const DeviceDescription { + const ret = api.call(.PJRT_Device_GetDescription, .{ + .device = self.inner(), + }) catch unreachable; + return @ptrCast(ret.device_description.?); + } + + pub fn isAddressable(self: *const Device, api: *const Api) bool { + const ret = api.call(.PJRT_Device_IsAddressable, .{ + .device = self.inner(), + }) catch unreachable; + return ret.is_addressable; + } + + pub fn getLocalHardwareId(self: *const Device, api: *const Api) usize { + const ret = api.call(.PJRT_Device_LocalHardwareId, .{ + .device = self.inner(), + }) catch unreachable; + return @intCast(ret.local_hardware_id); + } +}; + +pub const DeviceDescription = opaque { + const inner = InnerMixin(c.PJRT_DeviceDescription).inner; + + pub fn getId(self: *const DeviceDescription, api: *const Api) usize { + const ret = api.call(.PJRT_DeviceDescription_Id, .{ + .device_description = self.inner(), + }) catch unreachable; + return @intCast(ret.id); + } + + pub fn getProcessIndex(self: *const DeviceDescription, api: *const Api) usize { + const ret = api.call(.PJRT_DeviceDescription_ProcessIndex, .{ + .device_description = self.inner(), + }) catch unreachable; + return @intCast(ret.process_index); + } + + pub fn getKind(self: *const DeviceDescription, api: *const Api) []const u8 { + const ret = api.call(.PJRT_DeviceDescription_Kind, .{ + .device_description = self.inner(), + }) catch unreachable; + return ret.device_kind[0..ret.device_kind_size]; + } + + pub fn debugString(self: *const DeviceDescription, api: *const Api) []const u8 { + const ret = api.call(.PJRT_DeviceDescription_DebugString, .{ + .device_description = self.inner(), + }) catch unreachable; + return ret.debug_string[0..ret.debug_string_size]; + } + + pub fn toString(self: *const DeviceDescription, api: *const Api) []const u8 { + const ret = api.call(.PJRT_DeviceDescription_ToString, .{ + .device_description = self.inner(), + }) catch unreachable; + return ret.to_string[0..ret.to_string_size]; + } +}; + +pub const GetCostAnalysisError = std.mem.Allocator.Error || ApiError; + +pub const SerializeResult = struct { + bytes: []const u8, + handle: *anyopaque, + deleter: *const fn (?*anyopaque) callconv(.C) void, + + pub fn deinit(self: *SerializeResult) void { + self.deleter(self.handle); + self.bytes = &.{}; + self.* = undefined; + } +}; + +pub const Executable = opaque { + const inner = InnerMixin(c.PJRT_Executable).inner; + + pub fn deinit(self: *Executable, api: *const Api) void { + _ = api.call(.PJRT_Executable_Destroy, .{ + .executable = self.inner(), + }) catch unreachable; + } + + pub fn getCostAnalysis(self: *const Executable, api: *const Api) GetCostAnalysisError![]*const NamedValue { + const ret = try api.call(.PJRT_Executable_GetCostAnalysis, .{ + .executable = self.inner(), + }); + const values: [*]*const NamedValue = @ptrCast(ret.properties); + return values[0..ret.num_properties]; + } + + pub fn serialize(self: *const Executable, api: *const Api) ApiError!SerializeResult { + const ret = try api.call(.PJRT_Executable_Serialize, .{ + .executable = self.inner(), + }); + + return .{ + .bytes = ret.serialized_bytes[0..ret.serialized_bytes_size], + .handle = ret.serialized_executable.?, + .deleter = @ptrCast(ret.serialized_executable_deleter.?), + }; + } +}; + +pub const LoadedExecutable = opaque { + const inner = InnerMixin(c.PJRT_LoadedExecutable).inner; + + pub fn deinit(self: *LoadedExecutable, api: *const Api) void { + _ = api.call(.PJRT_LoadedExecutable_Destroy, .{ + .executable = self.inner(), + }) catch {}; + self.* = undefined; + } + + pub fn delete(self: *LoadedExecutable, api: *const Api) void { + _ = api.call(.PJRT_LoadedExecutable_Delete, .{ + .executable = self.inner(), + }) catch unreachable; + } + + pub fn isDeleted(self: *const LoadedExecutable, api: *const Api) bool { + const ret = api.call(.PJRT_LoadedExecutable_IsDeleted, .{ + .executable = self.inner(), + }) catch unreachable; + return ret.is_deleted; + } + + pub fn getAddressableDevices(self: *const LoadedExecutable, api: *const Api) []Device { + const ret = api.call(.PJRT_LoadedExecutable_AddressableDevices, .{ + .executable = self.inner(), + }) catch unreachable; + return @ptrCast(ret.addressable_devices); + } + + pub fn execute(self: *const LoadedExecutable, api: *const Api, args: struct { + num_args: usize, + arguments: []const [*]const *const Buffer, + results: []const [*]*Buffer, + events: []*Event, + non_donatable_input_indices: []const i64 = &.{}, + }) ApiError!void { + var options = pjrtStruct(c.PJRT_ExecuteOptions{ + .send_callbacks = null, + .recv_callbacks = null, + .num_send_ops = 0, + .num_recv_ops = 0, + .launch_id = 0, + .non_donatable_input_indices = @ptrCast(args.non_donatable_input_indices.ptr), + .num_non_donatable_input_indices = args.non_donatable_input_indices.len, + }); + _ = try api.call(.PJRT_LoadedExecutable_Execute, .{ + .executable = self.inner(), + .options = @ptrCast(&options), + .argument_lists = @ptrCast(args.arguments.ptr), + .num_devices = @intCast(args.arguments.len), + .num_args = args.num_args, + .output_lists = @ptrCast(args.results.ptr), + .device_complete_events = @ptrCast(args.events.ptr), + .execute_device = null, + }); + } + + pub fn getExecutable(self: *LoadedExecutable, api: *const Api) ApiError!*Executable { + const ret = try api.call(.PJRT_LoadedExecutable_GetExecutable, .{ + .loaded_executable = self.inner(), + }); + return @ptrCast(ret.executable.?); + } +}; + +pub const BufferType = enum(c.PJRT_Buffer_Type) { + INVALID = c.PJRT_Buffer_Type_INVALID, + PRED = c.PJRT_Buffer_Type_PRED, + S8 = c.PJRT_Buffer_Type_S8, + S16 = c.PJRT_Buffer_Type_S16, + S32 = c.PJRT_Buffer_Type_S32, + S64 = c.PJRT_Buffer_Type_S64, + U8 = c.PJRT_Buffer_Type_U8, + U16 = c.PJRT_Buffer_Type_U16, + U32 = c.PJRT_Buffer_Type_U32, + U64 = c.PJRT_Buffer_Type_U64, + F16 = c.PJRT_Buffer_Type_F16, + F32 = c.PJRT_Buffer_Type_F32, + F64 = c.PJRT_Buffer_Type_F64, + BF16 = c.PJRT_Buffer_Type_BF16, + C64 = c.PJRT_Buffer_Type_C64, + C128 = c.PJRT_Buffer_Type_C128, + F8E5M2 = c.PJRT_Buffer_Type_F8E5M2, + F8E4M3FN = c.PJRT_Buffer_Type_F8E4M3FN, + F8E4M3B11FNUZ = c.PJRT_Buffer_Type_F8E4M3B11FNUZ, + F8E5M2FNUZ = c.PJRT_Buffer_Type_F8E5M2FNUZ, + F8E4M3FNUZ = c.PJRT_Buffer_Type_F8E4M3FNUZ, + S4 = c.PJRT_Buffer_Type_S4, + U4 = c.PJRT_Buffer_Type_U4, +}; + +pub const MemoryLayoutType = enum(c.PJRT_Buffer_MemoryLayout_Type) { + Tiled = c.PJRT_Buffer_MemoryLayout_Type_Tiled, + Strides = c.PJRT_Buffer_MemoryLayout_Type_Strides, +}; + +pub const MemoryLayout = union(MemoryLayoutType) { + pub const Type = MemoryLayoutType; + + pub const Tiled = struct { + minor_to_major: []const i64, + tile_dims: []const i64, + tile_dims_sizes: []const usize, + }; + + pub const Strides = struct { + byte_strides: []const i64, + }; + + Tiled: Tiled, + Strides: Strides, + + fn toCStruct(self: MemoryLayout) c.PJRT_Buffer_MemoryLayout { + return pjrtStruct(switch (self) { + .Tiled => |v| c.PJRT_Buffer_MemoryLayout{ + .type = c.PJRT_Buffer_MemoryLayout_Type_Tiled, + .unnamed_0 = .{ + .tiled = c.PJRT_Buffer_MemoryLayout_Tiled{ + .minor_to_major = v.minor_to_major.ptr, + .minor_to_major_size = v.minor_to_major.len, + .tile_dims = v.tile_dims.ptr, + .tile_dim_sizes = v.tile_dims_sizes.ptr, + .num_tiles = v.tile_dims_sizes.len, + }, + }, + }, + .Strides => |v| c.PJRT_Buffer_MemoryLayout{ + .type = c.PJRT_Buffer_MemoryLayout_Type_Strides, + .unnamed_0 = .{ + .strides = c.PJRT_Buffer_MemoryLayout_Strides{ + .byte_strides = v.byte_strides.ptr, + .num_byte_strides = v.byte_strides.len, + }, + }, + }, + }); + } +}; + +pub const HostBufferSemantics = enum(c.PJRT_HostBufferSemantics) { + ImmutableOnlyDuringCall = c.PJRT_HostBufferSemantics_kImmutableOnlyDuringCall, + ImmutableUntilTransferCompletes = c.PJRT_HostBufferSemantics_kImmutableUntilTransferCompletes, + ImmutableZeroCopy = c.PJRT_HostBufferSemantics_kImmutableZeroCopy, + MutableZeroCopy = c.PJRT_HostBufferSemantics_kMutableZeroCopy, +}; + +pub const Buffer = opaque { + const inner = InnerMixin(c.PJRT_Buffer).inner; + + pub fn deinit(self: *Buffer, api: *const Api) void { + _ = api.call(.PJRT_Buffer_Destroy, .{ + .buffer = self.inner(), + }) catch unreachable; + } + + pub fn getDevice(self: *const Buffer, api: *const Api) ApiError!*Device { + const ret = try api.call(.PJRT_Buffer_Device, .{ + .buffer = self.inner(), + }); + return @ptrCast(ret.device.?); + } + + pub fn delete(self: *Buffer, api: *const Api) void { + _ = api.call(.PJRT_Buffer_Delete, .{ + .buffer = self.inner(), + }) catch unreachable; + } + + pub fn isDeleted(self: *const Buffer, api: *const Api) bool { + const ret = api.call(.PJRT_Buffer_IsDeleted, .{ + .buffer = self.inner(), + }) catch unreachable; + return ret.is_deleted; + } + + pub fn isOnCpu(self: *const Buffer, api: *const Api) bool { + const ret = api.call(.PJRT_Buffer_IsOnCpu, .{ + .buffer = self.inner(), + }) catch unreachable; + return ret.is_on_cpu; + } + + pub fn toHostBuffer(self: *const Buffer, api: *const Api, dst: []u8) ApiError!*Event { + const ret = try api.call(.PJRT_Buffer_ToHostBuffer, .{ + .src = self.inner(), + .dst = @ptrCast(dst.ptr), + .dst_size = dst.len, + }); + return @ptrCast(ret.event.?); + } + + pub fn getElementType(self: *const Buffer, api: *const Api) BufferType { + const ret = api.call(.PJRT_Buffer_ElementType, .{ + .buffer = self.inner(), + }) catch unreachable; + return @enumFromInt(ret.type); + } + + pub fn getDimensions(self: *const Buffer, api: *const Api) []const i64 { + const ret = api.call(.PJRT_Buffer_Dimensions, .{ + .buffer = self.inner(), + }) catch unreachable; + return ret.dims[0..ret.num_dims]; + } + + pub fn getUnpaddedDimensions(self: *const Buffer, api: *const Api) ApiError![]const i64 { + const ret = try api.call(.PJRT_Buffer_UnpaddedDimensions, .{ + .buffer = self.inner(), + }); + return ret.dims[0..ret.num_dims]; + } + + pub fn getOnDeviceSizeInBytes(self: *const Buffer, api: *const Api) ApiError!usize { + const ret = try api.call(.PJRT_Buffer_OnDeviceSizeInBytes, .{ + .buffer = self.inner(), + }); + return ret.on_device_size_in_bytes; + } + + pub fn copyToDevice(self: *const Buffer, api: *const Api, device: Device) ApiError!Buffer { + const ret = try api.call(.PJRT_Buffer_CopyToDevice, .{ + .buffer = self.inner(), + .dst_device = device.inner, + }); + return @ptrCast(ret.dst_buffer.?); + } + + pub fn getReadyEvent(self: *const Buffer, api: *const Api) *Event { + const ret = api.call(.PJRT_Buffer_ReadyEvent, .{ + .buffer = self.inner(), + }) catch unreachable; + return @ptrCast(ret.event.?); + } + + pub fn getOpaqueDeviceMemoryDataPointer(self: *const Buffer, api: *const Api) ApiError!*anyopaque { + const ret = try api.call(.PJRT_Buffer_OpaqueDeviceMemoryDataPointer, .{ + .buffer = self.inner(), + }); + return ret.device_memory_ptr.?; + } +}; + +pub const Event = opaque { + const inner = InnerMixin(c.PJRT_Event).inner; + + pub fn deinit(self: *Event, api: *const Api) void { + _ = api.call(.PJRT_Event_Destroy, .{ + .event = self.inner(), + }) catch unreachable; + } + + pub fn isReady(self: *const Event, api: *const Api) bool { + const ret = api.call(.PJRT_Event_IsReady, .{ + .event = self.inner(), + }) catch unreachable; + return ret.is_ready; + } + + pub fn getEventError(self: *const Event, api: *const Api) ApiError!?*Error { + const ret = try api.call(.PJRT_Event_Error, .{ + .event = self.inner(), + }); + return @ptrCast(ret); + } + + pub fn await_(self: *const Event, api: *const Api) ApiError!void { + _ = try api.call(.PJRT_Event_Await, .{ + .event = self.inner(), + }); + } + + pub fn onReady(self: *Event, api: *const Api, func: *const fn (err: ?*Error, user_arg: ?*anyopaque) callconv(.C) void, user_arg: ?*anyopaque) ApiError!void { + _ = try api.call(.PJRT_Event_OnReady, .{ + .event = self.inner(), + .callback = @ptrCast(func), + .user_arg = user_arg, + }); + } +}; + +pub const NamedValue = extern struct { + comptime { + std.debug.assert(@sizeOf(NamedValue) == @sizeOf(c.PJRT_NamedValue)); + } + + inner: c.PJRT_NamedValue, + + pub const Kind = enum(c.PJRT_NamedValue_Type) { + string = c.PJRT_NamedValue_kString, + int64 = c.PJRT_NamedValue_kInt64, + int64list = c.PJRT_NamedValue_kInt64List, + float = c.PJRT_NamedValue_kFloat, + bool = c.PJRT_NamedValue_kBool, + }; + + pub fn kind(self: NamedValue) Kind { + return @enumFromInt(self.inner.type); + } + + pub fn name(self: NamedValue) []const u8 { + return self.inner.name[0..self.inner.name_size]; + } + + pub fn from(name_: []const u8, value: anytype) NamedValue { + return switch (@TypeOf(value)) { + []u8, []const u8 => fromString(name_, value), + i64 => fromInt64(name_, value), + []i64, []const i64 => fromInt64List(name_, value), + f32 => fromFloat(name_, value), + bool => fromBool(name_, value), + else => unreachable, + }; + } + + pub fn fromString(name_: []const u8, value: []const u8) NamedValue { + return .{ .inner = pjrtStruct(c.PJRT_NamedValue{ + .name = @ptrCast(@constCast(name_.ptr)), + .name_size = name_.len, + .type = c.PJRT_NamedValue_kString, + .unnamed_0 = .{ .string_value = @ptrCast(@constCast(value.ptr)) }, + .value_size = value.len, + }) }; + } + + pub fn fromInt64(name_: []const u8, value: i64) NamedValue { + return .{ .inner = pjrtStruct(c.PJRT_NamedValue{ + .name = @ptrCast(@constCast(name_.ptr)), + .name_size = name_.len, + .type = c.PJRT_NamedValue_kInt64, + .unnamed_0 = .{ .int64_value = value }, + .value_size = 1, + }) }; + } + + pub fn fromInt64List(name_: []const u8, value: []const i64) NamedValue { + return .{ .inner = pjrtStruct(c.PJRT_NamedValue{ + .name = @ptrCast(@constCast(name_.ptr)), + .name_size = name_.len, + .type = c.PJRT_NamedValue_kInt64List, + .unnamed_0 = .{ .int64_array_value = @ptrCast(@constCast(value.ptr)) }, + .value_size = value.len, + }) }; + } + + pub fn fromFloat(name_: []const u8, value: f32) NamedValue { + return .{ .inner = pjrtStruct(c.PJRT_NamedValue{ + .name = @ptrCast(@constCast(name_.ptr)), + .name_size = name_.len, + .type = c.PJRT_NamedValue_kFloat, + .unnamed_0 = .{ .float_value = value }, + .value_size = 1, + }) }; + } + + pub fn fromBool(name_: []const u8, value: bool) NamedValue { + return .{ .inner = pjrtStruct(c.PJRT_NamedValue{ + .name = @ptrCast(@constCast(name_.ptr)), + .name_size = name_.len, + .type = c.PJRT_NamedValue_kBool, + .unnamed_0 = .{ .bool_value = value }, + .value_size = 1, + }) }; + } + + pub fn format( + self: NamedValue, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, + ) !void { + _ = fmt; + _ = options; + try writer.print("{s}{{ .name = {s},", .{ @typeName(NamedValue), self.inner.name[0..self.inner.name_size] }); + const u = self.inner.unnamed_0; + switch (self.kind()) { + .string => try writer.print(" .string = {s} ", .{u.string_value[0..self.inner.value_size]}), + .int64 => try writer.print(" .int64 = {d} ", .{u.int64_value}), + .int64list => try writer.print(" .int64list = {d} ", .{u.int64_array_value[0..self.inner.value_size]}), + .float => try writer.print(" .float = {d} ", .{u.float_value}), + .bool => try writer.print(" .bool = {} ", .{u.bool_value}), + } + try writer.writeAll("}"); + } +}; diff --git a/pjrt/profiler.zig b/pjrt/profiler.zig new file mode 100644 index 0000000..1cef566 --- /dev/null +++ b/pjrt/profiler.zig @@ -0,0 +1,205 @@ +const std = @import("std"); +const c = @import("c"); +const tsl_proto = @import("//tsl:profiler_options_proto"); + +const log = std.log.scoped(.zml_profiler); + +/// Pjrt Profiler extension +pub const Profiler = struct { + api: ?c.PLUGIN_Profiler_Api, + inner: *c.PLUGIN_Profiler, + last_error: ?*Error = null, + status: Status = .ready, + + pub const Status = enum { ready, started, stopped, done }; + pub const Error = c.PLUGIN_Profiler_Error; + pub const Options = tsl_proto.ProfileOptions; + + pub fn init(api: ?c.PLUGIN_Profiler_Api, options: Options) Profiler { + if (api == null) { + return .{ .api = null, .inner = undefined }; + } + + var buffer: [std.fs.max_path_bytes + @sizeOf(Options) * 4]u8 = undefined; + var fba = std.heap.FixedBufferAllocator.init(&buffer); + const byte_options = options.encode(fba.allocator()) catch unreachable; + var res: Profiler = .{ .api = api, .inner = undefined }; + var args: c.PLUGIN_Profiler_Create_Args = .{ + .options = byte_options.ptr, + .options_size = byte_options.len, + .profiler = undefined, // out + }; + res.check(api.?.create.?(&args)) catch unreachable; + + res.inner = args.profiler.?; + return res; + } + + fn transition(self: *Profiler, fn_name: []const u8, expected: Status, next: Status) void { + if (self.status == expected) { + self.status = next; + return; + } + std.debug.panic("Profiler can't `{s}()`. Current status: {}, expected: {}", .{ fn_name, self.status, expected }); + } + + pub fn start(self: *Profiler) void { + self.transition("start", .ready, .started); + if (self.api == null) return; + var args: c.PLUGIN_Profiler_Start_Args = .{ .profiler = self.inner }; + self.check(self.api.?.start.?(&args)) catch unreachable; + } + + pub fn stop(self: *Profiler) void { + self.transition("stop", .started, .stopped); + if (self.api == null) return; + + var args: c.PLUGIN_Profiler_Stop_Args = .{ .profiler = self.inner }; + self.check(self.api.?.stop.?(&args)) catch unreachable; + } + + pub fn collectData(self: *Profiler, allocator: std.mem.Allocator) !ProfilingData { + self.transition("collect_data", .stopped, .done); + if (self.api == null) return .{ .external = &.{} }; + + var args: c.PLUGIN_Profiler_CollectData_Args = .{ + .struct_size = c.PLUGIN_Profiler_CollectData_Args_STRUCT_SIZE, + .profiler = self.inner, + .buffer = null, + .buffer_size_in_bytes = 0, + }; + try self.check(self.api.?.collect_data.?(&args)); + std.debug.assert(args.buffer_size_in_bytes > 0); + const buffer: ProfilingData = if (args.buffer == null) blk: { + std.log.debug("Plugin profiler wants us to allocate {d} bytes for profile data", .{args.buffer_size_in_bytes}); + // The plugin want us to allocate memory for it: + const buffer = try allocator.alloc(u8, args.buffer_size_in_bytes); + args.buffer = buffer.ptr; + try self.check(self.api.?.collect_data.?(&args)); + break :blk .{ .owned = buffer }; + } else blk: { + std.log.debug("Plugin profiler has {d} bytes of profile data", .{args.buffer_size_in_bytes}); + // Drop sentinel. The profiler plugin returns a null terminated string. + // But this is creating issues if we save the sentinel on disk, + // because it will trip up protobuf readers. + var data = args.buffer[0..args.buffer_size_in_bytes]; + data = if (data.len > 0 and data[data.len - 1] == 0) data[0 .. data.len - 1] else data; + break :blk .{ .external = data }; + }; + + // printDataAsXSpace(allocator, buffer.items()); + return buffer; + } + + pub fn dumpDataTo( + self: *Profiler, + allocator: std.mem.Allocator, + dir: std.fs.Dir, + file_name: []const u8, + ) !void { + const profile_data = try self.collectData(allocator); + defer profile_data.free(allocator); + + if (profile_data.items().len == 0) return; + + const file = try dir.createFile(file_name, .{ .truncate = true }); + defer file.close(); + log.info("Writing profiling data to {s} ({} bytes)", .{ file_name, profile_data.items().len }); + return try file.writeAll(profile_data.items()); + } + + fn check(self: *Profiler, c_error: ?*Error) !void { + if (c_error) |err| { + self.last_error = err; + return error.PjrtProfilerError; + } + } + + pub fn deinit(self: Profiler) void { + switch (self.status) { + .started => log.warn("Profiler was never stopped", .{}), + .stopped => log.warn("Profiler data was never collected", .{}), + else => {}, + } + if (self.api == null) return; + + var args: c.PLUGIN_Profiler_Destroy_Args = .{ .profiler = self.inner }; + _ = self.api.?.destroy.?(&args); + } +}; + +// If this was working it would be a good alternative to xspace_to_json.cc +// const xspace = @import("xspace.pb.zig"); +// pub fn printDataAsXSpace(allocator: std.mem.Allocator, data: []const u8) void { +// var arena = std.heap.ArenaAllocator.init(allocator); +// defer arena.deinit(); +// +// const space = xspace.XSpace.decode(data, arena.allocator()) catch |e| { +// std.log.err("Couldn't load profiling data: {}", .{e}); +// return; +// }; +// +// for (space.errors.items) |err| { +// std.log.err("{s}", .{err.getSlice()}); +// } +// for (space.warnings.items) |warning| { +// std.log.warn("{s}", .{warning.getSlice()}); +// } +// for (space.hostnames.items) |host| { +// std.log.info("Profiled host {s}", .{host.getSlice()}); +// } +// for (space.planes.items) |plane| { +// var event_metadata = std.hash_map.AutoHashMap(i64, xspace.XEventMetadata).init(arena.allocator()); +// event_metadata.ensureTotalCapacity(@intCast(plane.event_metadata.items.len)) catch return; +// defer event_metadata.deinit(); +// for (plane.event_metadata.items) |event_meta_entry| { +// if (event_meta_entry.value) |event_meta| { +// event_metadata.putAssumeCapacity(event_meta.id, event_meta); +// } +// } +// std.log.info("Profiled device {s}", .{plane.name.getSlice()}); + +// for (plane.lines.items) |line| { +// std.log.info( +// "{d} -> {d} xline {s} ({d} events)", +// .{ line.timestamp_ns, line.duration_ps, line.name.getSlice(), line.events.items.len }, +// ); +// const ps_per_ns: i64 = 1000; +// var duration_ns: i64 = 0; +// var last_metadata_id: i64 = 0; +// for (line.events.items) |event| { +// if (event.metadata_id != last_metadata_id and duration_ns != 0) { +// const duration_us = @as(f32, @floatFromInt(duration_ns)) / std.time.ns_per_us; +// const meta = event_metadata.get(event.metadata_id).?; +// std.log.info("event {s}: {d:.1}μs", .{ meta.name.getSlice(), duration_us }); + +// last_metadata_id = event.metadata_id; +// duration_ns = 0; +// } +// duration_ns += @divFloor(event.duration_ps, ps_per_ns); + +// const duration_us = @as(f32, @floatFromInt(duration_ns)) / std.time.ns_per_us; +// const meta = event_metadata.get(event.metadata_id).?; +// std.log.info("event {s}: {d:.1}μs", .{ meta.name.getSlice(), duration_us }); +// } +// } +// } +// } + +const ProfilingData = union(enum) { + owned: []const u8, + external: []const u8, + + pub fn items(self: ProfilingData) []const u8 { + return switch (self) { + inline else => |x| x, + }; + } + + pub fn free(self: ProfilingData, allocator: std.mem.Allocator) void { + switch (self) { + .owned => |data| allocator.free(data), + .external => {}, + } + } +}; diff --git a/platform_mappings b/platform_mappings new file mode 100644 index 0000000..6fd7ceb --- /dev/null +++ b/platform_mappings @@ -0,0 +1,21 @@ +platforms: + @zml//platforms:linux_amd64 + --cpu=k8 + + @zml//platforms:linux_arm64 + --cpu=aarch64 + + @zml//platforms:macos_arm64 + --cpu=darwin_arm64 + --apple_platform_type=macos + +flags: + --cpu=darwin_arm64 + --apple_platform_type=macos + @zml//platforms:macos_arm64 + + --cpu=k8 + @zml//platforms:linux_amd64 + + --cpu=aarch64 + @zml//platforms:linux_arm64 diff --git a/platforms/BUILD.bazel b/platforms/BUILD.bazel new file mode 100644 index 0000000..05a143a --- /dev/null +++ b/platforms/BUILD.bazel @@ -0,0 +1,26 @@ +platform( + name = "linux_amd64", + constraint_values = [ + "@platforms//cpu:x86_64", + "@platforms//os:linux", + ], + visibility = ["//visibility:public"], +) + +platform( + name = "linux_arm64", + constraint_values = [ + "@platforms//cpu:aarch64", + "@platforms//os:linux", + ], + visibility = ["//visibility:public"], +) + +platform( + name = "macos_arm64", + constraint_values = [ + "@platforms//cpu:aarch64", + "@platforms//os:macos", + ], + visibility = ["//visibility:public"], +) diff --git a/runtimes/BUILD.bazel b/runtimes/BUILD.bazel new file mode 100644 index 0000000..291651c --- /dev/null +++ b/runtimes/BUILD.bazel @@ -0,0 +1,42 @@ +load("@bazel_skylib//rules:common_settings.bzl", "bool_flag") + +RUNTIMES = { + "cpu": True, + "cuda": False, + "rocm": False, + "tpu": False, +} + +[ + bool_flag( + name = runtime, + build_setting_default = default, + ) + for runtime, default in RUNTIMES.items() +] + +[ + config_setting( + name = "_{}".format(runtime), + flag_values = {":{}".format(runtime): "True"}, + ) + for runtime in RUNTIMES.keys() +] + +cc_library( + name = "runtimes", + visibility = ["//visibility:public"], + deps = select({ + ":_cpu": ["//runtimes/cpu"], + "//conditions:default": [], + }) + select({ + ":_cuda": ["//runtimes/cuda"], + "//conditions:default": [], + }) + select({ + ":_rocm": ["//runtimes/rocm"], + "//conditions:default": [], + }) + select({ + ":_tpu": ["//runtimes/tpu"], + "//conditions:default": [], + }), +) diff --git a/runtimes/cpu/BUILD.bazel b/runtimes/cpu/BUILD.bazel new file mode 100644 index 0000000..ac3ac6d --- /dev/null +++ b/runtimes/cpu/BUILD.bazel @@ -0,0 +1,8 @@ +alias( + name = "cpu", + actual = select({ + "@platforms//os:macos": "@libpjrt_cpu_darwin_arm64//:libpjrt_cpu", + "@platforms//os:linux": "@libpjrt_cpu_linux_amd64//:libpjrt_cpu", + }), + visibility = ["//visibility:public"], +) diff --git a/runtimes/cpu/cpu.bzl b/runtimes/cpu/cpu.bzl new file mode 100644 index 0000000..b358538 --- /dev/null +++ b/runtimes/cpu/cpu.bzl @@ -0,0 +1,34 @@ +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +_BUILD = """\ +cc_import( + name = "libpjrt_cpu", + shared_library = "libpjrt_cpu.{ext}", + visibility = ["//visibility:public"], +) +""" + +def _cpu_pjrt_plugin_impl(mctx): + http_archive( + name = "libpjrt_cpu_linux_amd64", + build_file_content = _BUILD.format(ext = "so"), + sha256 = "14317143acd6a38656e97280e8010c0b8d8c0863dff2ae82834b6f2fe747427b", + url = "https://github.com/zml/pjrt-artifacts/releases/download/v0.1.13/pjrt-cpu_linux-amd64.tar.gz", + ) + + http_archive( + name = "libpjrt_cpu_darwin_arm64", + build_file_content = _BUILD.format(ext = "dylib"), + sha256 = "3a26e1372f68fc11028c4ec22a0c72693f08e7690ba8c5f28b17f5baa9c9dc77", + url = "https://github.com/zml/pjrt-artifacts/releases/download/v0.1.13/pjrt-cpu_darwin-arm64.tar.gz", + ) + + return mctx.extension_metadata( + reproducible = True, + root_module_direct_deps = "all", + root_module_direct_dev_deps = [], + ) + +cpu_pjrt_plugin = module_extension( + implementation = _cpu_pjrt_plugin_impl, +) diff --git a/runtimes/cuda/BUILD.bazel b/runtimes/cuda/BUILD.bazel new file mode 100644 index 0000000..530c10d --- /dev/null +++ b/runtimes/cuda/BUILD.bazel @@ -0,0 +1,5 @@ +alias( + name = "cuda", + actual = "@libpjrt_cuda", + visibility = ["//visibility:public"], +) diff --git a/runtimes/cuda/cuda.bzl b/runtimes/cuda/cuda.bzl new file mode 100644 index 0000000..2f3acba --- /dev/null +++ b/runtimes/cuda/cuda.bzl @@ -0,0 +1,197 @@ +load("@bazel_skylib//lib:paths.bzl", "paths") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load("//bazel:http_deb_archive.bzl", "http_deb_archive") + +ARCH = "linux-x86_64" + +CUDA_VERSION = "12.6.1" +CUDNN_VERSION = "9.3.0" + +_CC_IMPORT_TPL = """\ +cc_import( + name = "{name}", + shared_library = "lib/{shared_library}", + visibility = ["@libpjrt_cuda//:__subpackages__"], +) +""" + +CUDA_PACKAGES = { + "cuda_cudart": _CC_IMPORT_TPL.format(name = "cudart", shared_library = "libcudart.so.12"), + "cuda_cupti": _CC_IMPORT_TPL.format(name = "cupti", shared_library = "libcupti.so.12"), + "libcufft": _CC_IMPORT_TPL.format(name = "cufft", shared_library = "libcufft.so.11"), + "libcusolver": _CC_IMPORT_TPL.format(name = "cusolver", shared_library = "libcusolver.so.11"), + "libcusparse": _CC_IMPORT_TPL.format(name = "cusparse", shared_library = "libcusparse.so.12"), + "libnvjitlink": _CC_IMPORT_TPL.format(name = "nvjitlink", shared_library = "libnvJitLink.so.12"), + "cuda_nvcc": """\ +filegroup( + name = "ptxas", + srcs = ["bin/ptxas"], + visibility = ["@libpjrt_cuda//:__subpackages__"], +) + +filegroup( + name = "libdevice", + srcs = ["nvvm/libdevice/libdevice.10.bc"], + visibility = ["@libpjrt_cuda//:__subpackages__"], +) + +cc_import( + name = "nvvm", + shared_library = "nvvm/lib64/libnvvm.so.4", + visibility = ["@libpjrt_cuda//:__subpackages__"], +) +""", + "cuda_nvrtc": """\ +cc_import( + name = "nvrtc", + shared_library = "lib/libnvrtc.so.12", + visibility = ["@libpjrt_cuda//:__subpackages__"], + deps = [":nvrtc_builtins"], +) + +cc_import( + name = "nvrtc_builtins", + shared_library = "lib/libnvrtc-builtins.so.12.6", +) +""", + "libcublas": """\ +cc_import( + name = "cublasLt", + shared_library = "lib/libcublasLt.so.12", +) + +cc_import( + name = "cublas", + shared_library = "lib/libcublas.so.12", + visibility = ["@libpjrt_cuda//:__subpackages__"], + deps = [":cublasLt"], +) +""", +} + +CUDNN_PACKAGES = { + "cudnn": """\ +cc_import( + name = "cudnn", + shared_library = "lib/libcudnn.so.9", + visibility = ["@libpjrt_cuda//:__subpackages__"], + deps = [ + ":cudnn_adv", + ":cudnn_ops", + ":cudnn_cnn", + ":cudnn_graph", + ":cudnn_engines_precompiled", + ":cudnn_engines_runtime_compiled", + ":cudnn_heuristic", + ], +) + +cc_import( + name = "cudnn_adv", + shared_library = "lib/libcudnn_adv.so.9", +) + +cc_import( + name = "cudnn_ops", + shared_library = "lib/libcudnn_ops.so.9", +) + +cc_import( + name = "cudnn_cnn", + shared_library = "lib/libcudnn_cnn.so.9", + deps = [":cudnn_ops"], +) + +cc_import( + name = "cudnn_graph", + shared_library = "lib/libcudnn_graph.so.9", +) + +cc_import( + name = "cudnn_engines_precompiled", + shared_library = "lib/libcudnn_engines_precompiled.so.9", +) + +cc_import( + name = "cudnn_engines_runtime_compiled", + shared_library = "lib/libcudnn_engines_runtime_compiled.so.9", +) + +cc_import( + name = "cudnn_heuristic", + shared_library = "lib/libcudnn_heuristic.so.9", +) +""", +} + +def _cuda_impl(mctx): + CUDA_REDIST = json.decode(mctx.read(Label("@zml//runtimes/cuda:cuda.redistrib_{}.json".format(CUDA_VERSION)))) + CUDNN_REDIST = json.decode(mctx.read(Label("@zml//runtimes/cuda:cudnn.redistrib_{}.json".format(CUDNN_VERSION)))) + + for pkg, build_file_content in CUDA_PACKAGES.items(): + pkg_data = CUDA_REDIST[pkg] + arch_data = pkg_data.get(ARCH) + if not arch_data: + continue + http_archive( + name = pkg, + build_file_content = build_file_content, + url = "https://developer.download.nvidia.com/compute/cuda/redist/" + arch_data["relative_path"], + sha256 = arch_data["sha256"], + strip_prefix = paths.basename(arch_data["relative_path"]).replace(".tar.xz", ""), + ) + + for pkg, build_file_content in CUDNN_PACKAGES.items(): + pkg_data = CUDNN_REDIST[pkg] + arch_data = pkg_data.get(ARCH) + if not arch_data: + continue + arch_data = arch_data.get("cuda12", arch_data) + http_archive( + name = pkg, + build_file_content = build_file_content, + url = "https://developer.download.nvidia.com/compute/cudnn/redist/" + arch_data["relative_path"], + sha256 = arch_data["sha256"], + strip_prefix = paths.basename(arch_data["relative_path"]).replace(".tar.xz", ""), + ) + + http_deb_archive( + name = "libnccl", + urls = ["https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/libnccl2_2.22.3-1+cuda12.6_amd64.deb"], + sha256 = "2f64685bcd503150ab45d00503236a56da58a15eac5fd36508045a74f4e10678", + build_file_content = """\ +cc_import( + name = "nccl", + shared_library = "usr/lib/x86_64-linux-gnu/libnccl.so.2", + visibility = ["@libpjrt_cuda//:__subpackages__"], +) +""", + ) + http_deb_archive( + name = "zlib", + urls = ["http://archive.ubuntu.com/ubuntu/pool/main/z/zlib/zlib1g_1.3.dfsg-3.1ubuntu2.1_amd64.deb"], + sha256 = "7074b6a2f6367a10d280c00a1cb02e74277709180bab4f2491a2f355ab2d6c20", + build_file_content = """\ +cc_import( + name = "zlib", + shared_library = "usr/lib/x86_64-linux-gnu/libz.so.1", + visibility = ["@libpjrt_cuda//:__subpackages__"], +) +""", + ) + http_archive( + name = "libpjrt_cuda", + build_file = "libpjrt_cuda.BUILD.bazel", + url = "https://github.com/zml/pjrt-artifacts/releases/download/v0.1.13/pjrt-cuda_linux-amd64.tar.gz", + sha256 = "b705f761e24d85ecd750df992a88715d9c461b7561c31722b9f878eeab32f39e", + ) + + return mctx.extension_metadata( + reproducible = True, + root_module_direct_deps = ["libpjrt_cuda"], + root_module_direct_dev_deps = [], + ) + +cuda_packages = module_extension( + implementation = _cuda_impl, +) diff --git a/runtimes/cuda/cuda.redistrib_12.6.1.json b/runtimes/cuda/cuda.redistrib_12.6.1.json new file mode 100644 index 0000000..bc24f87 --- /dev/null +++ b/runtimes/cuda/cuda.redistrib_12.6.1.json @@ -0,0 +1,1037 @@ +{ + "release_date": "2024-08-29", + "release_label": "12.6.1", + "release_product": "cuda", + "cuda_cccl": { + "name": "CXX Core Compute Libraries", + "license": "CUDA Toolkit", + "license_path": "cuda_cccl/LICENSE.txt", + "version": "12.6.37", + "linux-x86_64": { + "relative_path": "cuda_cccl/linux-x86_64/cuda_cccl-linux-x86_64-12.6.37-archive.tar.xz", + "sha256": "478adda30882b8fbff54d7da109708be5e6a988eafb18d9397868f8d6633981f", + "md5": "0aa87816194845693c6892628387a616", + "size": "932208" + }, + "linux-sbsa": { + "relative_path": "cuda_cccl/linux-sbsa/cuda_cccl-linux-sbsa-12.6.37-archive.tar.xz", + "sha256": "0985a1a4fe3f1e1b68d90909a1cad922194b111c5c965098978b66038c700436", + "md5": "ef44af859b3c9f4030029879b3c1fd99", + "size": "932348" + }, + "windows-x86_64": { + "relative_path": "cuda_cccl/windows-x86_64/cuda_cccl-windows-x86_64-12.6.37-archive.zip", + "sha256": "4fe0460b101887a62fd8ceb1e518926439148c23ec95ef41b694c583031392e9", + "md5": "886a846848192218aee2bf8982116aa7", + "size": "2929962" + }, + "linux-aarch64": { + "relative_path": "cuda_cccl/linux-aarch64/cuda_cccl-linux-aarch64-12.6.37-archive.tar.xz", + "sha256": "90166f9066db13bfb017a7a9a1cea52ac7d2d23637b555192f3f071bededa054", + "md5": "5904ec75b0853a4d26520f3486da2589", + "size": "932860" + } + }, + "cuda_compat": { + "name": "CUDA compat L4T", + "license": "CUDA Toolkit", + "license_path": "cuda_compat/LICENSE.txt", + "version": "12.6.36890662", + "linux-aarch64": { + "relative_path": "cuda_compat/linux-aarch64/cuda_compat-linux-aarch64-12.6.36890662-archive.tar.xz", + "sha256": "007cdab536bf0a1ec274faff73cde2233f3ccfe0e6dba2b015fb1b527e7e231f", + "md5": "de7405e0e2e570b52d16dedc14ebc44e", + "size": "19628624" + } + }, + "cuda_cudart": { + "name": "CUDA Runtime (cudart)", + "license": "CUDA Toolkit", + "license_path": "cuda_cudart/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_cudart/linux-x86_64/cuda_cudart-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "f7e2471305e7396597290d3ed3276829f7f56741fee569f9cb3c767bbbcf001c", + "md5": "7e6b002fd0b5be4bab911d40e08fc3af", + "size": "1124868" + }, + "linux-sbsa": { + "relative_path": "cuda_cudart/linux-sbsa/cuda_cudart-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "0a416361995b2c3aaedd9fe7a91f3902674eb245e286212f1218e4bf2f34b8ee", + "md5": "309afdbbf50e9f110265b107cc2521b6", + "size": "1113432" + }, + "windows-x86_64": { + "relative_path": "cuda_cudart/windows-x86_64/cuda_cudart-windows-x86_64-12.6.68-archive.zip", + "sha256": "d5873e4c508e05797cefe6d324b131e9ea3e44f41062e15cd7405d3806561a48", + "md5": "0dddfea98c1ff3564007342b57e38591", + "size": "2511937" + }, + "linux-aarch64": { + "relative_path": "cuda_cudart/linux-aarch64/cuda_cudart-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "bcd9b19f291e17d82dc7ffe1d2888a92f5d986cf3ca7305bf8b144edc7a58034", + "md5": "93186532b84a176791217d9b617e294b", + "size": "1176476" + } + }, + "cuda_cuobjdump": { + "name": "cuobjdump", + "license": "CUDA Toolkit", + "license_path": "cuda_cuobjdump/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_cuobjdump/linux-x86_64/cuda_cuobjdump-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "080e3a9af99ab8e955f99951034bd13974b19005854a405b3fa81c722d636e81", + "md5": "1d2f84c005a43bb5246097ac4334b13d", + "size": "218684" + }, + "linux-sbsa": { + "relative_path": "cuda_cuobjdump/linux-sbsa/cuda_cuobjdump-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "8a8eb2a78170185755e8ce59ff49aa434e708eb77e9a84aa8e76e3ff921552ff", + "md5": "85d559e8c3b6255c8ce534579b0a757b", + "size": "208960" + }, + "windows-x86_64": { + "relative_path": "cuda_cuobjdump/windows-x86_64/cuda_cuobjdump-windows-x86_64-12.6.68-archive.zip", + "sha256": "e3c48f5bbaac635d90eb507d3f5169d0d41c6615df0d53e67a9f181f643f7edb", + "md5": "26d7649f59c2e353c5bd7d7612688252", + "size": "4247914" + }, + "linux-aarch64": { + "relative_path": "cuda_cuobjdump/linux-aarch64/cuda_cuobjdump-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "c4a8d6ea5f03bb3456d7a626db779d8d53d689477c1645eb26a37ff690d06762", + "md5": "059a45ee72f415f4ea93e888ad151138", + "size": "196296" + } + }, + "cuda_cupti": { + "name": "CUPTI", + "license": "CUDA Toolkit", + "license_path": "cuda_cupti/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_cupti/linux-x86_64/cuda_cupti-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "f9bbaf8246a30fdccd2e280ad671b0475971feef96236c2c0635f3b3abc2afb1", + "md5": "046f8a5bcb52a6c6e4a374e64b011853", + "size": "13868140" + }, + "linux-sbsa": { + "relative_path": "cuda_cupti/linux-sbsa/cuda_cupti-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "50163cf147905bfe54a644d61c103cd3555d64e714e136f07392376d867b5eb1", + "md5": "81aac7011a3bc1625e2c48e77070855f", + "size": "11268224" + }, + "windows-x86_64": { + "relative_path": "cuda_cupti/windows-x86_64/cuda_cupti-windows-x86_64-12.6.68-archive.zip", + "sha256": "d1147cacc0567123f34082cb48a9e3d8f77c6010c3aab3286d516c576a9089a4", + "md5": "b5167522d2044d3a0807d3b8967f6b3c", + "size": "9815139" + }, + "linux-aarch64": { + "relative_path": "cuda_cupti/linux-aarch64/cuda_cupti-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "9cca71d65e08d1320b727559dcb5cf8637fdfbb742301612b8c447083a13c2c9", + "md5": "85ae4d88cf4f0c0b8c8d7c2ca7e98756", + "size": "4083648" + } + }, + "cuda_cuxxfilt": { + "name": "CUDA cuxxfilt (demangler)", + "license": "CUDA Toolkit", + "license_path": "cuda_cuxxfilt/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_cuxxfilt/linux-x86_64/cuda_cuxxfilt-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "e1ce886c4440ea05f815e8d67cf143dc9a635a30275260f3f72c73fcec7f3a00", + "md5": "dbf0daa609940f5e0d043d8aa349d471", + "size": "188976" + }, + "linux-sbsa": { + "relative_path": "cuda_cuxxfilt/linux-sbsa/cuda_cuxxfilt-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "9e976673c830a9f2295ef8d3d061964033bcf9a97c2fc400ee2c496e71c27469", + "md5": "8641fe68b18afa2dc77ed0158e4dfc2e", + "size": "177200" + }, + "windows-x86_64": { + "relative_path": "cuda_cuxxfilt/windows-x86_64/cuda_cuxxfilt-windows-x86_64-12.6.68-archive.zip", + "sha256": "13fd839d43aa88d934cc0b167f3868aabcc6c3128dbd413b9f271bc85e8e5695", + "md5": "f45be2c5243553871a3f893911ea3c4d", + "size": "170743" + }, + "linux-aarch64": { + "relative_path": "cuda_cuxxfilt/linux-aarch64/cuda_cuxxfilt-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "0db9fca79b856739969a8422fb61ff10eb3f770800b6748f574c6aa2df32e696", + "md5": "057022c5d05965d5e5d0aa385ad7e5ef", + "size": "170300" + } + }, + "cuda_demo_suite": { + "name": "CUDA Demo Suite", + "license": "CUDA Toolkit", + "license_path": "cuda_demo_suite/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_demo_suite/linux-x86_64/cuda_demo_suite-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "5c8f7c5703288f4043a75e37bfdb7789b82a35e261a3e9d77d226dd218f23b3f", + "md5": "0ea47afdfd6e384f3befbc48fd1066c9", + "size": "4003072" + }, + "windows-x86_64": { + "relative_path": "cuda_demo_suite/windows-x86_64/cuda_demo_suite-windows-x86_64-12.6.68-archive.zip", + "sha256": "7061cf268f868c959b46eef458f1949ceb5090e234ba2c68d413b49c5c2a9c57", + "md5": "95b8ed8b1290269863752a18ff956429", + "size": "5065609" + } + }, + "cuda_documentation": { + "name": "CUDA Documentation", + "license": "CUDA Toolkit", + "license_path": "cuda_documentation/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_documentation/linux-x86_64/cuda_documentation-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "6fb94edac546e0ddc5b308dad4c70e7ff8d88d2d2c609c7c1f2a33951ab6e75e", + "md5": "87d740758dfa2a28d06472a8cc3214dc", + "size": "67312" + }, + "linux-sbsa": { + "relative_path": "cuda_documentation/linux-sbsa/cuda_documentation-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "2d1f1109d4b0e3e0901f996b95d63e79270ce94e7c86d270e7ff1c2d2449167b", + "md5": "7509d31f9f17ebc064fa615256c8c704", + "size": "67136" + }, + "windows-x86_64": { + "relative_path": "cuda_documentation/windows-x86_64/cuda_documentation-windows-x86_64-12.6.68-archive.zip", + "sha256": "3c18670f19ee96b469d5f956dd4b1ca2521575d35b5c7d2f06beb4a35c8fc017", + "md5": "bc5312afb4f91a1dd4c57f2aaf007418", + "size": "105658" + }, + "linux-aarch64": { + "relative_path": "cuda_documentation/linux-aarch64/cuda_documentation-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "51559dcfd3f4469a50ca24fc9c30c70a2f316bf849c6ea108186eee005732579", + "md5": "7e4fd28e086bdd187efda36bcb4279d3", + "size": "67328" + } + }, + "cuda_gdb": { + "name": "CUDA GDB", + "license": "CUDA Toolkit", + "license_path": "cuda_gdb/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_gdb/linux-x86_64/cuda_gdb-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "ba1a1cc05b1d22d1fcf78c772777ad96fc294a00be835fd50cee36cde46fdd9c", + "md5": "8e74d2a503d3bf7303772866b463752c", + "size": "64658320" + }, + "linux-sbsa": { + "relative_path": "cuda_gdb/linux-sbsa/cuda_gdb-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "fc7b2493571c1e771f4b25c0d907c96b11487c3f19cc5d52f5f9741786c671d4", + "md5": "f2817629de2e33b80d68cf99aac0247c", + "size": "43486016" + }, + "linux-aarch64": { + "relative_path": "cuda_gdb/linux-aarch64/cuda_gdb-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "91a6508c0cb5f8429633e2fb22c1e4d030dc3409febcdbc63eea73ebf9651356", + "md5": "152e4f5b771b48e61e2d2f2a6f8f5b06", + "size": "43464836" + } + }, + "cuda_nsight": { + "name": "Nsight Eclipse Edition Plugin", + "license": "CUDA Toolkit", + "license_path": "cuda_nsight/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_nsight/linux-x86_64/cuda_nsight-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "46093db97de85a16e737ae6cce1c42ba90769fee98de15b5d22f3c96ce318f98", + "md5": "ab33b3825fc7b0bfb0ee4f1f0b544a4b", + "size": "118683196" + } + }, + "cuda_nvcc": { + "name": "CUDA NVCC", + "license": "CUDA Toolkit", + "license_path": "cuda_nvcc/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_nvcc/linux-x86_64/cuda_nvcc-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "b672d0c36a27ea4577536725713064c9daa5d7378ac85877bc847ca9a46b2645", + "md5": "f6f92db59515b090f52ad37c6ebe8a10", + "size": "50050104" + }, + "linux-sbsa": { + "relative_path": "cuda_nvcc/linux-sbsa/cuda_nvcc-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "f895c416e195240a9b89790bffc7a905adf2f33f817c19c081f9cbf44bc67f85", + "md5": "9af47828e804da222697596558509d64", + "size": "43891856" + }, + "windows-x86_64": { + "relative_path": "cuda_nvcc/windows-x86_64/cuda_nvcc-windows-x86_64-12.6.68-archive.zip", + "sha256": "03ef603c9d69a03861e7f021d46ef2932581d3ed8fee75e9b1a4788f22a1aea2", + "md5": "d15fe4ab184384094c3bd365809bf4e6", + "size": "79694104" + }, + "linux-aarch64": { + "relative_path": "cuda_nvcc/linux-aarch64/cuda_nvcc-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "33301f54597975af80d358dedd692994646520035f64cd76805c954a8f61a8b4", + "md5": "1860e2327dc65b849cd1428796006b6b", + "size": "45479008" + } + }, + "cuda_nvdisasm": { + "name": "CUDA nvdisasm", + "license": "CUDA Toolkit", + "license_path": "cuda_nvdisasm/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_nvdisasm/linux-x86_64/cuda_nvdisasm-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "7011130022fadf51619ac1bc44f3270d55a3c1e613b6e62bba0c33edcf5316ad", + "md5": "79e7545e02861a01d0618246b3e9243c", + "size": "49883992" + }, + "linux-sbsa": { + "relative_path": "cuda_nvdisasm/linux-sbsa/cuda_nvdisasm-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "4c20748fe3ce28071c12eec8a47e01dc0108985aa7ba2052ae695e6635b379d8", + "md5": "0e6c36a7b9eb2ccb44a55ba41d228299", + "size": "49812560" + }, + "windows-x86_64": { + "relative_path": "cuda_nvdisasm/windows-x86_64/cuda_nvdisasm-windows-x86_64-12.6.68-archive.zip", + "sha256": "ce7bc28fed1c071709bc1bb3e9d93a336b344d96ca3b8388e1a2d46024b6684f", + "md5": "2b68d39209e4c1831a45ab5262da9f16", + "size": "50158263" + }, + "linux-aarch64": { + "relative_path": "cuda_nvdisasm/linux-aarch64/cuda_nvdisasm-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "2a542487ac78e41743fc0cf8bbacfe67f210cb99d5798d89dc08de960f2e88ec", + "md5": "4a111d145123bcd6a905f5642a85eadc", + "size": "49821740" + } + }, + "cuda_nvml_dev": { + "name": "CUDA NVML Headers", + "license": "CUDA Toolkit", + "license_path": "cuda_nvml_dev/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_nvml_dev/linux-x86_64/cuda_nvml_dev-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "cbff0055190f51b6756a2fd13b5269ced3eb16c98b662357c95bdfd5fb48020a", + "md5": "17bf72f5015fce52684204b847d20229", + "size": "145504" + }, + "linux-sbsa": { + "relative_path": "cuda_nvml_dev/linux-sbsa/cuda_nvml_dev-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "09ef48841aa6bfeb7ea04c937499386de1f3d3f5e119d64b3140d9bf4995f550", + "md5": "1d54381ad20e7d0675d1c12c3d042331", + "size": "148268" + }, + "windows-x86_64": { + "relative_path": "cuda_nvml_dev/windows-x86_64/cuda_nvml_dev-windows-x86_64-12.6.68-archive.zip", + "sha256": "7e615b0a888e86db15cc405605b88fcb9e79b1406e10e39de1f71fc6de152437", + "md5": "6ebf051abe052b4a4f90806d1b080ca3", + "size": "129922" + }, + "linux-aarch64": { + "relative_path": "cuda_nvml_dev/linux-aarch64/cuda_nvml_dev-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "295c15220d5fccb009373946aebe8ac79abbcc33a9c1643ae7f13cba1be2e8df", + "md5": "88df23d0bc63b7c8e02c3b7846d4d7c1", + "size": "147932" + } + }, + "cuda_nvprof": { + "name": "CUDA nvprof", + "license": "CUDA Toolkit", + "license_path": "cuda_nvprof/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_nvprof/linux-x86_64/cuda_nvprof-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "a0bd653f2876a8ba09c3568ee0732e3bef5d44fb8d36a48d77f2ce19b2eac0c2", + "md5": "6c3ecdfa07cf92fbdf9b99e444c88aa7", + "size": "2437268" + }, + "windows-x86_64": { + "relative_path": "cuda_nvprof/windows-x86_64/cuda_nvprof-windows-x86_64-12.6.68-archive.zip", + "sha256": "76a9030891a902c2de5bf375e8cdc9a4702fa1d80fddcf3f7c04e8e3105d47a0", + "md5": "6bcd9abf6ad21e3a64e949b13d63ec74", + "size": "1703131" + } + }, + "cuda_nvprune": { + "name": "CUDA nvprune", + "license": "CUDA Toolkit", + "license_path": "cuda_nvprune/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_nvprune/linux-x86_64/cuda_nvprune-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "c0a8798e793e19658b4ad530447f2c6f72334288b6960a89e464df93ff216d75", + "md5": "2fa32e2d0dcf25a4a970761ab959815d", + "size": "57160" + }, + "linux-sbsa": { + "relative_path": "cuda_nvprune/linux-sbsa/cuda_nvprune-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "f01ea8b5f0631b64d66570bc6485ed4669ab1f5a6b5366e53d28f6493a3e225a", + "md5": "9818510fd87d76e740d9d63ed68822d2", + "size": "49028" + }, + "windows-x86_64": { + "relative_path": "cuda_nvprune/windows-x86_64/cuda_nvprune-windows-x86_64-12.6.68-archive.zip", + "sha256": "e749cf567403ed1137b41d7cb4c8cb5d3e904e9394aba16e85406f75e38daeef", + "md5": "78671e2b8914d126285ce62acee28639", + "size": "146650" + }, + "linux-aarch64": { + "relative_path": "cuda_nvprune/linux-aarch64/cuda_nvprune-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "51d71efecd4ab1f581300aec69bf67717fbe1dfe69fbacf63714100eb01cfa31", + "md5": "56f84b59754dc73a7f74c04875106fe4", + "size": "50856" + } + }, + "cuda_nvrtc": { + "name": "CUDA NVRTC", + "license": "CUDA Toolkit", + "license_path": "cuda_nvrtc/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_nvrtc/linux-x86_64/cuda_nvrtc-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "99c973550275157fe89cffc36c821df3ce3a4ea75aeabb57c12e8d9331bf20d9", + "md5": "7b82c85180c369ecb717224a426a8adc", + "size": "34355608" + }, + "linux-sbsa": { + "relative_path": "cuda_nvrtc/linux-sbsa/cuda_nvrtc-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "dbca520cfc045b946f1f8f69a0f28aaacaafefc97c71f66b579764257ec165b2", + "md5": "d5e00fc1c07dc78025312a8da356f6df", + "size": "31873824" + }, + "windows-x86_64": { + "relative_path": "cuda_nvrtc/windows-x86_64/cuda_nvrtc-windows-x86_64-12.6.68-archive.zip", + "sha256": "6c48c79c2e47a84baac36f327ace7b9c128ef1a6d33581c1740cfa8a6aab4cd8", + "md5": "e3928079fc25ed842a633c54e0c7882c", + "size": "186925533" + }, + "linux-aarch64": { + "relative_path": "cuda_nvrtc/linux-aarch64/cuda_nvrtc-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "ae4cc379df9def53dbda3853798c06a3480486cd5962aeb5115c3f4ccac12507", + "md5": "35d8964143adeba842c779aeb8751401", + "size": "33050352" + } + }, + "cuda_nvtx": { + "name": "CUDA NVTX", + "license": "CUDA Toolkit", + "license_path": "cuda_nvtx/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_nvtx/linux-x86_64/cuda_nvtx-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "cb1c8eac81ad0c4570ac7caf5319a7a1a058cefadca7150b2e01bf54210865b2", + "md5": "4099efd34c6eafe26948370dcedc214c", + "size": "48536" + }, + "linux-sbsa": { + "relative_path": "cuda_nvtx/linux-sbsa/cuda_nvtx-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "478cb70836db290879b123dae6158b8360dc86de9c90964b65ff5abdfd3754a7", + "md5": "15baa0ea9f688af538c2dc20614feaea", + "size": "49084" + }, + "windows-x86_64": { + "relative_path": "cuda_nvtx/windows-x86_64/cuda_nvtx-windows-x86_64-12.6.68-archive.zip", + "sha256": "e74661513bcacb1dab500043d4fe8f388862e9f2de3287a617e9ba822835af83", + "md5": "cf37f0945e505fda3f8bbeebe9072958", + "size": "65837" + }, + "linux-aarch64": { + "relative_path": "cuda_nvtx/linux-aarch64/cuda_nvtx-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "74ff140cf17df1670717fa099e00d5fdc35787f5656f1e60e58505c05b0b40d0", + "md5": "6ece79949eba9290b98e02d1ac127bd8", + "size": "51736" + } + }, + "cuda_nvvp": { + "name": "CUDA NVVP", + "license": "CUDA Toolkit", + "license_path": "cuda_nvvp/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_nvvp/linux-x86_64/cuda_nvvp-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "940a24cce6329284c92f7b89a73247906e96ccfcd465d839df5d0683a04311f6", + "md5": "b9130679efe71e6bb34d80a6ec9f6cc5", + "size": "117742036" + }, + "windows-x86_64": { + "relative_path": "cuda_nvvp/windows-x86_64/cuda_nvvp-windows-x86_64-12.6.68-archive.zip", + "sha256": "ef21f716eb951dbb5a56e89fd5958a9b6644ccdc24503aa5e0ef5d984337614c", + "md5": "ae4ccf3887c1547da247fa866ca96dbd", + "size": "120342345" + } + }, + "cuda_opencl": { + "name": "CUDA OpenCL", + "license": "CUDA Toolkit", + "license_path": "cuda_opencl/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_opencl/linux-x86_64/cuda_opencl-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "eba0676d777494890228b19ad6c46eb929e5779d9ca8fb258462fe39bef74323", + "md5": "3413a6ebcc1abe2db06875cd6e48e9ab", + "size": "92268" + }, + "windows-x86_64": { + "relative_path": "cuda_opencl/windows-x86_64/cuda_opencl-windows-x86_64-12.6.68-archive.zip", + "sha256": "3d0b4c5c7c42d3ec88eab577b683fdf6209c9a91e925961f56e752b3e61aa2bf", + "md5": "494df106c99bccb2a670b397c9b506b4", + "size": "137329" + } + }, + "cuda_profiler_api": { + "name": "CUDA Profiler API", + "license": "CUDA Toolkit", + "license_path": "cuda_profiler_api/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_profiler_api/linux-x86_64/cuda_profiler_api-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "db13ef65e65e654f3874c1f849a82fb2900b105a306abd6abfbe3e86f2e72af3", + "md5": "5b8ca62172e6b8c34f8bb195f49fb948", + "size": "16188" + }, + "linux-sbsa": { + "relative_path": "cuda_profiler_api/linux-sbsa/cuda_profiler_api-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "49e32f2e5af793d9a8b5ffef7e1c4e6050a848621c9f64ab3f51091ee0c5bdd6", + "md5": "8713ad13cfc60c18b8d5cb2046a7cbb2", + "size": "16180" + }, + "windows-x86_64": { + "relative_path": "cuda_profiler_api/windows-x86_64/cuda_profiler_api-windows-x86_64-12.6.68-archive.zip", + "sha256": "a6f09ebc12113db7e641b8518d8b3435841729715f3c34000a5131a5dc88ef7e", + "md5": "4258f83b13a1a8161ac87a1ee7ec2227", + "size": "20222" + }, + "linux-aarch64": { + "relative_path": "cuda_profiler_api/linux-aarch64/cuda_profiler_api-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "d076aa60d047fbbdd25475befad6716ca2d6d9db039ffcd73bb43c45caf22d0c", + "md5": "1cfd3e27f164b4189f9ed0c18b4095b2", + "size": "16176" + } + }, + "cuda_sanitizer_api": { + "name": "CUDA Compute Sanitizer API", + "license": "CUDA Toolkit", + "license_path": "cuda_sanitizer_api/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "cuda_sanitizer_api/linux-x86_64/cuda_sanitizer_api-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "aef606f0c289a36dae84c4c4e9f79f5bf6897f1ba3944037f49347e7c732cad3", + "md5": "082ff9d088195f2a33ae473d44776fcb", + "size": "9545716" + }, + "linux-sbsa": { + "relative_path": "cuda_sanitizer_api/linux-sbsa/cuda_sanitizer_api-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "601cb7a9807f119d3cd39c095465eed65c7bceb12b316d96fc3527cca975978e", + "md5": "75865f4f6a2fd9dd991d79cc94f28110", + "size": "7251812" + }, + "windows-x86_64": { + "relative_path": "cuda_sanitizer_api/windows-x86_64/cuda_sanitizer_api-windows-x86_64-12.6.68-archive.zip", + "sha256": "7579bb575731877072d0004943e81d061e4ef661db53b5da1f46724f95ecfe22", + "md5": "2219d5cd9a3b69be123df259097200a9", + "size": "9757678" + }, + "linux-aarch64": { + "relative_path": "cuda_sanitizer_api/linux-aarch64/cuda_sanitizer_api-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "0d69d797b00395eed9c1c1d9e2d7090153727aa99832c3e0bed64e1b31178584", + "md5": "b386c125b3d91f716e17f89e0c7cf1e2", + "size": "4103036" + } + }, + "fabricmanager": { + "name": "NVIDIA Fabric Manager", + "license": "NVIDIA Driver", + "license_path": "fabricmanager/LICENSE.txt", + "version": "560.35.03", + "linux-x86_64": { + "relative_path": "fabricmanager/linux-x86_64/fabricmanager-linux-x86_64-560.35.03-archive.tar.xz", + "sha256": "9fbb881948f524af417b46e9b17f2146d682d011ded3aa0e821309ed23df3aa5", + "md5": "a18c407a4379849b8ed0b38028797522", + "size": "6065756" + }, + "linux-sbsa": { + "relative_path": "fabricmanager/linux-sbsa/fabricmanager-linux-sbsa-560.35.03-archive.tar.xz", + "sha256": "e36fd543964eb3977d1086a59210b8a953afff03c1a9b91ccbe2681356bfa0bd", + "md5": "011d67ac6414fa3d2a4b04255d69a884", + "size": "5479452" + } + }, + "imex": { + "name": "Nvidia-Imex", + "license": "NVIDIA Proprietary", + "license_path": "imex/LICENSE.txt", + "version": "560.35.03", + "linux-x86_64": { + "relative_path": "imex/linux-x86_64/nvidia-imex-linux-x86_64-560.35.03-archive.tar.xz", + "sha256": "502f1579136741ea0e89e2b74e0303f671336e9fd9dafa6b0312a0f891a1559a", + "md5": "fd25e88f744d937e5d7e336dda15b633", + "size": "7419540" + }, + "linux-sbsa": { + "relative_path": "imex/linux-sbsa/nvidia-imex-linux-sbsa-560.35.03-archive.tar.xz", + "sha256": "5219e343fdcdef1be626a0f8632e3da23711cb63ef18b6b64cf3089a1b6f2025", + "md5": "01dfaec839ee13a2eafea256f2632fdb", + "size": "6617284" + } + }, + "libcublas": { + "name": "CUDA cuBLAS", + "license": "CUDA Toolkit", + "license_path": "libcublas/LICENSE.txt", + "version": "12.6.1.4", + "linux-x86_64": { + "relative_path": "libcublas/linux-x86_64/libcublas-linux-x86_64-12.6.1.4-archive.tar.xz", + "sha256": "78c4e88a3eddfc6ad7108541a76cb8f80b7c4028d90b9e5d5adc00db47370b88", + "md5": "14f3cdc0c736a386d220392a73a8e2ef", + "size": "507059912" + }, + "linux-sbsa": { + "relative_path": "libcublas/linux-sbsa/libcublas-linux-sbsa-12.6.1.4-archive.tar.xz", + "sha256": "f79d5f965dc6912b8abb50d20d93032d79bd96dacd65d8649ca750e863ac9185", + "md5": "c2c9635eb6a07e52ccc0f31f8f2b0a45", + "size": "505253952" + }, + "windows-x86_64": { + "relative_path": "libcublas/windows-x86_64/libcublas-windows-x86_64-12.6.1.4-archive.zip", + "sha256": "00096575f17339b7bf7ef7d8477337cb090206a47f710bb97ec5859604d0b8da", + "md5": "7ddf582853c811fc4c1ff47c37b6b6ee", + "size": "414877806" + }, + "linux-aarch64": { + "relative_path": "libcublas/linux-aarch64/libcublas-linux-aarch64-12.6.1.4-archive.tar.xz", + "sha256": "4f8f3df4e582abba889edc22f162574d199b2a23cb1bbc714a00d5fbb4b0f822", + "md5": "61e0d0de3db912d461785cad327659a6", + "size": "440994816" + } + }, + "libcudla": { + "name": "cuDLA", + "license": "CUDA Toolkit", + "license_path": "libcudla/LICENSE.txt", + "version": "12.6.68", + "linux-aarch64": { + "relative_path": "libcudla/linux-aarch64/libcudla-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "cb6dfd5618df21e25a32cb0dd278bdc6ea7eeee61cffc0526a16c17c4a25475a", + "md5": "e3bbb247e22db1f08c9f285a6b58f818", + "size": "38428" + } + }, + "libcufft": { + "name": "CUDA cuFFT", + "license": "CUDA Toolkit", + "license_path": "libcufft/LICENSE.txt", + "version": "11.2.6.59", + "linux-x86_64": { + "relative_path": "libcufft/linux-x86_64/libcufft-linux-x86_64-11.2.6.59-archive.tar.xz", + "sha256": "225c35b92301b670126ffc7b7aa5df09fbfbe85d3869d17e131523617544e628", + "md5": "de57c87ed59ec57d055de2792d84d2cf", + "size": "453145660" + }, + "linux-sbsa": { + "relative_path": "libcufft/linux-sbsa/libcufft-linux-sbsa-11.2.6.59-archive.tar.xz", + "sha256": "bd7d2464cbb7c66783d7bfbed7130c36caa213f4361cab2f00585fbfc783c434", + "md5": "030393814ce2f27b4d8d33a25697b1fe", + "size": "453102488" + }, + "windows-x86_64": { + "relative_path": "libcufft/windows-x86_64/libcufft-windows-x86_64-11.2.6.59-archive.zip", + "sha256": "9216351d17d9c7b4bb3b93ce278d928326ae7e9ab86ddab03b91accd64cb3a7e", + "md5": "1c40577fcc4f7a1c658adcadcc210223", + "size": "189989048" + }, + "linux-aarch64": { + "relative_path": "libcufft/linux-aarch64/libcufft-linux-aarch64-11.2.6.59-archive.tar.xz", + "sha256": "f0c49b97b4b1f1f35291e574dcd4d62ba779f578820a25323eaf2a2f080bf518", + "md5": "bd9e3c33a9f12c3ae6f46ab1f76b06f9", + "size": "453219536" + } + }, + "libcufile": { + "name": "CUDA cuFile", + "license": "CUDA Toolkit", + "license_path": "libcufile/LICENSE.txt", + "version": "1.11.1.6", + "linux-x86_64": { + "relative_path": "libcufile/linux-x86_64/libcufile-linux-x86_64-1.11.1.6-archive.tar.xz", + "sha256": "99ee42e0ebf826f13cea9d15d63f54f225ddc42ff87be1427c58be9692ae25bc", + "md5": "1cb6fc8741517038ab956e6eb141a262", + "size": "41841440" + }, + "linux-sbsa": { + "relative_path": "libcufile/linux-sbsa/libcufile-linux-sbsa-1.11.1.6-archive.tar.xz", + "sha256": "fda8d0491f9e3311adb317841893a531737b82316187619e2116d86d7a84faaf", + "md5": "9a3dcdf43d42e78ac29d366c46c17764", + "size": "41290172" + }, + "linux-aarch64": { + "relative_path": "libcufile/linux-aarch64/libcufile-linux-aarch64-1.11.1.6-archive.tar.xz", + "sha256": "2d2e461830748ebb508be8cc93c804486618dbd6a53de13fb7976d71a481013a", + "md5": "aed61fb0c12b25f8dcb8c80c82c6923f", + "size": "41280828" + } + }, + "libcurand": { + "name": "CUDA cuRAND", + "license": "CUDA Toolkit", + "license_path": "libcurand/LICENSE.txt", + "version": "10.3.7.68", + "linux-x86_64": { + "relative_path": "libcurand/linux-x86_64/libcurand-linux-x86_64-10.3.7.68-archive.tar.xz", + "sha256": "f3d7ed58fe61214c622a8d8853f65016ed4485a3a8d314edab11f50890a78545", + "md5": "a8186ffe345539bd7a554aa3fc1c21e0", + "size": "81729380" + }, + "linux-sbsa": { + "relative_path": "libcurand/linux-sbsa/libcurand-linux-sbsa-10.3.7.68-archive.tar.xz", + "sha256": "5da4634d4d4c2bf861f89f2efaa2734ceeeef3cb9163f738b45fc4001f9497bc", + "md5": "6575c88fe2498ee5d14d04125c982c68", + "size": "81713260" + }, + "windows-x86_64": { + "relative_path": "libcurand/windows-x86_64/libcurand-windows-x86_64-10.3.7.68-archive.zip", + "sha256": "adf734418c21fcf1cdb166e590a0212d49c43bb0c79405b6657fdcb17c5d59bc", + "md5": "cb116eafccf2be580714d3cbcf7cb725", + "size": "55075352" + }, + "linux-aarch64": { + "relative_path": "libcurand/linux-aarch64/libcurand-linux-aarch64-10.3.7.68-archive.tar.xz", + "sha256": "8ac4eec86c2f04083eb7b47b44205530ca8b59823ce360a09366edc4ad1b3535", + "md5": "1fa298ab8d420407b84111ab84914bc7", + "size": "83951384" + } + }, + "libcusolver": { + "name": "CUDA cuSOLVER", + "license": "CUDA Toolkit", + "license_path": "libcusolver/LICENSE.txt", + "version": "11.6.4.69", + "linux-x86_64": { + "relative_path": "libcusolver/linux-x86_64/libcusolver-linux-x86_64-11.6.4.69-archive.tar.xz", + "sha256": "4326a763c5a57bdd8ab937ebf430ea04b2bfa5ab5a1e0f02fff16861aa8c26ab", + "md5": "6f42b392a30f67fe406e090488557f60", + "size": "130221572" + }, + "linux-sbsa": { + "relative_path": "libcusolver/linux-sbsa/libcusolver-linux-sbsa-11.6.4.69-archive.tar.xz", + "sha256": "aef94a995c7afce20eac7de5926c1ccca09a7d592319fa28ce3ea06163158797", + "md5": "6ab1d3427f81509bf369ac5c861db9d1", + "size": "129198296" + }, + "windows-x86_64": { + "relative_path": "libcusolver/windows-x86_64/libcusolver-windows-x86_64-11.6.4.69-archive.zip", + "sha256": "f2083a14e7ad307d3833a81785dd2291783207cc3b6f9dea60a47fc1d6c642b3", + "md5": "f85833fb50e099a2d60aee6dea151635", + "size": "126188094" + }, + "linux-aarch64": { + "relative_path": "libcusolver/linux-aarch64/libcusolver-linux-aarch64-11.6.4.69-archive.tar.xz", + "sha256": "05d1325f6c96e5a796cc4fd22c1fa91d7675b03d4b8103f575176eaeb7c9c9ee", + "md5": "7aff4af4a65bca54c7afbba9499fb8cc", + "size": "141675048" + } + }, + "libcusparse": { + "name": "CUDA cuSPARSE", + "license": "CUDA Toolkit", + "license_path": "libcusparse/LICENSE.txt", + "version": "12.5.3.3", + "linux-x86_64": { + "relative_path": "libcusparse/linux-x86_64/libcusparse-linux-x86_64-12.5.3.3-archive.tar.xz", + "sha256": "be40783e089213921d99cbf0102f5f4d712e7c4996b6135e41ff35068e9e753d", + "md5": "7e9e42a60f5273fd811845242711cfbc", + "size": "236000168" + }, + "linux-sbsa": { + "relative_path": "libcusparse/linux-sbsa/libcusparse-linux-sbsa-12.5.3.3-archive.tar.xz", + "sha256": "901db312af40926b0225d88e74a1793e7c0dd367f2de7909a176738f9805f5b8", + "md5": "590363a67c9c47e5fa4ce89c1ed5ff1f", + "size": "235629148" + }, + "windows-x86_64": { + "relative_path": "libcusparse/windows-x86_64/libcusparse-windows-x86_64-12.5.3.3-archive.zip", + "sha256": "652c7784bca05bf58c99268a2fce3369a2c668cb0b769f1d829464deeab243b8", + "md5": "f2fb2529c57c5b097627c0abf8d24a9a", + "size": "211342957" + }, + "linux-aarch64": { + "relative_path": "libcusparse/linux-aarch64/libcusparse-linux-aarch64-12.5.3.3-archive.tar.xz", + "sha256": "98fbf8839a09f02b151292011e64c3e7960f43640ea8a2a701bda8083cc807f7", + "md5": "812cde18001569f06f0d86937a1f6953", + "size": "253334728" + } + }, + "libnpp": { + "name": "CUDA NPP", + "license": "CUDA Toolkit", + "license_path": "libnpp/LICENSE.txt", + "version": "12.3.1.54", + "linux-x86_64": { + "relative_path": "libnpp/linux-x86_64/libnpp-linux-x86_64-12.3.1.54-archive.tar.xz", + "sha256": "0a7f5bb81e65e60775f831990a567394682a209694b396a4e9233a6c91db65e3", + "md5": "f1a61e38a71c751a7c904a66362ccfea", + "size": "182688996" + }, + "linux-sbsa": { + "relative_path": "libnpp/linux-sbsa/libnpp-linux-sbsa-12.3.1.54-archive.tar.xz", + "sha256": "0901bdf3abc7c3d4143acebb058ba5f95c1dfd092f25ce0c52d6b6974585a564", + "md5": "3fbbf44ca4a36f6040ffe3b77fa82534", + "size": "182191412" + }, + "windows-x86_64": { + "relative_path": "libnpp/windows-x86_64/libnpp-windows-x86_64-12.3.1.54-archive.zip", + "sha256": "9a5271ce10478945eaa730360226e0c6f408425bb5689d5cf48bb4ca8085a008", + "md5": "4c9546d1e16b00cd400871dcfc17a537", + "size": "154933759" + }, + "linux-aarch64": { + "relative_path": "libnpp/linux-aarch64/libnpp-linux-aarch64-12.3.1.54-archive.tar.xz", + "sha256": "eb0473643b991be77b64b31f5e63437203e1167bbc9274d7f6a6ad5114d048fd", + "md5": "40c771b024287b7509ada380aad87a15", + "size": "200333628" + } + }, + "libnvfatbin": { + "name": "NVIDIA compiler library for fatbin interaction", + "license": "CUDA Toolkit", + "license_path": "libnvfatbin/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "libnvfatbin/linux-x86_64/libnvfatbin-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "cd492c887819241714f9eb756e09d277ae67585ee533d4d55c36d84e0411a7e4", + "md5": "c9f9a75e4add6b2690473cbfa60d157c", + "size": "909416" + }, + "linux-sbsa": { + "relative_path": "libnvfatbin/linux-sbsa/libnvfatbin-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "ec36e5c69be19de627418d2c61be4205d719ac70b4d7b5a093625a90b03e7806", + "md5": "fe6f9fe3ffbbfd943fed7e46b0f9f6ed", + "size": "819020" + }, + "windows-x86_64": { + "relative_path": "libnvfatbin/windows-x86_64/libnvfatbin-windows-x86_64-12.6.68-archive.zip", + "sha256": "dc9d572169f6da4d82b22584ab5088d0ce4ae82fbb8ce71f23bf29fb7162f203", + "md5": "20785b54ecf15c6d2b02ad90527a5d1a", + "size": "2181139" + }, + "linux-aarch64": { + "relative_path": "libnvfatbin/linux-aarch64/libnvfatbin-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "0c0c1274d5eac1d8c422e90f57e1fa21f6d57aa5f616efe4005c2725df0a1654", + "md5": "4c554f7a9093c2d71efb1a1d7b3f6229", + "size": "794012" + } + }, + "libnvidia_nscq": { + "name": "NVIDIA NSCQ API", + "license": "NVIDIA Driver", + "license_path": "libnvidia_nscq/LICENSE.txt", + "version": "560.35.03", + "linux-x86_64": { + "relative_path": "libnvidia_nscq/linux-x86_64/libnvidia_nscq-linux-x86_64-560.35.03-archive.tar.xz", + "sha256": "66349840f41caeb16b1b77f1ac4956abe787bf1bbd54ad19a30e7d904f06c942", + "md5": "f593eed9bea4e09980969a25525c6e03", + "size": "356820" + }, + "linux-sbsa": { + "relative_path": "libnvidia_nscq/linux-sbsa/libnvidia_nscq-linux-sbsa-560.35.03-archive.tar.xz", + "sha256": "5b851b42776367500c58b6481a0599daa7fd79f174f60dcc03630920c058eccf", + "md5": "038cb3140d08fb683cb51f0a02a98d80", + "size": "350984" + } + }, + "libnvjitlink": { + "name": "NVIDIA compiler library for JIT LTO functionality", + "license": "CUDA Toolkit", + "license_path": "libnvjitlink/LICENSE.txt", + "version": "12.6.68", + "linux-x86_64": { + "relative_path": "libnvjitlink/linux-x86_64/libnvjitlink-linux-x86_64-12.6.68-archive.tar.xz", + "sha256": "700a0c2cbd1e591213a2bac6e34ed4ba451224db86bcb782b4f6e052209e348c", + "md5": "5c84737d01c092c3580aa641b7a6c33a", + "size": "28936544" + }, + "linux-sbsa": { + "relative_path": "libnvjitlink/linux-sbsa/libnvjitlink-linux-sbsa-12.6.68-archive.tar.xz", + "sha256": "ae303c4c0ce235ab84d50c6f5917b1ebb50d3cf22e2614d5a55e1767f841215d", + "md5": "d08759a9e8d425f9b66db10d00e47c50", + "size": "26703500" + }, + "windows-x86_64": { + "relative_path": "libnvjitlink/windows-x86_64/libnvjitlink-windows-x86_64-12.6.68-archive.zip", + "sha256": "7b49eb751c7b99d777a173280afadab0707d34ad6e7ee0728fe8160a99d70e29", + "md5": "5eac982aff0888d09bfa335a93908ba2", + "size": "155333975" + }, + "linux-aarch64": { + "relative_path": "libnvjitlink/linux-aarch64/libnvjitlink-linux-aarch64-12.6.68-archive.tar.xz", + "sha256": "999117b1c362a6d032fbc6f19c44732d26ef0bfa58373a28beb2d912329d1ba1", + "md5": "f897b9f20a2756282882d31096ee5bde", + "size": "27872572" + } + }, + "libnvjpeg": { + "name": "CUDA nvJPEG", + "license": "CUDA Toolkit", + "license_path": "libnvjpeg/LICENSE.txt", + "version": "12.3.3.54", + "linux-x86_64": { + "relative_path": "libnvjpeg/linux-x86_64/libnvjpeg-linux-x86_64-12.3.3.54-archive.tar.xz", + "sha256": "f74f6aee35ef4fb1619bc2a67be943c3d1a84d6746b41788c44a7d3b0d9ae3b4", + "md5": "e21f0dc4f94bc875ef99e1afbfd85bbe", + "size": "2579560" + }, + "linux-sbsa": { + "relative_path": "libnvjpeg/linux-sbsa/libnvjpeg-linux-sbsa-12.3.3.54-archive.tar.xz", + "sha256": "6970db1c9757f3ae30adba21d7c1306fd5afc4cb034b0739c711691a481d3ed4", + "md5": "01811faaa7d3de0353169948247aeb02", + "size": "2418632" + }, + "windows-x86_64": { + "relative_path": "libnvjpeg/windows-x86_64/libnvjpeg-windows-x86_64-12.3.3.54-archive.zip", + "sha256": "15c1b28e623598eb75f48d02bfd34efa83b35e3f8d1d5241c93a385d0bea9d18", + "md5": "63f0c5626a07b2850e6eadb704685d69", + "size": "2829340" + }, + "linux-aarch64": { + "relative_path": "libnvjpeg/linux-aarch64/libnvjpeg-linux-aarch64-12.3.3.54-archive.tar.xz", + "sha256": "e81f56682cb4d6e837d5527aaf1acd26ab8eace470b5e7a32f9a8d685e7ef2bc", + "md5": "6e90b73e124be49f09b9fe517dff5bb6", + "size": "2562184" + } + }, + "libnvsdm": { + "name": "LIBNVSDM", + "license": "NVIDIA", + "license_path": "libnvsdm/LICENSE.txt", + "version": "560.35.03", + "linux-x86_64": { + "relative_path": "libnvsdm/linux-x86_64/libnvsdm-linux-x86_64-560.35.03-archive.tar.xz", + "sha256": "807f63491c351fb459876f39ee4455d6fb81b5cc6b17100e04c6f0c7f5a24970", + "md5": "bd9facf361fc729bf3676200b3223023", + "size": "550380" + } + }, + "nsight_compute": { + "name": "Nsight Compute", + "license": "NVIDIA SLA", + "license_path": "nsight_compute/LICENSE.txt", + "version": "2024.3.1.2", + "linux-x86_64": { + "relative_path": "nsight_compute/linux-x86_64/nsight_compute-linux-x86_64-2024.3.1.2-archive.tar.xz", + "sha256": "244e39cfc2c0ac02eaa8db20eb5fd45ec0ce31edf5481febb10acb5d144ce6da", + "md5": "4f91b9af45668e7abf0bfc9e0022e3a4", + "size": "429152828" + }, + "linux-sbsa": { + "relative_path": "nsight_compute/linux-sbsa/nsight_compute-linux-sbsa-2024.3.1.2-archive.tar.xz", + "sha256": "fc6519f2e5ab340a6d4f5d0ae3842b6c54bedb24964eba0e5bd04aa497f1138a", + "md5": "15d866cf6d0b7c031ff5557771e854c1", + "size": "218369356" + }, + "windows-x86_64": { + "relative_path": "nsight_compute/windows-x86_64/nsight_compute-windows-x86_64-2024.3.1.2-archive.zip", + "sha256": "8b630c2155f379f277b49a0c32cd30aa0b296f00cb08d8d0d31af93157373165", + "md5": "0fd3a20d746ed9f746be52fe1531c7a2", + "size": "462192068" + }, + "linux-aarch64": { + "relative_path": "nsight_compute/linux-aarch64/nsight_compute-linux-aarch64-2024.3.1.2-archive.tar.xz", + "sha256": "3cc91b715e06584c6dcdfe5c83d272ac6f37c7e149ec9755fb0d4c858bcc2020", + "md5": "44fe05f5cc5a0dca6c93fa1a8f2c6148", + "size": "429061300" + } + }, + "nsight_systems": { + "name": "Nsight Systems", + "license": "NVIDIA SLA", + "license_path": "nsight_systems/LICENSE.txt", + "version": "2024.4.2.133", + "linux-x86_64": { + "relative_path": "nsight_systems/linux-x86_64/nsight_systems-linux-x86_64-2024.4.2.133-archive.tar.xz", + "sha256": "7e5dae8b23da110462e2b9545360e37d9931a336ac8d4e1e14364fa516acc4db", + "md5": "f922c51cb16567c64737486d3cca9edd", + "size": "254795020" + }, + "linux-sbsa": { + "relative_path": "nsight_systems/linux-sbsa/nsight_systems-linux-sbsa-2024.4.2.133-archive.tar.xz", + "sha256": "9fa78d9f72160dea2a8a4075eaba6dbb61b54126fcec53138aec86df7f052660", + "md5": "a186b2aade2f2057e00995c67eeee7b4", + "size": "206467024" + }, + "windows-x86_64": { + "relative_path": "nsight_systems/windows-x86_64/nsight_systems-windows-x86_64-2024.4.2.133-archive.zip", + "sha256": "77cd8cd2cd4588acf5be36508db71e40e725dbd2c96c89d88ac243e26844d9ef", + "md5": "f15fda899004953ff9704b3e5cc594cd", + "size": "367169284" + } + }, + "nsight_vse": { + "name": "Nsight Visual Studio Edition (VSE)", + "license": "NVIDIA SLA", + "license_path": "nsight_vse/LICENSE.txt", + "version": "2024.3.0.24164", + "windows-x86_64": { + "relative_path": "nsight_vse/windows-x86_64/nsight_vse-windows-x86_64-2024.3.0.24164-archive.zip", + "sha256": "f06b1b9d9e4bcdf6cb44a85c506ecbf55482c4557df02c1906c1d469986b371a", + "md5": "e86b066ca8aa0922c2db274757e40dad", + "size": "471792358" + } + }, + "nvidia_driver": { + "name": "NVIDIA Linux Driver", + "license": "NVIDIA Driver", + "license_path": "nvidia_driver/LICENSE.txt", + "version": "560.35.03", + "linux-x86_64": { + "relative_path": "nvidia_driver/linux-x86_64/nvidia_driver-linux-x86_64-560.35.03-archive.tar.xz", + "sha256": "301e7bfb7868eeae74b076068f0ebc00b3732d718084a78261f9c862975d1058", + "md5": "74e3f5e5cb10326b3236cb3b5d1fb731", + "size": "374384124" + }, + "linux-sbsa": { + "relative_path": "nvidia_driver/linux-sbsa/nvidia_driver-linux-sbsa-560.35.03-archive.tar.xz", + "sha256": "6c41cc106562ba8969e00785eff1f91be2c0eb8bd3ee0fde78fa32b3dfc45a03", + "md5": "7a01f16712f0ac284db1addb86d95a3e", + "size": "289359252" + } + }, + "nvidia_fs": { + "name": "NVIDIA filesystem", + "license": "CUDA Toolkit", + "license_path": "nvidia_fs/LICENSE.txt", + "version": "2.22.3", + "linux-x86_64": { + "relative_path": "nvidia_fs/linux-x86_64/nvidia_fs-linux-x86_64-2.22.3-archive.tar.xz", + "sha256": "67ac2e05a6388db2824c454e0bdd808d662aa1fe63ad3292471b144fb0c7fad1", + "md5": "605ff67650a8ae1f72a9bd8540ed0ee0", + "size": "59284" + }, + "linux-sbsa": { + "relative_path": "nvidia_fs/linux-sbsa/nvidia_fs-linux-sbsa-2.22.3-archive.tar.xz", + "sha256": "1c73cfb016ce4c6b0c99d46084a678a5e062875e1180b556bda624f7648653f6", + "md5": "8debe062baaa33cd4283237d112633c4", + "size": "59284" + }, + "linux-aarch64": { + "relative_path": "nvidia_fs/linux-aarch64/nvidia_fs-linux-aarch64-2.22.3-archive.tar.xz", + "sha256": "7d8db9cf65b6c29198a6c29749ffb5aea3367c1adee71c6bd10169fcaca488db", + "md5": "076dbd175b9dbacd9a199f29069161e5", + "size": "59288" + } + }, + "visual_studio_integration": { + "name": "CUDA Visual Studio Integration", + "license": "CUDA Toolkit", + "license_path": "visual_studio_integration/LICENSE.txt", + "version": "12.6.68", + "windows-x86_64": { + "relative_path": "visual_studio_integration/windows-x86_64/visual_studio_integration-windows-x86_64-12.6.68-archive.zip", + "sha256": "fc2c684f4327040fb02c6c6e59a3e38713c1ddf9b91d95db173defb8a2146d0d", + "md5": "df08081ff0b07a90af9f20bc3b064da3", + "size": "533182" + } + } +} \ No newline at end of file diff --git a/runtimes/cuda/cudnn.redistrib_9.3.0.json b/runtimes/cuda/cudnn.redistrib_9.3.0.json new file mode 100644 index 0000000..d76b57c --- /dev/null +++ b/runtimes/cuda/cudnn.redistrib_9.3.0.json @@ -0,0 +1,77 @@ +{ + "release_date": "2024-08-01", + "release_label": "9.3.0", + "release_product": "cudnn", + "cudnn": { + "name": "NVIDIA CUDA Deep Neural Network library", + "license": "cudnn", + "license_path": "cudnn/LICENSE.txt", + "version": "9.3.0.75", + "linux-x86_64": { + "cuda11": { + "relative_path": "cudnn/linux-x86_64/cudnn-linux-x86_64-9.3.0.75_cuda11-archive.tar.xz", + "sha256": "069da084cd368f39fb830d4c4e931803064fb65e766f4cf7df2da4a346a2ba9f", + "md5": "4ab5cfb90cfe16c02cbdb88788165de5", + "size": "748177916" + }, + "cuda12": { + "relative_path": "cudnn/linux-x86_64/cudnn-linux-x86_64-9.3.0.75_cuda12-archive.tar.xz", + "sha256": "3d6ef10aa06dc9339a477e2b057e085ff8500bbdee79e42c7e13655c9eff2c26", + "md5": "2fa73268de8bbdab5560f4aa1a5a73ab", + "size": "756509380" + } + }, + "cuda_variant": [ + "11", + "12" + ], + "linux-sbsa": { + "cuda11": { + "relative_path": "cudnn/linux-sbsa/cudnn-linux-sbsa-9.3.0.75_cuda11-archive.tar.xz", + "sha256": "04b56fbf7bee15c24e339c2ba94d17aa88b9e334d0cd19e75853dc5452794bf7", + "md5": "eb3d809ff9c853721d342aa68564ed77", + "size": "746866932" + }, + "cuda12": { + "relative_path": "cudnn/linux-sbsa/cudnn-linux-sbsa-9.3.0.75_cuda12-archive.tar.xz", + "sha256": "1226dd9b989c898638552963d000a3cfbb8a0a0cb9baf8cb09e6abd77ed7d639", + "md5": "bdf5c7ba6ae34cc0dbcdfb98f3da746d", + "size": "754450192" + } + }, + "windows-x86_64": { + "cuda11": { + "relative_path": "cudnn/windows-x86_64/cudnn-windows-x86_64-9.3.0.75_cuda11-archive.zip", + "sha256": "0e6f9d39343b88208b1daea280d62d6f7a90355395999806de6624c8361c36fc", + "md5": "d7414555bd6c9e8a91139f00864fa2fa", + "size": "562755549" + }, + "cuda12": { + "relative_path": "cudnn/windows-x86_64/cudnn-windows-x86_64-9.3.0.75_cuda12-archive.zip", + "sha256": "864a85dc67c7f92b9a8639f323acb4af63ad65de2ca82dccdf2c0b6a701c27c0", + "md5": "5f82d9233dd22a6664abff13cd22a224", + "size": "566118754" + } + }, + "linux-aarch64": { + "cuda12": { + "relative_path": "cudnn/linux-aarch64/cudnn-linux-aarch64-9.3.0.75_cuda12-archive.tar.xz", + "sha256": "1aae4bfced63f930b4677f9e928e197878dece2edd51ca8fa7ab8363d0e6ed60", + "md5": "e5a94b1b0bbd313c0c11235d969ca028", + "size": "796357916" + } + } + }, + "cudnn_samples": { + "name": "NVIDIA cuDNN samples", + "license": "cudnn", + "license_path": "cudnn_samples/LICENSE.txt", + "version": "9.3.0.75", + "source": { + "relative_path": "cudnn_samples/source/cudnn_samples-source-9.3.0.75-archive.tar.xz", + "sha256": "5da5536bba749158b245ddf69b4a0e2f4bf122e9b3c0e7406d8c2ddd5dd97518", + "md5": "d855a9694631213fb6e78da90ae60fbe", + "size": "1666860" + } + } +} \ No newline at end of file diff --git a/runtimes/cuda/libpjrt_cuda.BUILD.bazel b/runtimes/cuda/libpjrt_cuda.BUILD.bazel new file mode 100644 index 0000000..6b609a3 --- /dev/null +++ b/runtimes/cuda/libpjrt_cuda.BUILD.bazel @@ -0,0 +1,32 @@ +load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory") +load("@zml//bazel:cc_import.bzl", "cc_import") + +copy_to_directory( + name = "sandbox", + srcs = [ + "@cuda_nvcc//:libdevice", + "@cuda_nvcc//:ptxas", + ], + include_external_repositories = ["**"], +) + +cc_import( + name = "libpjrt_cuda", + data = [":sandbox"], + shared_library = "libpjrt_cuda.so", + visibility = ["@zml//runtimes/cuda:__subpackages__"], + deps = [ + "@cuda_cudart//:cudart", + "@cuda_cupti//:cupti", + "@cuda_nvcc//:nvvm", + "@cuda_nvrtc//:nvrtc", + "@cudnn//:cudnn", + "@libcublas//:cublas", + "@libcufft//:cufft", + "@libcusolver//:cusolver", + "@libcusparse//:cusparse", + "@libnccl//:nccl", + "@libnvjitlink//:nvjitlink", + "@zlib", + ], +) diff --git a/runtimes/rocm/BUILD.bazel b/runtimes/rocm/BUILD.bazel new file mode 100644 index 0000000..a75fc83 --- /dev/null +++ b/runtimes/rocm/BUILD.bazel @@ -0,0 +1,21 @@ +filegroup( + name = "zmlrocmhooks_srcs", + srcs = ["zmlrocmhooks.cc"], + visibility = ["@libpjrt_rocm//:__subpackages__"], +) + +alias( + name = "hipblaslt", + actual = "@libpjrt_rocm//:hipblaslt", +) + +alias( + name = "gfx", + actual = "@libpjrt_rocm//:gfx", +) + +alias( + name = "rocm", + actual = "@libpjrt_rocm", + visibility = ["//visibility:public"], +) diff --git a/runtimes/rocm/gfx.bzl b/runtimes/rocm/gfx.bzl new file mode 100644 index 0000000..d63095c --- /dev/null +++ b/runtimes/rocm/gfx.bzl @@ -0,0 +1,49 @@ +load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") + +_ALL_GFX = ["gfx900", "gfx906", "gfx908", "gfx90a", "gfx940", "gfx941", "gfx942", "gfx1010", "gfx1012", "gfx1030", "gfx1100", "gfx1101", "gfx1102"] + +def _compute_enabled_gfx(values): + ret = {} + for v in values: + if (v == "all"): + ret = {gfx: True for gfx in _ALL_GFX} + elif (v == "none"): + ret = {} + else: + ret[v] = True + return ret + +def _gfx_from_file(file): + return file.basename[:-len(file.extension) - 1].rpartition("_")[-1].partition("-")[0] + +def _is_file_enabled(file, enabled_gfx): + gfx = _gfx_from_file(file) + return gfx in enabled_gfx or gfx == "fallback" + +def _bytecode_select_impl(ctx): + enabled_gfx = _compute_enabled_gfx(ctx.attr.enabled_gfx[BuildSettingInfo].value) + return [ + DefaultInfo( + files = depset([ + file + for file in ctx.files.bytecodes + if _is_file_enabled(file, enabled_gfx) + ]), + ), + ] + +bytecode_select = rule( + implementation = _bytecode_select_impl, + attrs = { + "bytecodes": attr.label_list(allow_files = True), + "enabled_gfx": attr.label(mandatory = True), + }, +) + + +def if_gfx(gfx, value): + return select({ + "@zml//runtimes/rocm:_{}".format(gfx): value, + "//conditions:default": [], + }) + diff --git a/runtimes/rocm/libpjrt_rocm.BUILD.bazel b/runtimes/rocm/libpjrt_rocm.BUILD.bazel new file mode 100644 index 0000000..e6e333a --- /dev/null +++ b/runtimes/rocm/libpjrt_rocm.BUILD.bazel @@ -0,0 +1,88 @@ +load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory") +load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "string_list_flag") +load("@zml//bazel:cc_import.bzl", "cc_import") + +string_list_flag( + name = "gfx", + build_setting_default = ["all"], + visibility = [ + "@rocblas//:__subpackages__", + "@hipblaslt-dev//:__subpackages__", + ], +) + +bool_flag( + name = "hipblaslt", + build_setting_default = True, +) + +config_setting( + name = "_hipblaslt", + flag_values = {":hipblaslt": "True"}, +) + +copy_to_directory( + name = "sandbox", + srcs = [ + "@rocm-device-libs//:runfiles", + "@rocm-llvm//:lld", + ], + include_external_repositories = ["*"], +) + +cc_library( + name = "zmlrocmhooks_lib", + data = ["@rocblas//:runfiles"], + srcs = ["@zml//runtimes/rocm:zmlrocmhooks_srcs"], + linkopts = [ + "-lc", + "-ldl", + ], + deps = ["@bazel_tools//tools/cpp/runfiles"], +) + +cc_shared_library( + name = "zmlrocmhooks_so", + shared_lib_name = "libzmlrocmhooks.so.0", + deps = [":zmlrocmhooks_lib"], +) + +cc_import( + name = "zmlrocmhooks", + shared_library = ":zmlrocmhooks_so", +) + +cc_import( + name = "libpjrt_rocm", + data = [ + ":sandbox", + "@rocblas//:runfiles", + ] + select({ + ":_hipblaslt": ["@hipblaslt-dev//:runfiles"], + "//conditions:default": [], + }), + shared_library = "libpjrt_rocm.so", + visibility = ["//visibility:public"], + deps = [ + ":zmlrocmhooks", + "@comgr//:amd_comgr", + "@hip-runtime-amd//:amdhip", + "@hipblaslt", + "@hsa-amd-aqlprofile//:hsa-amd-aqlprofile", + "@hsa-rocr//:hsa-runtime", + "@miopen-hip//:MIOpen", + "@rccl", + "@rocblas", + "@rocm-core", + "@rocm-smi-lib//:rocm_smi", + "@rocprofiler-register", + "@roctracer", + "@libelf", + "@libdrm", + "@libnuma", + "@libzstd", + "@libdrm-amdgpu", + "@libtinfo", + "@zlib1g", + ], +) diff --git a/runtimes/rocm/packages.amd64.txt b/runtimes/rocm/packages.amd64.txt new file mode 100644 index 0000000..2cfed1e --- /dev/null +++ b/runtimes/rocm/packages.amd64.txt @@ -0,0 +1,11376 @@ +Package: amd-smi-lib +Architecture: amd64 +Depends: sudo, python3 (>= 3.6.8), python3-pip, rocm-core +Priority: optional +Section: devel +Filename: pool/main/a/amd-smi-lib/amd-smi-lib_24.6.2.60200-66~20.04_amd64.deb +Size: 1325010 +SHA256: a4eeca0160afe7b3c973d5f9e3ea191d9f51a2b9472476e852d6841e1f4aba01 +SHA1: dccd97a09ccbd884c526e462e9f208deb09ca8b2 +MD5sum: 4fa13272e2f7bd70c06ee178c366c5c4 +Description: AMD System Management libraries +Maintainer: AMD-SMILib Support +Provides: amd-smi +Recommends: python3-argcomplete, libdrm-dev, python3-yaml +Version: 24.6.2.60200-66~20.04 +Installed-Size: 7695 + +Package: amd-smi-lib-asan +Architecture: amd64 +Depends: sudo, python3 (>= 3.6.8), python3-pip, rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/a/amd-smi-lib-asan/amd-smi-lib-asan_24.6.2.60200-66~20.04_amd64.deb +Size: 1171194 +SHA256: ff03c20115559e19fae13faf78292086890cd28fd5bb972d75e733f1f4461620 +SHA1: 22c2529f8a757ea3af647157804dcd2e561e350b +MD5sum: da265341631bc77c60c5c28efb50151d +Description: AMD System Management libraries +Maintainer: AMD-SMILib Support +Provides: amd-smi-lib-asan +Recommends: python3-argcomplete, libdrm-dev, python3-yaml +Version: 24.6.2.60200-66~20.04 +Installed-Size: 11610 + +Package: amd-smi-lib-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: aa3aad6a618050a4b72a077f9e0d8c0e88d3593f +Depends: amd-smi-lib-asan (= 24.6.2.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/a/amd-smi-lib-asan-dbgsym/amd-smi-lib-asan-dbgsym_24.6.2.60200-66~20.04_amd64.deb +Size: 5753660 +SHA256: e328382eb0b5f51b346286dbd91b878d77e6c15bf3714ef1a01dd9e0b4e02655 +SHA1: ab1164e53d03230007e7c5baa7aeb5ca39c52018 +MD5sum: cb0b1b9f4055995497a30c3df70afaca +Description: debug symbols for amd-smi-lib-asan +Maintainer: AMD-SMILib Support +Package-Type: ddeb +Version: 24.6.2.60200-66~20.04 +Installed-Size: 18279 + +Package: amd-smi-lib-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: aa3aad6a618050a4b72a077f9e0d8c0e88d3593f +Depends: amd-smi-lib-asan-rpath6.2.0 (= 24.6.2.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/a/amd-smi-lib-asan-dbgsym-rpath6.2.0/amd-smi-lib-asan-dbgsym-rpath6.2.0_24.6.2.60200-66~20.04_amd64.deb +Size: 3473844 +SHA256: f64aa53576c7cb5b7e4f4ccf750655cc84b68e91f5ce863ea1f44abd6d6c1c1f +SHA1: 163880f01decb8414568ba1fd06ef54055dce7db +MD5sum: 62b14e2a7762c3f7307139fe483ac695 +Description: debug symbols for amd-smi-lib-asan +Maintainer: AMD-SMILib Support +Package-Type: ddeb +Version: 24.6.2.60200-66~20.04 +Installed-Size: 18279 + +Package: amd-smi-lib-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: aa3aad6a618050a4b72a077f9e0d8c0e88d3593f +Depends: amd-smi-lib-asan6.2.0 (= 24.6.2.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/a/amd-smi-lib-asan-dbgsym6.2.0/amd-smi-lib-asan-dbgsym6.2.0_24.6.2.60200-66~20.04_amd64.deb +Size: 3473992 +SHA256: 44bb5d25f821742c60f329dfd8bfe8b52744e0a885e1bd05510be5def192f2b6 +SHA1: 9cf44ef8ce817b454d9ef7096c6fa5463864274b +MD5sum: 7ba01174fa8ff671ae4da16d44e5ded8 +Description: debug symbols for amd-smi-lib-asan +Maintainer: AMD-SMILib Support +Package-Type: ddeb +Version: 24.6.2.60200-66~20.04 +Installed-Size: 18279 + +Package: amd-smi-lib-asan-rpath6.2.0 +Architecture: amd64 +Depends: sudo, python3 (>= 3.6.8), python3-pip, rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/a/amd-smi-lib-asan-rpath6.2.0/amd-smi-lib-asan-rpath6.2.0_24.6.2.60200-66~20.04_amd64.deb +Size: 794352 +SHA256: 5712cab4af990a567dfd1add7e1f32b91da5388fe4c5b1910eedd55a15105c80 +SHA1: ade6f0c4d3966472cbb9a55559a2e2f40007fed0 +MD5sum: e410e4d51886d9c11d4f0b77adc17d7c +Description: AMD System Management libraries +Maintainer: AMD-SMILib Support +Provides: amd-smi-lib-asan-rpath6.2.0 +Recommends: python3-argcomplete, libdrm-dev, python3-yaml +Version: 24.6.2.60200-66~20.04 +Installed-Size: 11610 + +Package: amd-smi-lib-asan6.2.0 +Architecture: amd64 +Depends: sudo, python3 (>= 3.6.8), python3-pip, rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/a/amd-smi-lib-asan6.2.0/amd-smi-lib-asan6.2.0_24.6.2.60200-66~20.04_amd64.deb +Size: 793692 +SHA256: 543a76b3b3cfc12999031e2f02d24ed14709499ee16b0a4dde50ca5f1b71b9b7 +SHA1: 95d7afc8bf2aaeccb523d52ae73e12a390d487c5 +MD5sum: 7f7d3a1c2c03301c44941451d10d661d +Description: AMD System Management libraries +Maintainer: AMD-SMILib Support +Provides: amd-smi-lib-asan6.2.0 +Recommends: python3-argcomplete, libdrm-dev, python3-yaml +Version: 24.6.2.60200-66~20.04 +Installed-Size: 11610 + +Package: amd-smi-lib-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: a62623c3762dcb963dc58691799d15a10a465a77 a62623c3762dcb963dc58691799d15a10a465a77 +Depends: amd-smi-lib (= 24.6.2.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/a/amd-smi-lib-dbgsym/amd-smi-lib-dbgsym_24.6.2.60200-66~20.04_amd64.deb +Size: 10153596 +SHA256: 8d1b366ec661daf34bb004eda6babebc67453a40b17ad40d86f17dc17c6ea788 +SHA1: 3c6c3f030f7e8f8aaa223b4eca75890621a2b0fd +MD5sum: 26e50eaaccb900498151f928058b090c +Description: debug symbols for amd-smi-lib +Maintainer: AMD-SMILib Support +Package-Type: ddeb +Version: 24.6.2.60200-66~20.04 +Installed-Size: 39318 + +Package: amd-smi-lib-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: a62623c3762dcb963dc58691799d15a10a465a77 a62623c3762dcb963dc58691799d15a10a465a77 +Depends: amd-smi-lib-rpath6.2.0 (= 24.6.2.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/a/amd-smi-lib-dbgsym-rpath6.2.0/amd-smi-lib-dbgsym-rpath6.2.0_24.6.2.60200-66~20.04_amd64.deb +Size: 6649760 +SHA256: 75ea9e2777b9d59cbdb2834b52494ec8af508a7b93338b81ba6182f00f2a9091 +SHA1: 3a2bddf27333b36b959a3e327d17fa002259ebc0 +MD5sum: e6d3d29db2eeb72977f52c080ca1a136 +Description: debug symbols for amd-smi-lib +Maintainer: AMD-SMILib Support +Package-Type: ddeb +Version: 24.6.2.60200-66~20.04 +Installed-Size: 39318 + +Package: amd-smi-lib-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: a62623c3762dcb963dc58691799d15a10a465a77 a62623c3762dcb963dc58691799d15a10a465a77 +Depends: amd-smi-lib6.2.0 (= 24.6.2.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/a/amd-smi-lib-dbgsym6.2.0/amd-smi-lib-dbgsym6.2.0_24.6.2.60200-66~20.04_amd64.deb +Size: 6649152 +SHA256: 453ad7391101fcbcaa7a133d053e6f1f10f81526687d78aca7e046c07e885e1b +SHA1: 916a1335b9d4b828d9b0b4610c120e77712847da +MD5sum: beec1c143a9391f8287a228951881842 +Description: debug symbols for amd-smi-lib +Maintainer: AMD-SMILib Support +Package-Type: ddeb +Version: 24.6.2.60200-66~20.04 +Installed-Size: 39318 + +Package: amd-smi-lib-rpath6.2.0 +Architecture: amd64 +Depends: sudo, python3 (>= 3.6.8), python3-pip, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/a/amd-smi-lib-rpath6.2.0/amd-smi-lib-rpath6.2.0_24.6.2.60200-66~20.04_amd64.deb +Size: 559448 +SHA256: 9b742cff89af542ebf7604d53d93dc62a0af65bbb00f2c0917c2df357990fd5d +SHA1: 8614b0c722fa1deb625a9b49fe60059971cb43c0 +MD5sum: 5d2086bb0a43d077090a7e6176835f88 +Description: AMD System Management libraries +Maintainer: AMD-SMILib Support +Provides: amd-smi-rpath6.2.0 +Recommends: python3-argcomplete, libdrm-dev, python3-yaml +Version: 24.6.2.60200-66~20.04 +Installed-Size: 7695 + +Package: amd-smi-lib6.2.0 +Architecture: amd64 +Depends: sudo, python3 (>= 3.6.8), python3-pip, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/a/amd-smi-lib6.2.0/amd-smi-lib6.2.0_24.6.2.60200-66~20.04_amd64.deb +Size: 558416 +SHA256: eacf3267664658963ac4067dd2ba594b07f2c0af134f3b642fac3a23a79c6cd0 +SHA1: 5a8cd795ab3b97c9dcd5e61f08740a17eb718588 +MD5sum: 665892482c7b308e50d6deb0b4960bde +Description: AMD System Management libraries +Maintainer: AMD-SMILib Support +Provides: amd-smi6.2.0 +Recommends: python3-argcomplete, libdrm-dev, python3-yaml +Version: 24.6.2.60200-66~20.04 +Installed-Size: 7695 + +Package: comgr +Architecture: amd64 +Depends: libtinfo-dev, rocm-core +Priority: optional +Section: devel +Filename: pool/main/c/comgr/comgr_2.8.0.60200-66~20.04_amd64.deb +Size: 54853456 +SHA256: 0d4d5210fc98b8dfbd794d41610480c80c6abb5c7629ea549cfc221aa3c1c7b9 +SHA1: 33ae3424f30557e2bd0ffd4142b8436480767f25 +MD5sum: e4e20b5b9e7f24e3048cd29206fbf5fe +Description: Library to provide support functions for ROCm code objects. +Homepage: https://github.com/RadeonOpenCompute/ROCm-CompilerSupport +Maintainer: ROCm Compiler Support +Version: 2.8.0.60200-66~20.04 +Installed-Size: 447642 + +Package: comgr-asan +Architecture: amd64 +Depends: libtinfo-dev, rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/c/comgr-asan/comgr-asan_2.8.0.60200-66~20.04_amd64.deb +Size: 55320534 +SHA256: 420df47fb5400480c34dd6ae0ddc19e0b5fcd98fac2db757fbcb5c4d6471a091 +SHA1: 998436867e0ad33eaa985014db4c61ad0d7bb5cb +MD5sum: a93126989bb69b1f1e0f69e01bb31dfa +Description: AddressSanitizer Instrumented Libraries to provide support functions for ROCm code objects. +Homepage: https://github.com/RadeonOpenCompute/ROCm-CompilerSupport +Maintainer: ROCm Compiler Support +Version: 2.8.0.60200-66~20.04 +Installed-Size: 450510 + +Package: comgr-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 04ae002ce5a3d79769868440276f4b55b323dbd0 +Depends: comgr-asan (= 2.8.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/c/comgr-asan-dbgsym/comgr-asan-dbgsym_2.8.0.60200-66~20.04_amd64.deb +Size: 6678548 +SHA256: 58ec2bbf925c22defdcc630954c6e375192c658cb3340a8c14a185ccce15ef3d +SHA1: 9d6cc16e225cb3c286ed92764228d29a7666476c +MD5sum: 7c24519a56fb23f21c9632c1ea20242f +Description: debug symbols for comgr-asan +Maintainer: ROCm Compiler Support +Package-Type: ddeb +Version: 2.8.0.60200-66~20.04 +Installed-Size: 32173 + +Package: comgr-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 04ae002ce5a3d79769868440276f4b55b323dbd0 +Depends: comgr-asan-rpath6.2.0 (= 2.8.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/c/comgr-asan-dbgsym-rpath6.2.0/comgr-asan-dbgsym-rpath6.2.0_2.8.0.60200-66~20.04_amd64.deb +Size: 4272916 +SHA256: 7404240ed5dcddff7ccc6f0aafa4f3c2fae8d78f97e6c836472acd4be888b846 +SHA1: 967f6088d337d6f9902ff485b2550f311796b9c9 +MD5sum: 3c118c69233bd037439c0108d6913e82 +Description: debug symbols for comgr-asan +Maintainer: ROCm Compiler Support +Package-Type: ddeb +Version: 2.8.0.60200-66~20.04 +Installed-Size: 32173 + +Package: comgr-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 04ae002ce5a3d79769868440276f4b55b323dbd0 +Depends: comgr-asan6.2.0 (= 2.8.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/c/comgr-asan-dbgsym6.2.0/comgr-asan-dbgsym6.2.0_2.8.0.60200-66~20.04_amd64.deb +Size: 4272992 +SHA256: 10c75629b53ea8c067eda57d7c598c5a4f2ccb434e152d95a257ceb4c951d6c4 +SHA1: ff08521f92619d630f8cbe2cd3d5fca9e604c5c9 +MD5sum: b5a5f5e6633ad3be542c4e195cbd84b6 +Description: debug symbols for comgr-asan +Maintainer: ROCm Compiler Support +Package-Type: ddeb +Version: 2.8.0.60200-66~20.04 +Installed-Size: 32173 + +Package: comgr-asan-rpath6.2.0 +Architecture: amd64 +Depends: libtinfo-dev, rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/c/comgr-asan-rpath6.2.0/comgr-asan-rpath6.2.0_2.8.0.60200-66~20.04_amd64.deb +Size: 37824276 +SHA256: 7142041428ac8fad043bebb13dd2105b9ba5e2303f589759271ba39b2cdd184f +SHA1: e93549f4085341baf2bf68172903c853f7565e83 +MD5sum: d0f1a73cd432dc1cafa85e64a86dd150 +Description: AddressSanitizer Instrumented Libraries to provide support functions for ROCm code objects. +Homepage: https://github.com/RadeonOpenCompute/ROCm-CompilerSupport +Maintainer: ROCm Compiler Support +Version: 2.8.0.60200-66~20.04 +Installed-Size: 450510 + +Package: comgr-asan6.2.0 +Architecture: amd64 +Depends: libtinfo-dev, rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/c/comgr-asan6.2.0/comgr-asan6.2.0_2.8.0.60200-66~20.04_amd64.deb +Size: 37820340 +SHA256: 9932bfd59e2d85721ff7f650e4cd64525218a1ebd814eb068f3a5abb156b7102 +SHA1: af109ed37383cc41c9bfbdfca74dc2166820d135 +MD5sum: ae3b3d7ec3ab6a71dbf8f8923aecf594 +Description: AddressSanitizer Instrumented Libraries to provide support functions for ROCm code objects. +Homepage: https://github.com/RadeonOpenCompute/ROCm-CompilerSupport +Maintainer: ROCm Compiler Support +Version: 2.8.0.60200-66~20.04 +Installed-Size: 450510 + +Package: comgr-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: a5b65394af4e73d62b907e2d287587c751a37618 +Depends: comgr (= 2.8.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/c/comgr-dbgsym/comgr-dbgsym_2.8.0.60200-66~20.04_amd64.deb +Size: 15157634 +SHA256: c68e4a91a6de4b3721181a45985b9bc812db6de5719edd1f5a522a0279046deb +SHA1: 63569187973cfc80cf156ef2be5daedd97505c27 +MD5sum: 13cb5bdc14117a35d1b904ad9f79d6d3 +Description: debug symbols for comgr +Maintainer: ROCm Compiler Support +Package-Type: ddeb +Version: 2.8.0.60200-66~20.04 +Installed-Size: 57300 + +Package: comgr-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: a5b65394af4e73d62b907e2d287587c751a37618 +Depends: comgr-rpath6.2.0 (= 2.8.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/c/comgr-dbgsym-rpath6.2.0/comgr-dbgsym-rpath6.2.0_2.8.0.60200-66~20.04_amd64.deb +Size: 9126312 +SHA256: ee980a5d1f060ffbaf344645d32af44f1861e6e6d89224fc250347fdfbadc2f8 +SHA1: ba44dc2ffa00dbed219220942903949ae231b8ea +MD5sum: 54c618bfc2cfaafd86d16a7cdf84de7d +Description: debug symbols for comgr +Maintainer: ROCm Compiler Support +Package-Type: ddeb +Version: 2.8.0.60200-66~20.04 +Installed-Size: 57300 + +Package: comgr-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: a5b65394af4e73d62b907e2d287587c751a37618 +Depends: comgr6.2.0 (= 2.8.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/c/comgr-dbgsym6.2.0/comgr-dbgsym6.2.0_2.8.0.60200-66~20.04_amd64.deb +Size: 9127484 +SHA256: 49c2ac30f5114b6e67784f16e0b86ec443bf367577b3b4455b5ba494d3bdf8c2 +SHA1: c152a8afadfaaa9ff7d55555cd35f3e8cf1c3f94 +MD5sum: b833a33dcfd5cff1e12051de12457488 +Description: debug symbols for comgr +Maintainer: ROCm Compiler Support +Package-Type: ddeb +Version: 2.8.0.60200-66~20.04 +Installed-Size: 57300 + +Package: comgr-rpath6.2.0 +Architecture: amd64 +Depends: libtinfo-dev, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/c/comgr-rpath6.2.0/comgr-rpath6.2.0_2.8.0.60200-66~20.04_amd64.deb +Size: 37554260 +SHA256: 94c09c9b5952975c74bd762b63dd293f988fc2536ee2895c65eb41c2ba736be3 +SHA1: c8542d1b8c64bba35302be13c5d933863f307532 +MD5sum: f7471fb0caa8e5a5da2016549d2b949b +Description: Library to provide support functions for ROCm code objects. +Homepage: https://github.com/RadeonOpenCompute/ROCm-CompilerSupport +Maintainer: ROCm Compiler Support +Version: 2.8.0.60200-66~20.04 +Installed-Size: 447642 + +Package: comgr6.2.0 +Architecture: amd64 +Depends: libtinfo-dev, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/c/comgr6.2.0/comgr6.2.0_2.8.0.60200-66~20.04_amd64.deb +Size: 37547680 +SHA256: fabf4a831f21b5248932e08654149bc215da2a816613ad8d05b805d4e226171a +SHA1: 25f207e65ca40b972a396f0f35efb7ccb9d0f3e9 +MD5sum: faa54e936e2566ae88cbc81591b0d22a +Description: Library to provide support functions for ROCm code objects. +Homepage: https://github.com/RadeonOpenCompute/ROCm-CompilerSupport +Maintainer: ROCm Compiler Support +Version: 2.8.0.60200-66~20.04 +Installed-Size: 447642 + +Package: composablekernel-ckprofiler_gfx10 +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/c/composablekernel-ckprofiler_gfx10/composablekernel-ckprofiler_gfx10_1.1.0.60200-66~20.04_amd64.deb +Size: 12595502 +SHA256: ff407b4c060428514f9cc2acba315c40e6b0dbc90deedfd6f415b4f42c21ecb2 +SHA1: 0ac9f1c1fb246588e0907dee1a960c5866655503 +MD5sum: 33c0f44076f457d863437df39ca4713f +Description: High Performance Composable Kernel for AMD GPUs +Maintainer: MIOpen Kernels Dev Team +Version: 1.1.0.60200-66~20.04 +Installed-Size: 295377 + +Package: composablekernel-ckprofiler_gfx10-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/c/composablekernel-ckprofiler_gfx10-rpath6.2.0/composablekernel-ckprofiler_gfx10-rpath6.2.0_1.1.0.60200-66~20.04_amd64.deb +Size: 12575000 +SHA256: bcf06aa070eff3bc3eb093ab464c0d53c84aa1b82ee3103eada0b9cd835c5134 +SHA1: 81b6835b99da4ed842a0837d83acae3058ab50ab +MD5sum: 2acb61d498ea71d0a5a7d64abbed6ea8 +Description: High Performance Composable Kernel for AMD GPUs +Maintainer: MIOpen Kernels Dev Team +Version: 1.1.0.60200-66~20.04 +Installed-Size: 295377 + +Package: composablekernel-ckprofiler_gfx106.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/c/composablekernel-ckprofiler_gfx106.2.0/composablekernel-ckprofiler_gfx106.2.0_1.1.0.60200-66~20.04_amd64.deb +Size: 12574392 +SHA256: 377f02fcb768bd053809f7e7380b2a3de5ac2db2fa24794e9f38b57b074dbb31 +SHA1: cfe754adfdef6e3c6a333558ef6c6ac3d16051d6 +MD5sum: 22357dba7713eaee4c116d28394fabd5 +Description: High Performance Composable Kernel for AMD GPUs +Maintainer: MIOpen Kernels Dev Team +Version: 1.1.0.60200-66~20.04 +Installed-Size: 295377 + +Package: composablekernel-ckprofiler_gfx11 +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/c/composablekernel-ckprofiler_gfx11/composablekernel-ckprofiler_gfx11_1.1.0.60200-66~20.04_amd64.deb +Size: 28808326 +SHA256: feb95f84336e1037f5da0f50f49b4638a6e6445d5f49729d34cc4b4b18cf4bd5 +SHA1: 22ba496d9e012fb0f9ca3456c6ae86c1dc7e4078 +MD5sum: 17e7a7434fb7bbed19f4dc872bb33773 +Description: High Performance Composable Kernel for AMD GPUs +Maintainer: MIOpen Kernels Dev Team +Version: 1.1.0.60200-66~20.04 +Installed-Size: 784866 + +Package: composablekernel-ckprofiler_gfx11-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/c/composablekernel-ckprofiler_gfx11-rpath6.2.0/composablekernel-ckprofiler_gfx11-rpath6.2.0_1.1.0.60200-66~20.04_amd64.deb +Size: 28818724 +SHA256: ff252ca211af464016e0cd1b01634d85049b8ba2a7bc1bf181ccba1b03e04462 +SHA1: dcfa784f68c489b8ee9a00293fe63220b2527792 +MD5sum: 666b114d1c271be1af26958279a0eff1 +Description: High Performance Composable Kernel for AMD GPUs +Maintainer: MIOpen Kernels Dev Team +Version: 1.1.0.60200-66~20.04 +Installed-Size: 784866 + +Package: composablekernel-ckprofiler_gfx116.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/c/composablekernel-ckprofiler_gfx116.2.0/composablekernel-ckprofiler_gfx116.2.0_1.1.0.60200-66~20.04_amd64.deb +Size: 28818784 +SHA256: a086c3ad81192e86aee53b7d4b0ac0e2fd58928f9294751d807ace5aacc327f0 +SHA1: 8c5a0f46120fadccce73374a63d4660236f3b6e2 +MD5sum: 7febb5ff919f514a9dd72bf954d1cd8d +Description: High Performance Composable Kernel for AMD GPUs +Maintainer: MIOpen Kernels Dev Team +Version: 1.1.0.60200-66~20.04 +Installed-Size: 784866 + +Package: composablekernel-ckprofiler_gfx90 +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/c/composablekernel-ckprofiler_gfx90/composablekernel-ckprofiler_gfx90_1.1.0.60200-66~20.04_amd64.deb +Size: 105571830 +SHA256: b30096f4fc4d1172645b322d71cec60ba03e91c16a3888f86947c38c5ebe9bfc +SHA1: 6b1d46c40b74f07bc6f7bb9328e24f81417cbad1 +MD5sum: 93d511788da36d8d04e048561cfbf650 +Description: High Performance Composable Kernel for AMD GPUs +Maintainer: MIOpen Kernels Dev Team +Version: 1.1.0.60200-66~20.04 +Installed-Size: 2007269 + +Package: composablekernel-ckprofiler_gfx90-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/c/composablekernel-ckprofiler_gfx90-rpath6.2.0/composablekernel-ckprofiler_gfx90-rpath6.2.0_1.1.0.60200-66~20.04_amd64.deb +Size: 105553012 +SHA256: 392477d17c2afa2f6ea50b9964ebce5e7d3edd8583f3af0d30888d75b70477bd +SHA1: e6d4562716393c1fa8f4c6b0095ff09940c89e31 +MD5sum: c8436cb99f24939f5d480dc80350bc05 +Description: High Performance Composable Kernel for AMD GPUs +Maintainer: MIOpen Kernels Dev Team +Version: 1.1.0.60200-66~20.04 +Installed-Size: 2007269 + +Package: composablekernel-ckprofiler_gfx906.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/c/composablekernel-ckprofiler_gfx906.2.0/composablekernel-ckprofiler_gfx906.2.0_1.1.0.60200-66~20.04_amd64.deb +Size: 105555024 +SHA256: ae7ea8a2af86272272ed993a7b743fa512ef854313322c1d67ebef9a91de5cb1 +SHA1: 4113f2313bb0c491c0c4d6a402b0a020fc7244bc +MD5sum: 7ab53c05dd00f3ed42d725db670b8d10 +Description: High Performance Composable Kernel for AMD GPUs +Maintainer: MIOpen Kernels Dev Team +Version: 1.1.0.60200-66~20.04 +Installed-Size: 2007269 + +Package: composablekernel-ckprofiler_gfx94 +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/c/composablekernel-ckprofiler_gfx94/composablekernel-ckprofiler_gfx94_1.1.0.60200-66~20.04_amd64.deb +Size: 59255858 +SHA256: 0401bbef2a3dd23ae77d9fa80a76d4a0e885d9f7456ad609ed8e000df195b367 +SHA1: 7ccc1946e2d354527c3be85d148e80b04d608fec +MD5sum: ae2ed5663d5f1321ff76085e9878d74e +Description: High Performance Composable Kernel for AMD GPUs +Maintainer: MIOpen Kernels Dev Team +Version: 1.1.0.60200-66~20.04 +Installed-Size: 2135910 + +Package: composablekernel-ckprofiler_gfx94-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/c/composablekernel-ckprofiler_gfx94-rpath6.2.0/composablekernel-ckprofiler_gfx94-rpath6.2.0_1.1.0.60200-66~20.04_amd64.deb +Size: 59245200 +SHA256: 2b23632e9eadcf9ca73040730cc1d645e08e8f5270f0853faa90ced94d09eae0 +SHA1: 12626cfecc5c78991100e39089da3d41ef254cf7 +MD5sum: a3278dfea94f2e5dc991b37510c22b81 +Description: High Performance Composable Kernel for AMD GPUs +Maintainer: MIOpen Kernels Dev Team +Version: 1.1.0.60200-66~20.04 +Installed-Size: 2135910 + +Package: composablekernel-ckprofiler_gfx946.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/c/composablekernel-ckprofiler_gfx946.2.0/composablekernel-ckprofiler_gfx946.2.0_1.1.0.60200-66~20.04_amd64.deb +Size: 59243188 +SHA256: 6fc1136e1d7585280266d641076e807279a9bcb5c45d6750aa8e9b5dc1e7854d +SHA1: 8e9550c80ffbba4702fd603ea0a224d3afa5a255 +MD5sum: 4e3cc71ae7e7337e30769bce6c42da96 +Description: High Performance Composable Kernel for AMD GPUs +Maintainer: MIOpen Kernels Dev Team +Version: 1.1.0.60200-66~20.04 +Installed-Size: 2135910 + +Package: composablekernel-dev +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/c/composablekernel-dev/composablekernel-dev_1.1.0.60200-66~20.04_amd64.deb +Size: 205379206 +SHA256: d79d5734b2d674b1dfb5069b8c7e1013d4883a832a097596de7520fc422fef7e +SHA1: 015897a59400106fb5eeaf8cb6a119e811e19caf +MD5sum: f014f33258b35679c5b4ff0b2c77cd9d +Description: High Performance Composable Kernel for AMD GPUs +Maintainer: MIOpen Kernels Dev Team +Provides: CPACK_DEBIAN_PACKAGE_PROVIDES, composablekernel (= 1.1.0.60200) +Version: 1.1.0.60200-66~20.04 +Installed-Size: 5616038 + +Package: composablekernel-dev-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/c/composablekernel-dev-rpath6.2.0/composablekernel-dev-rpath6.2.0_1.1.0.60200-66~20.04_amd64.deb +Size: 205375548 +SHA256: f34d980604292f83b0347ca92123edfcfa3761f86543935580b24758523d2221 +SHA1: 79fa0aa4e05714ca8c9fdde687a7ea765762a1d2 +MD5sum: 71d1c98810b06a7ab652c6e4b7e7b01d +Description: High Performance Composable Kernel for AMD GPUs +Maintainer: MIOpen Kernels Dev Team +Provides: CPACK_DEBIAN_PACKAGE_PROVIDES, composablekernel-rpath6.2.0 (= 1.1.0.60200) +Version: 1.1.0.60200-66~20.04 +Installed-Size: 5616038 + +Package: composablekernel-dev6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/c/composablekernel-dev6.2.0/composablekernel-dev6.2.0_1.1.0.60200-66~20.04_amd64.deb +Size: 205375572 +SHA256: 12d3d5cca95ab2ebdefdc14853103b658de81228fd9fedbfaa7e360958b0bc84 +SHA1: 0506129e0d0350632b35a2af5a923a22d655f2f1 +MD5sum: b9908ff66500455494359469eeffb07b +Description: High Performance Composable Kernel for AMD GPUs +Maintainer: MIOpen Kernels Dev Team +Provides: CPACK_DEBIAN_PACKAGE_PROVIDES, composablekernel6.2.0 (= 1.1.0.60200) +Version: 1.1.0.60200-66~20.04 +Installed-Size: 5616038 + +Package: half +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/half/half_1.12.0.60200-66~20.04_amd64.deb +Size: 19532 +SHA256: dad23f5475c731f0601d744d12944728661896ce2b7bf2f9121d277375d730a0 +SHA1: ee70a929a0fef7f027ed6040ead20abd46820eb5 +MD5sum: 9ae11178a828ebb0d6a242483b3cbce0 +Description: HALF-PRECISION FLOATING POINT LIBRARY +Maintainer: Paul Fultz II +Version: 1.12.0.60200-66~20.04 +Installed-Size: 175 + +Package: half-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/half-rpath6.2.0/half-rpath6.2.0_1.12.0.60200-66~20.04_amd64.deb +Size: 19708 +SHA256: 13fecaf5ff45fc2f2691e754d5037f29f70fd109b8f2cc87cd7e43a473c4af08 +SHA1: fcc8ecc0112c4472286a1cab5ff751103e5c6b7a +MD5sum: 7170a0c6f6d02fdc7a7b69820855d6b3 +Description: HALF-PRECISION FLOATING POINT LIBRARY +Maintainer: Paul Fultz II +Version: 1.12.0.60200-66~20.04 +Installed-Size: 175 + +Package: half6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/half6.2.0/half6.2.0_1.12.0.60200-66~20.04_amd64.deb +Size: 19720 +SHA256: e128ebff24722d17ecf922c779681c7cbd3304f71104641be7d04c92abb9bc92 +SHA1: 74d7f81034c21a02f28d5fca5ad8b6ec750ef22c +MD5sum: 71c55541f87d69d6f0491dc6f408f65b +Description: HALF-PRECISION FLOATING POINT LIBRARY +Maintainer: Paul Fultz II +Version: 1.12.0.60200-66~20.04 +Installed-Size: 175 + +Package: hip-dev +Architecture: amd64 +Depends: perl (>= 5.0), libfile-copy-recursive-perl, libfile-listing-perl, libfile-which-perl, liburi-perl, libc6, file, hip-runtime-amd, rocm-llvm, rocm-core, hsa-rocr-dev +Priority: optional +Section: devel +Filename: pool/main/h/hip-dev/hip-dev_6.2.41133.60200-66~20.04_amd64.deb +Size: 307034 +SHA256: 97e6e77eaea56de6cc4ea2c525dd8b9a587546eb99c782c7af46cdc5363b99bf +SHA1: 4cabdee729d074bc84bc3eeff36520ee55f1f48e +MD5sum: d23057b374338da8e2d3547953a8c96c +Description: HIP:Heterogenous-computing Interface for Portability + HIP: Heterogenous-computing Interface for Portability [DEVELOPMENT] +Maintainer: HIP Support +Provides: hip-base +Replaces: hip-base +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 2276 + +Package: hip-dev-rpath6.2.0 +Architecture: amd64 +Depends: perl (>= 5.0), libfile-copy-recursive-perl, libfile-listing-perl, libfile-which-perl, liburi-perl, libc6, file, hip-runtime-amd-rpath6.2.0, rocm-llvm-rpath6.2.0, rocm-core-rpath6.2.0, hsa-rocr-dev-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hip-dev-rpath6.2.0/hip-dev-rpath6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 222964 +SHA256: d5023e08f9cc14a5453ae2ef081f3d7c2318067fbacfcfbbd6fbe97365ace83a +SHA1: c19465d291177248e608f7e28820b41d08adc251 +MD5sum: 56983e9a02f6c5742cb23aa2861fee5f +Description: HIP:Heterogenous-computing Interface for Portability + HIP: Heterogenous-computing Interface for Portability [DEVELOPMENT] +Maintainer: HIP Support +Provides: hip-base-rpath6.2.0 +Replaces: hip-base-rpath6.2.0 +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 2276 + +Package: hip-dev6.2.0 +Architecture: amd64 +Depends: perl (>= 5.0), libfile-copy-recursive-perl, libfile-listing-perl, libfile-which-perl, liburi-perl, libc6, file, hip-runtime-amd6.2.0, rocm-llvm6.2.0, rocm-core6.2.0, hsa-rocr-dev6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hip-dev6.2.0/hip-dev6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 222984 +SHA256: e901d66275b3b520ee73250caa4a1836be142823083528b4db6cc31a18bfb94d +SHA1: bc780970abb8ef699092579e2b09339f17c11a9a +MD5sum: 11911ad0354c8ff0faf01cb65e2385d7 +Description: HIP:Heterogenous-computing Interface for Portability + HIP: Heterogenous-computing Interface for Portability [DEVELOPMENT] +Maintainer: HIP Support +Provides: hip-base6.2.0 +Replaces: hip-base6.2.0 +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 2276 + +Package: hip-doc +Architecture: amd64 +Depends: hip-dev (= 6.2.41133.60200-66~20.04), rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/hip-doc/hip-doc_6.2.41133.60200-66~20.04_amd64.deb +Size: 89084 +SHA256: 0b5833e95a36781cccd533de2df79c32f96dfe00013c06227125dd0d879066e0 +SHA1: aa0d205c673d52c166f5a410ecaced1bd179a873 +MD5sum: 48d906e57e72318660b63f847eb84042 +Description: HIP:Heterogenous-computing Interface for Portability + HIP: Heterogenous-computing Interface for Portability [DOCUMENTATION] +Maintainer: HIP Support +Provides: hip-doc +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 294 + +Package: hip-doc-rpath6.2.0 +Architecture: amd64 +Depends: hip-dev-rpath6.2.0 (= 6.2.41133.60200-66~20.04), rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hip-doc-rpath6.2.0/hip-doc-rpath6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 79160 +SHA256: 18894cfef791dad9e7f3a9102c2e185842c8f85d39fbbaab510987e05bbcd882 +SHA1: 38b31298ad2473caa9886b0b6537d62f29750afc +MD5sum: a5f0d5b6d7cf47e34a93eac040514c99 +Description: HIP:Heterogenous-computing Interface for Portability + HIP: Heterogenous-computing Interface for Portability [DOCUMENTATION] +Maintainer: HIP Support +Provides: hip-doc-rpath6.2.0 +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 294 + +Package: hip-doc6.2.0 +Architecture: amd64 +Depends: hip-dev6.2.0 (= 6.2.41133.60200-66~20.04), rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hip-doc6.2.0/hip-doc6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 79128 +SHA256: ebdb76e4344493788a1ffcdeb46649231f068e0feca8c73edf36b6532f504fc2 +SHA1: 5550befdd3de11a6b70e70a546467e77eb43a283 +MD5sum: be89dfeed01801c784f01e55e61a8e61 +Description: HIP:Heterogenous-computing Interface for Portability + HIP: Heterogenous-computing Interface for Portability [DOCUMENTATION] +Maintainer: HIP Support +Provides: hip-doc6.2.0 +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 294 + +Package: hip-runtime-amd +Architecture: amd64 +Depends: hsa-rocr, rocminfo, comgr, rocm-core, rocprofiler-register, libnuma1, libstdc++6, libgcc-s1, libc6 +Priority: optional +Section: devel +Filename: pool/main/h/hip-runtime-amd/hip-runtime-amd_6.2.41133.60200-66~20.04_amd64.deb +Size: 13954758 +SHA256: 3813c60294c628857d38100a8c8e71e725909e5c10514c72f01064649c829b70 +SHA1: f12e9bd835a7331f666684987eb227166fabb99b +MD5sum: 0e5e5e493d90e9669a28859be1df9079 +Description: HIP:Heterogenous-computing Interface for Portability + HIP:Heterogenous-computing Interface for Portability [RUNTIME - AMD] +Maintainer: HIP Support +Provides: hip-rocclr (= 6.2.41133.60200) +Replaces: hip-rocclr (= 6.2.41133.60200) +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 81182 + +Package: hip-runtime-amd-asan +Architecture: amd64 +Depends: hsa-rocr-asan, rocminfo, comgr-asan, rocm-llvm, rocm-core-asan, libnuma1, libstdc++6, libgcc-s1, libc6 +Priority: optional +Section: devel +Filename: pool/main/h/hip-runtime-amd-asan/hip-runtime-amd-asan_6.2.41133.60200-66~20.04_amd64.deb +Size: 15865374 +SHA256: add7e5315aa42caee23d7f9a3117f049a7b7b318f5af4aa6a659fa7074d34cb4 +SHA1: e04dda1e0db59c6fa693cbe39a60b82e5ba31d0a +MD5sum: a6deda5376420d823c4145a056cf899f +Description: HIP:Heterogenous-computing Interface for Portability + HIP:Heterogenous-computing Interface for Portability [AddressSanitizer libraries] +Maintainer: HIP Support +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 104280 + +Package: hip-runtime-amd-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 2376a694a751623e5c01909d935eff0eb89f91d9 afa3d17a80f13cb9ef220b8c04b20019ac361089 6d7225fe92f048c5e11ae2be4df84be110730315 +Depends: hip-runtime-amd-asan (= 6.2.41133.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hip-runtime-amd-asan-dbgsym/hip-runtime-amd-asan-dbgsym_6.2.41133.60200-66~20.04_amd64.deb +Size: 16382142 +SHA256: 99eaef0cccdc5d356a84cdf427fc09e88770ce3aae366be3d9dcb888a12418fc +SHA1: 7a15d59d108d03a9e38fc490a4b129171b6edeb1 +MD5sum: f6d1c71a3e6773b420a8c512f75c3a76 +Description: debug symbols for hip-runtime-amd-asan +Maintainer: HIP Support +Package-Type: ddeb +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 51593 + +Package: hip-runtime-amd-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 2376a694a751623e5c01909d935eff0eb89f91d9 afa3d17a80f13cb9ef220b8c04b20019ac361089 6d7225fe92f048c5e11ae2be4df84be110730315 +Depends: hip-runtime-amd-asan-rpath6.2.0 (= 6.2.41133.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hip-runtime-amd-asan-dbgsym-rpath6.2.0/hip-runtime-amd-asan-dbgsym-rpath6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 9545400 +SHA256: 74c05872a905c5e849ad85da3cef650103b16f1c535d02906a96dfe25aa8e99e +SHA1: 689fbb4f2017d067efb5a54c1f30689d4b955552 +MD5sum: 21e35bbf27186626ec8e9d0c088d1c80 +Description: debug symbols for hip-runtime-amd-asan +Maintainer: HIP Support +Package-Type: ddeb +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 51593 + +Package: hip-runtime-amd-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 2376a694a751623e5c01909d935eff0eb89f91d9 afa3d17a80f13cb9ef220b8c04b20019ac361089 6d7225fe92f048c5e11ae2be4df84be110730315 +Depends: hip-runtime-amd-asan6.2.0 (= 6.2.41133.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hip-runtime-amd-asan-dbgsym6.2.0/hip-runtime-amd-asan-dbgsym6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 9545716 +SHA256: 5634fa79b7eacb5724f28656d6d3a111dc78fb208228fdc4e987372bf2e29867 +SHA1: 4ce179c68559d249e4db06b91c2192053044c04c +MD5sum: ac115e0f246e52d5b99b9d6ec74e96f5 +Description: debug symbols for hip-runtime-amd-asan +Maintainer: HIP Support +Package-Type: ddeb +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 51593 + +Package: hip-runtime-amd-asan-rpath6.2.0 +Architecture: amd64 +Depends: hsa-rocr-asan-rpath6.2.0, rocminfo-rpath6.2.0, comgr-asan-rpath6.2.0, rocm-llvm-rpath6.2.0, rocm-core-asan-rpath6.2.0, libnuma1, libstdc++6, libgcc-s1, libc6 +Priority: optional +Section: devel +Filename: pool/main/h/hip-runtime-amd-asan-rpath6.2.0/hip-runtime-amd-asan-rpath6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 11606684 +SHA256: 657f609bf77022b4527dfb13efa683c462ad164491472b5a0191228bdbffdc31 +SHA1: 4110a24afb5f067c23a4a93f1d42cbd06fa85823 +MD5sum: 623c2a16618ad8825dd0bbc482c9e200 +Description: HIP:Heterogenous-computing Interface for Portability + HIP:Heterogenous-computing Interface for Portability [AddressSanitizer libraries] +Maintainer: HIP Support +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 104280 + +Package: hip-runtime-amd-asan6.2.0 +Architecture: amd64 +Depends: hsa-rocr-asan6.2.0, rocminfo6.2.0, comgr-asan6.2.0, rocm-llvm6.2.0, rocm-core-asan6.2.0, libnuma1, libstdc++6, libgcc-s1, libc6 +Priority: optional +Section: devel +Filename: pool/main/h/hip-runtime-amd-asan6.2.0/hip-runtime-amd-asan6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 11611692 +SHA256: 924ec05491dc04c5c5f71ae3b48ece93cbb1117881a2f3498fdcec862c770c1e +SHA1: addb2b8bb4b568b656bb8627a4d216351a40a719 +MD5sum: 28ff5a789ac57787398cf0bf32b791f3 +Description: HIP:Heterogenous-computing Interface for Portability + HIP:Heterogenous-computing Interface for Portability [AddressSanitizer libraries] +Maintainer: HIP Support +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 104280 + +Package: hip-runtime-amd-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 2af2acd296814442f0fb6e9716cdf77fda4036f7 18f18c89fda46b6b126803b84e3bf66325a64160 d37b705c17241024af832e70433b33d9ebe09857 +Depends: hip-runtime-amd (= 6.2.41133.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hip-runtime-amd-dbgsym/hip-runtime-amd-dbgsym_6.2.41133.60200-66~20.04_amd64.deb +Size: 32274124 +SHA256: 4f4ed50e47f03ae2baacc46f78ec09e7eeb495993a3d52aaa943c65e7d89f9fb +SHA1: 13301dafb53f37d34020f2399484262881a483ba +MD5sum: 1738c857d569398beab8692e6ae362a3 +Description: debug symbols for hip-runtime-amd +Maintainer: HIP Support +Package-Type: ddeb +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 115400 + +Package: hip-runtime-amd-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 2af2acd296814442f0fb6e9716cdf77fda4036f7 18f18c89fda46b6b126803b84e3bf66325a64160 d37b705c17241024af832e70433b33d9ebe09857 +Depends: hip-runtime-amd-rpath6.2.0 (= 6.2.41133.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hip-runtime-amd-dbgsym-rpath6.2.0/hip-runtime-amd-dbgsym-rpath6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 20405776 +SHA256: d7a56b23cde1948c14791dc11d83c3c6114882e5d6802dd13b6f4d7358717012 +SHA1: e0054b69886f5e3b47ce8fed95df9c608d3e9201 +MD5sum: 8b0391a243a7b7b27a42bda44e29b72e +Description: debug symbols for hip-runtime-amd +Maintainer: HIP Support +Package-Type: ddeb +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 115400 + +Package: hip-runtime-amd-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 2af2acd296814442f0fb6e9716cdf77fda4036f7 18f18c89fda46b6b126803b84e3bf66325a64160 d37b705c17241024af832e70433b33d9ebe09857 +Depends: hip-runtime-amd6.2.0 (= 6.2.41133.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hip-runtime-amd-dbgsym6.2.0/hip-runtime-amd-dbgsym6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 20405216 +SHA256: e40442a3dca92124514d256f558ddf2e58a689df9fe78539977cfcdc8e98d958 +SHA1: 0cee124c7d711be7b4b9d1d75ce1c100341d2e5e +MD5sum: 197b1d9a84e5ab1aac448d3c9ec55648 +Description: debug symbols for hip-runtime-amd +Maintainer: HIP Support +Package-Type: ddeb +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 115400 + +Package: hip-runtime-amd-rpath6.2.0 +Architecture: amd64 +Depends: hsa-rocr-rpath6.2.0, rocminfo-rpath6.2.0, comgr-rpath6.2.0, rocm-core-rpath6.2.0, rocprofiler-register-rpath6.2.0, libnuma1, libstdc++6, libgcc-s1, libc6 +Priority: optional +Section: devel +Filename: pool/main/h/hip-runtime-amd-rpath6.2.0/hip-runtime-amd-rpath6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 10544216 +SHA256: 61ef2382cd2c5d93732d4378c70232d85c5e772c9b1b0620afea57961c76c0a4 +SHA1: 46ed9c01706002c07ef53a21b5550f9b0789d61b +MD5sum: 7d0b35dee46c8bbc8bc96ea476e84bb1 +Description: HIP:Heterogenous-computing Interface for Portability + HIP:Heterogenous-computing Interface for Portability [RUNTIME - AMD] +Maintainer: HIP Support +Provides: hip-rocclr-rpath6.2.0 (= 6.2.41133.60200) +Replaces: hip-rocclr-rpath6.2.0 (= 6.2.41133.60200) +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 81182 + +Package: hip-runtime-amd6.2.0 +Architecture: amd64 +Depends: hsa-rocr6.2.0, rocminfo6.2.0, comgr6.2.0, rocm-core6.2.0, rocprofiler-register6.2.0, libnuma1, libstdc++6, libgcc-s1, libc6 +Priority: optional +Section: devel +Filename: pool/main/h/hip-runtime-amd6.2.0/hip-runtime-amd6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 10540424 +SHA256: 215fae8759742bc048699feaacd6256a3ac2138771b69731dab7779325bb1b41 +SHA1: 4a590c6e3431a7a20e55206cffb8bf42413b5c8a +MD5sum: 0e9d8a3677f66e82ad26065f32787434 +Description: HIP:Heterogenous-computing Interface for Portability + HIP:Heterogenous-computing Interface for Portability [RUNTIME - AMD] +Maintainer: HIP Support +Provides: hip-rocclr6.2.0 (= 6.2.41133.60200) +Replaces: hip-rocclr6.2.0 (= 6.2.41133.60200) +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 81182 + +Package: hip-runtime-nvidia +Architecture: amd64 +Depends: cuda (>= 7.5), rocm-core, hipcc-nvidia +Priority: optional +Section: devel +Filename: pool/main/h/hip-runtime-nvidia/hip-runtime-nvidia_6.2.41133.60200-66~20.04_amd64.deb +Size: 692 +SHA256: 85caeb67b17e46b57664f9dc6801058d630e6f1226f1333334d6c83c2a8cd66f +SHA1: b10c71e4fff3bab08710c79e8433f7bcd0553f88 +MD5sum: 6001a46573289b44f70127391165b889 +Description: HIP:Heterogenous-computing Interface for Portability + HIP: Heterogenous-computing Interface for Portability [RUNTIME-NVIDIA] +Maintainer: HIP Support +Provides: hip-nvcc +Replaces: hip-nvcc +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 8 + +Package: hip-runtime-nvidia-rpath6.2.0 +Architecture: amd64 +Depends: cuda (>= 7.5), rocm-core-rpath6.2.0, hipcc-nvidia-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hip-runtime-nvidia-rpath6.2.0/hip-runtime-nvidia-rpath6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 908 +SHA256: ffd86a0ea58b884e0eddc1da21bcfd17110491e20b514d90103a6805ac091aa0 +SHA1: 05eb56ecdff5a590f3574608a25f9d5f28a9ca01 +MD5sum: 2f9b44462aa0724dab627fd79cf3170b +Description: HIP:Heterogenous-computing Interface for Portability + HIP: Heterogenous-computing Interface for Portability [RUNTIME-NVIDIA] +Maintainer: HIP Support +Provides: hip-nvcc-rpath6.2.0 +Replaces: hip-nvcc-rpath6.2.0 +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 8 + +Package: hip-runtime-nvidia6.2.0 +Architecture: amd64 +Depends: cuda (>= 7.5), rocm-core6.2.0, hipcc-nvidia6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hip-runtime-nvidia6.2.0/hip-runtime-nvidia6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 896 +SHA256: 9916227f9de55b63af30e68f2dc099eeffad4ef55cd0b9458ec1a3cd06807d22 +SHA1: a378990702f74a5dd23722ca6e106ee172f4b5c5 +MD5sum: 986e11eff84f929c3a15e01f9b28dc09 +Description: HIP:Heterogenous-computing Interface for Portability + HIP: Heterogenous-computing Interface for Portability [RUNTIME-NVIDIA] +Maintainer: HIP Support +Provides: hip-nvcc6.2.0 +Replaces: hip-nvcc6.2.0 +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 8 + +Package: hip-samples +Architecture: amd64 +Depends: rocm-core, hip-dev, hipcc +Priority: optional +Section: devel +Filename: pool/main/h/hip-samples/hip-samples_6.2.41133.60200-66~20.04_amd64.deb +Size: 51292 +SHA256: 17fba3cc7e12f0eacc323b9a175c519db44014101b7a380613ee81f9a2a5dae3 +SHA1: 9b38842f2884a8bd624e403d124db7b4429df88c +MD5sum: 7dc6df536edca471a587699f32234165 +Description: HIP: Heterogenous-computing Interface for Portability [HIP SAMPLES] + HIP: + Heterogenous-computing Interface for Portability [HIP SAMPLES] +Maintainer: HIP Support +Provides: hip-samples +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 461 + +Package: hip-samples-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0, hip-dev-rpath6.2.0, hipcc-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hip-samples-rpath6.2.0/hip-samples-rpath6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 38924 +SHA256: 9e35c20ee0701b666ca13f6424c2d65eb1e68c6c18d84fe1c921cb7569783ca0 +SHA1: eb1959b65febba75eb36fa931e820085aeb99d44 +MD5sum: db9a369a33f785d76c8b0f86a5f3bc8d +Description: HIP: Heterogenous-computing Interface for Portability [HIP SAMPLES] + HIP: + Heterogenous-computing Interface for Portability [HIP SAMPLES] +Maintainer: HIP Support +Provides: hip-samples-rpath6.2.0 +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 461 + +Package: hip-samples6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0, hip-dev6.2.0, hipcc6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hip-samples6.2.0/hip-samples6.2.0_6.2.41133.60200-66~20.04_amd64.deb +Size: 38900 +SHA256: 957618531e4df5cde5013973b8fb3395dda029d09ffae4aadf5669fb9e6adffe +SHA1: 886bb68a053c050e698a3d94fa44303e6422792c +MD5sum: a52a9631092ad4cf0573cafeb7983478 +Description: HIP: Heterogenous-computing Interface for Portability [HIP SAMPLES] + HIP: + Heterogenous-computing Interface for Portability [HIP SAMPLES] +Maintainer: HIP Support +Provides: hip-samples6.2.0 +Version: 6.2.41133.60200-66~20.04 +Installed-Size: 461 + +Package: hipblas +Architecture: amd64 +Depends: rocblas (>= 4.2.0), rocsolver (>= 3.26.0), rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/hipblas/hipblas_2.2.0.60200-66~20.04_amd64.deb +Size: 134966 +SHA256: 05e90c662f4d18e41a7e8a9570490d9693d7769544eefb5b6b023fe4416b5f87 +SHA1: b3bc29048657685a5b721fc77cc87ec6a2e8274d +MD5sum: 26264b9b0359799274f528273fd2b3f6 +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLAS Maintainer +Recommends: hipblas-dev (>=2.2.0.60200) +Version: 2.2.0.60200-66~20.04 +Installed-Size: 2090 + +Package: hipblas-asan +Architecture: amd64 +Depends: rocblas (>= 4.2.0), rocsolver (>= 3.26.0), rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/h/hipblas-asan/hipblas-asan_2.2.0.60200-66~20.04_amd64.deb +Size: 215042 +SHA256: 8c243ce91b5e4a613d8d6f1a05540877b88e6275f5ed3eb2865db1257416f74d +SHA1: 3021118ada7514de8997a8909c6fe398e9cf576c +MD5sum: fdd581746427ef295f609167009b216a +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLAS Maintainer +Recommends: hipblas-asan-dev (>=2.2.0.60200) +Version: 2.2.0.60200-66~20.04 +Installed-Size: 4850 + +Package: hipblas-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 7c90307643eda3f8fdfcf5f467fc7ea0a91ab3f4 +Depends: hipblas-asan (= 2.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipblas-asan-dbgsym/hipblas-asan-dbgsym_2.2.0.60200-66~20.04_amd64.deb +Size: 637354 +SHA256: db0d55def7ac006c98b5f86821fc31216b220012f08be77a5430cf0682b86969 +SHA1: a7761c2558985a05d7d57cb0633038370f47be5f +MD5sum: 6e511a89dc4e3aea3181c95d63442d20 +Description: debug symbols for hipblas-asan +Maintainer: hipBLAS Maintainer +Package-Type: ddeb +Version: 2.2.0.60200-66~20.04 +Installed-Size: 1201 + +Package: hipblas-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 7c90307643eda3f8fdfcf5f467fc7ea0a91ab3f4 +Depends: hipblas-asan-rpath6.2.0 (= 2.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipblas-asan-dbgsym-rpath6.2.0/hipblas-asan-dbgsym-rpath6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 635820 +SHA256: 7b04b3159c5510b34b0b7bb0f8ad9f702fc1a906e965ee4617ed0a35c1fa7f03 +SHA1: 92c3754c264781daff0112d1b0a543911c322813 +MD5sum: f099b303886ca6618bd58a081e38aefb +Description: debug symbols for hipblas-asan +Maintainer: hipBLAS Maintainer +Package-Type: ddeb +Version: 2.2.0.60200-66~20.04 +Installed-Size: 1201 + +Package: hipblas-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 7c90307643eda3f8fdfcf5f467fc7ea0a91ab3f4 +Depends: hipblas-asan6.2.0 (= 2.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipblas-asan-dbgsym6.2.0/hipblas-asan-dbgsym6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 636868 +SHA256: 187ae891d9df0d6c840ccbbf72e4759e2465a5162adb58554676b5fcfc32bdae +SHA1: 1320bcde11855e34c78f91ab2a8c32d693d2c47f +MD5sum: a1c315495c5aa23bbefc34b9ac3abb0f +Description: debug symbols for hipblas-asan +Maintainer: hipBLAS Maintainer +Package-Type: ddeb +Version: 2.2.0.60200-66~20.04 +Installed-Size: 1201 + +Package: hipblas-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocblas-rpath6.2.0 (>= 4.2.0), rocsolver-rpath6.2.0 (>= 3.26.0), rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipblas-asan-rpath6.2.0/hipblas-asan-rpath6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 215652 +SHA256: be8e2d911c17af0246ecab63f797197122cb9df8e69d906211d2d24f0101e806 +SHA1: 0d52096454542054464a6a02fe81fd85fc016fba +MD5sum: 0e610a4fdba23d80f5b0fbfbb9f45717 +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLAS Maintainer +Recommends: hipblas-asan-dev (>=2.2.0.60200) +Version: 2.2.0.60200-66~20.04 +Installed-Size: 4850 + +Package: hipblas-asan6.2.0 +Architecture: amd64 +Depends: rocblas6.2.0 (>= 4.2.0), rocsolver6.2.0 (>= 3.26.0), rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipblas-asan6.2.0/hipblas-asan6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 215184 +SHA256: 0bd0ac45732e03e373a2474aa5359241b13caf8558d55c552eae6e3e65ff2e7e +SHA1: da403c14e93b621cd771dbe82f85993a8e1653fa +MD5sum: 99a2bbd484e03184f0e92779dfddf7c3 +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLAS Maintainer +Recommends: hipblas-asan-dev (>=2.2.0.60200) +Version: 2.2.0.60200-66~20.04 +Installed-Size: 4850 + +Package: hipblas-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 71dd9d2a43978d356cd5bacd0f7d4f0e8eea8b77 +Depends: hipblas (= 2.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipblas-dbgsym/hipblas-dbgsym_2.2.0.60200-66~20.04_amd64.deb +Size: 701476 +SHA256: d60ef2deaac336ebd90c5dc64042cfcb073affaece1c61a8838dfe259c8bee68 +SHA1: 4558c9e5f1238e120c1583127f611b64b95c7f88 +MD5sum: b4519832c6afeae22ea1f77996f456aa +Description: debug symbols for hipblas +Maintainer: hipBLAS Maintainer +Package-Type: ddeb +Version: 2.2.0.60200-66~20.04 +Installed-Size: 5208 + +Package: hipblas-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 71dd9d2a43978d356cd5bacd0f7d4f0e8eea8b77 +Depends: hipblas-rpath6.2.0 (= 2.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipblas-dbgsym-rpath6.2.0/hipblas-dbgsym-rpath6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 694960 +SHA256: 816c16f197e40ace076a466e65e525b55ec6fbd0eb30f5b726d2d5ef11cb9194 +SHA1: 50af494097c7a575cc404ddef8d3bf197938d615 +MD5sum: 6bee82281707f0c3857c36d5ddc0abd6 +Description: debug symbols for hipblas +Maintainer: hipBLAS Maintainer +Package-Type: ddeb +Version: 2.2.0.60200-66~20.04 +Installed-Size: 5208 + +Package: hipblas-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 71dd9d2a43978d356cd5bacd0f7d4f0e8eea8b77 +Depends: hipblas6.2.0 (= 2.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipblas-dbgsym6.2.0/hipblas-dbgsym6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 695628 +SHA256: 46d96280b9203c587f56ec61e0cc6c28b975246b2f42c670b96ac5cf44751d70 +SHA1: 39980d204f2eb9e23fc8cf7c59f45fa777633774 +MD5sum: aaf3a828fbb0aad7693c17bfc23a37c5 +Description: debug symbols for hipblas +Maintainer: hipBLAS Maintainer +Package-Type: ddeb +Version: 2.2.0.60200-66~20.04 +Installed-Size: 5208 + +Package: hipblas-dev +Architecture: amd64 +Depends: hipblas (>= 2.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipblas-dev/hipblas-dev_2.2.0.60200-66~20.04_amd64.deb +Size: 89490 +SHA256: ed8535336912b2f67cc3968ca2a994b4c61da984d20a1501fb15a81d4a78c619 +SHA1: f1aee11ef68df09541a8c09a1f9b4131282b9186 +MD5sum: 7014af00525886c3e73a50330ce83347 +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLAS Maintainer +Version: 2.2.0.60200-66~20.04 +Installed-Size: 2784 + +Package: hipblas-dev-rpath6.2.0 +Architecture: amd64 +Depends: hipblas-rpath6.2.0 (>= 2.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipblas-dev-rpath6.2.0/hipblas-dev-rpath6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 89668 +SHA256: 3c3478464c0752c438486c7a741a557091f459ff0cd143bc491feed1dae95fc1 +SHA1: cde64869321756144b96e27228e03145f08b2618 +MD5sum: 1a86dc9fa2a7cbd4a897dbc78a8e8d41 +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLAS Maintainer +Version: 2.2.0.60200-66~20.04 +Installed-Size: 2784 + +Package: hipblas-dev6.2.0 +Architecture: amd64 +Depends: hipblas6.2.0 (>= 2.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipblas-dev6.2.0/hipblas-dev6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 89620 +SHA256: ab3ee54b33eba013fbf3d9aefe64b54e1918b9fb72790ca0b57fb391cb662cf0 +SHA1: 99ac9f03fbe8ec8ba62ce9eceaf4e430d3625278 +MD5sum: 9fbfd08b030d5af746f46aa41b88aba4 +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLAS Maintainer +Version: 2.2.0.60200-66~20.04 +Installed-Size: 2784 + +Package: hipblas-rpath6.2.0 +Architecture: amd64 +Depends: rocblas-rpath6.2.0 (>= 4.2.0), rocsolver-rpath6.2.0 (>= 3.26.0), rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipblas-rpath6.2.0/hipblas-rpath6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 134248 +SHA256: 9a13c43151ae13b9ad6d78179684ac414b05ecd1f5f538aa66b882806b5d240c +SHA1: 71495f5d73ccb79617ee17e64ccc6bfbcb956bf3 +MD5sum: a488ffff102471b3e28d80accaa76f4f +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLAS Maintainer +Recommends: hipblas-dev-rpath6.2.0 (>=2.2.0.60200) +Version: 2.2.0.60200-66~20.04 +Installed-Size: 2090 + +Package: hipblas6.2.0 +Architecture: amd64 +Depends: rocblas6.2.0 (>= 4.2.0), rocsolver6.2.0 (>= 3.26.0), rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipblas6.2.0/hipblas6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 137928 +SHA256: f8a20128b5c26198bd9ecec894f8a4c74fa28ee668e4ef1bf73d0c3edff8c144 +SHA1: 62c7baf41bce0b4fff292995b683d6ed17404c16 +MD5sum: ba6317e79662f13c6b185b67c335a5c5 +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLAS Maintainer +Recommends: hipblas-dev6.2.0 (>=2.2.0.60200) +Version: 2.2.0.60200-66~20.04 +Installed-Size: 2090 + +Package: hipblaslt +Architecture: amd64 +Depends: hipblas (>= 0.50.0), rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/hipblaslt/hipblaslt_0.8.0.60200-66~20.04_amd64.deb +Size: 995834 +SHA256: 56a7980a8953aa12d1a4b840d542c594079acda8598843f05e0ccd7ea54f4961 +SHA1: bfa1245a5ebfa79e9aa5676e8ad81b6d2bbbbe72 +MD5sum: a720852063d43c1410ff865f187553c2 +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLASLt Maintainer +Recommends: hipblaslt-dev (>=0.8.0.60200) +Version: 0.8.0.60200-66~20.04 +Installed-Size: 20227 + +Package: hipblaslt-asan +Architecture: amd64 +Depends: hipblas (>= 0.50.0), rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/h/hipblaslt-asan/hipblaslt-asan_0.8.0.60200-66~20.04_amd64.deb +Size: 18057696 +SHA256: 74c6ab08a4b0aa56ea49c2257176e7bb5730a0afbab9951672bf382d7a621a3a +SHA1: a602daa6582230668155cf7066902f6b589c18d3 +MD5sum: 00f71bfb6ba0b03f70bf255a3d94bc66 +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLASLt Maintainer +Recommends: hipblaslt-asan-dev (>=0.8.0.60200) +Version: 0.8.0.60200-66~20.04 +Installed-Size: 69374 + +Package: hipblaslt-asan-rpath6.2.0 +Architecture: amd64 +Depends: hipblas-rpath6.2.0 (>= 0.50.0), rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipblaslt-asan-rpath6.2.0/hipblaslt-asan-rpath6.2.0_0.8.0.60200-66~20.04_amd64.deb +Size: 18055512 +SHA256: 539c72bec8ff7e473dfcb9e07afc287c5f19754dd878b0653bb2564d1394b250 +SHA1: 15ca545203f694e5144f0022514288481fcd4d41 +MD5sum: 08df576e10605ce5bbdf05cbea4d5412 +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLASLt Maintainer +Recommends: hipblaslt-asan-dev (>=0.8.0.60200) +Version: 0.8.0.60200-66~20.04 +Installed-Size: 69374 + +Package: hipblaslt-asan6.2.0 +Architecture: amd64 +Depends: hipblas6.2.0 (>= 0.50.0), rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipblaslt-asan6.2.0/hipblaslt-asan6.2.0_0.8.0.60200-66~20.04_amd64.deb +Size: 18055416 +SHA256: bd0f189ddbfac193cde2e7451abc77edab7e6635ec869486ef411e3c0c6e8148 +SHA1: ab70aa15ecf259b8d8de69f83023b67a61c96645 +MD5sum: b3f27d4a550f6632a85df5b5c66cc7a5 +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLASLt Maintainer +Recommends: hipblaslt-asan-dev (>=0.8.0.60200) +Version: 0.8.0.60200-66~20.04 +Installed-Size: 69374 + +Package: hipblaslt-dev +Architecture: amd64 +Depends: hipblaslt (>= 0.8.0.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipblaslt-dev/hipblaslt-dev_0.8.0.60200-66~20.04_amd64.deb +Size: 171494892 +SHA256: 4f5af60b49b77cbfa8be38ba1e2fca985621d5a76202f13f4cf1d5c49dd3fafa +SHA1: 4b2164b02333e7fffefd92b26d26a727fe500161 +MD5sum: d62cec8f2d056ef8868bee661e11f372 +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLASLt Maintainer +Version: 0.8.0.60200-66~20.04 +Installed-Size: 4938166 + +Package: hipblaslt-dev-rpath6.2.0 +Architecture: amd64 +Depends: hipblaslt-rpath6.2.0 (>= 0.8.0.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipblaslt-dev-rpath6.2.0/hipblaslt-dev-rpath6.2.0_0.8.0.60200-66~20.04_amd64.deb +Size: 171535288 +SHA256: 3ff789e0fde04f383c4c0c4e6a925ab35e5db68cf48f9c0772f096402c0a3f2d +SHA1: 65108fbf43df1b4fb2fe8e38b7fbaadd4e8f5d15 +MD5sum: e5102d02f6f8a9b61e657d7abb634f5d +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLASLt Maintainer +Version: 0.8.0.60200-66~20.04 +Installed-Size: 4938166 + +Package: hipblaslt-dev6.2.0 +Architecture: amd64 +Depends: hipblaslt6.2.0 (>= 0.8.0.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipblaslt-dev6.2.0/hipblaslt-dev6.2.0_0.8.0.60200-66~20.04_amd64.deb +Size: 171535052 +SHA256: 5e2ca28ea10ff16eb75bde5c69aef6dbe3566d8fc49c3d2ace0ae7a777c1ffae +SHA1: 0389f959bbdfed8e28edad217404a552db86beba +MD5sum: 5695de2ababb4530c3aa1a1415035f43 +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLASLt Maintainer +Version: 0.8.0.60200-66~20.04 +Installed-Size: 4938166 + +Package: hipblaslt-rpath6.2.0 +Architecture: amd64 +Depends: hipblas-rpath6.2.0 (>= 0.50.0), rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipblaslt-rpath6.2.0/hipblaslt-rpath6.2.0_0.8.0.60200-66~20.04_amd64.deb +Size: 995372 +SHA256: ac46c22eb29ae52508a8c20809877aa709185af2fed8078f7ac9e8be6eac1cad +SHA1: 00f0778d2c7aba66b1a3b23ee6be401d009d6665 +MD5sum: 0aecb59e479f02f50e04a058acc1d6c5 +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLASLt Maintainer +Recommends: hipblaslt-dev-rpath6.2.0 (>=0.8.0.60200) +Version: 0.8.0.60200-66~20.04 +Installed-Size: 20227 + +Package: hipblaslt6.2.0 +Architecture: amd64 +Depends: hipblas6.2.0 (>= 0.50.0), rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipblaslt6.2.0/hipblaslt6.2.0_0.8.0.60200-66~20.04_amd64.deb +Size: 995008 +SHA256: a9fb63b30c3383b37479253c59c85493b75646037e016f68b136d12c5e6a4adb +SHA1: 6add52b9ff2e3d46fae435f34799b74f6564b473 +MD5sum: b13da7f0e916427f60c2bc42c70f850f +Description: Radeon Open Compute BLAS marshalling library +Maintainer: hipBLASLt Maintainer +Recommends: hipblaslt-dev6.2.0 (>=0.8.0.60200) +Version: 0.8.0.60200-66~20.04 +Installed-Size: 20227 + +Package: hipcc +Architecture: amd64 +Depends: perl (>= 5.0), hip-dev, rocm-core, rocm-llvm +Priority: optional +Section: devel +Filename: pool/main/h/hipcc/hipcc_1.1.1.60200-66~20.04_amd64.deb +Size: 229886 +SHA256: 5802a9e9703999a1f5628bf1dfe708f0cb81b1f905256a99a44250f43d0aeed1 +SHA1: ff9db6347e4ff1f80fd6b3e9171d9d66a8bf9021 +MD5sum: 831333fd6b220eed256ddf2e4515e1c8 +Description: hipcc built using CMake +Homepage: https://github.com/ROCm-Developer-Tools/HIPCC +Maintainer: ROCm Compiler Support +Version: 1.1.1.60200-66~20.04 +Installed-Size: 602 + +Package: hipcc-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: e515e51ee214784ef900cd92723ca6b4d9e6669a e515e51ee214784ef900cd92723ca6b4d9e6669a +Depends: hipcc (= 1.1.1.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipcc-dbgsym/hipcc-dbgsym_1.1.1.60200-66~20.04_amd64.deb +Size: 1527792 +SHA256: bcfeb489191dc90fc7eb1697c5c62483e884359a97c2be5c6d486850dc7a9196 +SHA1: a7b3f04b75d290dd853b21aa1126e9441da77cb4 +MD5sum: 7be2cde9c15c200cab7ee40154134ce8 +Description: debug symbols for hipcc +Maintainer: ROCm Compiler Support +Package-Type: ddeb +Version: 1.1.1.60200-66~20.04 +Installed-Size: 6856 + +Package: hipcc-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: e515e51ee214784ef900cd92723ca6b4d9e6669a e515e51ee214784ef900cd92723ca6b4d9e6669a +Depends: hipcc-rpath6.2.0 (= 1.1.1.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipcc-dbgsym-rpath6.2.0/hipcc-dbgsym-rpath6.2.0_1.1.1.60200-66~20.04_amd64.deb +Size: 1060992 +SHA256: 2703dc7697dd2d0dc97a36f5a8249e506e3bc65db77263c349b13aa9fbbcb5c7 +SHA1: ad8ccddd87e7926f2d4c17062721cb66e71f1d44 +MD5sum: c2d2897f67a38f24cd8f2c741ab88cfc +Description: debug symbols for hipcc +Maintainer: ROCm Compiler Support +Package-Type: ddeb +Version: 1.1.1.60200-66~20.04 +Installed-Size: 6856 + +Package: hipcc-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: e515e51ee214784ef900cd92723ca6b4d9e6669a e515e51ee214784ef900cd92723ca6b4d9e6669a +Depends: hipcc6.2.0 (= 1.1.1.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipcc-dbgsym6.2.0/hipcc-dbgsym6.2.0_1.1.1.60200-66~20.04_amd64.deb +Size: 1061008 +SHA256: f67f19da5ad09342b3ad104ced58a81451ceee6ef736c296ad673f2be5baeea1 +SHA1: 96376ec5dc618842877fbcecae66370c9d015209 +MD5sum: 35d07f2a26778f2db2ade6bd6e2d8e78 +Description: debug symbols for hipcc +Maintainer: ROCm Compiler Support +Package-Type: ddeb +Version: 1.1.1.60200-66~20.04 +Installed-Size: 6856 + +Package: hipcc-nvidia +Architecture: amd64 +Depends: perl (>= 5.0), hip-dev, rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/hipcc-nvidia/hipcc-nvidia_1.1.1.60200-66~20.04_amd64.deb +Size: 229892 +SHA256: f31a16f3b0ca14e0cacbe8e4135b957847223b2569d520afb90ff7c21a5a06db +SHA1: 3ea92d8359d96bcb730ffe5904500a15575258ba +MD5sum: decc13318b40020b79e27dfade7db4c7 +Description: hipcc built using CMake +Homepage: https://github.com/ROCm-Developer-Tools/HIPCC +Maintainer: ROCm Compiler Support +Version: 1.1.1.60200-66~20.04 +Installed-Size: 602 + +Package: hipcc-nvidia-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: e515e51ee214784ef900cd92723ca6b4d9e6669a e515e51ee214784ef900cd92723ca6b4d9e6669a +Depends: hipcc-nvidia (= 1.1.1.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipcc-nvidia-dbgsym/hipcc-nvidia-dbgsym_1.1.1.60200-66~20.04_amd64.deb +Size: 1527800 +SHA256: bf04b3b0dc5c5551062dccd03d191ace897202ee34a4467dcfbdbc21d10fd985 +SHA1: efde4f8b840fc02cafc1686ab1c4b7325d02cb13 +MD5sum: 5e86af206a1077d5023e5a9cc143bda9 +Description: debug symbols for hipcc-nvidia +Maintainer: ROCm Compiler Support +Package-Type: ddeb +Version: 1.1.1.60200-66~20.04 +Installed-Size: 6856 + +Package: hipcc-nvidia-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: e515e51ee214784ef900cd92723ca6b4d9e6669a e515e51ee214784ef900cd92723ca6b4d9e6669a +Depends: hipcc-nvidia-rpath6.2.0 (= 1.1.1.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipcc-nvidia-dbgsym-rpath6.2.0/hipcc-nvidia-dbgsym-rpath6.2.0_1.1.1.60200-66~20.04_amd64.deb +Size: 1060740 +SHA256: a6c3284728a750532e79bb09b1cfbcd7d7236fbbf6809962f3054fe71a4cf5da +SHA1: 48b4d1e71ebc317423ca3fa0bf0121b0b4d2c6a7 +MD5sum: f5fcd78735c36f42e3ae141df4a2be60 +Description: debug symbols for hipcc-nvidia +Maintainer: ROCm Compiler Support +Package-Type: ddeb +Version: 1.1.1.60200-66~20.04 +Installed-Size: 6856 + +Package: hipcc-nvidia-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: e515e51ee214784ef900cd92723ca6b4d9e6669a e515e51ee214784ef900cd92723ca6b4d9e6669a +Depends: hipcc-nvidia6.2.0 (= 1.1.1.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipcc-nvidia-dbgsym6.2.0/hipcc-nvidia-dbgsym6.2.0_1.1.1.60200-66~20.04_amd64.deb +Size: 1061164 +SHA256: f48cc70da56077d9b2dab2414c7e5e319795449640350639ad30e5081fa7376b +SHA1: 917b46edfe6affbbcf333733f31f53cacfbbd66c +MD5sum: 37efdba73cb124a1b1b22ade51180b22 +Description: debug symbols for hipcc-nvidia +Maintainer: ROCm Compiler Support +Package-Type: ddeb +Version: 1.1.1.60200-66~20.04 +Installed-Size: 6856 + +Package: hipcc-nvidia-rpath6.2.0 +Architecture: amd64 +Depends: perl (>= 5.0), hip-dev-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipcc-nvidia-rpath6.2.0/hipcc-nvidia-rpath6.2.0_1.1.1.60200-66~20.04_amd64.deb +Size: 97852 +SHA256: 34ae13790a06c0eabaa85e9fd83cb63a4a503bd8d7a5dde3a15e363a1c46e684 +SHA1: 6a8ac65de346502ef6e9a3610568e97e5a0de6f2 +MD5sum: 6cb9594663c6975d245f09397f2ec3af +Description: hipcc built using CMake +Homepage: https://github.com/ROCm-Developer-Tools/HIPCC +Maintainer: ROCm Compiler Support +Version: 1.1.1.60200-66~20.04 +Installed-Size: 602 + +Package: hipcc-nvidia6.2.0 +Architecture: amd64 +Depends: perl (>= 5.0), hip-dev6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipcc-nvidia6.2.0/hipcc-nvidia6.2.0_1.1.1.60200-66~20.04_amd64.deb +Size: 98080 +SHA256: cc47d8196b1516f97d31d246f317b28770187020fc10ec37f32488c2d3328415 +SHA1: bb0da44e468ce3a1e2a8a35be37b706e3d5c648e +MD5sum: 4b2c5612b76d9c1e7e889e660ba35ccc +Description: hipcc built using CMake +Homepage: https://github.com/ROCm-Developer-Tools/HIPCC +Maintainer: ROCm Compiler Support +Version: 1.1.1.60200-66~20.04 +Installed-Size: 602 + +Package: hipcc-rpath6.2.0 +Architecture: amd64 +Depends: perl (>= 5.0), hip-dev-rpath6.2.0, rocm-core-rpath6.2.0, rocm-llvm-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipcc-rpath6.2.0/hipcc-rpath6.2.0_1.1.1.60200-66~20.04_amd64.deb +Size: 97768 +SHA256: e98437ea93140fafa822551f937c2beb2909058626a39c50d17f0ec50c9bdd10 +SHA1: 2fd422828b90b607dcb9927588f64d78fa8879d9 +MD5sum: b1d80a9674f09791946190190e79b114 +Description: hipcc built using CMake +Homepage: https://github.com/ROCm-Developer-Tools/HIPCC +Maintainer: ROCm Compiler Support +Version: 1.1.1.60200-66~20.04 +Installed-Size: 602 + +Package: hipcc6.2.0 +Architecture: amd64 +Depends: perl (>= 5.0), hip-dev6.2.0, rocm-core6.2.0, rocm-llvm6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipcc6.2.0/hipcc6.2.0_1.1.1.60200-66~20.04_amd64.deb +Size: 97868 +SHA256: a68123c046b8c913705262014463a8a30768167a1b68a78d8455deaf85a802d7 +SHA1: 20d184140fcb18b63c212e0b287febda6ca9911d +MD5sum: 43d4d6c2a1f1f961c768016383ba2b60 +Description: hipcc built using CMake +Homepage: https://github.com/ROCm-Developer-Tools/HIPCC +Maintainer: ROCm Compiler Support +Version: 1.1.1.60200-66~20.04 +Installed-Size: 602 + +Package: hipcub-dev +Architecture: amd64 +Depends: rocprim-dev (>= 2.10.1), rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/hipcub-dev/hipcub-dev_3.2.0.60200-66~20.04_amd64.deb +Size: 73338 +SHA256: 49a841a8065227f19b17888a5e6189e2f3b4dcf0cd996b44655a5ebc91f5cf7e +SHA1: a5bc67f4551e73e451cb63dd36d3546ffe67e368 +MD5sum: 805233343d5d51a76151d7efb847fe54 +Description: hipCUB (rocPRIM backend) +Maintainer: hipcub-maintainer@amd.com +Provides: CPACK_DEBIAN_PACKAGE_PROVIDES, hipcub (= 3.2.0.60200) +Replaces: cub-hip +Version: 3.2.0.60200-66~20.04 +Installed-Size: 1253 + +Package: hipcub-dev-rpath6.2.0 +Architecture: amd64 +Depends: rocprim-dev-rpath6.2.0 (>= 2.10.1), rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipcub-dev-rpath6.2.0/hipcub-dev-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 73008 +SHA256: 187dfcaad5756de2d4e0d646e1265b17ad505b408f2684baf14cfb74d128e9ec +SHA1: 93bf6580b7a9e5c527d9cb9633ba0f39f05d7f13 +MD5sum: a29cdbf2f8d968e2a61f62e49b859696 +Description: hipCUB (rocPRIM backend) +Maintainer: hipcub-maintainer@amd.com +Provides: CPACK_DEBIAN_PACKAGE_PROVIDES, hipcub-rpath6.2.0 (= 3.2.0.60200) +Replaces: cub-hip-rpath6.2.0 +Version: 3.2.0.60200-66~20.04 +Installed-Size: 1253 + +Package: hipcub-dev6.2.0 +Architecture: amd64 +Depends: rocprim-dev6.2.0 (>= 2.10.1), rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipcub-dev6.2.0/hipcub-dev6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 72984 +SHA256: c71fab59f62ad9d4b60aa4217f4db42c6996d83d5ad7ba29e127cc13bda59afc +SHA1: ee3139d9192f00b8c6e1cfd4aecd807b772f7d59 +MD5sum: 57198c8a4b26aca653bc65670432f3cc +Description: hipCUB (rocPRIM backend) +Maintainer: hipcub-maintainer@amd.com +Provides: CPACK_DEBIAN_PACKAGE_PROVIDES, hipcub6.2.0 (= 3.2.0.60200) +Replaces: cub-hip6.2.0 +Version: 3.2.0.60200-66~20.04 +Installed-Size: 1253 + +Package: hipfft +Architecture: amd64 +Depends: rocfft (>= 1.0.21), rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/hipfft/hipfft_1.0.14.60200-66~20.04_amd64.deb +Size: 25108 +SHA256: 17cb3bcde6d01527f57ac8a7a27678570af19cc033ad22761545e8908165ad4a +SHA1: 5fa37a084ddfa6828b4a20b7d7504b4adb9e3774 +MD5sum: 56ad384954c1614d0e8d2375f1f3cb97 +Description: ROCm FFT marshalling library +Maintainer: hipfft-maintainer@amd.com +Recommends: hipfft-dev (>=1.0.14.60200) +Version: 1.0.14.60200-66~20.04 +Installed-Size: 151 + +Package: hipfft-asan +Architecture: amd64 +Depends: rocfft (>= 1.0.21), rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/h/hipfft-asan/hipfft-asan_1.0.14.60200-66~20.04_amd64.deb +Size: 45236 +SHA256: 6ec7e5570d39c0e924fe1f4cca19f26a9ad1db361aae9d180f2607fac7c491e7 +SHA1: 81704a8a750ad1c25eda344fdb0db5fdf809cc36 +MD5sum: 8183493234d79c5ae901daffd4382cdc +Description: ROCm FFT marshalling library +Maintainer: hipfft-maintainer@amd.com +Recommends: hipfft-asan-dev (>=1.0.14.60200) +Version: 1.0.14.60200-66~20.04 +Installed-Size: 302 + +Package: hipfft-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 3792838e5fdbd65963e005e013f3e29ddfb81a80 +Depends: hipfft-asan (= 1.0.14.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipfft-asan-dbgsym/hipfft-asan-dbgsym_1.0.14.60200-66~20.04_amd64.deb +Size: 176240 +SHA256: 12ab84cbfda179ef982ddaa51059283f848d71245553e2ef69888a609dc643cf +SHA1: 03595b5cc909c2564c529e411cdedb97a6d9ea48 +MD5sum: 625f1d43407aeee165d75f4c3bc89e09 +Description: debug symbols for hipfft-asan +Maintainer: hipfft-maintainer@amd.com +Package-Type: ddeb +Version: 1.0.14.60200-66~20.04 +Installed-Size: 230 + +Package: hipfft-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 3792838e5fdbd65963e005e013f3e29ddfb81a80 +Depends: hipfft-asan-rpath6.2.0 (= 1.0.14.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipfft-asan-dbgsym-rpath6.2.0/hipfft-asan-dbgsym-rpath6.2.0_1.0.14.60200-66~20.04_amd64.deb +Size: 176420 +SHA256: 36acddc6054c2589e09b65686e0d5d4f7271fa60388a68f06ce3170740aa541e +SHA1: 1d91dcebb12262ba9b8ecfff6c495f493549b709 +MD5sum: f8240e053b7f5700057daf99527a0004 +Description: debug symbols for hipfft-asan +Maintainer: hipfft-maintainer@amd.com +Package-Type: ddeb +Version: 1.0.14.60200-66~20.04 +Installed-Size: 230 + +Package: hipfft-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 3792838e5fdbd65963e005e013f3e29ddfb81a80 +Depends: hipfft-asan6.2.0 (= 1.0.14.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipfft-asan-dbgsym6.2.0/hipfft-asan-dbgsym6.2.0_1.0.14.60200-66~20.04_amd64.deb +Size: 176416 +SHA256: 2f39dce8eb0c4979dac721f527b007fee1d22f1fb446da6950d6177f70ec12a8 +SHA1: 1478e47c61f533d367593c1e6c20ad2fd7d54ae9 +MD5sum: 1df20cd971693104d1bb0520916c9466 +Description: debug symbols for hipfft-asan +Maintainer: hipfft-maintainer@amd.com +Package-Type: ddeb +Version: 1.0.14.60200-66~20.04 +Installed-Size: 230 + +Package: hipfft-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocfft-rpath6.2.0 (>= 1.0.21), rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipfft-asan-rpath6.2.0/hipfft-asan-rpath6.2.0_1.0.14.60200-66~20.04_amd64.deb +Size: 45288 +SHA256: 8de39d2a6dd6151df3c1fdc82bbc3a1bcb21f45de98f5414b3178c33fc42f5ea +SHA1: a70b2eed5df0399c4ddbe418448f7cef08dc27ef +MD5sum: c732236a741eadef2ca231e976c89b5c +Description: ROCm FFT marshalling library +Maintainer: hipfft-maintainer@amd.com +Recommends: hipfft-asan-dev (>=1.0.14.60200) +Version: 1.0.14.60200-66~20.04 +Installed-Size: 302 + +Package: hipfft-asan6.2.0 +Architecture: amd64 +Depends: rocfft6.2.0 (>= 1.0.21), rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipfft-asan6.2.0/hipfft-asan6.2.0_1.0.14.60200-66~20.04_amd64.deb +Size: 45396 +SHA256: a7195332044a3e0a55916d61944ad488743ff57b53d191ac214eda44e62d5c77 +SHA1: afdeb337a9c132d54c556547ef8f9b19a0e3aa2b +MD5sum: 0e9ff7989bfa2319d43bd820d7e3806c +Description: ROCm FFT marshalling library +Maintainer: hipfft-maintainer@amd.com +Recommends: hipfft-asan-dev (>=1.0.14.60200) +Version: 1.0.14.60200-66~20.04 +Installed-Size: 302 + +Package: hipfft-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: dc631eb6ab24e4b5412c0d0c9f07bec7235ef02a +Depends: hipfft (= 1.0.14.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipfft-dbgsym/hipfft-dbgsym_1.0.14.60200-66~20.04_amd64.deb +Size: 101464 +SHA256: 42ae37c8d0ced86a60d5f9e634a0d82f7fabeef577a5d5743b2f04a32c08eaa7 +SHA1: 673e6e1781605eae7cac6e9be748d195f6eaedaf +MD5sum: 46d64e492f441729f34951d689fdc720 +Description: debug symbols for hipfft +Maintainer: hipfft-maintainer@amd.com +Package-Type: ddeb +Version: 1.0.14.60200-66~20.04 +Installed-Size: 387 + +Package: hipfft-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: dc631eb6ab24e4b5412c0d0c9f07bec7235ef02a +Depends: hipfft-rpath6.2.0 (= 1.0.14.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipfft-dbgsym-rpath6.2.0/hipfft-dbgsym-rpath6.2.0_1.0.14.60200-66~20.04_amd64.deb +Size: 101716 +SHA256: 93bed266afc24bc34cfa4575fed22eccdd98fc1997da4c1c2b66342feb6166aa +SHA1: 423e46ef498d039619aee1317337054639f00ddd +MD5sum: a9ef62bec6e40518d4c0e8ebe71e5091 +Description: debug symbols for hipfft +Maintainer: hipfft-maintainer@amd.com +Package-Type: ddeb +Version: 1.0.14.60200-66~20.04 +Installed-Size: 387 + +Package: hipfft-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: dc631eb6ab24e4b5412c0d0c9f07bec7235ef02a +Depends: hipfft6.2.0 (= 1.0.14.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipfft-dbgsym6.2.0/hipfft-dbgsym6.2.0_1.0.14.60200-66~20.04_amd64.deb +Size: 101708 +SHA256: 9e8b049c139f17162d5b935664cf50cacd2623097b8c91863da9dd70d446de61 +SHA1: ae9ea924981dab1903aeb2e7359571d49717f984 +MD5sum: 28be58fb419701d55768a8146bfa1c2e +Description: debug symbols for hipfft +Maintainer: hipfft-maintainer@amd.com +Package-Type: ddeb +Version: 1.0.14.60200-66~20.04 +Installed-Size: 387 + +Package: hipfft-dev +Architecture: amd64 +Depends: hipfft (>= 1.0.14.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipfft-dev/hipfft-dev_1.0.14.60200-66~20.04_amd64.deb +Size: 11162 +SHA256: cd5335500e9a22db1cf8a7afe12e89ddeb682296416ef753881e2ca9045f8611 +SHA1: 185228615c7220e9357d6a69f062d2065935868d +MD5sum: 32d918e40a136775ce6aa62820ac03b6 +Description: ROCm FFT marshalling library +Maintainer: hipfft-maintainer@amd.com +Version: 1.0.14.60200-66~20.04 +Installed-Size: 90 + +Package: hipfft-dev-rpath6.2.0 +Architecture: amd64 +Depends: hipfft-rpath6.2.0 (>= 1.0.14.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipfft-dev-rpath6.2.0/hipfft-dev-rpath6.2.0_1.0.14.60200-66~20.04_amd64.deb +Size: 11308 +SHA256: 0bfc569baf7f7ae4c38d15da147c5f00d49896c1f90144fedb010afccfbd55c1 +SHA1: d75a89529e7a025bc8c95f0b8f19a24f88ad1fcb +MD5sum: b1c775000774fd5c15df959e78964efe +Description: ROCm FFT marshalling library +Maintainer: hipfft-maintainer@amd.com +Version: 1.0.14.60200-66~20.04 +Installed-Size: 90 + +Package: hipfft-dev6.2.0 +Architecture: amd64 +Depends: hipfft6.2.0 (>= 1.0.14.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipfft-dev6.2.0/hipfft-dev6.2.0_1.0.14.60200-66~20.04_amd64.deb +Size: 11304 +SHA256: 3cfec840c79c6bce4e83bf6e056e241cc13ff572352b040a952c7642b61d45aa +SHA1: c6be5c7813e001bae323fd61d0eb3a8b33ae5fa1 +MD5sum: becd3ff417c38558f3d7868170c02db5 +Description: ROCm FFT marshalling library +Maintainer: hipfft-maintainer@amd.com +Version: 1.0.14.60200-66~20.04 +Installed-Size: 90 + +Package: hipfft-rpath6.2.0 +Architecture: amd64 +Depends: rocfft-rpath6.2.0 (>= 1.0.21), rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipfft-rpath6.2.0/hipfft-rpath6.2.0_1.0.14.60200-66~20.04_amd64.deb +Size: 25224 +SHA256: 98639936ee25008c8b9464708022c4d83e4706bb196397ba976a71ecc5181bc3 +SHA1: 051f24285770f7eca7daeaa58f815417e4072f92 +MD5sum: e460d9136f9eabe293ae42e2c9ddffd3 +Description: ROCm FFT marshalling library +Maintainer: hipfft-maintainer@amd.com +Recommends: hipfft-dev-rpath6.2.0 (>=1.0.14.60200) +Version: 1.0.14.60200-66~20.04 +Installed-Size: 151 + +Package: hipfft6.2.0 +Architecture: amd64 +Depends: rocfft6.2.0 (>= 1.0.21), rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipfft6.2.0/hipfft6.2.0_1.0.14.60200-66~20.04_amd64.deb +Size: 25228 +SHA256: 25887526ea2e955d4c0afa4749f8db55a49e399a349d43ccf66e0ad99ff78b2a +SHA1: 415aa911cc392dd990c9c3bb67c4e52eca8f196f +MD5sum: be7eadabefa08557e9865a76ba83c08c +Description: ROCm FFT marshalling library +Maintainer: hipfft-maintainer@amd.com +Recommends: hipfft-dev6.2.0 (>=1.0.14.60200) +Version: 1.0.14.60200-66~20.04 +Installed-Size: 151 + +Package: hipfort-dev +Architecture: amd64 +Conflicts: hipfort +Depends: hip-runtime-amd (>= 4.5.0), rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/hipfort-dev/hipfort-dev_0.4.0.60200-66~20.04_amd64.deb +Size: 6664132 +SHA256: 7bf8b39f63fb5eed4ea471e8e110dc0234cc4f92a2fd4022c88c5765cce11b57 +SHA1: d902b920689320b805f8b851f23d4c93af96d50a +MD5sum: 269362525b44759c068e7c909724fd10 +Description: Fortran Interface For GPU Kernel Libraries +Maintainer: Hipfort maintainer +Provides: CPACK_DEBIAN_PACKAGE_PROVIDES, hipfort (= 0.4.0.60200) +Replaces: hipfort +Version: 0.4.0.60200-66~20.04 +Installed-Size: 88514 + +Package: hipfort-dev-rpath6.2.0 +Architecture: amd64 +Conflicts: hipfort-rpath6.2.0 +Depends: hip-runtime-amd-rpath6.2.0 (>= 4.5.0), rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipfort-dev-rpath6.2.0/hipfort-dev-rpath6.2.0_0.4.0.60200-66~20.04_amd64.deb +Size: 6665484 +SHA256: 4926efa80e3d644ff7d5c414a957f1d360564a313ac3f9392e7bbd045ba54c7c +SHA1: 547d3c2f105c3bdefc6c00f1b66ed764cbd14cef +MD5sum: 9f47d0e9bbca5f3a04ec292efb106c08 +Description: Fortran Interface For GPU Kernel Libraries +Maintainer: Hipfort maintainer +Provides: CPACK_DEBIAN_PACKAGE_PROVIDES, hipfort-rpath6.2.0 (= 0.4.0.60200) +Replaces: hipfort-rpath6.2.0 +Version: 0.4.0.60200-66~20.04 +Installed-Size: 88514 + +Package: hipfort-dev6.2.0 +Architecture: amd64 +Conflicts: hipfort6.2.0 +Depends: hip-runtime-amd6.2.0 (>= 4.5.0), rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipfort-dev6.2.0/hipfort-dev6.2.0_0.4.0.60200-66~20.04_amd64.deb +Size: 6666696 +SHA256: 744ee5b10005607d227f7cf324e7123cc35822e5a99e17773efdb231cbdc0874 +SHA1: 7b32ef09cbde2e773359ed97bc382554a0b12d75 +MD5sum: 63b36392e107097439bb0636ec44210e +Description: Fortran Interface For GPU Kernel Libraries +Maintainer: Hipfort maintainer +Provides: CPACK_DEBIAN_PACKAGE_PROVIDES, hipfort6.2.0 (= 0.4.0.60200) +Replaces: hipfort6.2.0 +Version: 0.4.0.60200-66~20.04 +Installed-Size: 88514 + +Package: hipify-clang +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/hipify-clang/hipify-clang_18.0.0.60200-66~20.04_amd64.deb +Size: 21042784 +SHA256: 25781c9a7c19968eb90a6d6c6dd8f6363dc0f6c6131733a392da07956a0e3525 +SHA1: 652904ceac2fc41327d3672bb64c9924f1a08978 +MD5sum: 88708898c233f999999210d64b0e24d9 +Description: Hipify CUDA source + This tool translates CUDA source code into portable HIP C++ automatically +Maintainer: ROCm Compiler Support +Version: 18.0.0.60200-66~20.04 +Installed-Size: 53933 + +Package: hipify-clang-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipify-clang-rpath6.2.0/hipify-clang-rpath6.2.0_18.0.0.60200-66~20.04_amd64.deb +Size: 14653844 +SHA256: 97ebbf294e9db0800c5dbdfb371e174409b3c418496cd19a53d1776c28929bc7 +SHA1: 6786ee76b8accbbea03c24a31b4254899813c73d +MD5sum: 70ec0a4a0e062ae56f1ef3bec5c76af2 +Description: Hipify CUDA source + This tool translates CUDA source code into portable HIP C++ automatically +Maintainer: ROCm Compiler Support +Version: 18.0.0.60200-66~20.04 +Installed-Size: 53933 + +Package: hipify-clang6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipify-clang6.2.0/hipify-clang6.2.0_18.0.0.60200-66~20.04_amd64.deb +Size: 14653524 +SHA256: 1159815886b214185d2fca9230ae8824dd39b503116fce61ff27185887589bc7 +SHA1: 5357138378232e8aefae1e210e0a6d4f0eaee72e +MD5sum: 46b1826527f009f757b0169df2e0532d +Description: Hipify CUDA source + This tool translates CUDA source code into portable HIP C++ automatically +Maintainer: ROCm Compiler Support +Version: 18.0.0.60200-66~20.04 +Installed-Size: 53933 + +Package: hiprand +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/hiprand/hiprand_2.11.0.60200-66~20.04_amd64.deb +Size: 5010 +SHA256: 409938b12d392841f01bb15628ed8a67da8d09bae013c7368e69413c8b03a501 +SHA1: f3a64b6a6ceeb814fa25ffa5795275c49d059931 +MD5sum: df2e2bbd299aadb213d33bcf19a1bd4a +Description: Radeon Open Compute RAND library +Maintainer: hipRAND Maintainer +Recommends: hiprand-dev (>=2.11.0.60200) +Version: 2.11.0.60200-66~20.04 +Installed-Size: 54 + +Package: hiprand-asan +Architecture: amd64 +Depends: rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/h/hiprand-asan/hiprand-asan_2.11.0.60200-66~20.04_amd64.deb +Size: 7018 +SHA256: c035e730876638b5580c84b7992087e2d9525d2bb84684e2621128457263082c +SHA1: 2e2497cb801dc40e30c3e8102992da12d0ed923b +MD5sum: 176e5d7a346346b8d885e3b8f9a28fe9 +Description: Radeon Open Compute RAND library +Maintainer: hipRAND Maintainer +Recommends: hiprand-asan-dev (>=2.11.0.60200) +Version: 2.11.0.60200-66~20.04 +Installed-Size: 81 + +Package: hiprand-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 29869ecf69237450349bda61dc4c650a42ed7d7a +Depends: hiprand-asan (= 2.11.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hiprand-asan-dbgsym/hiprand-asan-dbgsym_2.11.0.60200-66~20.04_amd64.deb +Size: 30618 +SHA256: 9a2f07a7dc38b8bd116eb5ed8c7088d51d3a664baa2aeb880e309bda83472b94 +SHA1: 495fb5c335e60f05c139b56df867d88c1fd97b15 +MD5sum: 1f25fa0803acdf41765c41dfdab88266 +Description: debug symbols for hiprand-asan +Maintainer: hipRAND Maintainer +Package-Type: ddeb +Version: 2.11.0.60200-66~20.04 +Installed-Size: 74 + +Package: hiprand-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 29869ecf69237450349bda61dc4c650a42ed7d7a +Depends: hiprand-asan-rpath6.2.0 (= 2.11.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hiprand-asan-dbgsym-rpath6.2.0/hiprand-asan-dbgsym-rpath6.2.0_2.11.0.60200-66~20.04_amd64.deb +Size: 30780 +SHA256: 6650810d8244826d981b2158c68017d6a02142bdc56716f4b653065d6e4de89d +SHA1: 0b6422ce4166bf60b309508ec42fe65fc3412236 +MD5sum: 22a717ad0b3754c714333e4db2793338 +Description: debug symbols for hiprand-asan +Maintainer: hipRAND Maintainer +Package-Type: ddeb +Version: 2.11.0.60200-66~20.04 +Installed-Size: 74 + +Package: hiprand-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 29869ecf69237450349bda61dc4c650a42ed7d7a +Depends: hiprand-asan6.2.0 (= 2.11.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hiprand-asan-dbgsym6.2.0/hiprand-asan-dbgsym6.2.0_2.11.0.60200-66~20.04_amd64.deb +Size: 30772 +SHA256: 5b21caf0fe5c31eeccb1bf1abe7e10c00791d91fb71774989cd9f3ffb76f45ae +SHA1: eee91e75d550cb513e012f854e1ee5e5f26ee358 +MD5sum: 569fcda1165e9e8e663fb680df59e3a5 +Description: debug symbols for hiprand-asan +Maintainer: hipRAND Maintainer +Package-Type: ddeb +Version: 2.11.0.60200-66~20.04 +Installed-Size: 74 + +Package: hiprand-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hiprand-asan-rpath6.2.0/hiprand-asan-rpath6.2.0_2.11.0.60200-66~20.04_amd64.deb +Size: 7200 +SHA256: cbe553db80a2767ec64baaaf3ff1b7c724480a83424ac923b4fe7cc23867c1c4 +SHA1: daaf53f57c226e4a8e29510ca0da4db1d09c0c27 +MD5sum: ff05cddf8abe9db3cf2651aab4790554 +Description: Radeon Open Compute RAND library +Maintainer: hipRAND Maintainer +Recommends: hiprand-asan-dev (>=2.11.0.60200) +Version: 2.11.0.60200-66~20.04 +Installed-Size: 81 + +Package: hiprand-asan6.2.0 +Architecture: amd64 +Depends: rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hiprand-asan6.2.0/hiprand-asan6.2.0_2.11.0.60200-66~20.04_amd64.deb +Size: 7172 +SHA256: a961ff44f102b86d874df485290a885580fe7f9fd3be783325fc847c56c4a672 +SHA1: a25e642ea668568ce0a43f2a21330dbf0830bf29 +MD5sum: 366f04df3aff474c8ded892cea5a44bb +Description: Radeon Open Compute RAND library +Maintainer: hipRAND Maintainer +Recommends: hiprand-asan-dev (>=2.11.0.60200) +Version: 2.11.0.60200-66~20.04 +Installed-Size: 81 + +Package: hiprand-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: d5dd7a0db48fe0e9023c620e24fc138d887a2e33 +Depends: hiprand (= 2.11.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hiprand-dbgsym/hiprand-dbgsym_2.11.0.60200-66~20.04_amd64.deb +Size: 18142 +SHA256: d96a20e5479ab28edd9fc5818731c1377f4d82019b06ea3098be6131c20f5b38 +SHA1: 13310eb2ed5b53f04926f924ebff23ce7020094b +MD5sum: 617374a1a242b2aa8faee598ae1771ff +Description: debug symbols for hiprand +Maintainer: hipRAND Maintainer +Package-Type: ddeb +Version: 2.11.0.60200-66~20.04 +Installed-Size: 77 + +Package: hiprand-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: d5dd7a0db48fe0e9023c620e24fc138d887a2e33 +Depends: hiprand-rpath6.2.0 (= 2.11.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hiprand-dbgsym-rpath6.2.0/hiprand-dbgsym-rpath6.2.0_2.11.0.60200-66~20.04_amd64.deb +Size: 18328 +SHA256: 9cc2c643ec944399384c29e7e487b7b8960e854ee64ed60e127a38de0ba50275 +SHA1: eb774c1e2e560dd4b5f1be1cb5e474ffb818c58b +MD5sum: 678c2ca6adf056e5b85ded936179458f +Description: debug symbols for hiprand +Maintainer: hipRAND Maintainer +Package-Type: ddeb +Version: 2.11.0.60200-66~20.04 +Installed-Size: 77 + +Package: hiprand-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: d5dd7a0db48fe0e9023c620e24fc138d887a2e33 +Depends: hiprand6.2.0 (= 2.11.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hiprand-dbgsym6.2.0/hiprand-dbgsym6.2.0_2.11.0.60200-66~20.04_amd64.deb +Size: 18320 +SHA256: c38a2da3f24ebd843860ae64d32f17761ce8c1b0ead68e62b26d37fe6852ce78 +SHA1: a49245859a8b8aa818b85998b919c9d5c92ecd36 +MD5sum: a90a517c8c7ec8fb9bc2262a973151ef +Description: debug symbols for hiprand +Maintainer: hipRAND Maintainer +Package-Type: ddeb +Version: 2.11.0.60200-66~20.04 +Installed-Size: 77 + +Package: hiprand-dev +Architecture: amd64 +Depends: hiprand (>= 2.11.0.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hiprand-dev/hiprand-dev_2.11.0.60200-66~20.04_amd64.deb +Size: 21158 +SHA256: a14bd9301aef807d031311ee6da6660b8f9061074e096e1a97a225d676810345 +SHA1: 1b3034642e1e1de7c625501d9dd5a6ed405796a6 +MD5sum: 09995784e8fd5411d7bdbad6e707aff1 +Description: Radeon Open Compute RAND library +Maintainer: hipRAND Maintainer +Version: 2.11.0.60200-66~20.04 +Installed-Size: 209 + +Package: hiprand-dev-rpath6.2.0 +Architecture: amd64 +Depends: hiprand-rpath6.2.0 (>= 2.11.0.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hiprand-dev-rpath6.2.0/hiprand-dev-rpath6.2.0_2.11.0.60200-66~20.04_amd64.deb +Size: 21288 +SHA256: 590df1afb8a67f650095e1e20516cc80e4b1840838c25cd8408581d5a5728c1f +SHA1: 834e0f5f2c53d027c615e452c9174c0ae99bd2ae +MD5sum: bde692a11224d1e56eab9b19e96d3b79 +Description: Radeon Open Compute RAND library +Maintainer: hipRAND Maintainer +Version: 2.11.0.60200-66~20.04 +Installed-Size: 209 + +Package: hiprand-dev6.2.0 +Architecture: amd64 +Depends: hiprand6.2.0 (>= 2.11.0.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hiprand-dev6.2.0/hiprand-dev6.2.0_2.11.0.60200-66~20.04_amd64.deb +Size: 21268 +SHA256: 19564fb2f9616860234aa8bd69cca324a1a3ec33476581ec57200a1dac1d4dcb +SHA1: e9d59b9c69d2e8e4853bbd8ce0cdfbcba92f7ddb +MD5sum: fce0956feddeff5446e5e3a05723439f +Description: Radeon Open Compute RAND library +Maintainer: hipRAND Maintainer +Version: 2.11.0.60200-66~20.04 +Installed-Size: 209 + +Package: hiprand-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hiprand-rpath6.2.0/hiprand-rpath6.2.0_2.11.0.60200-66~20.04_amd64.deb +Size: 5180 +SHA256: 6614296711617d66f2f45f0668ab1ccbfe6227abb4d345956d359591455eca9a +SHA1: 2e422f53e235ae31cace7890b753fe146b4a7a35 +MD5sum: fffe1c4707b94e019ffc26048416f76a +Description: Radeon Open Compute RAND library +Maintainer: hipRAND Maintainer +Recommends: hiprand-dev-rpath6.2.0 (>=2.11.0.60200) +Version: 2.11.0.60200-66~20.04 +Installed-Size: 54 + +Package: hiprand6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hiprand6.2.0/hiprand6.2.0_2.11.0.60200-66~20.04_amd64.deb +Size: 5164 +SHA256: 2efed49be9413e08e91b3fb67736644bb0e8809fc673d310a0abab65b69eacad +SHA1: a43d4a04769d2bb374fabc1b03935df3d6540147 +MD5sum: a995c546a90dad85feb508359c959bff +Description: Radeon Open Compute RAND library +Maintainer: hipRAND Maintainer +Recommends: hiprand-dev6.2.0 (>=2.11.0.60200) +Version: 2.11.0.60200-66~20.04 +Installed-Size: 54 + +Package: hipsolver +Architecture: amd64 +Depends: rocblas (>= 4.2.0), rocsolver (>= 3.26.0), rocsparse (>= 2.3.0), libcholmod3, libsuitesparseconfig5, rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/hipsolver/hipsolver_2.2.0.60200-66~20.04_amd64.deb +Size: 56012 +SHA256: b914018b8315f9399777cdc6746540fd89c9d1252ec7972835d3714c716fc411 +SHA1: 80d5491904e9ebc05027bcb037cdbc7317f40231 +MD5sum: 420cbe5011a7c53feb7c38ff5625ba30 +Description: Radeon Open Compute LAPACK marshalling library +Maintainer: hipSOLVER Maintainer +Recommends: hipsolver-dev (>=2.2.0.60200) +Version: 2.2.0.60200-66~20.04 +Installed-Size: 715 + +Package: hipsolver-asan +Architecture: amd64 +Depends: rocblas (>= 4.2.0), rocsolver (>= 3.26.0), rocsparse (>= 2.3.0), libcholmod3, libsuitesparseconfig5, rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/h/hipsolver-asan/hipsolver-asan_2.2.0.60200-66~20.04_amd64.deb +Size: 77654 +SHA256: 8c1bea01cf837fb12edc10c903591128f514b0260ab4c0627160b7e84bb56eee +SHA1: e9e7e60d33f6bbb31307bbe5e78d708b6636864f +MD5sum: 0768a71c9d4849b0f8e5aa06ac0bc212 +Description: Radeon Open Compute LAPACK marshalling library +Maintainer: hipSOLVER Maintainer +Recommends: hipsolver-asan-dev (>=2.2.0.60200) +Version: 2.2.0.60200-66~20.04 +Installed-Size: 900 + +Package: hipsolver-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 46e5d4c62c4cf5e61acfc4d0559396548c339332 +Depends: hipsolver-asan (= 2.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipsolver-asan-dbgsym/hipsolver-asan-dbgsym_2.2.0.60200-66~20.04_amd64.deb +Size: 288208 +SHA256: 76c70008a46ed100b6622a6fcd376c686be9dc0f97794e9cbafd8ab0da8798fd +SHA1: cbbf4b09d4dd1d666ba3d094aa5beb62f5e70ae2 +MD5sum: 47e7e0087bcda133d02e610ee0cb6e23 +Description: debug symbols for hipsolver-asan +Maintainer: hipSOLVER Maintainer +Package-Type: ddeb +Version: 2.2.0.60200-66~20.04 +Installed-Size: 373 + +Package: hipsolver-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 46e5d4c62c4cf5e61acfc4d0559396548c339332 +Depends: hipsolver-asan-rpath6.2.0 (= 2.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipsolver-asan-dbgsym-rpath6.2.0/hipsolver-asan-dbgsym-rpath6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 288208 +SHA256: 0b875868336846f750365f9f49cefcdc5990249485b56f0a30e9f67e03984c66 +SHA1: b502402f8c8990237c8c2cc17fb0c7257f93fc2a +MD5sum: 4c5c1c1fa5adab3d8a860f4b150daafa +Description: debug symbols for hipsolver-asan +Maintainer: hipSOLVER Maintainer +Package-Type: ddeb +Version: 2.2.0.60200-66~20.04 +Installed-Size: 373 + +Package: hipsolver-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 46e5d4c62c4cf5e61acfc4d0559396548c339332 +Depends: hipsolver-asan6.2.0 (= 2.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipsolver-asan-dbgsym6.2.0/hipsolver-asan-dbgsym6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 288260 +SHA256: 29f8f6363ae61857caf2cdc162c42d19a960e78565cfc18a31fbc8b9e1b3efd9 +SHA1: 1dfedd1c5829b19b978b0505a6b167817403a430 +MD5sum: d262c0795f577b07fff9a428e8806e99 +Description: debug symbols for hipsolver-asan +Maintainer: hipSOLVER Maintainer +Package-Type: ddeb +Version: 2.2.0.60200-66~20.04 +Installed-Size: 373 + +Package: hipsolver-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocblas-rpath6.2.0 (>= 4.2.0), rocsolver-rpath6.2.0 (>= 3.26.0), rocsparse-rpath6.2.0 (>= 2.3.0), libcholmod3, libsuitesparseconfig5, rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipsolver-asan-rpath6.2.0/hipsolver-asan-rpath6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 77612 +SHA256: f92a593bb7535ea678cd1b5e56d5d5b7e021f1680b3b36eed19201d9b80da498 +SHA1: 766e0e7d3582927f00edcccdd1ac131a6b222e46 +MD5sum: 1453b7e68b2fa91c43b03e7e9787fb9a +Description: Radeon Open Compute LAPACK marshalling library +Maintainer: hipSOLVER Maintainer +Recommends: hipsolver-asan-dev (>=2.2.0.60200) +Version: 2.2.0.60200-66~20.04 +Installed-Size: 900 + +Package: hipsolver-asan6.2.0 +Architecture: amd64 +Depends: rocblas6.2.0 (>= 4.2.0), rocsolver6.2.0 (>= 3.26.0), rocsparse6.2.0 (>= 2.3.0), libcholmod3, libsuitesparseconfig5, rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipsolver-asan6.2.0/hipsolver-asan6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 77928 +SHA256: 6358725141d39d3cfb567e5466a577011ac890b5b66c0a1fc9cc51b447ab1872 +SHA1: 89b869512697440bf6696c75067e1a6f64262499 +MD5sum: 52c492e20f8612bd7644f26336bed2b3 +Description: Radeon Open Compute LAPACK marshalling library +Maintainer: hipSOLVER Maintainer +Recommends: hipsolver-asan-dev (>=2.2.0.60200) +Version: 2.2.0.60200-66~20.04 +Installed-Size: 900 + +Package: hipsolver-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 4a15088d8c1f1c21156aabbcce4f9ce3c23e5457 +Depends: hipsolver (= 2.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipsolver-dbgsym/hipsolver-dbgsym_2.2.0.60200-66~20.04_amd64.deb +Size: 189120 +SHA256: 54a33aba8731b7e1a26bfc80527355115762b0158ac21c767045ad550f137306 +SHA1: 4b5ad59dfbc10be0badf51fea11b21fb6b55dc6c +MD5sum: a267d5eba6beb7dc8bd61daea3ecfa13 +Description: debug symbols for hipsolver +Maintainer: hipSOLVER Maintainer +Package-Type: ddeb +Version: 2.2.0.60200-66~20.04 +Installed-Size: 756 + +Package: hipsolver-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 4a15088d8c1f1c21156aabbcce4f9ce3c23e5457 +Depends: hipsolver-rpath6.2.0 (= 2.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipsolver-dbgsym-rpath6.2.0/hipsolver-dbgsym-rpath6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 189168 +SHA256: 96e3cf112fc300848ff47bd5ecc7faef2628cf4a94a29bd5145125d093d7f020 +SHA1: 1b6943cebd0742bca9c577852bdd1b1eb5eaf519 +MD5sum: e09705094627d7d95cacd2d61f4344b9 +Description: debug symbols for hipsolver +Maintainer: hipSOLVER Maintainer +Package-Type: ddeb +Version: 2.2.0.60200-66~20.04 +Installed-Size: 756 + +Package: hipsolver-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 4a15088d8c1f1c21156aabbcce4f9ce3c23e5457 +Depends: hipsolver6.2.0 (= 2.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipsolver-dbgsym6.2.0/hipsolver-dbgsym6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 189456 +SHA256: 3ab6dd893fe2fdcdb2dfb3dac67b12f7a7b206590cb06e1bdfc1dbaad73db04a +SHA1: b950cfc4f624304a35ed0d69ee3249d402649d64 +MD5sum: 9f12ec2cd4fe58b86478c2146e649e48 +Description: debug symbols for hipsolver +Maintainer: hipSOLVER Maintainer +Package-Type: ddeb +Version: 2.2.0.60200-66~20.04 +Installed-Size: 756 + +Package: hipsolver-dev +Architecture: amd64 +Depends: hipsolver (>= 2.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipsolver-dev/hipsolver-dev_2.2.0.60200-66~20.04_amd64.deb +Size: 18690 +SHA256: 97617759b79e7650c0de4af2f4a2824b25823ef9420a198547617704f3943910 +SHA1: 26865680661d5e5bfb33d710497bf6720ea9c9c3 +MD5sum: 19871631befd9d4e12d00206fdc00350 +Description: Radeon Open Compute LAPACK marshalling library +Maintainer: hipSOLVER Maintainer +Version: 2.2.0.60200-66~20.04 +Installed-Size: 460 + +Package: hipsolver-dev-rpath6.2.0 +Architecture: amd64 +Depends: hipsolver-rpath6.2.0 (>= 2.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipsolver-dev-rpath6.2.0/hipsolver-dev-rpath6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 18820 +SHA256: 60cb34459507bd795d33dcde8fd042f40f5c76bd2488c2acd324570edd235e57 +SHA1: 334c4b48ac2ad75490f8c34fd9ad5e7a154c73e0 +MD5sum: 93227aa42f9ba02ab8df52499cf2cdce +Description: Radeon Open Compute LAPACK marshalling library +Maintainer: hipSOLVER Maintainer +Version: 2.2.0.60200-66~20.04 +Installed-Size: 460 + +Package: hipsolver-dev6.2.0 +Architecture: amd64 +Depends: hipsolver6.2.0 (>= 2.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipsolver-dev6.2.0/hipsolver-dev6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 18820 +SHA256: 1e968f9405c8b90fbb58dff09d8bab08cf31c8386880fff95e1cb8932320bc37 +SHA1: a10259dd23db5223bd3cf82687477c89d1ac678c +MD5sum: c8c2a66ea13f3a3797e7b56c22c13481 +Description: Radeon Open Compute LAPACK marshalling library +Maintainer: hipSOLVER Maintainer +Version: 2.2.0.60200-66~20.04 +Installed-Size: 460 + +Package: hipsolver-rpath6.2.0 +Architecture: amd64 +Depends: rocblas-rpath6.2.0 (>= 4.2.0), rocsolver-rpath6.2.0 (>= 3.26.0), rocsparse-rpath6.2.0 (>= 2.3.0), libcholmod3, libsuitesparseconfig5, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipsolver-rpath6.2.0/hipsolver-rpath6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 56512 +SHA256: adc16eea435dd0dd16ce1c20618e4af7d9bd7fe6efa493a340c1e5960e580757 +SHA1: 7e816a0a98931c4defa5bce423703893dfe7c507 +MD5sum: 54889a63d5f93c23b35e6c2bebbad74e +Description: Radeon Open Compute LAPACK marshalling library +Maintainer: hipSOLVER Maintainer +Recommends: hipsolver-dev-rpath6.2.0 (>=2.2.0.60200) +Version: 2.2.0.60200-66~20.04 +Installed-Size: 715 + +Package: hipsolver6.2.0 +Architecture: amd64 +Depends: rocblas6.2.0 (>= 4.2.0), rocsolver6.2.0 (>= 3.26.0), rocsparse6.2.0 (>= 2.3.0), libcholmod3, libsuitesparseconfig5, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipsolver6.2.0/hipsolver6.2.0_2.2.0.60200-66~20.04_amd64.deb +Size: 56864 +SHA256: cb56dd79ff52eaddfed379831023484d9ec32b9538bc3d02ee34c328457cd20e +SHA1: 861fa158f2c6373cce92aca23bb2ca9cad8f604a +MD5sum: 81cebab22441fece4c08945b9e05c962 +Description: Radeon Open Compute LAPACK marshalling library +Maintainer: hipSOLVER Maintainer +Recommends: hipsolver-dev6.2.0 (>=2.2.0.60200) +Version: 2.2.0.60200-66~20.04 +Installed-Size: 715 + +Package: hipsparse +Architecture: amd64 +Depends: rocsparse (>= 1.12.10), rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/hipsparse/hipsparse_3.1.1.60200-66~20.04_amd64.deb +Size: 45502 +SHA256: d562f6853b4bbedd2c4862723cc3a02632d04a52c4419666ff521e61afbd924b +SHA1: 0b3d6ed9bd076a2fc3bbd1678ec39f5474827d3d +MD5sum: fd4d34ae650e6e91d3dd2c4ae8aad8e3 +Description: ROCm SPARSE library +Maintainer: hipSPARSE Maintainer +Recommends: hipsparse-dev (>=3.1.1.60200) +Version: 3.1.1.60200-66~20.04 +Installed-Size: 518 + +Package: hipsparse-asan +Architecture: amd64 +Depends: rocsparse (>= 1.12.10), rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/h/hipsparse-asan/hipsparse-asan_3.1.1.60200-66~20.04_amd64.deb +Size: 71324 +SHA256: 362f108ef06d908d8da44d4fed0aa1815fccae56c32bb388a4648ba2611efe04 +SHA1: 7a0653b854fe85b13411f4d3ec9670e4d81a7b5a +MD5sum: 6575e74bcb8d61daebf0f22d0e8d8e28 +Description: ROCm SPARSE library +Maintainer: hipSPARSE Maintainer +Recommends: hipsparse-asan-dev (>=3.1.1.60200) +Version: 3.1.1.60200-66~20.04 +Installed-Size: 1015 + +Package: hipsparse-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 71833e396ff6acb0d52c128fd03af44795736acf +Depends: hipsparse-asan (= 3.1.1.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipsparse-asan-dbgsym/hipsparse-asan-dbgsym_3.1.1.60200-66~20.04_amd64.deb +Size: 242442 +SHA256: de7f0745b49573d6e0c8e8f787f7f0322d81336cde29e1be3238947ed2f05a72 +SHA1: b5df1a12d332aa4f77135ceaff229868125fc901 +MD5sum: 37edb19736de87447dec816e4c692675 +Description: debug symbols for hipsparse-asan +Maintainer: hipSPARSE Maintainer +Package-Type: ddeb +Version: 3.1.1.60200-66~20.04 +Installed-Size: 397 + +Package: hipsparse-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 71833e396ff6acb0d52c128fd03af44795736acf +Depends: hipsparse-asan-rpath6.2.0 (= 3.1.1.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipsparse-asan-dbgsym-rpath6.2.0/hipsparse-asan-dbgsym-rpath6.2.0_3.1.1.60200-66~20.04_amd64.deb +Size: 242752 +SHA256: 4ab69c12b6610c2f63fd178520f502420a9101aa3aaa66711352fffc831e3540 +SHA1: efa6c638d8644fe336e4147fdb640e90204f3796 +MD5sum: bc1e7447b136c649af91ff036fd75239 +Description: debug symbols for hipsparse-asan +Maintainer: hipSPARSE Maintainer +Package-Type: ddeb +Version: 3.1.1.60200-66~20.04 +Installed-Size: 397 + +Package: hipsparse-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 71833e396ff6acb0d52c128fd03af44795736acf +Depends: hipsparse-asan6.2.0 (= 3.1.1.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipsparse-asan-dbgsym6.2.0/hipsparse-asan-dbgsym6.2.0_3.1.1.60200-66~20.04_amd64.deb +Size: 242676 +SHA256: 85ae1d4052593638351292a3bac82177c817dd46a1e47b901ff102d1e2a4b32b +SHA1: 1cf38d14aa290ca5173a007f7778172e4ddac977 +MD5sum: 97d6b0e3f0f39402c35625e2cb286514 +Description: debug symbols for hipsparse-asan +Maintainer: hipSPARSE Maintainer +Package-Type: ddeb +Version: 3.1.1.60200-66~20.04 +Installed-Size: 397 + +Package: hipsparse-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocsparse-rpath6.2.0 (>= 1.12.10), rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipsparse-asan-rpath6.2.0/hipsparse-asan-rpath6.2.0_3.1.1.60200-66~20.04_amd64.deb +Size: 71760 +SHA256: 3f953566ccf3c6eafaf7b82927a5edbb52bf94befd134c216e7bea0bf0120845 +SHA1: 4aadb83da04b342c68d3592fb5cf912afa57add3 +MD5sum: 83b0ee5db6fde6a66af88e917940ab6d +Description: ROCm SPARSE library +Maintainer: hipSPARSE Maintainer +Recommends: hipsparse-asan-dev (>=3.1.1.60200) +Version: 3.1.1.60200-66~20.04 +Installed-Size: 1015 + +Package: hipsparse-asan6.2.0 +Architecture: amd64 +Depends: rocsparse6.2.0 (>= 1.12.10), rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipsparse-asan6.2.0/hipsparse-asan6.2.0_3.1.1.60200-66~20.04_amd64.deb +Size: 71560 +SHA256: 48d3e9f3c20e2eaaba9953ff3b8644471007f07365cff894246d6867c2ed77b6 +SHA1: 8a1e7cf123b4267290383ea7a813b407aaf5d48f +MD5sum: d65d517d50293637b10d493c635e9b48 +Description: ROCm SPARSE library +Maintainer: hipSPARSE Maintainer +Recommends: hipsparse-asan-dev (>=3.1.1.60200) +Version: 3.1.1.60200-66~20.04 +Installed-Size: 1015 + +Package: hipsparse-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: c3177eb1999321f716e2aeb3750c51d00f122a6c +Depends: hipsparse (= 3.1.1.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipsparse-dbgsym/hipsparse-dbgsym_3.1.1.60200-66~20.04_amd64.deb +Size: 177564 +SHA256: cc02b8e1c3a16efb2932d660f8dd921250e439375c5b7d6b5aa7f79e7657d200 +SHA1: 795f1ed2895f43c89aeac98142b2e21a0b441838 +MD5sum: 9ae4deb778737934229fc373173c826c +Description: debug symbols for hipsparse +Maintainer: hipSPARSE Maintainer +Package-Type: ddeb +Version: 3.1.1.60200-66~20.04 +Installed-Size: 1096 + +Package: hipsparse-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: c3177eb1999321f716e2aeb3750c51d00f122a6c +Depends: hipsparse-rpath6.2.0 (= 3.1.1.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipsparse-dbgsym-rpath6.2.0/hipsparse-dbgsym-rpath6.2.0_3.1.1.60200-66~20.04_amd64.deb +Size: 178100 +SHA256: c34be26a7c6225d1b95732aeac9e36594147fa316b193e8ce1d92e237c1d5e70 +SHA1: 7d12e5f44a731be119e192a53310a0259f09c3e0 +MD5sum: c9224f140dd2072b331f90e6e2fe04f5 +Description: debug symbols for hipsparse +Maintainer: hipSPARSE Maintainer +Package-Type: ddeb +Version: 3.1.1.60200-66~20.04 +Installed-Size: 1096 + +Package: hipsparse-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: c3177eb1999321f716e2aeb3750c51d00f122a6c +Depends: hipsparse6.2.0 (= 3.1.1.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hipsparse-dbgsym6.2.0/hipsparse-dbgsym6.2.0_3.1.1.60200-66~20.04_amd64.deb +Size: 178072 +SHA256: a188d1f2d2f5c67599df01e6949ac2abe7e874d5c942c139decb0a30956f99e8 +SHA1: 86755eafbc4198cb7d98790caee00a4daec64d40 +MD5sum: 7e3b8f93c93948652abc301e8e74184e +Description: debug symbols for hipsparse +Maintainer: hipSPARSE Maintainer +Package-Type: ddeb +Version: 3.1.1.60200-66~20.04 +Installed-Size: 1096 + +Package: hipsparse-dev +Architecture: amd64 +Depends: hipsparse (>= 3.1.1.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipsparse-dev/hipsparse-dev_3.1.1.60200-66~20.04_amd64.deb +Size: 40918 +SHA256: f3003da871ef03ebbae40f5aa84f41ee726acf708bdeabd781acb7f56f7bb171 +SHA1: 89616f8d6c5011649295ce13ac02ffe9aef52e46 +MD5sum: 77f24f1073321e999622385abb1b4947 +Description: ROCm SPARSE library +Maintainer: hipSPARSE Maintainer +Version: 3.1.1.60200-66~20.04 +Installed-Size: 749 + +Package: hipsparse-dev-rpath6.2.0 +Architecture: amd64 +Depends: hipsparse-rpath6.2.0 (>= 3.1.1.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipsparse-dev-rpath6.2.0/hipsparse-dev-rpath6.2.0_3.1.1.60200-66~20.04_amd64.deb +Size: 41060 +SHA256: d3e8d83dbd927cbd134c64597c02a548d9d816883642ec9165d4ae447384bad5 +SHA1: fae1964d6f438c91062612d7ebbe3a64ecedd7b5 +MD5sum: 5d29c3e81256682f51015a005a6d649a +Description: ROCm SPARSE library +Maintainer: hipSPARSE Maintainer +Version: 3.1.1.60200-66~20.04 +Installed-Size: 749 + +Package: hipsparse-dev6.2.0 +Architecture: amd64 +Depends: hipsparse6.2.0 (>= 3.1.1.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipsparse-dev6.2.0/hipsparse-dev6.2.0_3.1.1.60200-66~20.04_amd64.deb +Size: 41060 +SHA256: e9464369619bbea7299ac83e17b3cbbabdeb16e6d4da116400532e7737332b65 +SHA1: e786bb257f1ae296b193bcf8390d0f9d1df22fb7 +MD5sum: 2b503a6558c674ed237672886ce2224c +Description: ROCm SPARSE library +Maintainer: hipSPARSE Maintainer +Version: 3.1.1.60200-66~20.04 +Installed-Size: 749 + +Package: hipsparse-rpath6.2.0 +Architecture: amd64 +Depends: rocsparse-rpath6.2.0 (>= 1.12.10), rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipsparse-rpath6.2.0/hipsparse-rpath6.2.0_3.1.1.60200-66~20.04_amd64.deb +Size: 46144 +SHA256: 92cf9473bc4bfccab00e21d5a68517f836ef0627cf501205217cc8c98511b285 +SHA1: 2a862f6cfd9cc2e37e5bdb688a9c204468accfa5 +MD5sum: 203b638b451f3fcebd55762e28085796 +Description: ROCm SPARSE library +Maintainer: hipSPARSE Maintainer +Recommends: hipsparse-dev-rpath6.2.0 (>=3.1.1.60200) +Version: 3.1.1.60200-66~20.04 +Installed-Size: 518 + +Package: hipsparse6.2.0 +Architecture: amd64 +Depends: rocsparse6.2.0 (>= 1.12.10), rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipsparse6.2.0/hipsparse6.2.0_3.1.1.60200-66~20.04_amd64.deb +Size: 45940 +SHA256: f08ba25b6b950754b5a2bb64c125a01b9f44280f227ff19eeb78e188f0b17320 +SHA1: c51ffcbd4b75f83333508139ddcaba39554180e8 +MD5sum: 5e6d227f17867bf360c9610694fea3da +Description: ROCm SPARSE library +Maintainer: hipSPARSE Maintainer +Recommends: hipsparse-dev6.2.0 (>=3.1.1.60200) +Version: 3.1.1.60200-66~20.04 +Installed-Size: 518 + +Package: hipsparselt +Architecture: amd64 +Depends: hipsparse (>= 2.1.0), rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/hipsparselt/hipsparselt_0.2.1.60200-66~20.04_amd64.deb +Size: 6633746 +SHA256: 2921793b52e30e183545be1487a5d678810e1ce344f1bd7ea2cf339a76138fed +SHA1: 2c4a4fa51be3b35e7811cc06651c0e88e662647f +MD5sum: a2520264a976b6ee6bc74cc1d96a0d7f +Description: Radeon Open Compute Structured Sparsity Matrix Multiplication marshalling library +Maintainer: hipSPARSELt Maintainer +Recommends: hipsparselt-dev (>=0.2.1.60200) +Version: 0.2.1.60200-66~20.04 +Installed-Size: 232218 + +Package: hipsparselt-asan +Architecture: amd64 +Depends: hipsparse (>= 2.1.0), rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/h/hipsparselt-asan/hipsparselt-asan_0.2.1.60200-66~20.04_amd64.deb +Size: 16481154 +SHA256: fabfcca527a77c6d3989499b128934b179336fccaaf445801ccb5bda4856cc6c +SHA1: 9d737d2e45273e8029649564235556ac985f13db +MD5sum: 2d0df9f4276bf15cf9b57553991e69ec +Description: Radeon Open Compute Structured Sparsity Matrix Multiplication marshalling library +Maintainer: hipSPARSELt Maintainer +Recommends: hipsparselt-asan-dev (>=0.2.1.60200) +Version: 0.2.1.60200-66~20.04 +Installed-Size: 59811 + +Package: hipsparselt-asan-rpath6.2.0 +Architecture: amd64 +Depends: hipsparse-rpath6.2.0 (>= 2.1.0), rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipsparselt-asan-rpath6.2.0/hipsparselt-asan-rpath6.2.0_0.2.1.60200-66~20.04_amd64.deb +Size: 16481308 +SHA256: a4d555db431ee12138387cf2879dcbcae490e588222cf1c68eef142d94a68c4b +SHA1: ca7c9785d7a7f9d09a2d0899514e4a65276e6e34 +MD5sum: 8f956f01149942b1d8baf6932744f5e9 +Description: Radeon Open Compute Structured Sparsity Matrix Multiplication marshalling library +Maintainer: hipSPARSELt Maintainer +Recommends: hipsparselt-asan-dev (>=0.2.1.60200) +Version: 0.2.1.60200-66~20.04 +Installed-Size: 59811 + +Package: hipsparselt-asan6.2.0 +Architecture: amd64 +Depends: hipsparse6.2.0 (>= 2.1.0), rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipsparselt-asan6.2.0/hipsparselt-asan6.2.0_0.2.1.60200-66~20.04_amd64.deb +Size: 16481864 +SHA256: ac9658b2c509115845ab7a6f26aeb7bd952c708c4538d970eeace7208a7e55c5 +SHA1: 148c1cba03c7998edd2fd4f74059402dad1500df +MD5sum: cfab0baa1b5568ee0808d4bcfb3fcd00 +Description: Radeon Open Compute Structured Sparsity Matrix Multiplication marshalling library +Maintainer: hipSPARSELt Maintainer +Recommends: hipsparselt-asan-dev (>=0.2.1.60200) +Version: 0.2.1.60200-66~20.04 +Installed-Size: 59811 + +Package: hipsparselt-dev +Architecture: amd64 +Depends: hipsparselt (>= 0.2.1.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipsparselt-dev/hipsparselt-dev_0.2.1.60200-66~20.04_amd64.deb +Size: 11608 +SHA256: 9b3b0c8e3f1380a0b42c24fd144cb8dc0df2eebbc449622f78c6c34dc13d0fe0 +SHA1: e58f04fcb58ad7dd3d525a049b3af7b5576aa2c3 +MD5sum: 89035c61b3d5b271f7dad3e3518041ab +Description: Radeon Open Compute Structured Sparsity Matrix Multiplication marshalling library +Maintainer: hipSPARSELt Maintainer +Version: 0.2.1.60200-66~20.04 +Installed-Size: 94 + +Package: hipsparselt-dev-rpath6.2.0 +Architecture: amd64 +Depends: hipsparselt-rpath6.2.0 (>= 0.2.1.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipsparselt-dev-rpath6.2.0/hipsparselt-dev-rpath6.2.0_0.2.1.60200-66~20.04_amd64.deb +Size: 11760 +SHA256: a2e86261498a26616bfdb80da9a619daff4c508aeaa8c29a5b0786d6d218dbc2 +SHA1: e1e5bbd246189d2c6d5bad1b638e151a72c7a02f +MD5sum: 4da3f4fc2dc47c46c14d2ef430634483 +Description: Radeon Open Compute Structured Sparsity Matrix Multiplication marshalling library +Maintainer: hipSPARSELt Maintainer +Version: 0.2.1.60200-66~20.04 +Installed-Size: 94 + +Package: hipsparselt-dev6.2.0 +Architecture: amd64 +Depends: hipsparselt6.2.0 (>= 0.2.1.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hipsparselt-dev6.2.0/hipsparselt-dev6.2.0_0.2.1.60200-66~20.04_amd64.deb +Size: 11756 +SHA256: 2c2d60c7b08583bfdbac7b4dc815962eb1b7dcc5a1dbc41ed3244587312576c8 +SHA1: 42933a1cd422a8686cf0fc39b4b0ccbbdfa5b676 +MD5sum: eaa02a8d13cfe9819086fd2abda17239 +Description: Radeon Open Compute Structured Sparsity Matrix Multiplication marshalling library +Maintainer: hipSPARSELt Maintainer +Version: 0.2.1.60200-66~20.04 +Installed-Size: 94 + +Package: hipsparselt-rpath6.2.0 +Architecture: amd64 +Depends: hipsparse-rpath6.2.0 (>= 2.1.0), rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipsparselt-rpath6.2.0/hipsparselt-rpath6.2.0_0.2.1.60200-66~20.04_amd64.deb +Size: 6631292 +SHA256: de565103a1a7abec54754a7eed23c2f3a97b9237393d95521999d12685321e55 +SHA1: e478095f7cd39240999baf23e064fe086a957a1d +MD5sum: 12cfebce2672cee86777f30b6fa96a69 +Description: Radeon Open Compute Structured Sparsity Matrix Multiplication marshalling library +Maintainer: hipSPARSELt Maintainer +Recommends: hipsparselt-dev-rpath6.2.0 (>=0.2.1.60200) +Version: 0.2.1.60200-66~20.04 +Installed-Size: 232218 + +Package: hipsparselt6.2.0 +Architecture: amd64 +Depends: hipsparse6.2.0 (>= 2.1.0), rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hipsparselt6.2.0/hipsparselt6.2.0_0.2.1.60200-66~20.04_amd64.deb +Size: 6631400 +SHA256: 6dad161c0b0fad2b3cf478221df2e92bb394366b492d4f0b8f90ae81eb0f8899 +SHA1: 28246229843ce53ca077e22a38b05f5bc352fb1e +MD5sum: ce1c6753beea66fcd33fed81b461da5e +Description: Radeon Open Compute Structured Sparsity Matrix Multiplication marshalling library +Maintainer: hipSPARSELt Maintainer +Recommends: hipsparselt-dev6.2.0 (>=0.2.1.60200) +Version: 0.2.1.60200-66~20.04 +Installed-Size: 232218 + +Package: hiptensor +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/hiptensor/hiptensor_1.3.0.60200-66~20.04_amd64.deb +Size: 40336262 +SHA256: 59ee45ce2c3b760dd5391cc7965bdb43f89c01b8739a271813de8306abf17bdd +SHA1: baf2038285ce6876f872ffad31b1648800d29e49 +MD5sum: 50fa86e658b6d3a4a12742e7d3663bd5 +Description: AMD high-performance HIP library for tensor primitives +Maintainer: hiptensor Maintainer +Recommends: hiptensor-dev (>=1.3.0.60200) +Version: 1.3.0.60200-66~20.04 +Installed-Size: 1113647 + +Package: hiptensor-asan +Architecture: amd64 +Depends: rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/h/hiptensor-asan/hiptensor-asan_1.3.0.60200-66~20.04_amd64.deb +Size: 1429513764 +SHA256: 8142a078bd7a9340689e6187aef8297ea2a7f5f9c0e7c429f0f416a4b3c4e4da +SHA1: bdd1aee3ff33e7ad445335bcac084e5ccc948b27 +MD5sum: 151f4b2c57cdae16cb74fbca223a35fe +Description: AMD high-performance HIP library for tensor primitives +Maintainer: hiptensor Maintainer +Recommends: hiptensor-asan-dev (>=1.3.0.60200) +Version: 1.3.0.60200-66~20.04 +Installed-Size: 5160554 + +Package: hiptensor-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hiptensor-asan-rpath6.2.0/hiptensor-asan-rpath6.2.0_1.3.0.60200-66~20.04_amd64.deb +Size: 1429510844 +SHA256: b7d468f71e8b984e9e54281ddd333e7473ed83b0444dedfc4f5fade224a6552d +SHA1: ab914abe7e248e1bcfce79d2c0a8f8397669080a +MD5sum: 0f21c72606212b24790e709c0dc25dbe +Description: AMD high-performance HIP library for tensor primitives +Maintainer: hiptensor Maintainer +Recommends: hiptensor-asan-dev (>=1.3.0.60200) +Version: 1.3.0.60200-66~20.04 +Installed-Size: 5160554 + +Package: hiptensor-asan6.2.0 +Architecture: amd64 +Depends: rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hiptensor-asan6.2.0/hiptensor-asan6.2.0_1.3.0.60200-66~20.04_amd64.deb +Size: 1429519964 +SHA256: ce5ebbddfeae965b2d634abcd0d32248d1229376b2f7a5028e265d26fd5b0542 +SHA1: 7c4515db968fd4dfb142386891553145166230dd +MD5sum: 134b48bea06e081692db559f5f3283a5 +Description: AMD high-performance HIP library for tensor primitives +Maintainer: hiptensor Maintainer +Recommends: hiptensor-asan-dev (>=1.3.0.60200) +Version: 1.3.0.60200-66~20.04 +Installed-Size: 5160554 + +Package: hiptensor-dev +Architecture: amd64 +Depends: hiptensor (>= 1.3.0.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hiptensor-dev/hiptensor-dev_1.3.0.60200-66~20.04_amd64.deb +Size: 12426 +SHA256: 0e92be9776aec58db541c8e1493bb8b1536b74f84bd621048d5da3b1e442ab46 +SHA1: 1629ad02c42fc6234f358509a327f22d33034254 +MD5sum: c99d8be4778c9ccaee52a30f10594d70 +Description: AMD high-performance HIP library for tensor primitives +Maintainer: hiptensor Maintainer +Version: 1.3.0.60200-66~20.04 +Installed-Size: 98 + +Package: hiptensor-dev-rpath6.2.0 +Architecture: amd64 +Depends: hiptensor-rpath6.2.0 (>= 1.3.0.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hiptensor-dev-rpath6.2.0/hiptensor-dev-rpath6.2.0_1.3.0.60200-66~20.04_amd64.deb +Size: 12572 +SHA256: e1a63dec0ab3fb77a711f67417bf65fb4933ea292697b979e3037aa7a5809114 +SHA1: d2a12ee6593f3f47b90d5ce90dfd9f055e220f87 +MD5sum: cb56fd385696cfe88b960d7695b6d0f3 +Description: AMD high-performance HIP library for tensor primitives +Maintainer: hiptensor Maintainer +Version: 1.3.0.60200-66~20.04 +Installed-Size: 98 + +Package: hiptensor-dev6.2.0 +Architecture: amd64 +Depends: hiptensor6.2.0 (>= 1.3.0.60200) +Priority: optional +Section: devel +Filename: pool/main/h/hiptensor-dev6.2.0/hiptensor-dev6.2.0_1.3.0.60200-66~20.04_amd64.deb +Size: 12568 +SHA256: c67828e756b9b56fa081101c00dd020cc136ae3882c470e59363f669feb7c98f +SHA1: a6e1128ee7fe65da75e5d4a81e6d54fc1dbd7f24 +MD5sum: 1e92900de486a8131b1934daeabda32a +Description: AMD high-performance HIP library for tensor primitives +Maintainer: hiptensor Maintainer +Version: 1.3.0.60200-66~20.04 +Installed-Size: 98 + +Package: hiptensor-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hiptensor-rpath6.2.0/hiptensor-rpath6.2.0_1.3.0.60200-66~20.04_amd64.deb +Size: 40347124 +SHA256: 3a98aa96ffeb6bfa9114747269d404962e2e6a7c1d622569faa5c42db7fa7b54 +SHA1: 5df2793226c87b9c9d05908faf367fc6ee7d234b +MD5sum: f09669d5feb3906f077231e1ea4f2a86 +Description: AMD high-performance HIP library for tensor primitives +Maintainer: hiptensor Maintainer +Recommends: hiptensor-dev-rpath6.2.0 (>=1.3.0.60200) +Version: 1.3.0.60200-66~20.04 +Installed-Size: 1113647 + +Package: hiptensor6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hiptensor6.2.0/hiptensor6.2.0_1.3.0.60200-66~20.04_amd64.deb +Size: 40342856 +SHA256: 696a99aa327c240aea09b731ff75e941e4d8f8bf90f3706b19d5225729dcc74e +SHA1: 0293b9b1b56de2037cd040bd2ccacb430b1fd51d +MD5sum: 5ae2a1a2a32f4776065caff9cbb2ddd8 +Description: AMD high-performance HIP library for tensor primitives +Maintainer: hiptensor Maintainer +Recommends: hiptensor-dev6.2.0 (>=1.3.0.60200) +Version: 1.3.0.60200-66~20.04 +Installed-Size: 1113647 + +Package: hsa-amd-aqlprofile +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/hsa-amd-aqlprofile/hsa-amd-aqlprofile_1.0.0.60200.60200-66~20.04_amd64.deb +Size: 459166 +SHA256: 75f4417477abb80f6a453f836d1ac44c8a3d24447b21cfa4b29787a73725ef4e +SHA1: 35adfab6648d0eef43ad8b8a8a16d00b16106192 +MD5sum: c40cf4a6f70f0f5c9cb8d8d6e67a1263 +Description: AQLPROFILE library for AMD HSA runtime API extension support + Dynamic libraries for the AQLProfile +Homepage: https://github.com/RadeonOpenCompute/HSA-AqlProfile-AMD-extension +Maintainer: ROCm Profiler Support +Version: 1.0.0.60200.60200-66~20.04 +Installed-Size: 2748 + +Package: hsa-amd-aqlprofile-asan +Architecture: amd64 +Depends: rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/h/hsa-amd-aqlprofile-asan/hsa-amd-aqlprofile-asan_1.0.0.60200.60200-66~20.04_amd64.deb +Size: 6428728 +SHA256: 8cbca864eb3bd58ebca7a8dc369e17f2123c183ca2301f8c45a1ee052fcd099d +SHA1: a1087b2c285d5df3f4fdd7a4c6fcc5ad9584d98d +MD5sum: eee1ccdcd24d9b09bb23c94d917f0c7a +Description: AQLPROFILE library for AMD HSA runtime API extension support + ASAN libraries for the AQLProfile +Homepage: https://github.com/RadeonOpenCompute/HSA-AqlProfile-AMD-extension +Maintainer: ROCm Profiler Support +Version: 1.0.0.60200.60200-66~20.04 +Installed-Size: 30650 + +Package: hsa-amd-aqlprofile-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hsa-amd-aqlprofile-asan-rpath6.2.0/hsa-amd-aqlprofile-asan-rpath6.2.0_1.0.0.60200.60200-66~20.04_amd64.deb +Size: 3816500 +SHA256: 9073976d832c101f66160ea59150edecae96c813eee88369eaa13f8835cba3f6 +SHA1: 367ba1a9f16ac9dea25ae62c91b7f0c72d59327a +MD5sum: bdb4bd2907cfeee3e77c945049c4ff3d +Description: AQLPROFILE library for AMD HSA runtime API extension support + ASAN libraries for the AQLProfile +Homepage: https://github.com/RadeonOpenCompute/HSA-AqlProfile-AMD-extension +Maintainer: ROCm Profiler Support +Version: 1.0.0.60200.60200-66~20.04 +Installed-Size: 30650 + +Package: hsa-amd-aqlprofile-asan6.2.0 +Architecture: amd64 +Depends: rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hsa-amd-aqlprofile-asan6.2.0/hsa-amd-aqlprofile-asan6.2.0_1.0.0.60200.60200-66~20.04_amd64.deb +Size: 3816684 +SHA256: 8a286a100dd26526e4b739f5ba9819de9a1e33ab7025c46c7223e5e9a44d8a1b +SHA1: dcf2b1660077428e618a7d729b4e3fc043729f6c +MD5sum: 8776443fddbf20a732ffc3b5533acf51 +Description: AQLPROFILE library for AMD HSA runtime API extension support + ASAN libraries for the AQLProfile +Homepage: https://github.com/RadeonOpenCompute/HSA-AqlProfile-AMD-extension +Maintainer: ROCm Profiler Support +Version: 1.0.0.60200.60200-66~20.04 +Installed-Size: 30650 + +Package: hsa-amd-aqlprofile-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hsa-amd-aqlprofile-rpath6.2.0/hsa-amd-aqlprofile-rpath6.2.0_1.0.0.60200.60200-66~20.04_amd64.deb +Size: 267268 +SHA256: 17e5e2108e5ff584a5b87e13b4b322fe1305dd1c242df71f4620ec84cd5b9b40 +SHA1: b4d8ff3c6ba6b1619a2ca3933e505b4a2b9cc72f +MD5sum: b66305b15fea51e0458b3f88bf57a8fc +Description: AQLPROFILE library for AMD HSA runtime API extension support + Dynamic libraries for the AQLProfile +Homepage: https://github.com/RadeonOpenCompute/HSA-AqlProfile-AMD-extension +Maintainer: ROCm Profiler Support +Version: 1.0.0.60200.60200-66~20.04 +Installed-Size: 2748 + +Package: hsa-amd-aqlprofile6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hsa-amd-aqlprofile6.2.0/hsa-amd-aqlprofile6.2.0_1.0.0.60200.60200-66~20.04_amd64.deb +Size: 267332 +SHA256: b667fe3b24d1f56701e746028998bb00a828b7f8250cfb8f11bf6c06b3b2bc83 +SHA1: a5256cd8c664693a51418028317a7f9cd126f4c9 +MD5sum: db32a95d72a26a504a0a96dc4e379521 +Description: AQLPROFILE library for AMD HSA runtime API extension support + Dynamic libraries for the AQLProfile +Homepage: https://github.com/RadeonOpenCompute/HSA-AqlProfile-AMD-extension +Maintainer: ROCm Profiler Support +Version: 1.0.0.60200.60200-66~20.04 +Installed-Size: 2748 + +Package: hsa-rocr +Architecture: amd64 +Breaks: hsa-ext-rocr-dev +Depends: libdrm-amdgpu-amdgpu1 | libdrm-amdgpu1, libnuma1, libelf1, rocm-core, rocprofiler-register +Priority: optional +Section: devel +Filename: pool/main/h/hsa-rocr/hsa-rocr_1.14.0.60200-66~20.04_amd64.deb +Size: 930778 +SHA256: 5b46c494fe8f3975551652344bf35aa198094922a6272f905160bbad4ac58a64 +SHA1: 306612d1b6825a8531c3feefc1a616a1db191478 +MD5sum: 727a9e3eca4fa7cd74cbbc2be7457bdd +Description: AMD Heterogeneous System Architecture HSA - Linux HSA Runtime for Boltzmann (ROCm) platforms +Homepage: https://github.com/RadeonOpenCompute/ROCR-Runtime +Maintainer: AMD HSA Support +Recommends: libdrm-amdgpu-amdgpu1 +Replaces: hsa-ext-rocr-dev +Version: 1.14.0.60200-66~20.04 +Installed-Size: 9478 + +Package: hsa-rocr-asan +Architecture: amd64 +Breaks: hsa-ext-rocr-dev +Depends: libdrm-amdgpu-amdgpu1 | libdrm-amdgpu1, libnuma1, libelf1, rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/h/hsa-rocr-asan/hsa-rocr-asan_1.14.0.60200-66~20.04_amd64.deb +Size: 1639270 +SHA256: 0a4137e1b38924eb6786e8fa067c0014ac5f16ef4b0b238514374c8a44e10b3a +SHA1: 629177fb2a41d292bca8f5b636ace470585d364c +MD5sum: 0007c8b40dbbfd367a82fceb97bddc59 +Description: AMD Heterogeneous System Architecture HSA - Linux HSA instrumented libraries for Boltzmann (ROCm) platforms +Homepage: https://github.com/RadeonOpenCompute/ROCR-Runtime +Maintainer: AMD HSA Support +Replaces: hsa-ext-rocr-dev +Version: 1.14.0.60200-66~20.04 +Installed-Size: 17127 + +Package: hsa-rocr-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: b6ce3378742769728dc16404d9ccadf056a00b86 +Depends: hsa-rocr-asan (= 1.14.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hsa-rocr-asan-dbgsym/hsa-rocr-asan-dbgsym_1.14.0.60200-66~20.04_amd64.deb +Size: 4976242 +SHA256: e812116afb0e75922e70f8cb1fe141aa45586b77dfe6b5cd2a971c99c10f8278 +SHA1: 71688691b02fad86df55dc8e331405431df0f8f7 +MD5sum: daf372000b4a47dbf2a60df3887bddf6 +Description: debug symbols for hsa-rocr-asan +Maintainer: AMD HSA Support +Package-Type: ddeb +Version: 1.14.0.60200-66~20.04 +Installed-Size: 13772 + +Package: hsa-rocr-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: b6ce3378742769728dc16404d9ccadf056a00b86 +Depends: hsa-rocr-asan-rpath6.2.0 (= 1.14.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hsa-rocr-asan-dbgsym-rpath6.2.0/hsa-rocr-asan-dbgsym-rpath6.2.0_1.14.0.60200-66~20.04_amd64.deb +Size: 3467028 +SHA256: a5d4c0a5bcc22a4dac23cb722cd0148795c1ee6420e64046c60e99ba1213b0ef +SHA1: ea8aec636567cdaaf9f4f83ac9b47da8d22ea3ee +MD5sum: 9aa03c9ddfc96d7dd0e7eec5947cde43 +Description: debug symbols for hsa-rocr-asan +Maintainer: AMD HSA Support +Package-Type: ddeb +Version: 1.14.0.60200-66~20.04 +Installed-Size: 13772 + +Package: hsa-rocr-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: b6ce3378742769728dc16404d9ccadf056a00b86 +Depends: hsa-rocr-asan6.2.0 (= 1.14.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hsa-rocr-asan-dbgsym6.2.0/hsa-rocr-asan-dbgsym6.2.0_1.14.0.60200-66~20.04_amd64.deb +Size: 3467032 +SHA256: e670de6b50f4efab661471eadf65b7375d19c21a629e8135d05fd91b7ff5a700 +SHA1: 1e3448b07fe2c812a44e929c9bd824249be2c933 +MD5sum: ae1aa5e9d06ef8166229bf4b69b4f765 +Description: debug symbols for hsa-rocr-asan +Maintainer: AMD HSA Support +Package-Type: ddeb +Version: 1.14.0.60200-66~20.04 +Installed-Size: 13772 + +Package: hsa-rocr-asan-rpath6.2.0 +Architecture: amd64 +Breaks: hsa-ext-rocr-dev-rpath6.2.0 +Depends: libdrm-amdgpu-amdgpu1 | libdrm-amdgpu1, libnuma1, libelf1, rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hsa-rocr-asan-rpath6.2.0/hsa-rocr-asan-rpath6.2.0_1.14.0.60200-66~20.04_amd64.deb +Size: 1030072 +SHA256: 7e8475bf54723ce27d667af43b015e41d2a267caa73a084bde482ea153066150 +SHA1: 22ddf184da1b216fc867dd81ae3d3d5382faaaf6 +MD5sum: 9f164b138bdb9185696cf0b13d8e2db9 +Description: AMD Heterogeneous System Architecture HSA - Linux HSA instrumented libraries for Boltzmann (ROCm) platforms +Homepage: https://github.com/RadeonOpenCompute/ROCR-Runtime +Maintainer: AMD HSA Support +Replaces: hsa-ext-rocr-dev-rpath6.2.0 +Version: 1.14.0.60200-66~20.04 +Installed-Size: 17127 + +Package: hsa-rocr-asan6.2.0 +Architecture: amd64 +Breaks: hsa-ext-rocr-dev6.2.0 +Depends: libdrm-amdgpu-amdgpu1 | libdrm-amdgpu1, libnuma1, libelf1, rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hsa-rocr-asan6.2.0/hsa-rocr-asan6.2.0_1.14.0.60200-66~20.04_amd64.deb +Size: 1030020 +SHA256: e371d837115585f93148dce73f5c1c565589f504e7d8996f8ffc5257cbc502e2 +SHA1: e5fb97b140d5bba704550535f78e51d03355f588 +MD5sum: 12357e183cecb0472f7146e948c67d0a +Description: AMD Heterogeneous System Architecture HSA - Linux HSA instrumented libraries for Boltzmann (ROCm) platforms +Homepage: https://github.com/RadeonOpenCompute/ROCR-Runtime +Maintainer: AMD HSA Support +Replaces: hsa-ext-rocr-dev6.2.0 +Version: 1.14.0.60200-66~20.04 +Installed-Size: 17127 + +Package: hsa-rocr-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 701d1b38bb7e301c7835f97cca10a236be30a1f8 +Depends: hsa-rocr (= 1.14.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hsa-rocr-dbgsym/hsa-rocr-dbgsym_1.14.0.60200-66~20.04_amd64.deb +Size: 10264456 +SHA256: 8ddbca024436b641078e5bf0b1752f2df4e5315d809850772130bb492968add0 +SHA1: f484d8809e93a9cdf10cdec36652c38846ee59c7 +MD5sum: f0822b28d979edf4d25dc26fa37bcae2 +Description: debug symbols for hsa-rocr +Maintainer: AMD HSA Support +Package-Type: ddeb +Version: 1.14.0.60200-66~20.04 +Installed-Size: 34542 + +Package: hsa-rocr-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 701d1b38bb7e301c7835f97cca10a236be30a1f8 +Depends: hsa-rocr-rpath6.2.0 (= 1.14.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hsa-rocr-dbgsym-rpath6.2.0/hsa-rocr-dbgsym-rpath6.2.0_1.14.0.60200-66~20.04_amd64.deb +Size: 6878128 +SHA256: 93eb2c9623b7b1a08fa42ea79e4bf5d7ffa2c2d24858501eadb5e1b3f5fe68cf +SHA1: 718898a9a9942db8f92793c9e51efb20e15622da +MD5sum: 0570e2e661378fbaea621299872fbc34 +Description: debug symbols for hsa-rocr +Maintainer: AMD HSA Support +Package-Type: ddeb +Version: 1.14.0.60200-66~20.04 +Installed-Size: 34542 + +Package: hsa-rocr-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 701d1b38bb7e301c7835f97cca10a236be30a1f8 +Depends: hsa-rocr6.2.0 (= 1.14.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/h/hsa-rocr-dbgsym6.2.0/hsa-rocr-dbgsym6.2.0_1.14.0.60200-66~20.04_amd64.deb +Size: 6876316 +SHA256: c481349b659f0fdc0f57f9a828cc23fe0bf290c20addf6fcefd777c9b492ef05 +SHA1: af17349cadfe9cb38eb63452ec8dcd99fd9724ea +MD5sum: f9af6a57364ddf01d9cb509c0dbf3049 +Description: debug symbols for hsa-rocr +Maintainer: AMD HSA Support +Package-Type: ddeb +Version: 1.14.0.60200-66~20.04 +Installed-Size: 34542 + +Package: hsa-rocr-dev +Architecture: amd64 +Breaks: hsa-ext-rocr-dev +Depends: hsa-rocr, hsakmt-roct-dev +Priority: optional +Section: devel +Filename: pool/main/h/hsa-rocr-dev/hsa-rocr-dev_1.14.0.60200-66~20.04_amd64.deb +Size: 105936 +SHA256: 6b825c39e55a9260d7ba0049d698b5a4a348b34213e91ce6593420382ddd8aca +SHA1: d5881471a7db915bccf49a40fed2a32af15d57fc +MD5sum: dd5ad7ea2968b529436b94222c27d0ec +Description: AMD Heterogeneous System Architecture HSA development package. + This package contains the headers and cmake files for the hsa-rocr package. +Homepage: https://github.com/RadeonOpenCompute/ROCR-Runtime +Maintainer: AMD HSA Support +Replaces: hsa-ext-rocr-dev +Version: 1.14.0.60200-66~20.04 +Installed-Size: 584 + +Package: hsa-rocr-dev-rpath6.2.0 +Architecture: amd64 +Breaks: hsa-ext-rocr-dev-rpath6.2.0 +Depends: hsa-rocr-rpath6.2.0, hsakmt-roct-dev-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hsa-rocr-dev-rpath6.2.0/hsa-rocr-dev-rpath6.2.0_1.14.0.60200-66~20.04_amd64.deb +Size: 81132 +SHA256: 38b9a1cf5de04218284cdc3e582079388c48122f40f36ca009d5b66be38d6b4c +SHA1: de436e226e71506f6c3bd8ba2f709473eb032538 +MD5sum: c0bc9e201d0440db89950be1255894d4 +Description: AMD Heterogeneous System Architecture HSA development package. + This package contains the headers and cmake files for the hsa-rocr package. +Homepage: https://github.com/RadeonOpenCompute/ROCR-Runtime +Maintainer: AMD HSA Support +Replaces: hsa-ext-rocr-dev-rpath6.2.0 +Version: 1.14.0.60200-66~20.04 +Installed-Size: 584 + +Package: hsa-rocr-dev6.2.0 +Architecture: amd64 +Breaks: hsa-ext-rocr-dev6.2.0 +Depends: hsa-rocr6.2.0, hsakmt-roct-dev6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hsa-rocr-dev6.2.0/hsa-rocr-dev6.2.0_1.14.0.60200-66~20.04_amd64.deb +Size: 81128 +SHA256: 51071ba65ef455cb272236fff793b8a1f19a1f650d6874db599875ab09396ea9 +SHA1: 4a603e3d3c17a9d470521374b1e24dd3f41da607 +MD5sum: 5748aa007bdec6ff7196c3311f0ee50a +Description: AMD Heterogeneous System Architecture HSA development package. + This package contains the headers and cmake files for the hsa-rocr package. +Homepage: https://github.com/RadeonOpenCompute/ROCR-Runtime +Maintainer: AMD HSA Support +Replaces: hsa-ext-rocr-dev6.2.0 +Version: 1.14.0.60200-66~20.04 +Installed-Size: 584 + +Package: hsa-rocr-rpath6.2.0 +Architecture: amd64 +Breaks: hsa-ext-rocr-dev-rpath6.2.0 +Depends: libdrm-amdgpu-amdgpu1 | libdrm-amdgpu1, libnuma1, libelf1, rocm-core-rpath6.2.0, rocprofiler-register-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hsa-rocr-rpath6.2.0/hsa-rocr-rpath6.2.0_1.14.0.60200-66~20.04_amd64.deb +Size: 553052 +SHA256: d76ccf5d0997b8e69b92c231af91974e5b9a7581d1764c7bee410e722a45ffd9 +SHA1: ed5eec9a83f0e6ec28f004d4ca7bb1739343757e +MD5sum: 28ad1e99a20c4d88785ccdd76b19dceb +Description: AMD Heterogeneous System Architecture HSA - Linux HSA Runtime for Boltzmann (ROCm) platforms +Homepage: https://github.com/RadeonOpenCompute/ROCR-Runtime +Maintainer: AMD HSA Support +Recommends: libdrm-amdgpu-amdgpu1 +Replaces: hsa-ext-rocr-dev-rpath6.2.0 +Version: 1.14.0.60200-66~20.04 +Installed-Size: 9478 + +Package: hsa-rocr6.2.0 +Architecture: amd64 +Breaks: hsa-ext-rocr-dev6.2.0 +Depends: libdrm-amdgpu-amdgpu1 | libdrm-amdgpu1, libnuma1, libelf1, rocm-core6.2.0, rocprofiler-register6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hsa-rocr6.2.0/hsa-rocr6.2.0_1.14.0.60200-66~20.04_amd64.deb +Size: 553124 +SHA256: e4940a5d47e9e39d603f18936e7921c603fd8dde0e359e0be796f9c1cdacd431 +SHA1: 3b3ecca863e44efee1370ede6aa8629dad7997f0 +MD5sum: 328a9e8be6a5a0496565457b56ab4594 +Description: AMD Heterogeneous System Architecture HSA - Linux HSA Runtime for Boltzmann (ROCm) platforms +Homepage: https://github.com/RadeonOpenCompute/ROCR-Runtime +Maintainer: AMD HSA Support +Recommends: libdrm-amdgpu-amdgpu1 +Replaces: hsa-ext-rocr-dev6.2.0 +Version: 1.14.0.60200-66~20.04 +Installed-Size: 9478 + +Package: hsakmt-roct-asan +Architecture: amd64 +Depends: libdrm-amdgpu-dev | libdrm-dev, rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/h/hsakmt-roct-asan/hsakmt-roct-asan_20240607.3.8.60200-66~20.04_amd64.deb +Size: 447530 +SHA256: d88bbaa8265b16f68c4b5060248c361a695e1c7eac96efbfd24f00b6b3f7bf05 +SHA1: 89a4e0834b9ac8b959746ab4092424e38b7412b1 +MD5sum: fe26078fabf973e8c3039ac21b8d51d3 +Description: ASAN libraries for the LIBHSAKMT +Homepage: https://github.com/ROCm/ROCT-Thunk-Interface +Maintainer: AMD GFX mailing list +Provides: hsakmt-roct +Recommends: libdrm-amdgpu-dev +Replaces: hsakmt-roct +Version: 20240607.3.8.60200-66~20.04 +Installed-Size: 1502 + +Package: hsakmt-roct-asan-rpath6.2.0 +Architecture: amd64 +Depends: libdrm-amdgpu-dev | libdrm-dev, rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hsakmt-roct-asan-rpath6.2.0/hsakmt-roct-asan-rpath6.2.0_20240607.3.8.60200-66~20.04_amd64.deb +Size: 300244 +SHA256: f1fe8018429a68e049afc0e51da6b96f286bb0fab2cbdddb73a928d2a50fc8a8 +SHA1: 5c88a75ac567a271590986c6cdddf2c66a945ea6 +MD5sum: 1f4cc6fe72e8cd1208bfc485a686f349 +Description: ASAN libraries for the LIBHSAKMT +Homepage: https://github.com/ROCm/ROCT-Thunk-Interface +Maintainer: AMD GFX mailing list +Provides: hsakmt-roct-rpath6.2.0 +Recommends: libdrm-amdgpu-dev +Replaces: hsakmt-roct-rpath6.2.0 +Version: 20240607.3.8.60200-66~20.04 +Installed-Size: 1502 + +Package: hsakmt-roct-asan6.2.0 +Architecture: amd64 +Depends: libdrm-amdgpu-dev | libdrm-dev, rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hsakmt-roct-asan6.2.0/hsakmt-roct-asan6.2.0_20240607.3.8.60200-66~20.04_amd64.deb +Size: 300232 +SHA256: 7ff0c203f70305b6b7394849a2f9ca828f55e1e78a0cb81d12afb49115bf51ce +SHA1: 8141864921c763f229e14d88240667bb78ff61ab +MD5sum: c61a5ef3f189661f58bc8426993f9d63 +Description: ASAN libraries for the LIBHSAKMT +Homepage: https://github.com/ROCm/ROCT-Thunk-Interface +Maintainer: AMD GFX mailing list +Provides: hsakmt-roct6.2.0 +Recommends: libdrm-amdgpu-dev +Replaces: hsakmt-roct6.2.0 +Version: 20240607.3.8.60200-66~20.04 +Installed-Size: 1502 + +Package: hsakmt-roct-dev +Architecture: amd64 +Depends: libdrm-amdgpu-dev | libdrm-dev, rocm-core +Priority: optional +Section: devel +Filename: pool/main/h/hsakmt-roct-dev/hsakmt-roct-dev_20240607.3.8.60200-66~20.04_amd64.deb +Size: 782218 +SHA256: 3d54c51e64bddf350f23be1e2cf8d82f0ebe2decaf9ca4c75628a9411f0580d1 +SHA1: ad22ce58d54647289d96787ed60ab4d4e6aa428b +MD5sum: c4ec533b6260dc3a106890ae75ae58f5 +Description: hsakmt built using CMake +Homepage: https://github.com/ROCm/ROCT-Thunk-Interface +Maintainer: AMD GFX mailing list +Provides: hsakmt-roct +Recommends: libdrm-amdgpu-dev +Replaces: hsakmt-roct +Version: 20240607.3.8.60200-66~20.04 +Installed-Size: 2884 + +Package: hsakmt-roct-dev-rpath6.2.0 +Architecture: amd64 +Depends: libdrm-amdgpu-dev | libdrm-dev, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hsakmt-roct-dev-rpath6.2.0/hsakmt-roct-dev-rpath6.2.0_20240607.3.8.60200-66~20.04_amd64.deb +Size: 278428 +SHA256: 2f514eb87e957654a8953e8146050aea9e23ceb8346143db9a05b421a7e62403 +SHA1: 83e6c0aeec64b4358a9157d9850e651c49ad529b +MD5sum: 691a3a7f8ad0437b57e591c6fa48e6af +Description: hsakmt built using CMake +Homepage: https://github.com/ROCm/ROCT-Thunk-Interface +Maintainer: AMD GFX mailing list +Provides: hsakmt-roct-rpath6.2.0 +Recommends: libdrm-amdgpu-dev +Replaces: hsakmt-roct-rpath6.2.0 +Version: 20240607.3.8.60200-66~20.04 +Installed-Size: 2884 + +Package: hsakmt-roct-dev6.2.0 +Architecture: amd64 +Depends: libdrm-amdgpu-dev | libdrm-dev, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/h/hsakmt-roct-dev6.2.0/hsakmt-roct-dev6.2.0_20240607.3.8.60200-66~20.04_amd64.deb +Size: 278112 +SHA256: fb8bcb1216931669a9262a597e6265d70e350c2ff0f9815c063c9135d9917dc0 +SHA1: da167ae60275cd9166300c5c94d721844c681fa0 +MD5sum: ead6b87104f17588b3940ff37833eaac +Description: hsakmt built using CMake +Homepage: https://github.com/ROCm/ROCT-Thunk-Interface +Maintainer: AMD GFX mailing list +Provides: hsakmt-roct6.2.0 +Recommends: libdrm-amdgpu-dev +Replaces: hsakmt-roct6.2.0 +Version: 20240607.3.8.60200-66~20.04 +Installed-Size: 2884 + +Package: migraphx +Architecture: amd64 +Depends: hip-dev, hip-runtime-amd, half, miopen-hip, rocblas, rocm-core +Priority: optional +Section: devel +Filename: pool/main/m/migraphx/migraphx_2.10.0.60200-66~20.04_amd64.deb +Size: 42151978 +SHA256: bd601a1fb9567d60613395b2ee088fecbef48369d21799ffe6c0352a9282c34e +SHA1: 555e822ef8b37503cc9ff525df3db27ee2ab2a4e +MD5sum: cb5987c19c81b6caab3d3fd8f3876e7a +Description: AMD graph optimizer +Maintainer: AMDMIGraphX Maintainer +Recommends: migraphx-dev (>=2.10.0.60200) +Version: 2.10.0.60200-66~20.04 +Installed-Size: 792875 + +Package: migraphx-asan +Architecture: amd64 +Depends: hip-dev, hip-runtime-amd, half, miopen-hip, rocblas, rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/m/migraphx-asan/migraphx-asan_2.10.0.60200-66~20.04_amd64.deb +Size: 85370708 +SHA256: 1ec51eac60e38c8cfa3a2f3c7486e68790e8176f5d75b1b53bcefe205c4ff811 +SHA1: 1d2abb15ef7fbd88f8eda7c50cf91aa41ce44d99 +MD5sum: 14f01c04e952c0aa82f6a6feafbdc8ca +Description: AMD graph optimizer +Maintainer: AMDMIGraphX Maintainer +Recommends: migraphx-asan-dev (>=2.10.0.60200) +Version: 2.10.0.60200-66~20.04 +Installed-Size: 1194723 + +Package: migraphx-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: d83dffefb334458ef607bbabf045c2cef0a92995 dccdb497b6d62c1492142b6f31a55685b5e9cd4f fcb6c6222c75956b040ad9d7ecb8a3dc46ef2c37 3da1df8cb620c8d69a1fd5c6167b7e9311bf82ca f58f51efe9a11fe6afdff2e1bb9ee506bea46b24 fa85cf540292d02396484433b7745585b2b73d99 bb9eec1b22287e3b7d8961d8fd9ac6e197560be2 fe45d72dc050db5880ef6e411cec28b9d48a7bbb 29e16f1ea31aaa595363094c96bebf2175b8baf4 870ce1e6975006e8cafee52a015924402a5f0b66 08ed9bbb04d0ce7eaef788fc345f98c901de4cc7 +Depends: migraphx-asan (= 2.10.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/m/migraphx-asan-dbgsym/migraphx-asan-dbgsym_2.10.0.60200-66~20.04_amd64.deb +Size: 690171182 +SHA256: f0fccc62bd2840f0e6469e5a3888d84057e6e5ff932fe18056e8a7fdb8eda9f2 +SHA1: 6b4294e6d96a801cceeea12d82d6696bc8db4893 +MD5sum: c7b64205ffdac2eb6e1395ec719d4f40 +Description: debug symbols for migraphx-asan +Maintainer: AMDMIGraphX Maintainer +Package-Type: ddeb +Version: 2.10.0.60200-66~20.04 +Installed-Size: 779261 + +Package: migraphx-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: d83dffefb334458ef607bbabf045c2cef0a92995 dccdb497b6d62c1492142b6f31a55685b5e9cd4f fcb6c6222c75956b040ad9d7ecb8a3dc46ef2c37 3da1df8cb620c8d69a1fd5c6167b7e9311bf82ca f58f51efe9a11fe6afdff2e1bb9ee506bea46b24 fa85cf540292d02396484433b7745585b2b73d99 bb9eec1b22287e3b7d8961d8fd9ac6e197560be2 fe45d72dc050db5880ef6e411cec28b9d48a7bbb 29e16f1ea31aaa595363094c96bebf2175b8baf4 870ce1e6975006e8cafee52a015924402a5f0b66 08ed9bbb04d0ce7eaef788fc345f98c901de4cc7 +Depends: migraphx-asan-rpath6.2.0 (= 2.10.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/m/migraphx-asan-dbgsym-rpath6.2.0/migraphx-asan-dbgsym-rpath6.2.0_2.10.0.60200-66~20.04_amd64.deb +Size: 690153004 +SHA256: 6e74ebe99ea1c28df91ac13f081bbe14d9ddccb1ba67fdf393bd026f9d6aa00d +SHA1: c09619c758b05a79a21a5169622dfb95e18b0824 +MD5sum: 7332a8f72e2c510bc77a1d9cb86c0797 +Description: debug symbols for migraphx-asan +Maintainer: AMDMIGraphX Maintainer +Package-Type: ddeb +Version: 2.10.0.60200-66~20.04 +Installed-Size: 779261 + +Package: migraphx-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: d83dffefb334458ef607bbabf045c2cef0a92995 dccdb497b6d62c1492142b6f31a55685b5e9cd4f fcb6c6222c75956b040ad9d7ecb8a3dc46ef2c37 3da1df8cb620c8d69a1fd5c6167b7e9311bf82ca f58f51efe9a11fe6afdff2e1bb9ee506bea46b24 fa85cf540292d02396484433b7745585b2b73d99 bb9eec1b22287e3b7d8961d8fd9ac6e197560be2 fe45d72dc050db5880ef6e411cec28b9d48a7bbb 29e16f1ea31aaa595363094c96bebf2175b8baf4 870ce1e6975006e8cafee52a015924402a5f0b66 08ed9bbb04d0ce7eaef788fc345f98c901de4cc7 +Depends: migraphx-asan6.2.0 (= 2.10.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/m/migraphx-asan-dbgsym6.2.0/migraphx-asan-dbgsym6.2.0_2.10.0.60200-66~20.04_amd64.deb +Size: 690152996 +SHA256: f51a5780677503d2bc9b696d343122025d9027ba70b99beb8133b6007b6cec28 +SHA1: e26e3daccf646374a6087f1080cd5d7c6f29df6e +MD5sum: 4f056472c35d84e2151f324ac958ca7c +Description: debug symbols for migraphx-asan +Maintainer: AMDMIGraphX Maintainer +Package-Type: ddeb +Version: 2.10.0.60200-66~20.04 +Installed-Size: 779261 + +Package: migraphx-asan-rpath6.2.0 +Architecture: amd64 +Depends: hip-dev-rpath6.2.0, hip-runtime-amd-rpath6.2.0, half-rpath6.2.0, miopen-hip-rpath6.2.0, rocblas-rpath6.2.0, rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/migraphx-asan-rpath6.2.0/migraphx-asan-rpath6.2.0_2.10.0.60200-66~20.04_amd64.deb +Size: 85045136 +SHA256: 8ae165f438f772430550d07d0628105fc57d55a16dfbc1c48316c654d3bd068e +SHA1: fd6f607d657d5f82a3e2c2f6f05399235849bd49 +MD5sum: 1d931093cd7de6e886e603fd83d723bf +Description: AMD graph optimizer +Maintainer: AMDMIGraphX Maintainer +Recommends: migraphx-asan-dev (>=2.10.0.60200) +Version: 2.10.0.60200-66~20.04 +Installed-Size: 1194723 + +Package: migraphx-asan6.2.0 +Architecture: amd64 +Depends: hip-dev6.2.0, hip-runtime-amd6.2.0, half6.2.0, miopen-hip6.2.0, rocblas6.2.0, rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/migraphx-asan6.2.0/migraphx-asan6.2.0_2.10.0.60200-66~20.04_amd64.deb +Size: 85042588 +SHA256: c34957eec964f2693cabec6c38ae89fbf340d19d4ca48a195e2519997fc28d37 +SHA1: a15ee20848ab84a91ad30e5d542fd069572f6fab +MD5sum: 600ccb89faba12f5bae8a0fa2acc4158 +Description: AMD graph optimizer +Maintainer: AMDMIGraphX Maintainer +Recommends: migraphx-asan-dev (>=2.10.0.60200) +Version: 2.10.0.60200-66~20.04 +Installed-Size: 1194723 + +Package: migraphx-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: cfd4134d798fd88be51d9356b696dfde183c2090 8e1771bd22eb916b23f4d3c228f59d0bcd7e0e39 6716a1ba47d0a5074413d7aaea1f80d9c469970d f17428a35a712ca9f97c899f325fb70be5ef04f2 8c5810558b3b95b94e83bd60708f3507457b1f6f 2fdbb5f592aa246ba302d10753219d75d6a40c1d bf5fd652d363fee374f3d535c665ad4d7c009c5c bedb1b4967c22f28fb79427e9387d1caf4718cbb f688828f8fbcd1e7e4afd870d374c8dfcc024b6e 9b74a708cd38a1dde1eea436f72d87fcefe06e5a 7aecf176a757bd779b225052127a46a57a11f0b9 +Depends: migraphx (= 2.10.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/m/migraphx-dbgsym/migraphx-dbgsym_2.10.0.60200-66~20.04_amd64.deb +Size: 64875396 +SHA256: 9383df8f2f6f2026c0e0edae7fe80a7a348fd5560982fe3dd5f08d2bfea436d7 +SHA1: d74d3bea16d8719b97a183af604c549180a558f5 +MD5sum: 6494fe0a2e2ceb8f94aff6f6169fc776 +Description: debug symbols for migraphx +Maintainer: AMDMIGraphX Maintainer +Package-Type: ddeb +Version: 2.10.0.60200-66~20.04 +Installed-Size: 495335 + +Package: migraphx-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: cfd4134d798fd88be51d9356b696dfde183c2090 8e1771bd22eb916b23f4d3c228f59d0bcd7e0e39 6716a1ba47d0a5074413d7aaea1f80d9c469970d f17428a35a712ca9f97c899f325fb70be5ef04f2 8c5810558b3b95b94e83bd60708f3507457b1f6f 2fdbb5f592aa246ba302d10753219d75d6a40c1d bf5fd652d363fee374f3d535c665ad4d7c009c5c bedb1b4967c22f28fb79427e9387d1caf4718cbb f688828f8fbcd1e7e4afd870d374c8dfcc024b6e 9b74a708cd38a1dde1eea436f72d87fcefe06e5a 7aecf176a757bd779b225052127a46a57a11f0b9 +Depends: migraphx-rpath6.2.0 (= 2.10.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/m/migraphx-dbgsym-rpath6.2.0/migraphx-dbgsym-rpath6.2.0_2.10.0.60200-66~20.04_amd64.deb +Size: 64870188 +SHA256: 30e8312af063bd4fa392f07640e5f56956cfa22dfb8296fd0011c7b9612bbdf4 +SHA1: a588a5d6b79b8f475f1d1e753a98b1965a431afe +MD5sum: 72cd387b9d14f43f24f77d02ce34a4af +Description: debug symbols for migraphx +Maintainer: AMDMIGraphX Maintainer +Package-Type: ddeb +Version: 2.10.0.60200-66~20.04 +Installed-Size: 495335 + +Package: migraphx-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: cfd4134d798fd88be51d9356b696dfde183c2090 8e1771bd22eb916b23f4d3c228f59d0bcd7e0e39 6716a1ba47d0a5074413d7aaea1f80d9c469970d f17428a35a712ca9f97c899f325fb70be5ef04f2 8c5810558b3b95b94e83bd60708f3507457b1f6f 2fdbb5f592aa246ba302d10753219d75d6a40c1d bf5fd652d363fee374f3d535c665ad4d7c009c5c bedb1b4967c22f28fb79427e9387d1caf4718cbb f688828f8fbcd1e7e4afd870d374c8dfcc024b6e 9b74a708cd38a1dde1eea436f72d87fcefe06e5a 7aecf176a757bd779b225052127a46a57a11f0b9 +Depends: migraphx6.2.0 (= 2.10.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/m/migraphx-dbgsym6.2.0/migraphx-dbgsym6.2.0_2.10.0.60200-66~20.04_amd64.deb +Size: 64874684 +SHA256: 09a937bbc4f064ecd270d9bf45f9d5b74a7fbaa7b1f24d82582b6cbc2400d381 +SHA1: f9d9ad59ed45f15b8f404c6bb262489eba5c9ca8 +MD5sum: 1fdf3414b0e506c3412ea50d992cb712 +Description: debug symbols for migraphx +Maintainer: AMDMIGraphX Maintainer +Package-Type: ddeb +Version: 2.10.0.60200-66~20.04 +Installed-Size: 495335 + +Package: migraphx-dev +Architecture: amd64 +Depends: migraphx (>= 2.10.0.60200) +Priority: optional +Section: devel +Filename: pool/main/m/migraphx-dev/migraphx-dev_2.10.0.60200-66~20.04_amd64.deb +Size: 158166 +SHA256: e0978025acdc15eee3c7a9a4f8e3d20f5f164fc6005f097f8482a772ad61ff61 +SHA1: 16397eff2299f4639a4e5d9bc40ee02a3ff8d7cc +MD5sum: f4870c1153809407061c58214e44d883 +Description: AMD graph optimizer +Maintainer: AMDMIGraphX Maintainer +Version: 2.10.0.60200-66~20.04 +Installed-Size: 1555 + +Package: migraphx-dev-rpath6.2.0 +Architecture: amd64 +Depends: migraphx-rpath6.2.0 (>= 2.10.0.60200) +Priority: optional +Section: devel +Filename: pool/main/m/migraphx-dev-rpath6.2.0/migraphx-dev-rpath6.2.0_2.10.0.60200-66~20.04_amd64.deb +Size: 156788 +SHA256: 9144042c3f3cf9032a6a9674e3a940a60ef51fe3d5474501550ffc89deaadf9f +SHA1: cb88921a4baf2052e92ab08f9f39a19b682fe7df +MD5sum: 634d8c66cf598e3614bdcd677a775129 +Description: AMD graph optimizer +Maintainer: AMDMIGraphX Maintainer +Version: 2.10.0.60200-66~20.04 +Installed-Size: 1555 + +Package: migraphx-dev6.2.0 +Architecture: amd64 +Depends: migraphx6.2.0 (>= 2.10.0.60200) +Priority: optional +Section: devel +Filename: pool/main/m/migraphx-dev6.2.0/migraphx-dev6.2.0_2.10.0.60200-66~20.04_amd64.deb +Size: 156824 +SHA256: 3d1ba2e8ed4963e9a25bb7fa82640a944507b9ffc37bd9dee51b01e9cfe4a4e3 +SHA1: 8490624c4a3b094ac1f1c3171317d9343c6609d3 +MD5sum: 671a992c63d37488d0d0f1845ea55af2 +Description: AMD graph optimizer +Maintainer: AMDMIGraphX Maintainer +Version: 2.10.0.60200-66~20.04 +Installed-Size: 1555 + +Package: migraphx-rpath6.2.0 +Architecture: amd64 +Depends: hip-dev-rpath6.2.0, hip-runtime-amd-rpath6.2.0, half-rpath6.2.0, miopen-hip-rpath6.2.0, rocblas-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/migraphx-rpath6.2.0/migraphx-rpath6.2.0_2.10.0.60200-66~20.04_amd64.deb +Size: 42234304 +SHA256: be2af3646eadcb3f26011c21834588e52cc81007865f929a67ca0ecd1b94956a +SHA1: f9951843e978c1fdb88f463e3c17789087416025 +MD5sum: 768a56fe843094cb7fb602a5d50f4697 +Description: AMD graph optimizer +Maintainer: AMDMIGraphX Maintainer +Recommends: migraphx-dev-rpath6.2.0 (>=2.10.0.60200) +Version: 2.10.0.60200-66~20.04 +Installed-Size: 792875 + +Package: migraphx6.2.0 +Architecture: amd64 +Depends: hip-dev6.2.0, hip-runtime-amd6.2.0, half6.2.0, miopen-hip6.2.0, rocblas6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/migraphx6.2.0/migraphx6.2.0_2.10.0.60200-66~20.04_amd64.deb +Size: 42243568 +SHA256: 6975786b3fed397403d53de8264218ab2a3478c40605e341d703a0da30e0c9db +SHA1: d6db5ac4222d46c632d8c0054e274331273f135e +MD5sum: b01d7a51ac03111bf9b683a9c9c6829d +Description: AMD graph optimizer +Maintainer: AMDMIGraphX Maintainer +Recommends: migraphx-dev6.2.0 (>=2.10.0.60200) +Version: 2.10.0.60200-66~20.04 +Installed-Size: 792875 + +Package: miopen-hip +Architecture: amd64 +Conflicts: miopen-opencl +Depends: hip-runtime-amd, comgr, roctracer, rocblas, rocm-core, rocrand, rocm-core +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip/miopen-hip_3.2.0.60200-66~20.04_amd64.deb +Size: 115249340 +SHA256: e3c8c3656a18610db9729ce3aa9db7a8802889befbe76cab878fdd7f4c9148fa +SHA1: 410cc471afce4e63fd56016659ad3c82d68b3a10 +MD5sum: e5b2885baa9e9d348cfd8f40afbaee1c +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Recommends: miopen-hip-dev (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 3372775 + +Package: miopen-hip-asan +Architecture: amd64 +Conflicts: miopen-opencl +Depends: hip-runtime-amd-asan, comgr, roctracer, rocblas, rocm-core, rocrand, rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-asan/miopen-hip-asan_3.2.0.60200-66~20.04_amd64.deb +Size: 78787918 +SHA256: 5018fbefd858698e76d9b33ec8032d6d3db131ec5125740d1c3afd2153b6db3d +SHA1: e9e9a0873855cf57b8c3504f9881627ff55d624c +MD5sum: 46294ac40b883cf5a7df1605ddf01289 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Recommends: miopen-hip-asan-dev (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 3039992 + +Package: miopen-hip-asan-rpath6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl-rpath6.2.0 +Depends: hip-runtime-amd-asan-rpath6.2.0, comgr-rpath6.2.0, roctracer-rpath6.2.0, rocblas-rpath6.2.0, rocm-core-rpath6.2.0, rocrand-rpath6.2.0, rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-asan-rpath6.2.0/miopen-hip-asan-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 78772608 +SHA256: 1203605ae648df0bfdd9066e50e2be20d88830d204f398ce3e1693fbc94fd3d9 +SHA1: 983292bcb770dc7629ac8dffd3650e10507ee420 +MD5sum: 76838e8ee6c75505938d1582423b86df +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Recommends: miopen-hip-asan-dev (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 3039992 + +Package: miopen-hip-asan6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl6.2.0 +Depends: hip-runtime-amd-asan6.2.0, comgr6.2.0, roctracer6.2.0, rocblas6.2.0, rocm-core6.2.0, rocrand6.2.0, rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-asan6.2.0/miopen-hip-asan6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 78784068 +SHA256: 6340c3e9b63267b332f9a33b8de6ce3e8633b1e91173ce208d7c5e0a0359ea3d +SHA1: 07be8430f5ef158eb36eb5d3b65b17c04b4749e5 +MD5sum: ed064aa9b4bf6f0f81090c7529bba0ce +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Recommends: miopen-hip-asan-dev (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 3039992 + +Package: miopen-hip-client +Architecture: amd64 +Conflicts: miopen-opencl +Depends: hip-runtime-amd, comgr, roctracer, rocblas, rocm-core, rocrand, rocm-core +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-client/miopen-hip-client_3.2.0.60200-66~20.04_amd64.deb +Size: 742 +SHA256: 5a26f3aec648caf0795749507837cb64acc3e9ee3478b3e527b340d1891e81ed +SHA1: a098238807fe07840969b40fc1676759c8ffa782 +MD5sum: 58593453d935875f62e8ceffab1ef2ba +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 8 + +Package: miopen-hip-client-rpath6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl-rpath6.2.0 +Depends: hip-runtime-amd-rpath6.2.0, comgr-rpath6.2.0, roctracer-rpath6.2.0, rocblas-rpath6.2.0, rocm-core-rpath6.2.0, rocrand-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-client-rpath6.2.0/miopen-hip-client-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 908 +SHA256: 8eac816e8e083daa7e28bb9800d7a2853c08a4eb48a239a142672c0779543cbf +SHA1: 4aa532259bcfa5ec301f4c309e4fc5b4cbea0532 +MD5sum: 17e8c8c2914aa2d31e6f058ea666f347 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 8 + +Package: miopen-hip-client6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl6.2.0 +Depends: hip-runtime-amd6.2.0, comgr6.2.0, roctracer6.2.0, rocblas6.2.0, rocm-core6.2.0, rocrand6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-client6.2.0/miopen-hip-client6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 900 +SHA256: 09425b361ddfdbe57ebe12f9073697800a9ed550524854ed2a9def997b031e55 +SHA1: 6c47ffd53d96ebd0a49ef55b492b252285092947 +MD5sum: bc7bba9954ae0043e41e24aa7dba54ad +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 8 + +Package: miopen-hip-dev +Architecture: amd64 +Conflicts: miopen-opencl +Depends: miopen-hip (>= 3.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-dev/miopen-hip-dev_3.2.0.60200-66~20.04_amd64.deb +Size: 44116 +SHA256: 77c9d26c4f0053b71fb86f7a6b489655e27053f9605efca3a16344ccf286e313 +SHA1: 5436b1a35326534eafacbb95f0bd05a6412ab460 +MD5sum: b2a599f11e7b71c62928a71e48be4a53 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 409 + +Package: miopen-hip-dev-rpath6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl-rpath6.2.0 +Depends: miopen-hip-rpath6.2.0 (>= 3.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-dev-rpath6.2.0/miopen-hip-dev-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 44280 +SHA256: e406144dcc88b83bb63cbad89ba5a188bfbbfebb45842fa997053674740e69d1 +SHA1: b6a1aa34a63cec8624358370465eac8ab794964d +MD5sum: 8c3e5d51d8dc353ceee339ef475bb918 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 409 + +Package: miopen-hip-dev6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl6.2.0 +Depends: miopen-hip6.2.0 (>= 3.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-dev6.2.0/miopen-hip-dev6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 44244 +SHA256: 6b7329cbabd04b8d312887b76fd5615d33b637cab08947b338019f71edec3b5c +SHA1: 32bc1d1aa5804c9d6f726ab7660f2e84178412d4 +MD5sum: 3a01f8d2453ba68e87b629b24b971955 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 409 + +Package: miopen-hip-gfx1030kdb +Architecture: amd64 +Conflicts: miopen-opencl +Depends: hip-runtime-amd, comgr, roctracer, rocblas, rocm-core, rocrand, rocm-core +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-gfx1030kdb/miopen-hip-gfx1030kdb_3.2.0.60200-66~20.04_amd64.deb +Size: 390901264 +SHA256: 3024629318163d38c79bed5cbf54797849d31a1228e54799c5a0632c5ba9ef6c +SHA1: 6e5499007c27faf5f63e3fd64f1b01db3fafd95f +MD5sum: e7c7568a357c09673806b1c14630b7e4 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 727956 + +Package: miopen-hip-gfx1030kdb-rpath6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl-rpath6.2.0 +Depends: hip-runtime-amd-rpath6.2.0, comgr-rpath6.2.0, roctracer-rpath6.2.0, rocblas-rpath6.2.0, rocm-core-rpath6.2.0, rocrand-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-gfx1030kdb-rpath6.2.0/miopen-hip-gfx1030kdb-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 390902872 +SHA256: de63c05afbbd6201fb8d543e2c9a807345ffcb7a13bdc14c83da6cd04b0473a8 +SHA1: f1575b12042cb27a5e256b206a97b77f1d5b9f6b +MD5sum: cd71d127fb85f2ca69ef5f79f7037b16 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 727956 + +Package: miopen-hip-gfx1030kdb6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl6.2.0 +Depends: hip-runtime-amd6.2.0, comgr6.2.0, roctracer6.2.0, rocblas6.2.0, rocm-core6.2.0, rocrand6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-gfx1030kdb6.2.0/miopen-hip-gfx1030kdb6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 390902864 +SHA256: 9196e2f2d9f63c0fe635efbaa7fb602cef7ad91d83c25428dcf050706305bc71 +SHA1: 55c90e27017819497a3108a44944ac6b3649093b +MD5sum: dd50952dd8043a723e1018c573fa7a34 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 727956 + +Package: miopen-hip-gfx900kdb +Architecture: amd64 +Conflicts: miopen-opencl +Depends: hip-runtime-amd, comgr, roctracer, rocblas, rocm-core, rocrand, rocm-core +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-gfx900kdb/miopen-hip-gfx900kdb_3.2.0.60200-66~20.04_amd64.deb +Size: 272266618 +SHA256: 6ce6fd60680906cdfd9a374f9bdf352a89e5b32b14fd1113f9242e07e9a99a96 +SHA1: c027d4b5ddbfd96013a93fc62712e3d73c807135 +MD5sum: ba8c1ffea3abce022cc93a8d392100e9 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 518104 + +Package: miopen-hip-gfx900kdb-rpath6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl-rpath6.2.0 +Depends: hip-runtime-amd-rpath6.2.0, comgr-rpath6.2.0, roctracer-rpath6.2.0, rocblas-rpath6.2.0, rocm-core-rpath6.2.0, rocrand-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-gfx900kdb-rpath6.2.0/miopen-hip-gfx900kdb-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 272266000 +SHA256: f59a6afac60efecf852895f56a3c3d2a8cf946eda81f4e93034abdb7a6537b89 +SHA1: 91bc0d94cd1d188b140c7cd9415fafad6d2012a5 +MD5sum: 88ed3e8af85178b148219f8a9f189c15 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 518104 + +Package: miopen-hip-gfx900kdb6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl6.2.0 +Depends: hip-runtime-amd6.2.0, comgr6.2.0, roctracer6.2.0, rocblas6.2.0, rocm-core6.2.0, rocrand6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-gfx900kdb6.2.0/miopen-hip-gfx900kdb6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 272265492 +SHA256: af1f8e4aafd5526702d1126f1ef53036ff5b50f55de38c8b2d5c56c333e47ec1 +SHA1: c2356c18bb336d00d47cba6b861b221191b12c6d +MD5sum: c4c246a3b51b1247a19bf88c341f0e2e +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 518104 + +Package: miopen-hip-gfx906kdb +Architecture: amd64 +Conflicts: miopen-opencl +Depends: hip-runtime-amd, comgr, roctracer, rocblas, rocm-core, rocrand, rocm-core +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-gfx906kdb/miopen-hip-gfx906kdb_3.2.0.60200-66~20.04_amd64.deb +Size: 321529376 +SHA256: 40135ec212e0f0ee8d6ad5f7ce173452f38a6b339e476fc878b42b53ab7abada +SHA1: 1bde974b46ae52376fa9a98d2a085b9a1ea278a9 +MD5sum: 699b2b5227668d93900c629caf4d1b29 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 608416 + +Package: miopen-hip-gfx906kdb-rpath6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl-rpath6.2.0 +Depends: hip-runtime-amd-rpath6.2.0, comgr-rpath6.2.0, roctracer-rpath6.2.0, rocblas-rpath6.2.0, rocm-core-rpath6.2.0, rocrand-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-gfx906kdb-rpath6.2.0/miopen-hip-gfx906kdb-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 321529912 +SHA256: 7c57d283be1dbff5991bbb1a56a4a52a8e02f9c44c2eba4e78305d64e8893dfa +SHA1: 70164449b941c3fda4ef406b4091297fc22e4ab7 +MD5sum: 742fb0f7f34186cd7a01fb2e8a2c80e1 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 608416 + +Package: miopen-hip-gfx906kdb6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl6.2.0 +Depends: hip-runtime-amd6.2.0, comgr6.2.0, roctracer6.2.0, rocblas6.2.0, rocm-core6.2.0, rocrand6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-gfx906kdb6.2.0/miopen-hip-gfx906kdb6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 321530372 +SHA256: 9c2f5a5c094db89f0f60a17baecf4be93578c10ba38ff751a037d048b0876f18 +SHA1: 8e3fb60f15a871cfb66ac40a58bf7100b2f91146 +MD5sum: d77584e9727a1d322500f8153135ef90 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 608416 + +Package: miopen-hip-gfx908kdb +Architecture: amd64 +Conflicts: miopen-opencl +Depends: hip-runtime-amd, comgr, roctracer, rocblas, rocm-core, rocrand, rocm-core +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-gfx908kdb/miopen-hip-gfx908kdb_3.2.0.60200-66~20.04_amd64.deb +Size: 241882726 +SHA256: 63fa5871b13eb2511668907e7b270f0c1c5ca2b3fa644e3797adcff33fc1ddb9 +SHA1: 5a509dc4037f02927b507ad9026d99561457c7cc +MD5sum: 0da41af24aa8e1658f8a096471ed5904 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 629992 + +Package: miopen-hip-gfx908kdb-rpath6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl-rpath6.2.0 +Depends: hip-runtime-amd-rpath6.2.0, comgr-rpath6.2.0, roctracer-rpath6.2.0, rocblas-rpath6.2.0, rocm-core-rpath6.2.0, rocrand-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-gfx908kdb-rpath6.2.0/miopen-hip-gfx908kdb-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 241884244 +SHA256: 585c0bba6c4e39d20a43ac6179f0fa5955abad18b27030f2bc1b5211befa2f40 +SHA1: 55ca953289f6fba837ce1256fd60c38c75ca440a +MD5sum: d18c4749b16d74c6bbf911275a183d13 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 629992 + +Package: miopen-hip-gfx908kdb6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl6.2.0 +Depends: hip-runtime-amd6.2.0, comgr6.2.0, roctracer6.2.0, rocblas6.2.0, rocm-core6.2.0, rocrand6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-gfx908kdb6.2.0/miopen-hip-gfx908kdb6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 241883764 +SHA256: 64227285b7b0aec0deaebcc2b19bf753fa98dc9e1ee45bc50344ec8113e30a26 +SHA1: 1594a3fa325c1a5a3f3bd74cbe107b5858912c98 +MD5sum: 94b698460cb3c4b4ffbb3176770b21df +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 629992 + +Package: miopen-hip-gfx90akdb +Architecture: amd64 +Conflicts: miopen-opencl +Depends: hip-runtime-amd, comgr, roctracer, rocblas, rocm-core, rocrand, rocm-core +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-gfx90akdb/miopen-hip-gfx90akdb_3.2.0.60200-66~20.04_amd64.deb +Size: 134607178 +SHA256: aacf1af7a452121f029707581a5398a1c74c3483418ac315dfedad7c5a598ab5 +SHA1: b2a7212464cb8cc2cbdaefb383ead88a78e5875b +MD5sum: 9affa1659fb194ce2d6dcc37cd4bc969 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 342828 + +Package: miopen-hip-gfx90akdb-rpath6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl-rpath6.2.0 +Depends: hip-runtime-amd-rpath6.2.0, comgr-rpath6.2.0, roctracer-rpath6.2.0, rocblas-rpath6.2.0, rocm-core-rpath6.2.0, rocrand-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-gfx90akdb-rpath6.2.0/miopen-hip-gfx90akdb-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 134605196 +SHA256: 733acb6008c2fc6dcb29e1bde4f9ff02a9872ba0ed1a1988de0fd9974ca23218 +SHA1: 06279ce18a7c3f55cff641a6a6c0337b6c2c7b7c +MD5sum: c259df402a093f54a6a3484187e22191 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 342828 + +Package: miopen-hip-gfx90akdb6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl6.2.0 +Depends: hip-runtime-amd6.2.0, comgr6.2.0, roctracer6.2.0, rocblas6.2.0, rocm-core6.2.0, rocrand6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-gfx90akdb6.2.0/miopen-hip-gfx90akdb6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 134605344 +SHA256: a21ebe4b7366c1fa141fd7abb8195d1b8eeac00b69f01085a4991fef59293117 +SHA1: 2d71d426089c8b60de94966b37e6b8c141330334 +MD5sum: d340ba8f14d4a91ad17cd918c22ab5eb +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 342828 + +Package: miopen-hip-rpath6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl-rpath6.2.0 +Depends: hip-runtime-amd-rpath6.2.0, comgr-rpath6.2.0, roctracer-rpath6.2.0, rocblas-rpath6.2.0, rocm-core-rpath6.2.0, rocrand-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip-rpath6.2.0/miopen-hip-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 115266104 +SHA256: d52f9ca4daf4f32ee7e878455f780c51b88e1f16c90702e4f3f80226a5a6e5ca +SHA1: 0af3025d597420e3545a6d6c38d86ccd76a9f191 +MD5sum: 7e4115a1430bf73958f96e1193b9430e +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Recommends: miopen-hip-dev-rpath6.2.0 (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 3372775 + +Package: miopen-hip6.2.0 +Architecture: amd64 +Conflicts: miopen-opencl6.2.0 +Depends: hip-runtime-amd6.2.0, comgr6.2.0, roctracer6.2.0, rocblas6.2.0, rocm-core6.2.0, rocrand6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/miopen-hip6.2.0/miopen-hip6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 115258592 +SHA256: 638a28c5407c3af7d16e1b0179b7494b0aeb36c314114af148b1bcd52e883db1 +SHA1: a163eff172547604470a3c908373b4167633c4d4 +MD5sum: f54d690736fe703d1a1eda81532d5fe0 +Description: AMD DNN Library +Maintainer: MIOpen Maintainer +Recommends: miopen-hip-dev6.2.0 (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 3372775 + +Package: mivisionx +Architecture: amd64 +Depends: rocm-core, rocm-hip-runtime, half, rpp, rocblas, miopen-hip, migraphx, rocdecode +Priority: optional +Section: devel +Filename: pool/main/m/mivisionx/mivisionx_3.0.0.60200-66~20.04_amd64.deb +Size: 43551050 +SHA256: 5253190503d6f26a681b410dcc6e17303e47622d9ef1f4e34f55fd77501c81a3 +SHA1: fd6e1e10ca262fade978a5da3c2baee4e5b19d36 +MD5sum: 19fbd4cff72da3b42246cb06f7ae1e91 +Description: AMD MIVisionX is a comprehensive Computer Vision and ML Inference Toolkit. MIVisionX runtime package provides MIVisionX libraries and license.txt +Homepage: https://github.com/ROCm/MIVisionX +Maintainer: MIVisionX Support +Version: 3.0.0.60200-66~20.04 +Installed-Size: 265857 + +Package: mivisionx-asan +Architecture: amd64 +Depends: rocm-core-asan, rocm-hip-runtime, half, rpp, rocblas, miopen-hip, migraphx, rocdecode +Priority: optional +Section: devel +Filename: pool/main/m/mivisionx-asan/mivisionx-asan_3.0.0.60200-66~20.04_amd64.deb +Size: 40756380 +SHA256: 5a061916c5c07061057c792e810de0ef38c9ce12f9f8d19a8eb1d6c6355a6906 +SHA1: 376baa1258294d59ee25c84cf1b05345fddd8848 +MD5sum: 835296b748f558797da600c5fa35f8dc +Description: AMD MIVisionX is a comprehensive Computer Vision and ML Inference Toolkit. MIVisionX ASAN package provides MIVisionX ASAN libraries +Homepage: https://github.com/ROCm/MIVisionX +Maintainer: MIVisionX Support +Version: 3.0.0.60200-66~20.04 +Installed-Size: 281386 + +Package: mivisionx-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 4a8a1b72e0c664211323af56b024c9323522abe3 19fe207dab4e46b9b14f6e94895140d5ad99dc90 4f0dc4c51b527f60b07b5c8f82639b57b5e82c08 6fac15bab31088481ecf9afc65c4df04d2af4ff3 e839af650e106514c9145b8049b7b18d2934c713 954b5b8065e4964e1d733e282b7eeb3fe03f5bc8 723594f7fc1c767c3032f278680997d3ff72585d 2b6ab9f7385e0a0896ad6fc71f56309e961d9fe6 +Depends: mivisionx-asan (= 3.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/m/mivisionx-asan-dbgsym/mivisionx-asan-dbgsym_3.0.0.60200-66~20.04_amd64.deb +Size: 7337006 +SHA256: 7d0446fbf27e396cfdfe3e7c9d1e985753e4dafeec302acffe6f4d8fab05b49c +SHA1: 8fb14d86a19f8d6d49acb3f770cf8ea39e5be88d +MD5sum: 6920b273681f3d1f69125ca4eaf62f15 +Description: debug symbols for mivisionx-asan +Maintainer: MIVisionX Support +Package-Type: ddeb +Version: 3.0.0.60200-66~20.04 +Installed-Size: 8486 + +Package: mivisionx-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 4a8a1b72e0c664211323af56b024c9323522abe3 19fe207dab4e46b9b14f6e94895140d5ad99dc90 4f0dc4c51b527f60b07b5c8f82639b57b5e82c08 6fac15bab31088481ecf9afc65c4df04d2af4ff3 e839af650e106514c9145b8049b7b18d2934c713 954b5b8065e4964e1d733e282b7eeb3fe03f5bc8 723594f7fc1c767c3032f278680997d3ff72585d 2b6ab9f7385e0a0896ad6fc71f56309e961d9fe6 +Depends: mivisionx-asan-rpath6.2.0 (= 3.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/m/mivisionx-asan-dbgsym-rpath6.2.0/mivisionx-asan-dbgsym-rpath6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 7171716 +SHA256: 541de694fe20196708da8d990813334067071fb7f248279fcb297773fdf3f6f5 +SHA1: 59aa44088fed311893e7c09325f39973db64ead4 +MD5sum: 725b8fe580935540f15e108e8464833c +Description: debug symbols for mivisionx-asan +Maintainer: MIVisionX Support +Package-Type: ddeb +Version: 3.0.0.60200-66~20.04 +Installed-Size: 8486 + +Package: mivisionx-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 4a8a1b72e0c664211323af56b024c9323522abe3 19fe207dab4e46b9b14f6e94895140d5ad99dc90 4f0dc4c51b527f60b07b5c8f82639b57b5e82c08 6fac15bab31088481ecf9afc65c4df04d2af4ff3 e839af650e106514c9145b8049b7b18d2934c713 954b5b8065e4964e1d733e282b7eeb3fe03f5bc8 723594f7fc1c767c3032f278680997d3ff72585d 2b6ab9f7385e0a0896ad6fc71f56309e961d9fe6 +Depends: mivisionx-asan6.2.0 (= 3.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/m/mivisionx-asan-dbgsym6.2.0/mivisionx-asan-dbgsym6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 7172684 +SHA256: 16ee1321e925d87af82a01dc558dbadb4a16b25bdf1ef90552a76d1d35837e44 +SHA1: daf49aff777d239b86214935b93b7db89b44224f +MD5sum: 0fac6d9fe391f58775bd39e2740c77c9 +Description: debug symbols for mivisionx-asan +Maintainer: MIVisionX Support +Package-Type: ddeb +Version: 3.0.0.60200-66~20.04 +Installed-Size: 8486 + +Package: mivisionx-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-asan-rpath6.2.0, rocm-hip-runtime-rpath6.2.0, half-rpath6.2.0, rpp-rpath6.2.0, rocblas-rpath6.2.0, miopen-hip-rpath6.2.0, migraphx-rpath6.2.0, rocdecode-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/mivisionx-asan-rpath6.2.0/mivisionx-asan-rpath6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 18458080 +SHA256: 42e9488e6e74ec4352bac5e5e171d86b6a3e602b1f3048e508073d30a81338b1 +SHA1: b78c8e9b632828bb5315810264bc14d8bbbee717 +MD5sum: 25fc498c956da26c2c697fb20fd0f409 +Description: AMD MIVisionX is a comprehensive Computer Vision and ML Inference Toolkit. MIVisionX ASAN package provides MIVisionX ASAN libraries +Homepage: https://github.com/ROCm/MIVisionX +Maintainer: MIVisionX Support +Version: 3.0.0.60200-66~20.04 +Installed-Size: 281386 + +Package: mivisionx-asan6.2.0 +Architecture: amd64 +Depends: rocm-core-asan6.2.0, rocm-hip-runtime6.2.0, half6.2.0, rpp6.2.0, rocblas6.2.0, miopen-hip6.2.0, migraphx6.2.0, rocdecode6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/mivisionx-asan6.2.0/mivisionx-asan6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 18458236 +SHA256: 1a6a30c8aa7fdfb836c5f2076ae995f84ea46a8c5bb9d0fe95aad179aa7ba7c3 +SHA1: 7d11c5e5df7b470787911a52196264e74fa0f7f4 +MD5sum: 8ea19ad1b4cb13f39666cce5c3356b09 +Description: AMD MIVisionX is a comprehensive Computer Vision and ML Inference Toolkit. MIVisionX ASAN package provides MIVisionX ASAN libraries +Homepage: https://github.com/ROCm/MIVisionX +Maintainer: MIVisionX Support +Version: 3.0.0.60200-66~20.04 +Installed-Size: 281386 + +Package: mivisionx-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 5515c365a55d977b989a9a78b6dce53a6ad734c0 476938f82d3f92c1b7b01846f3bd474a7d37128f 37110ad8939a6a401888fef3c57412c56072305a 004b5a174d48c99cacabbcb4d9fe82b2dc2a372a c26c0dc48bf5d1e2e2a823a0c84615da23446a22 ef96c5e926c2260f34462d5c992c4348cc9eb466 23ad4ff77f77cd44ffbbe5177c0bb6a06f6d0bb5 0a91d76e27537a308de864dd59540bb1433a46dd 53c1283b93e6aeced954b96a1514305d2166cce0 9cb79a73ca77170401b7797edeeafb4b74cd1108 +Depends: mivisionx (= 3.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/m/mivisionx-dbgsym/mivisionx-dbgsym_3.0.0.60200-66~20.04_amd64.deb +Size: 16570768 +SHA256: ca14cef0c544b9fc40f3cb754bdfb8782ed33185f2477d0bd7fb42a84c78c778 +SHA1: 421f67732e66f701a94170b448e0934db58d45e8 +MD5sum: 39b7bb76129e9ad80408b9c581177228 +Description: debug symbols for mivisionx +Maintainer: MIVisionX Support +Package-Type: ddeb +Version: 3.0.0.60200-66~20.04 +Installed-Size: 47232 + +Package: mivisionx-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 5515c365a55d977b989a9a78b6dce53a6ad734c0 476938f82d3f92c1b7b01846f3bd474a7d37128f 37110ad8939a6a401888fef3c57412c56072305a 004b5a174d48c99cacabbcb4d9fe82b2dc2a372a c26c0dc48bf5d1e2e2a823a0c84615da23446a22 ef96c5e926c2260f34462d5c992c4348cc9eb466 23ad4ff77f77cd44ffbbe5177c0bb6a06f6d0bb5 0a91d76e27537a308de864dd59540bb1433a46dd 53c1283b93e6aeced954b96a1514305d2166cce0 9cb79a73ca77170401b7797edeeafb4b74cd1108 +Depends: mivisionx-rpath6.2.0 (= 3.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/m/mivisionx-dbgsym-rpath6.2.0/mivisionx-dbgsym-rpath6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 6910684 +SHA256: 7525b2005b05712cbcb53d1a35b83bee947b9ec0473edeec4d13db1c252b802b +SHA1: b5e44ef2f060d8fafeef78b77dc18026bb50603d +MD5sum: b5e7ef24c673f72b5305cbc0290ef91b +Description: debug symbols for mivisionx +Maintainer: MIVisionX Support +Package-Type: ddeb +Version: 3.0.0.60200-66~20.04 +Installed-Size: 47232 + +Package: mivisionx-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 5515c365a55d977b989a9a78b6dce53a6ad734c0 476938f82d3f92c1b7b01846f3bd474a7d37128f 37110ad8939a6a401888fef3c57412c56072305a 004b5a174d48c99cacabbcb4d9fe82b2dc2a372a c26c0dc48bf5d1e2e2a823a0c84615da23446a22 ef96c5e926c2260f34462d5c992c4348cc9eb466 23ad4ff77f77cd44ffbbe5177c0bb6a06f6d0bb5 0a91d76e27537a308de864dd59540bb1433a46dd 53c1283b93e6aeced954b96a1514305d2166cce0 9cb79a73ca77170401b7797edeeafb4b74cd1108 +Depends: mivisionx6.2.0 (= 3.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/m/mivisionx-dbgsym6.2.0/mivisionx-dbgsym6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 6910172 +SHA256: ce2bee0424d0c271ab1025675bd1cad847cf1f2837d175050de56171b3ad8a79 +SHA1: 2c1152db3c74f668425147e8f6b1c6008ed89551 +MD5sum: c69c2342b591d813c32b783fd0ee69af +Description: debug symbols for mivisionx +Maintainer: MIVisionX Support +Package-Type: ddeb +Version: 3.0.0.60200-66~20.04 +Installed-Size: 47232 + +Package: mivisionx-dev +Architecture: amd64 +Depends: rocm-core, mivisionx, rocm-hip-runtime-dev, rpp-dev, rocblas-dev, miopen-hip-dev, migraphx-dev, ffmpeg, libavcodec-dev, libavformat-dev, libavutil-dev, libswscale-dev, rocdecode-dev +Priority: optional +Section: devel +Filename: pool/main/m/mivisionx-dev/mivisionx-dev_3.0.0.60200-66~20.04_amd64.deb +Size: 23597368 +SHA256: a32a300409c3a4120361443ded3877357bf377c22bdab5d9d9b96f2ad6143a11 +SHA1: 4c020c03e51bbc5ffe28a94d174f80e69db64259 +MD5sum: 285c54e6192e98aec9675396bf9c3538 +Description: AMD MIVisionX is a comprehensive Computer Vision and ML Inference Toolkit. MIVisionX develop package provides MIVisionX libraries, header files, samples, and license.txt +Homepage: https://github.com/ROCm/MIVisionX +Maintainer: MIVisionX Support +Version: 3.0.0.60200-66~20.04 +Installed-Size: 41263 + +Package: mivisionx-dev-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0, mivisionx-rpath6.2.0, rocm-hip-runtime-dev-rpath6.2.0, rpp-dev-rpath6.2.0, rocblas-dev-rpath6.2.0, miopen-hip-dev-rpath6.2.0, migraphx-dev-rpath6.2.0, ffmpeg, libavcodec-dev, libavformat-dev, libavutil-dev, libswscale-dev, rocdecode-dev-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/mivisionx-dev-rpath6.2.0/mivisionx-dev-rpath6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 19275748 +SHA256: 8d00298909479a0aad5a7b238ad6035614acaddb1ea4d13c581c9f7780298e17 +SHA1: 9165745edaea5eb2282b8ad1d5d915c4cec99d42 +MD5sum: 5fdf534164af4eb3e1ef29c334e9998f +Description: AMD MIVisionX is a comprehensive Computer Vision and ML Inference Toolkit. MIVisionX develop package provides MIVisionX libraries, header files, samples, and license.txt +Homepage: https://github.com/ROCm/MIVisionX +Maintainer: MIVisionX Support +Version: 3.0.0.60200-66~20.04 +Installed-Size: 41263 + +Package: mivisionx-dev6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0, mivisionx6.2.0, rocm-hip-runtime-dev6.2.0, rpp-dev6.2.0, rocblas-dev6.2.0, miopen-hip-dev6.2.0, migraphx-dev6.2.0, ffmpeg, libavcodec-dev, libavformat-dev, libavutil-dev, libswscale-dev, rocdecode-dev6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/mivisionx-dev6.2.0/mivisionx-dev6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 19275960 +SHA256: 6159a33af6b64184b6e70f66ed3ca6737cfa1bb0274add1d3d787e5dc3987989 +SHA1: 6b58d1ffc404f23d7dfaa9a4a2b45faa265495b5 +MD5sum: 9062032eabd9ad6ba850e6fec03d9ff4 +Description: AMD MIVisionX is a comprehensive Computer Vision and ML Inference Toolkit. MIVisionX develop package provides MIVisionX libraries, header files, samples, and license.txt +Homepage: https://github.com/ROCm/MIVisionX +Maintainer: MIVisionX Support +Version: 3.0.0.60200-66~20.04 +Installed-Size: 41263 + +Package: mivisionx-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0, rocm-hip-runtime-rpath6.2.0, half-rpath6.2.0, rpp-rpath6.2.0, rocblas-rpath6.2.0, miopen-hip-rpath6.2.0, migraphx-rpath6.2.0, rocdecode-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/mivisionx-rpath6.2.0/mivisionx-rpath6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 10919468 +SHA256: b1eaf6590fe165fe2f5cc363226cb21ce73943e08340952326ce6cf4f94a359e +SHA1: cb4d3bb71bfee508f94cad780417fd9e8a526bcf +MD5sum: a1c2c636c4a22532863df92fd229f281 +Description: AMD MIVisionX is a comprehensive Computer Vision and ML Inference Toolkit. MIVisionX runtime package provides MIVisionX libraries and license.txt +Homepage: https://github.com/ROCm/MIVisionX +Maintainer: MIVisionX Support +Version: 3.0.0.60200-66~20.04 +Installed-Size: 265857 + +Package: mivisionx-test +Architecture: amd64 +Depends: rocm-core, mivisionx-dev +Priority: optional +Section: devel +Filename: pool/main/m/mivisionx-test/mivisionx-test_3.0.0.60200-66~20.04_amd64.deb +Size: 10595674 +SHA256: 2fdd92cc92c3128da34ddc26b39411676b539e5056f5d37d796ff31941818a57 +SHA1: 6c4815038e984a65b92cc84797cc737d44204c68 +MD5sum: 0a991f4c3dceb2839c8aa0ab99b68abb +Description: AMD MIVisionX is a comprehensive Computer Vision and ML Inference Toolkit. MIVisionX Test package provides MIVisionX Test Components +Homepage: https://github.com/ROCm/MIVisionX +Maintainer: MIVisionX Support +Version: 3.0.0.60200-66~20.04 +Installed-Size: 18030 + +Package: mivisionx-test-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0, mivisionx-dev-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/mivisionx-test-rpath6.2.0/mivisionx-test-rpath6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 7473444 +SHA256: 068928904a57c603cb113bbdc8ff3313479b79ca3d7e53e5a00b43c9596798d1 +SHA1: c8d3de21dfa416c667b76b7ba0b91624b9e7ea13 +MD5sum: b317da80301408d6f931a3a6fa05462d +Description: AMD MIVisionX is a comprehensive Computer Vision and ML Inference Toolkit. MIVisionX Test package provides MIVisionX Test Components +Homepage: https://github.com/ROCm/MIVisionX +Maintainer: MIVisionX Support +Version: 3.0.0.60200-66~20.04 +Installed-Size: 18030 + +Package: mivisionx-test6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0, mivisionx-dev6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/mivisionx-test6.2.0/mivisionx-test6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 7454284 +SHA256: b1ba554185941270c095493fe9db0b7b9d4579cca382d2ba9999f47e90cb510c +SHA1: 9911636edfc050ddf7891fb235fc82f0a708d3e5 +MD5sum: 0b6428c8f21e255af07716a79db28a3e +Description: AMD MIVisionX is a comprehensive Computer Vision and ML Inference Toolkit. MIVisionX Test package provides MIVisionX Test Components +Homepage: https://github.com/ROCm/MIVisionX +Maintainer: MIVisionX Support +Version: 3.0.0.60200-66~20.04 +Installed-Size: 18030 + +Package: mivisionx6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0, rocm-hip-runtime6.2.0, half6.2.0, rpp6.2.0, rocblas6.2.0, miopen-hip6.2.0, migraphx6.2.0, rocdecode6.2.0 +Priority: optional +Section: devel +Filename: pool/main/m/mivisionx6.2.0/mivisionx6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 10918068 +SHA256: ec7f6ecad00f3ab0575af3b70ed930572b5cf53f6ce1a08d458418e63ab1fe11 +SHA1: 43b3765a8caebee366971ca322131dd90c25acdf +MD5sum: 54568a7b49eedad94949fb4e04cda5ef +Description: AMD MIVisionX is a comprehensive Computer Vision and ML Inference Toolkit. MIVisionX runtime package provides MIVisionX libraries and license.txt +Homepage: https://github.com/ROCm/MIVisionX +Maintainer: MIVisionX Support +Version: 3.0.0.60200-66~20.04 +Installed-Size: 265857 + +Package: omniperf +Architecture: amd64 +Depends: rocprofiler +Priority: optional +Section: devel +Filename: pool/main/o/omniperf/omniperf_2.0.1.60200-66~20.04_amd64.deb +Size: 2620638 +SHA256: 997426a5118ca6ae30e06d7a7b1be72774ca790d4eb7b1e642e54370c9127e05 +SHA1: 5de5388e9f360eb1cf79fadd617b1a081ff0ab59 +MD5sum: fdb14738d62db36086fba5e1e4efbb82 +Description: Omniperf: tool for GPU performance profiling +Homepage: https://github.com/ROCm/omniperf +Maintainer: https://github.com/ROCm/omniperf +Version: 2.0.1.60200-66~20.04 +Installed-Size: 12689 + +Package: omniperf-rpath6.2.0 +Architecture: amd64 +Depends: rocprofiler-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/o/omniperf-rpath6.2.0/omniperf-rpath6.2.0_2.0.1.60200-66~20.04_amd64.deb +Size: 1663552 +SHA256: 53f46447785bc8dd3f400eb63532c12744337800a917d572857a2fae2e607806 +SHA1: eeabe89f3b52ae4600827600914ea8f83c32419b +MD5sum: c4974e716d4ca65d4e023db0cdb5dd01 +Description: Omniperf: tool for GPU performance profiling +Homepage: https://github.com/ROCm/omniperf +Maintainer: https://github.com/ROCm/omniperf +Version: 2.0.1.60200-66~20.04 +Installed-Size: 12689 + +Package: omniperf6.2.0 +Architecture: amd64 +Depends: rocprofiler6.2.0 +Priority: optional +Section: devel +Filename: pool/main/o/omniperf6.2.0/omniperf6.2.0_2.0.1.60200-66~20.04_amd64.deb +Size: 1663720 +SHA256: 7fa772422b2468235a47a007eadbf1051b9cb4cfe63d30961175b62ba948959b +SHA1: 2d5fa2890993f9d03bdef63bf1ebc6d1b0504372 +MD5sum: 4a5c5d6ddd6f2344fbb4dd0e77780dab +Description: Omniperf: tool for GPU performance profiling +Homepage: https://github.com/ROCm/omniperf +Maintainer: https://github.com/ROCm/omniperf +Version: 2.0.1.60200-66~20.04 +Installed-Size: 12689 + +Package: omnitrace +Architecture: amd64 +Depends: libgomp1, rocm-smi-lib (>= 6.0.0.60200), roctracer-dev (>= 1.0.0.60200), rocprofiler-dev (>= 1.0.0.60200), libbz2-1.0, libc6 (>= 2.30), libgcc-s1 (>= 3.0), libgomp1 (>= 6), liblzma5 (>= 5.1.1alpha+20120614), libstdc++6 (>= 9), zlib1g (>= 1:1.2.2.3) +Priority: optional +Section: devel +Filename: pool/main/o/omnitrace/omnitrace_1.11.2.60200-66~20.04_amd64.deb +Size: 40312874 +SHA256: a7c78aab23066411214a258d017c4f6e976002b4c106ce523ddc4737f0590dfd +SHA1: d4d9a5c4d31e2282ff9b1456fddb77b8a71597f3 +MD5sum: ebdbe995a3c1323a29ea065b0592bf47 +Description: Runtime instrumentation and binary rewriting for Perfetto via Dyninst +Homepage: https://github.com/ROCm/omnitrace +Maintainer: jonathan.madsen@amd.com +Version: 1.11.2.60200-66~20.04 +Installed-Size: 247179 + +Package: omnitrace-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: eac6018245ae1ab6a190826381d54153e26a0333 b3d66f3e904037452436fe15cfe28ae8603578d1 5ee3b06799b87a484be3cacaa2e1f2456769fc64 bd4e4c7eebfc57d119e9f7335f82221c5ef81d24 c5659842a2fc6c0500be26b3644e4bca2c291676 2a14778353135340141f9f2bf2277891a60c7a34 b1c0ba4b1b1e282ba18eeea9da2b721bc25778b9 b4053a9e681f77f68a20e864048cd3608b8e0eb7 d4752efac240904543eff29cc9b7b1d401d491b6 b674b1f00bde8499ef4ad317f20049c1658a97c6 c0c0d879c4659580bffe1ac674da3092bc86a9f1 03f1f4487a07016d970b9fe73850158a5b8ff614 571c29a98604f0998baf065ff377e50e107b66e9 7e26e5020a2665496c4f0bf393c5e360b2896d52 10cbea4ee1a63a5f3ff0ebf60975f763833b7f42 71b301a0cd95aea5ebb650b8b6131f39b5fbcf64 5fe9076b6106191c259e65e6064cc18bc5bc2234 4eb469c832aca954b04fe0def8c4f46d001586aa 36efdc9cbeb84a9533d527f9562b140836f3d288 52ea4e7f7f429451751fda3d1e73a4c02a9b272c 25f772f6ed806046e1fdc2ee8d04ba8e7e3869bb c19463bc8cf86ac9038edeac60845a303d6d5be6 36d6e98f567ef617872abcb5103f08f6c647da53 bce54e8143963e26663bbca7b0512847cfd58535 dc5c3734dd59cb9f6e9894bfc6e7ec9fa3fe49bf 4a62d200925c4f02f1e1c99b52b8aa24e24f5346 c323d5999292b93e0e1645f661b7492195baf3c1 0e760371e572ed657abe47253fbaf53627e6ebed c174f94221af80cbee0b5ed9cbd764e944374a27 d622ba94fcb15809e803c73456449f7465e81309 c19463bc8cf86ac9038edeac60845a303d6d5be6 99ca4257dbd41ac17a17a81842c119a24228362f 7e534a2cd50b1b309d90b95b16f5068f0ee532aa c7a630225000b86ce3e18d41225640780c7c1f17 21b4811cfe3b68bda7b9c94b232e5682cbcc91bb 1e440a4c4b2d3bc4ea190648190506fefe3ca6a5 6bdffbb68823670516d1063da1010bb651ece1e9 e3a1a11e75eb616ec3125ad788ffce5ee040f307 de930c9567f15ab1896a3be37fc767592555bb78 e68255fb37dfb7044c3f8bfe232efd4a2be9aaf2 +Depends: omnitrace (= 1.11.2.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/o/omnitrace-dbgsym/omnitrace-dbgsym_1.11.2.60200-66~20.04_amd64.deb +Size: 818813856 +SHA256: 5716bed4f88f4dd235a239ebaaf7b383f59bbe73e3bf07311754559ca376af9c +SHA1: 99dbc5f9db54c3351599f0e7fd162196ce15e906 +MD5sum: a4657fe43ec518fd5723ef1ce316287c +Description: debug symbols for omnitrace +Maintainer: jonathan.madsen@amd.com +Package-Type: ddeb +Version: 1.11.2.60200-66~20.04 +Installed-Size: 3083709 + +Package: omnitrace-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: eac6018245ae1ab6a190826381d54153e26a0333 b3d66f3e904037452436fe15cfe28ae8603578d1 5ee3b06799b87a484be3cacaa2e1f2456769fc64 bd4e4c7eebfc57d119e9f7335f82221c5ef81d24 c5659842a2fc6c0500be26b3644e4bca2c291676 2a14778353135340141f9f2bf2277891a60c7a34 b1c0ba4b1b1e282ba18eeea9da2b721bc25778b9 b4053a9e681f77f68a20e864048cd3608b8e0eb7 d4752efac240904543eff29cc9b7b1d401d491b6 b674b1f00bde8499ef4ad317f20049c1658a97c6 c0c0d879c4659580bffe1ac674da3092bc86a9f1 03f1f4487a07016d970b9fe73850158a5b8ff614 571c29a98604f0998baf065ff377e50e107b66e9 7e26e5020a2665496c4f0bf393c5e360b2896d52 10cbea4ee1a63a5f3ff0ebf60975f763833b7f42 71b301a0cd95aea5ebb650b8b6131f39b5fbcf64 5fe9076b6106191c259e65e6064cc18bc5bc2234 4eb469c832aca954b04fe0def8c4f46d001586aa 36efdc9cbeb84a9533d527f9562b140836f3d288 52ea4e7f7f429451751fda3d1e73a4c02a9b272c 25f772f6ed806046e1fdc2ee8d04ba8e7e3869bb c19463bc8cf86ac9038edeac60845a303d6d5be6 36d6e98f567ef617872abcb5103f08f6c647da53 bce54e8143963e26663bbca7b0512847cfd58535 dc5c3734dd59cb9f6e9894bfc6e7ec9fa3fe49bf 4a62d200925c4f02f1e1c99b52b8aa24e24f5346 c323d5999292b93e0e1645f661b7492195baf3c1 0e760371e572ed657abe47253fbaf53627e6ebed c174f94221af80cbee0b5ed9cbd764e944374a27 d622ba94fcb15809e803c73456449f7465e81309 c19463bc8cf86ac9038edeac60845a303d6d5be6 99ca4257dbd41ac17a17a81842c119a24228362f 7e534a2cd50b1b309d90b95b16f5068f0ee532aa c7a630225000b86ce3e18d41225640780c7c1f17 21b4811cfe3b68bda7b9c94b232e5682cbcc91bb 1e440a4c4b2d3bc4ea190648190506fefe3ca6a5 6bdffbb68823670516d1063da1010bb651ece1e9 e3a1a11e75eb616ec3125ad788ffce5ee040f307 de930c9567f15ab1896a3be37fc767592555bb78 e68255fb37dfb7044c3f8bfe232efd4a2be9aaf2 +Depends: omnitrace-rpath6.2.0 (= 1.11.2.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/o/omnitrace-dbgsym-rpath6.2.0/omnitrace-dbgsym-rpath6.2.0_1.11.2.60200-66~20.04_amd64.deb +Size: 515194272 +SHA256: df50a39e1b749cca01033aeec89716f72497268bcfa1d6f8234c56ec6eb2b17f +SHA1: 9645809ef972133428421f18b597352cbcc4f021 +MD5sum: 59798abd8e2904c5eedcd140219093b9 +Description: debug symbols for omnitrace +Maintainer: jonathan.madsen@amd.com +Package-Type: ddeb +Version: 1.11.2.60200-66~20.04 +Installed-Size: 3083709 + +Package: omnitrace-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: eac6018245ae1ab6a190826381d54153e26a0333 b3d66f3e904037452436fe15cfe28ae8603578d1 5ee3b06799b87a484be3cacaa2e1f2456769fc64 bd4e4c7eebfc57d119e9f7335f82221c5ef81d24 c5659842a2fc6c0500be26b3644e4bca2c291676 2a14778353135340141f9f2bf2277891a60c7a34 b1c0ba4b1b1e282ba18eeea9da2b721bc25778b9 b4053a9e681f77f68a20e864048cd3608b8e0eb7 d4752efac240904543eff29cc9b7b1d401d491b6 b674b1f00bde8499ef4ad317f20049c1658a97c6 c0c0d879c4659580bffe1ac674da3092bc86a9f1 03f1f4487a07016d970b9fe73850158a5b8ff614 571c29a98604f0998baf065ff377e50e107b66e9 7e26e5020a2665496c4f0bf393c5e360b2896d52 10cbea4ee1a63a5f3ff0ebf60975f763833b7f42 71b301a0cd95aea5ebb650b8b6131f39b5fbcf64 5fe9076b6106191c259e65e6064cc18bc5bc2234 4eb469c832aca954b04fe0def8c4f46d001586aa 36efdc9cbeb84a9533d527f9562b140836f3d288 52ea4e7f7f429451751fda3d1e73a4c02a9b272c 25f772f6ed806046e1fdc2ee8d04ba8e7e3869bb c19463bc8cf86ac9038edeac60845a303d6d5be6 36d6e98f567ef617872abcb5103f08f6c647da53 bce54e8143963e26663bbca7b0512847cfd58535 dc5c3734dd59cb9f6e9894bfc6e7ec9fa3fe49bf 4a62d200925c4f02f1e1c99b52b8aa24e24f5346 c323d5999292b93e0e1645f661b7492195baf3c1 0e760371e572ed657abe47253fbaf53627e6ebed c174f94221af80cbee0b5ed9cbd764e944374a27 d622ba94fcb15809e803c73456449f7465e81309 c19463bc8cf86ac9038edeac60845a303d6d5be6 99ca4257dbd41ac17a17a81842c119a24228362f 7e534a2cd50b1b309d90b95b16f5068f0ee532aa c7a630225000b86ce3e18d41225640780c7c1f17 21b4811cfe3b68bda7b9c94b232e5682cbcc91bb 1e440a4c4b2d3bc4ea190648190506fefe3ca6a5 6bdffbb68823670516d1063da1010bb651ece1e9 e3a1a11e75eb616ec3125ad788ffce5ee040f307 de930c9567f15ab1896a3be37fc767592555bb78 e68255fb37dfb7044c3f8bfe232efd4a2be9aaf2 +Depends: omnitrace6.2.0 (= 1.11.2.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/o/omnitrace-dbgsym6.2.0/omnitrace-dbgsym6.2.0_1.11.2.60200-66~20.04_amd64.deb +Size: 515195360 +SHA256: 337e4de6dadefa0ab20ed1d99559a84034b4fc1f1b130d242f4ad92c7be98bd1 +SHA1: ec72979e8e37682434240f1be4a0b8c8588d9af4 +MD5sum: a756695c028f23a36479f4719fd759a9 +Description: debug symbols for omnitrace +Maintainer: jonathan.madsen@amd.com +Package-Type: ddeb +Version: 1.11.2.60200-66~20.04 +Installed-Size: 3083709 + +Package: omnitrace-rpath6.2.0 +Architecture: amd64 +Depends: libgomp1, rocm-smi-lib-rpath6.2.0 (>= 6.0.0.60200), roctracer-dev-rpath6.2.0 (>= 1.0.0.60200), rocprofiler-dev-rpath6.2.0 (>= 1.0.0.60200), libbz2-1.0, libc6 (>= 2.30), libgcc-s1 (>= 3.0), libgomp1 (>= 6), liblzma5 (>= 5.1.1alpha+20120614), libstdc++6 (>= 9), zlib1g (>= 1:1.2.2.3) +Priority: optional +Section: devel +Filename: pool/main/o/omnitrace-rpath6.2.0/omnitrace-rpath6.2.0_1.11.2.60200-66~20.04_amd64.deb +Size: 22442960 +SHA256: aaa6f6d168f327fc94be24fb7d41904e7bfe80721d747143421609cf8846f09f +SHA1: b2bf674e0334513566de6d99f68642708cbe2185 +MD5sum: 7a3cd61d81451ce5fb5f5a2909fbf03d +Description: Runtime instrumentation and binary rewriting for Perfetto via Dyninst +Homepage: https://github.com/ROCm/omnitrace +Maintainer: jonathan.madsen@amd.com +Version: 1.11.2.60200-66~20.04 +Installed-Size: 247179 + +Package: omnitrace6.2.0 +Architecture: amd64 +Depends: libgomp1, rocm-smi-lib6.2.0 (>= 6.0.0.60200), roctracer-dev6.2.0 (>= 1.0.0.60200), rocprofiler-dev6.2.0 (>= 1.0.0.60200), libbz2-1.0, libc6 (>= 2.30), libgcc-s1 (>= 3.0), libgomp1 (>= 6), liblzma5 (>= 5.1.1alpha+20120614), libstdc++6 (>= 9), zlib1g (>= 1:1.2.2.3) +Priority: optional +Section: devel +Filename: pool/main/o/omnitrace6.2.0/omnitrace6.2.0_1.11.2.60200-66~20.04_amd64.deb +Size: 22450904 +SHA256: f7da0e9f49b95f47d46415531a3f9b0a0ac0acf3d9586203a79be9aecad3c732 +SHA1: 5f3dc98354dfedb0a3fd3e56a1a4c5d19e61aae3 +MD5sum: 6587eaeb89b6322074593d0f3cf13b43 +Description: Runtime instrumentation and binary rewriting for Perfetto via Dyninst +Homepage: https://github.com/ROCm/omnitrace +Maintainer: jonathan.madsen@amd.com +Version: 1.11.2.60200-66~20.04 +Installed-Size: 247179 + +Package: openmp-extras-asan +Architecture: amd64 +Maintainer: Openmp Extras Support +Version: 18.62.0.60200-66~20.04 +Depends: hsa-rocr-asan, rocm-core-asan +Recommends: gcc, g++ +Priority: optional +Section: devel +Filename: pool/main/o/openmp-extras-asan/openmp-extras-asan_18.62.0.60200-66~20.04_amd64.deb +Size: 188686746 +SHA256: b426227ce5c668e5c522ea6228a955ac02864024e61b9c239777028d5fc6ba8e +SHA1: 847054cb51035f58e452ac98c1e0a1f9482fad63 +MD5sum: a2e487474a632aef0e90c0e9c46db635 +Description: AddressSanitizer OpenMP Extras provides instrumented openmp and flang libraries. + openmp-extras 18.62.0.60200 is based on LLVM 17 and is used for offloading to Radeon GPUs. + +Package: openmp-extras-asan-rpath6.2.0 +Architecture: amd64 +Maintainer: Openmp Extras Support +Version: 18.62.0.60200-66~20.04 +Depends: hsa-rocr-asan-rpath6.2.0, rocm-core-asan-rpath6.2.0 +Recommends: gcc, g++ +Priority: optional +Section: devel +Filename: pool/main/o/openmp-extras-asan-rpath6.2.0/openmp-extras-asan-rpath6.2.0_18.62.0.60200-66~20.04_amd64.deb +Size: 114667596 +SHA256: 42d4a5223f598874627c266f893a874f7d5c13021a3c808695b262a8c7def74e +SHA1: 76dd09b3dbcd19c2c4f978fc12a3e70beffd5a94 +MD5sum: 5862aec69c9fba086696ce9a9319af0b +Description: AddressSanitizer OpenMP Extras provides instrumented openmp and flang libraries. + openmp-extras 18.62.0.60200 is based on LLVM 17 and is used for offloading to Radeon GPUs. + +Package: openmp-extras-asan6.2.0 +Architecture: amd64 +Maintainer: Openmp Extras Support +Version: 18.62.0.60200-66~20.04 +Depends: hsa-rocr-asan6.2.0, rocm-core-asan6.2.0 +Recommends: gcc, g++ +Priority: optional +Section: devel +Filename: pool/main/o/openmp-extras-asan6.2.0/openmp-extras-asan6.2.0_18.62.0.60200-66~20.04_amd64.deb +Size: 114667840 +SHA256: 575910724762e3b0332672ca08750c54deafdc4ebe63605eb8a08418cab56018 +SHA1: 3616069e3de08c683c174ad0ea0cec2407d1469c +MD5sum: 77223399a8720ad3e4d68a160e59f258 +Description: AddressSanitizer OpenMP Extras provides instrumented openmp and flang libraries. + openmp-extras 18.62.0.60200 is based on LLVM 17 and is used for offloading to Radeon GPUs. + +Package: openmp-extras-dev +Architecture: amd64 +Maintainer: Openmp Extras Support +Version: 18.62.0.60200-66~20.04 +Depends: rocm-llvm, rocm-device-libs, rocm-core, openmp-extras-runtime, hsa-rocr-dev +Recommends: gcc, g++ +Provides: openmp-extras +Conflicts: openmp-extras +Replaces: openmp-extras +Priority: optional +Section: devel +Filename: pool/main/o/openmp-extras-dev/openmp-extras-dev_18.62.0.60200-66~20.04_amd64.deb +Size: 49047178 +SHA256: 14f44473c869483bca29016799817736f11c92dd6554b3480487d1e4147168f3 +SHA1: fbab2ad6014ab48e2e742c8d4744133ec86f31da +MD5sum: 587eb5eb7db324b45458f015ff6e205c +Description: OpenMP Extras provides openmp and flang libraries. + openmp-extras 18.62.0.60200 is based on LLVM 17 and is used for offloading to Radeon GPUs. + +Package: openmp-extras-dev-rpath6.2.0 +Architecture: amd64 +Maintainer: Openmp Extras Support +Version: 18.62.0.60200-66~20.04 +Depends: rocm-llvm-rpath6.2.0, rocm-device-libs-rpath6.2.0, rocm-core-rpath6.2.0, openmp-extras-runtime-rpath6.2.0, hsa-rocr-dev-rpath6.2.0 +Recommends: gcc, g++ +Provides: openmp-extras-rpath6.2.0 +Conflicts: openmp-extras-rpath6.2.0 +Replaces: openmp-extras-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/o/openmp-extras-dev-rpath6.2.0/openmp-extras-dev-rpath6.2.0_18.62.0.60200-66~20.04_amd64.deb +Size: 25650268 +SHA256: e6030bb3e9ccf2ef35c5ab695f385348520e0e729abf66e7f48238f4771f43fc +SHA1: 8e088dfb90f9528a3767f2df5a33e3f07040054e +MD5sum: 224c5ec863c0713221998480ccc86310 +Description: OpenMP Extras provides openmp and flang libraries. + openmp-extras 18.62.0.60200 is based on LLVM 17 and is used for offloading to Radeon GPUs. + +Package: openmp-extras-dev6.2.0 +Architecture: amd64 +Maintainer: Openmp Extras Support +Version: 18.62.0.60200-66~20.04 +Depends: rocm-llvm6.2.0, rocm-device-libs6.2.0, rocm-core6.2.0, openmp-extras-runtime6.2.0, hsa-rocr-dev6.2.0 +Recommends: gcc, g++ +Provides: openmp-extras6.2.0 +Conflicts: openmp-extras6.2.0 +Replaces: openmp-extras6.2.0 +Priority: optional +Section: devel +Filename: pool/main/o/openmp-extras-dev6.2.0/openmp-extras-dev6.2.0_18.62.0.60200-66~20.04_amd64.deb +Size: 25651764 +SHA256: 9f69f3c877dad83c33f98c73c1f197df23d1debc0def050a3f58e5f9f55399cf +SHA1: a0945510f17813874924d193b642bedc8032eebf +MD5sum: 402ed7e1ad1ab076c51caa3bdbbe12de +Description: OpenMP Extras provides openmp and flang libraries. + openmp-extras 18.62.0.60200 is based on LLVM 17 and is used for offloading to Radeon GPUs. + +Package: openmp-extras-runtime +Architecture: amd64 +Maintainer: Openmp Extras Support +Version: 18.62.0.60200-66~20.04 +Depends: rocm-core, hsa-rocr +Recommends: gcc, g++ +Priority: optional +Section: devel +Filename: pool/main/o/openmp-extras-runtime/openmp-extras-runtime_18.62.0.60200-66~20.04_amd64.deb +Size: 150945722 +SHA256: 9fa4045082f66f87de70235dd97d16f512d326324e9b8c1ec6ea6427ceb9e1e0 +SHA1: 88d721f8867890c4a606659ce4277d8419178847 +MD5sum: 20bd3d89f885c0ce835eabd21efd07c2 +Description: OpenMP Extras provides openmp and flang libraries. + openmp-extras 18.62.0.60200 is based on LLVM 17 and is used for offloading to Radeon GPUs. + +Package: openmp-extras-runtime-rpath6.2.0 +Architecture: amd64 +Maintainer: Openmp Extras Support +Version: 18.62.0.60200-66~20.04 +Depends: rocm-core-rpath6.2.0, hsa-rocr-rpath6.2.0 +Recommends: gcc, g++ +Priority: optional +Section: devel +Filename: pool/main/o/openmp-extras-runtime-rpath6.2.0/openmp-extras-runtime-rpath6.2.0_18.62.0.60200-66~20.04_amd64.deb +Size: 98082256 +SHA256: 1575061fa21fd64c6fdd90ce30d043aa0c467b89678cbfc9e1d037a7f48ae49a +SHA1: d75b5e716254a0643fad5165bc10d31289c213a7 +MD5sum: a6ccc7885bfc448d9acb2d931dce7821 +Description: OpenMP Extras provides openmp and flang libraries. + openmp-extras 18.62.0.60200 is based on LLVM 17 and is used for offloading to Radeon GPUs. + +Package: openmp-extras-runtime6.2.0 +Architecture: amd64 +Maintainer: Openmp Extras Support +Version: 18.62.0.60200-66~20.04 +Depends: rocm-core6.2.0, hsa-rocr6.2.0 +Recommends: gcc, g++ +Priority: optional +Section: devel +Filename: pool/main/o/openmp-extras-runtime6.2.0/openmp-extras-runtime6.2.0_18.62.0.60200-66~20.04_amd64.deb +Size: 98093936 +SHA256: 0e490f829f530f71d3e0931cc9c9effe328199d10e2d8914d27c20ca573a9029 +SHA1: 11a4d5c6850e5971e88d8f7ceab7c5f57a77e130 +MD5sum: b872a9faa71e462246a3585d4af8fb55 +Description: OpenMP Extras provides openmp and flang libraries. + openmp-extras 18.62.0.60200 is based on LLVM 17 and is used for offloading to Radeon GPUs. + +Package: rccl +Architecture: amd64 +Depends: hip-runtime-amd (>= 4.5.0), rocm-smi-lib (>= 4.0.0), rocm-core, libc6 (>= 2.17), libgcc-s1 (>= 3.0), libstdc++6 (>= 9) +Priority: optional +Section: devel +Filename: pool/main/r/rccl/rccl_2.20.5.60200-66~20.04_amd64.deb +Size: 63015656 +SHA256: 6141284a3a58eea20eea036e6ff8dc4791ad57f81dbe1aad0abd7fcdcf5a532a +SHA1: 22606358ad4b6f2a83a228c9f4f24ee4558226c5 +MD5sum: 85fe3ef2e78758e20707d8383b5048e5 +Description: ROCm Communication Collectives Library + ROCm Communication Collectives Library + Optimized primitives for collective multi-GPU communication +Maintainer: RCCL Maintainer +Recommends: rccl-dev (>=2.20.5.60200) +Version: 2.20.5.60200-66~20.04 +Installed-Size: 1821373 + +Package: rccl-asan +Architecture: amd64 +Depends: hip-runtime-amd-asan (>= 4.5.0), rocm-smi-lib (>= 4.0.0), rocm-core-asan, libc6 (>= 2.10), libgcc-s1 (>= 3.0), libstdc++6 (>= 9) +Priority: optional +Section: devel +Filename: pool/main/r/rccl-asan/rccl-asan_2.20.5.60200-66~20.04_amd64.deb +Size: 121313860 +SHA256: d06f62799e84007d64efba4213651e31adb1fc8952861a845c13cfc8564f873a +SHA1: 2c21c738619f5b63328eede8f0a8285b6c996a3b +MD5sum: fc28bb0df794ae88087a5abe42cf74b0 +Description: ROCm Communication Collectives Library + ROCm Communication Collectives Library + Optimized primitives for collective multi-GPU communication +Maintainer: RCCL Maintainer +Recommends: rccl-asan-dev (>=2.20.5.60200) +Version: 2.20.5.60200-66~20.04 +Installed-Size: 1057824 + +Package: rccl-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 718120cde42a58cad747087931103d75d7ee7274 +Depends: rccl-asan (= 2.20.5.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rccl-asan-dbgsym/rccl-asan-dbgsym_2.20.5.60200-66~20.04_amd64.deb +Size: 2344524 +SHA256: 3a05eaa857e0798f78cf50a46daca17efc03f8906c50299ce6d2df6dae432381 +SHA1: 414d503ec0acd7d9d246d45768fd58c6aa427ac2 +MD5sum: 90954d71bb62095255bcafd735d425e0 +Description: debug symbols for rccl-asan +Maintainer: RCCL Maintainer +Package-Type: ddeb +Version: 2.20.5.60200-66~20.04 +Installed-Size: 2757 + +Package: rccl-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 718120cde42a58cad747087931103d75d7ee7274 +Depends: rccl-asan-rpath6.2.0 (= 2.20.5.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rccl-asan-dbgsym-rpath6.2.0/rccl-asan-dbgsym-rpath6.2.0_2.20.5.60200-66~20.04_amd64.deb +Size: 2344660 +SHA256: f43f1215c8153eb813a2c12928c51a83d58f344743c0b24cb38341a258d00c24 +SHA1: 6311946e102cc95c7c5a9c793a32651fcb6cd63c +MD5sum: 61fabec683da89e97392630d2b98c1b5 +Description: debug symbols for rccl-asan +Maintainer: RCCL Maintainer +Package-Type: ddeb +Version: 2.20.5.60200-66~20.04 +Installed-Size: 2757 + +Package: rccl-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 718120cde42a58cad747087931103d75d7ee7274 +Depends: rccl-asan6.2.0 (= 2.20.5.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rccl-asan-dbgsym6.2.0/rccl-asan-dbgsym6.2.0_2.20.5.60200-66~20.04_amd64.deb +Size: 2344644 +SHA256: 1edcad2cbc0b5b6843cfb90fd989b102110c899658197cb281dfb8c278848da8 +SHA1: d8e5ca6ef7d016e879eff032a60e04011ced7a06 +MD5sum: 1f61ed739e44623d4c21083ba2c9b2cc +Description: debug symbols for rccl-asan +Maintainer: RCCL Maintainer +Package-Type: ddeb +Version: 2.20.5.60200-66~20.04 +Installed-Size: 2757 + +Package: rccl-asan-rpath6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd-asan-rpath6.2.0 (>= 4.5.0), rocm-smi-lib-rpath6.2.0 (>= 4.0.0), rocm-core-asan-rpath6.2.0, libc6 (>= 2.10), libgcc-s1 (>= 3.0), libstdc++6 (>= 9) +Priority: optional +Section: devel +Filename: pool/main/r/rccl-asan-rpath6.2.0/rccl-asan-rpath6.2.0_2.20.5.60200-66~20.04_amd64.deb +Size: 121312964 +SHA256: ab0142c343cc9f817cd623d35110f283da8002d49a1b55f60eddc37248985a9e +SHA1: efcacc02bff0ebef252f051fb98451e0076f614d +MD5sum: a8165f0ebb7749df46a5db2ef6ef9c93 +Description: ROCm Communication Collectives Library + ROCm Communication Collectives Library + Optimized primitives for collective multi-GPU communication +Maintainer: RCCL Maintainer +Recommends: rccl-asan-dev (>=2.20.5.60200) +Version: 2.20.5.60200-66~20.04 +Installed-Size: 1057824 + +Package: rccl-asan6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd-asan6.2.0 (>= 4.5.0), rocm-smi-lib6.2.0 (>= 4.0.0), rocm-core-asan6.2.0, libc6 (>= 2.10), libgcc-s1 (>= 3.0), libstdc++6 (>= 9) +Priority: optional +Section: devel +Filename: pool/main/r/rccl-asan6.2.0/rccl-asan6.2.0_2.20.5.60200-66~20.04_amd64.deb +Size: 121312872 +SHA256: abb5e55bda1695ab228eaf390eb9a6ac18ef610d67133411a57dcf92cf0686b3 +SHA1: 09c42db9fef00fc4760191621cb0097f8f63d8e0 +MD5sum: 78150d5e6ad256aa6e6e860ffbe53df5 +Description: ROCm Communication Collectives Library + ROCm Communication Collectives Library + Optimized primitives for collective multi-GPU communication +Maintainer: RCCL Maintainer +Recommends: rccl-asan-dev (>=2.20.5.60200) +Version: 2.20.5.60200-66~20.04 +Installed-Size: 1057824 + +Package: rccl-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 82ac8328c0d4c57f79df95f5adf350a34e9b5106 +Depends: rccl (= 2.20.5.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rccl-dbgsym/rccl-dbgsym_2.20.5.60200-66~20.04_amd64.deb +Size: 1250500 +SHA256: 5672a8eb1b48909d0b7bfeaa0f75b2a81b7243a58117faf7e9b9ec52a8088ff2 +SHA1: 90f2fc12b041ef99cf25f8be40ce4f790bb04d23 +MD5sum: bc1fc046d89ca86590c989da64156ddb +Description: debug symbols for rccl +Maintainer: RCCL Maintainer +Package-Type: ddeb +Version: 2.20.5.60200-66~20.04 +Installed-Size: 6345 + +Package: rccl-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 82ac8328c0d4c57f79df95f5adf350a34e9b5106 +Depends: rccl-rpath6.2.0 (= 2.20.5.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rccl-dbgsym-rpath6.2.0/rccl-dbgsym-rpath6.2.0_2.20.5.60200-66~20.04_amd64.deb +Size: 1250376 +SHA256: 485ef175fbc931cd6d778614dfe1df34adceeda613df7d9d00cb958c8d15fbc1 +SHA1: 42fc88330f086dbda95c241108c10230aa5e8c14 +MD5sum: 1bfe9f816a56df5c459066aa386edfa9 +Description: debug symbols for rccl +Maintainer: RCCL Maintainer +Package-Type: ddeb +Version: 2.20.5.60200-66~20.04 +Installed-Size: 6345 + +Package: rccl-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 82ac8328c0d4c57f79df95f5adf350a34e9b5106 +Depends: rccl6.2.0 (= 2.20.5.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rccl-dbgsym6.2.0/rccl-dbgsym6.2.0_2.20.5.60200-66~20.04_amd64.deb +Size: 1250548 +SHA256: 1a8a78084c473ba2a4ddf9030f305eacebc314b9034589716a1a636e12b51bc1 +SHA1: a725830dc752a3990dbd350345b26e2c55281a48 +MD5sum: 47a9d801a28cf4233f22ce11f0bcdc3f +Description: debug symbols for rccl +Maintainer: RCCL Maintainer +Package-Type: ddeb +Version: 2.20.5.60200-66~20.04 +Installed-Size: 6345 + +Package: rccl-dev +Architecture: amd64 +Depends: rccl (>= 2.20.5.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rccl-dev/rccl-dev_2.20.5.60200-66~20.04_amd64.deb +Size: 160112 +SHA256: 354b96e606de9ab880ed9baa6f04adcdf8c0e6ae40554f9a9fe2f51c3560a06b +SHA1: 451ffbe754b121e40cff08dc219ac3f9ea4d410b +MD5sum: 814bdd6b9d13dd9bdd137cb225c9fe76 +Description: ROCm Communication Collectives Library + ROCm Communication Collectives Library + Optimized primitives for collective multi-GPU communication +Maintainer: RCCL Maintainer +Version: 2.20.5.60200-66~20.04 +Installed-Size: 17430 + +Package: rccl-dev-rpath6.2.0 +Architecture: amd64 +Depends: rccl-rpath6.2.0 (>= 2.20.5.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rccl-dev-rpath6.2.0/rccl-dev-rpath6.2.0_2.20.5.60200-66~20.04_amd64.deb +Size: 160184 +SHA256: 0dc0bb55faebe38fb4f63c5bc35d0950e27cdb1aa6de3f8367f51d0e61bbd220 +SHA1: 32072e99426346f165be4c67afb05f179caaf607 +MD5sum: 0600561b4c9e374d3998928b19e8f5d1 +Description: ROCm Communication Collectives Library + ROCm Communication Collectives Library + Optimized primitives for collective multi-GPU communication +Maintainer: RCCL Maintainer +Version: 2.20.5.60200-66~20.04 +Installed-Size: 17430 + +Package: rccl-dev6.2.0 +Architecture: amd64 +Depends: rccl6.2.0 (>= 2.20.5.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rccl-dev6.2.0/rccl-dev6.2.0_2.20.5.60200-66~20.04_amd64.deb +Size: 160272 +SHA256: 0dedbffa5bb272d656086a9586e3705551345945f35f4f6be6dc8a27b63127a9 +SHA1: 9796e8a4416e59debd500818d1046611ca320ded +MD5sum: 6e2e2edfd1199f09e7e968daff0a9069 +Description: ROCm Communication Collectives Library + ROCm Communication Collectives Library + Optimized primitives for collective multi-GPU communication +Maintainer: RCCL Maintainer +Version: 2.20.5.60200-66~20.04 +Installed-Size: 17430 + +Package: rccl-rdma-sharp-plugins +Version: 1.0.60200-66~20.04 +Architecture: amd64 +Maintainer: rccl-maintainer@amd.com +Installed-Size: 334 +Depends: libc6 (>= 2.14), libibverbs1 (>= 28), sharp, ucx +Homepage: http://www.amd.com +Priority: extra +Section: libs +Filename: pool/main/r/rccl-rdma-sharp-plugins/rccl-rdma-sharp-plugins_1.0.60200-66~20.04_amd64.deb +Size: 111318 +SHA256: 62f48150481f8d6549f6bb2bfcd79821f3f1ea50d4734e88ec1342c5ad04fe80 +SHA1: 0091c926709865427390c0fc6a79dd5f58843993 +MD5sum: 94686949a5122e6ddb8da9e05c5c3ae7 +Description: RDMA and SHARP plugin for NCCL + Plugin enabled RDMA and switch collectives(SHARP) in RCCL + +Package: rccl-rdma-sharp-plugins-rpath6.2.0 +Version: 1.0.60200-66~20.04 +Architecture: amd64 +Maintainer: rccl-maintainer@amd.com +Installed-Size: 334 +Depends: libc6 (>= 2.14), libibverbs1 (>= 28), sharp, ucx +Homepage: http://www.amd.com +Priority: extra +Section: libs +Filename: pool/main/r/rccl-rdma-sharp-plugins-rpath6.2.0/rccl-rdma-sharp-plugins-rpath6.2.0_1.0.60200-66~20.04_amd64.deb +Size: 69180 +SHA256: 5b86ea986685e8e376b848ac9e0cff8bb3b60d8443e1cd41d1b4bdcb5f41e2d9 +SHA1: 8d7e8a3e3c24a83a482ec219e446d4f758078082 +MD5sum: 97b49319ac0030f4e0cce3f55ef0200c +Description: RDMA and SHARP plugin for NCCL + Plugin enabled RDMA and switch collectives(SHARP) in RCCL + +Package: rccl-rdma-sharp-plugins6.2.0 +Version: 1.0.60200-66~20.04 +Architecture: amd64 +Maintainer: rccl-maintainer@amd.com +Installed-Size: 334 +Depends: libc6 (>= 2.14), libibverbs1 (>= 28), sharp, ucx +Homepage: http://www.amd.com +Priority: extra +Section: libs +Filename: pool/main/r/rccl-rdma-sharp-plugins6.2.0/rccl-rdma-sharp-plugins6.2.0_1.0.60200-66~20.04_amd64.deb +Size: 69096 +SHA256: 0391aa8a74069ea442332779f12a404a93ffc101bb6b04ba8f22a6b02661c2bf +SHA1: 49fe7c11c9434043a1ce0dcdfe7bc59790700b66 +MD5sum: e16a5162d91cdc2ebe8ac0193bb635c0 +Description: RDMA and SHARP plugin for NCCL + Plugin enabled RDMA and switch collectives(SHARP) in RCCL + +Package: rccl-rpath6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd-rpath6.2.0 (>= 4.5.0), rocm-smi-lib-rpath6.2.0 (>= 4.0.0), rocm-core-rpath6.2.0, libc6 (>= 2.17), libgcc-s1 (>= 3.0), libstdc++6 (>= 9) +Priority: optional +Section: devel +Filename: pool/main/r/rccl-rpath6.2.0/rccl-rpath6.2.0_2.20.5.60200-66~20.04_amd64.deb +Size: 63014604 +SHA256: 62107c2432536c2f7aa3baa413c17bbec265c4c8483c48383c845d11be4fca36 +SHA1: bbb7af612475644bb0ef4dd730e605107b8f365a +MD5sum: f9e4e45e022084bf405cb3ae53f1e98f +Description: ROCm Communication Collectives Library + ROCm Communication Collectives Library + Optimized primitives for collective multi-GPU communication +Maintainer: RCCL Maintainer +Recommends: rccl-dev-rpath6.2.0 (>=2.20.5.60200) +Version: 2.20.5.60200-66~20.04 +Installed-Size: 1821373 + +Package: rccl-unittests +Architecture: amd64 +Depends: rccl (>= 2.20.5.60200), libc6 (>= 2.14), libgcc-s1 (>= 3.0), libstdc++6 (>= 9) +Priority: optional +Section: devel +Filename: pool/main/r/rccl-unittests/rccl-unittests_2.20.5.60200-66~20.04_amd64.deb +Size: 352754 +SHA256: 51677dc714a5d20189e246321ee60b0bc495500822954eef4432d6c9e584143f +SHA1: 2f4e7c10e418f7c934eb16aedfd9b02b141f907b +MD5sum: 869f70bd491ebb26bc6713cdb12d48d5 +Description: ROCm Communication Collectives Library + ROCm Communication Collectives Library + Optimized primitives for collective multi-GPU communication +Maintainer: RCCL Maintainer +Version: 2.20.5.60200-66~20.04 +Installed-Size: 1619 + +Package: rccl-unittests-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 71ccf98b7eb706ff6f98aa5690bd2c581ad41db4 +Depends: rccl-unittests (= 2.20.5.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rccl-unittests-dbgsym/rccl-unittests-dbgsym_2.20.5.60200-66~20.04_amd64.deb +Size: 856476 +SHA256: f7e16f740fdf0446f15157c85307dcf52e600bb0ee7a75273dcc3d9fbc9fbf40 +SHA1: fcde67a92755bd2934ec98b5b088938b0a11d05f +MD5sum: 5f1e07dcc3bae8fcb0dd01c51881dd8f +Description: debug symbols for rccl-unittests +Maintainer: RCCL Maintainer +Package-Type: ddeb +Version: 2.20.5.60200-66~20.04 +Installed-Size: 4748 + +Package: rccl-unittests-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 71ccf98b7eb706ff6f98aa5690bd2c581ad41db4 +Depends: rccl-unittests-rpath6.2.0 (= 2.20.5.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rccl-unittests-dbgsym-rpath6.2.0/rccl-unittests-dbgsym-rpath6.2.0_2.20.5.60200-66~20.04_amd64.deb +Size: 856048 +SHA256: 209dda6c80ea5b20402a43b56b77c73ad6c38e1581ff08c28b0ddcea871e2cf0 +SHA1: 4c027d43164c4330303c242695e051c9ce5d8dab +MD5sum: bad428305825b933d1929a2cde48c798 +Description: debug symbols for rccl-unittests +Maintainer: RCCL Maintainer +Package-Type: ddeb +Version: 2.20.5.60200-66~20.04 +Installed-Size: 4748 + +Package: rccl-unittests-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 71ccf98b7eb706ff6f98aa5690bd2c581ad41db4 +Depends: rccl-unittests6.2.0 (= 2.20.5.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rccl-unittests-dbgsym6.2.0/rccl-unittests-dbgsym6.2.0_2.20.5.60200-66~20.04_amd64.deb +Size: 856656 +SHA256: 792578173c0636eb3f2751cd2e2d4bcdc1e93885029cf877c8ca43b4a9e5ae93 +SHA1: a9fcbf6ea3528d6f0d4853f9c1bb40fe887fe630 +MD5sum: b1a115b15eb1b5c8ed1bcc2fa6cdd3a9 +Description: debug symbols for rccl-unittests +Maintainer: RCCL Maintainer +Package-Type: ddeb +Version: 2.20.5.60200-66~20.04 +Installed-Size: 4748 + +Package: rccl-unittests-rpath6.2.0 +Architecture: amd64 +Depends: rccl-rpath6.2.0 (>= 2.20.5.60200), libc6 (>= 2.14), libgcc-s1 (>= 3.0), libstdc++6 (>= 9) +Priority: optional +Section: devel +Filename: pool/main/r/rccl-unittests-rpath6.2.0/rccl-unittests-rpath6.2.0_2.20.5.60200-66~20.04_amd64.deb +Size: 353820 +SHA256: 1e17cc70857a421a7bfd364b417ab8c5f6f89529ffee22baef0be4154545bb28 +SHA1: 4e5c8d16aa9818401551921eec7e3c9608bca8dc +MD5sum: d739276ddb8374660145cf95b3c77d3a +Description: ROCm Communication Collectives Library + ROCm Communication Collectives Library + Optimized primitives for collective multi-GPU communication +Maintainer: RCCL Maintainer +Version: 2.20.5.60200-66~20.04 +Installed-Size: 1619 + +Package: rccl-unittests6.2.0 +Architecture: amd64 +Depends: rccl6.2.0 (>= 2.20.5.60200), libc6 (>= 2.14), libgcc-s1 (>= 3.0), libstdc++6 (>= 9) +Priority: optional +Section: devel +Filename: pool/main/r/rccl-unittests6.2.0/rccl-unittests6.2.0_2.20.5.60200-66~20.04_amd64.deb +Size: 353788 +SHA256: 95aed1d73f29bd8d8c517f4f9509d8b4863b96b94d6cf7a239f0ac05dcedcd97 +SHA1: 625f345062aabef3108aaa27563e459b8b39ad2b +MD5sum: 3cc0395ea198394e2340de1953f5e844 +Description: ROCm Communication Collectives Library + ROCm Communication Collectives Library + Optimized primitives for collective multi-GPU communication +Maintainer: RCCL Maintainer +Version: 2.20.5.60200-66~20.04 +Installed-Size: 1619 + +Package: rccl6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd6.2.0 (>= 4.5.0), rocm-smi-lib6.2.0 (>= 4.0.0), rocm-core6.2.0, libc6 (>= 2.17), libgcc-s1 (>= 3.0), libstdc++6 (>= 9) +Priority: optional +Section: devel +Filename: pool/main/r/rccl6.2.0/rccl6.2.0_2.20.5.60200-66~20.04_amd64.deb +Size: 63015392 +SHA256: 2b3ce1ca2e58e891963f26d4bd31ae45894480483f691d371f269e698f75f8eb +SHA1: 9489ad8f9f2673cd6bbfad177868bc2ac2407293 +MD5sum: a89aca479736a4d9ed7711d5e1b0f8cd +Description: ROCm Communication Collectives Library + ROCm Communication Collectives Library + Optimized primitives for collective multi-GPU communication +Maintainer: RCCL Maintainer +Recommends: rccl-dev6.2.0 (>=2.20.5.60200) +Version: 2.20.5.60200-66~20.04 +Installed-Size: 1821373 + +Package: rdc +Architecture: amd64 +Depends: amd-smi-lib, libc6 +Priority: optional +Section: devel +Filename: pool/main/r/rdc/rdc_0.3.0.60200-66~20.04_amd64.deb +Size: 17997562 +SHA256: 91b03d101f712dceef2eccbaecd899264e739e366f8312d4f67849f16e0cd457 +SHA1: fcd7cce36e90e26ad479ad02f0ae486fdb1f1f0d +MD5sum: 04fedff31506140a700b94e3d3e8f912 +Description: Radeon Data Center Tools +Homepage: https://github.com/RadeonOpenCompute/rdc +Maintainer: RDC Support +Version: 0.3.0.60200-66~20.04 +Installed-Size: 135988 + +Package: rdc-rpath6.2.0 +Architecture: amd64 +Depends: amd-smi-lib-rpath6.2.0, libc6 +Priority: optional +Section: devel +Filename: pool/main/r/rdc-rpath6.2.0/rdc-rpath6.2.0_0.3.0.60200-66~20.04_amd64.deb +Size: 11336520 +SHA256: c91922b5f407b14689a0546de853673a0840b392d432469e6fc4c1ec4152d5c5 +SHA1: b5b9173f025ef915833c050d46b35e73fe0f5c67 +MD5sum: b3f06e7024b10812c7e7b37f08a22254 +Description: Radeon Data Center Tools +Homepage: https://github.com/RadeonOpenCompute/rdc +Maintainer: RDC Support +Version: 0.3.0.60200-66~20.04 +Installed-Size: 135988 + +Package: rdc6.2.0 +Architecture: amd64 +Depends: amd-smi-lib6.2.0, libc6 +Priority: optional +Section: devel +Filename: pool/main/r/rdc6.2.0/rdc6.2.0_0.3.0.60200-66~20.04_amd64.deb +Size: 11335860 +SHA256: 036806cbda93c5b117e6c29f71ce9ea08645dc588d2f81232828797a54562fd0 +SHA1: 000c9c5c889caf400b8bda9eec73cf99b19a39eb +MD5sum: abdfd58d159142fe4c49ae942e427c5d +Description: Radeon Data Center Tools +Homepage: https://github.com/RadeonOpenCompute/rdc +Maintainer: RDC Support +Version: 0.3.0.60200-66~20.04 +Installed-Size: 135988 + +Package: rocal +Architecture: amd64 +Depends: rpp, mivisionx +Priority: optional +Section: devel +Filename: pool/main/r/rocal/rocal_1.0.0.60200-66~20.04_amd64.deb +Size: 1169518 +SHA256: d9893fa03a81d33b134338411ed93cf6c065f75db630f17438c8a4de0ec246c5 +SHA1: c81eb623ee70771fc6a057ec8b83344826c6b983 +MD5sum: 05d77e2dc84af4d4e73699f95587f113 +Description: AMD rocAL is a comprehensive augmentation library. rocAL runtime package provides rocAL libraries and license.txt +Homepage: https://github.com/ROCm/rocAL +Maintainer: rocAL Support +Version: 1.0.0.60200-66~20.04 +Installed-Size: 7142 + +Package: rocal-dev +Architecture: amd64 +Depends: rocal, rpp-dev, mivisionx-dev, liblmdb-dev +Priority: optional +Section: devel +Filename: pool/main/r/rocal-dev/rocal-dev_1.0.0.60200-66~20.04_amd64.deb +Size: 14792 +SHA256: 7e23bab43d8b10991405f5bbe4bf507fdb33c7835d5e33af9f75316035b9be00 +SHA1: f1a88c5f05c1941078bf2a5203c69740c307866b +MD5sum: 3946dae3a734a72d2c1265fef1e86ef8 +Description: AMD rocAL is a comprehensive augmentation library. rocAL develop package provides rocAL libraries, header files, samples, and license.txt +Homepage: https://github.com/ROCm/rocAL +Maintainer: rocAL Support +Version: 1.0.0.60200-66~20.04 +Installed-Size: 170 + +Package: rocal-dev-rpath6.2.0 +Architecture: amd64 +Depends: rocal-rpath6.2.0, rpp-dev-rpath6.2.0, mivisionx-dev-rpath6.2.0, liblmdb-dev +Priority: optional +Section: devel +Filename: pool/main/r/rocal-dev-rpath6.2.0/rocal-dev-rpath6.2.0_1.0.0.60200-66~20.04_amd64.deb +Size: 12664 +SHA256: 71bbe9c7b3cb180540d4a8c5de62d896619212ad3d9744ddf3fe34076da6cbdb +SHA1: 6604317e5a5bde3a744e2a8a2cdbdca7e8bcc196 +MD5sum: 75eaf71339f40019b2a7451a58f9768c +Description: AMD rocAL is a comprehensive augmentation library. rocAL develop package provides rocAL libraries, header files, samples, and license.txt +Homepage: https://github.com/ROCm/rocAL +Maintainer: rocAL Support +Version: 1.0.0.60200-66~20.04 +Installed-Size: 170 + +Package: rocal-dev6.2.0 +Architecture: amd64 +Depends: rocal6.2.0, rpp-dev6.2.0, mivisionx-dev6.2.0, liblmdb-dev +Priority: optional +Section: devel +Filename: pool/main/r/rocal-dev6.2.0/rocal-dev6.2.0_1.0.0.60200-66~20.04_amd64.deb +Size: 12664 +SHA256: c310fe62d7e97c31d64a90b146c781839657817a017d24940f3ec517e78a0bde +SHA1: 15279cd95843430046ffb5560f99cfc030651598 +MD5sum: 87f7d44299aa0ac98fb91d188120adf8 +Description: AMD rocAL is a comprehensive augmentation library. rocAL develop package provides rocAL libraries, header files, samples, and license.txt +Homepage: https://github.com/ROCm/rocAL +Maintainer: rocAL Support +Version: 1.0.0.60200-66~20.04 +Installed-Size: 170 + +Package: rocal-rpath6.2.0 +Architecture: amd64 +Depends: rpp-rpath6.2.0, mivisionx-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocal-rpath6.2.0/rocal-rpath6.2.0_1.0.0.60200-66~20.04_amd64.deb +Size: 802188 +SHA256: 77631ed8c59e9ce0a142da5dacc22d73b60daf3395bbea8a544f309762e78a65 +SHA1: 521ea4d9f568a914cfd771c4075ca70564f885fa +MD5sum: 70d4f3d4978b3f63ed03ae53b37cdebc +Description: AMD rocAL is a comprehensive augmentation library. rocAL runtime package provides rocAL libraries and license.txt +Homepage: https://github.com/ROCm/rocAL +Maintainer: rocAL Support +Version: 1.0.0.60200-66~20.04 +Installed-Size: 7142 + +Package: rocal-test +Architecture: amd64 +Depends: rocal-dev +Priority: optional +Section: devel +Filename: pool/main/r/rocal-test/rocal-test_1.0.0.60200-66~20.04_amd64.deb +Size: 32027952 +SHA256: 89827a1696cbf19fe0dfbf5a8593624ce0cd78be9e104a7f237009f284f5488e +SHA1: d6c052a9ba16b7cb6d60de59dbfe6b677f9971a8 +MD5sum: 4ab799cf1847c47e9ccfab743296256a +Description: AMD rocAL is a comprehensive augmentation library. rocAL Test package provides rocAL Test Components +Homepage: https://github.com/ROCm/rocAL +Maintainer: rocAL Support +Version: 1.0.0.60200-66~20.04 +Installed-Size: 34869 + +Package: rocal-test-rpath6.2.0 +Architecture: amd64 +Depends: rocal-dev-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocal-test-rpath6.2.0/rocal-test-rpath6.2.0_1.0.0.60200-66~20.04_amd64.deb +Size: 31883344 +SHA256: d366c5b2db8c866cd8eff6b9df99b0fb0e6ea97a6437d3244545b4a2ccb5c41a +SHA1: 6b4845d610d76f27f5877ac71860c81b5cc0200c +MD5sum: 30bdfbd6021a30b70ec30bd6410070cb +Description: AMD rocAL is a comprehensive augmentation library. rocAL Test package provides rocAL Test Components +Homepage: https://github.com/ROCm/rocAL +Maintainer: rocAL Support +Version: 1.0.0.60200-66~20.04 +Installed-Size: 34869 + +Package: rocal-test6.2.0 +Architecture: amd64 +Depends: rocal-dev6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocal-test6.2.0/rocal-test6.2.0_1.0.0.60200-66~20.04_amd64.deb +Size: 31883384 +SHA256: e812d0ff1d6c8d3d8e5340df16292f6824f2b03c423aa55f956aba5efbc71a41 +SHA1: eac8c5051b2641e9d632c3536059f8079910d02f +MD5sum: 0e2cd625a4316acc1a95973d8bfb79b6 +Description: AMD rocAL is a comprehensive augmentation library. rocAL Test package provides rocAL Test Components +Homepage: https://github.com/ROCm/rocAL +Maintainer: rocAL Support +Version: 1.0.0.60200-66~20.04 +Installed-Size: 34869 + +Package: rocal6.2.0 +Architecture: amd64 +Depends: rpp6.2.0, mivisionx6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocal6.2.0/rocal6.2.0_1.0.0.60200-66~20.04_amd64.deb +Size: 803392 +SHA256: 8a77daf4aebaa6600d326299f52815c693578f7220f5f71d43493c5a95b213d2 +SHA1: 1afed62dbf144b5f22c534f6bd6be2bdf1698231 +MD5sum: 18f73968d56ba88774a24db288a70e33 +Description: AMD rocAL is a comprehensive augmentation library. rocAL runtime package provides rocAL libraries and license.txt +Homepage: https://github.com/ROCm/rocAL +Maintainer: rocAL Support +Version: 1.0.0.60200-66~20.04 +Installed-Size: 7142 + +Package: rocalution +Architecture: amd64 +Depends: hip-runtime-amd (>= 4.5.0), rocsparse (>= 1.12.10), rocblas (>= 2.22.0), rocrand (>= 2.1.0), rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocalution/rocalution_3.2.0.60200-66~20.04_amd64.deb +Size: 4565782 +SHA256: 2ee9c88ce8c13c71aba4465fc29a274d1618e25a8a8b39b9720037608f16fbdb +SHA1: e7e01e63227403accdfe5df49406a91f2702deb2 +MD5sum: b8cfad2a301588fe1d30115b2c3afece +Description: ROCm library for sparse linear systems +Maintainer: rocALUTION Maintainer +Recommends: rocalution-dev (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 162424 + +Package: rocalution-asan +Architecture: amd64 +Depends: hip-runtime-amd-asan (>= 4.5.0), rocsparse (>= 1.12.10), rocblas (>= 2.22.0), rocrand (>= 2.1.0), rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/r/rocalution-asan/rocalution-asan_3.2.0.60200-66~20.04_amd64.deb +Size: 6141752 +SHA256: 188dd2d04e90731a71688c76cc89728ebe1dd70e3ac62365c795890552ab4e71 +SHA1: e6a25b44f93710ff7034e2d020da9b135866d5c2 +MD5sum: a01fdbefaa107105e1977c763493aa77 +Description: ROCm library for sparse linear systems +Maintainer: rocALUTION Maintainer +Recommends: rocalution-asan-dev (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 192449 + +Package: rocalution-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: d1708bd4d1f87efc3e81565b32943a52a488e2ee affc9de8e6ff6accbf4623d08e229cfe5cf008b0 +Depends: rocalution-asan (= 3.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocalution-asan-dbgsym/rocalution-asan-dbgsym_3.2.0.60200-66~20.04_amd64.deb +Size: 10879852 +SHA256: d4fd6e3c959d9f449f8b46a21198fa8aaeea4418d63a750e1503446d09a6fbe4 +SHA1: 561e032d824702e813ea97a0e3432ba1ae6f25d4 +MD5sum: 3a00afb65cb5a0dd5f2f758979fdf254 +Description: debug symbols for rocalution-asan +Maintainer: rocALUTION Maintainer +Package-Type: ddeb +Version: 3.2.0.60200-66~20.04 +Installed-Size: 15216 + +Package: rocalution-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: d1708bd4d1f87efc3e81565b32943a52a488e2ee affc9de8e6ff6accbf4623d08e229cfe5cf008b0 +Depends: rocalution-asan-rpath6.2.0 (= 3.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocalution-asan-dbgsym-rpath6.2.0/rocalution-asan-dbgsym-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 10880008 +SHA256: e78bde7bf86a0e1fcaa5a8dbe749c63d94ab014c1a4a30c585daa4f709ddb789 +SHA1: 7f962f2f089ed4b859153593f8085039848648b0 +MD5sum: da79ea237f96ab3e669d0b738e05c69d +Description: debug symbols for rocalution-asan +Maintainer: rocALUTION Maintainer +Package-Type: ddeb +Version: 3.2.0.60200-66~20.04 +Installed-Size: 15216 + +Package: rocalution-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: d1708bd4d1f87efc3e81565b32943a52a488e2ee affc9de8e6ff6accbf4623d08e229cfe5cf008b0 +Depends: rocalution-asan6.2.0 (= 3.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocalution-asan-dbgsym6.2.0/rocalution-asan-dbgsym6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 10880028 +SHA256: f6d83698dfa1f3f64052c485a8e0f5bde05dc0b836df95f609a77551c04bfaee +SHA1: 5ea110a76f08925ff896e072c075f41a9b4930bd +MD5sum: ed52cfd6041f52a492c80600b87a60e2 +Description: debug symbols for rocalution-asan +Maintainer: rocALUTION Maintainer +Package-Type: ddeb +Version: 3.2.0.60200-66~20.04 +Installed-Size: 15216 + +Package: rocalution-asan-rpath6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd-asan-rpath6.2.0 (>= 4.5.0), rocsparse-rpath6.2.0 (>= 1.12.10), rocblas-rpath6.2.0 (>= 2.22.0), rocrand-rpath6.2.0 (>= 2.1.0), rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocalution-asan-rpath6.2.0/rocalution-asan-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 6143020 +SHA256: f4e4623e413e096e4e2fdd5b86ecfad65166e92492369059e0c8c0d7d92a43db +SHA1: 78e12b6f0a4a4550b6d79f91309fc685aed9a65b +MD5sum: e762aa99f9909f0062c86176bb34a930 +Description: ROCm library for sparse linear systems +Maintainer: rocALUTION Maintainer +Recommends: rocalution-asan-dev (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 192449 + +Package: rocalution-asan6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd-asan6.2.0 (>= 4.5.0), rocsparse6.2.0 (>= 1.12.10), rocblas6.2.0 (>= 2.22.0), rocrand6.2.0 (>= 2.1.0), rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocalution-asan6.2.0/rocalution-asan6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 6144664 +SHA256: b5b81f01fe5776ecf6d0e671a088d97fcb9cbf24f009da2d1f788de919fd8c95 +SHA1: bc0d3c8cbb136ddd684b596a40855a890e33d383 +MD5sum: b9b5f720a78dceebdd139d553e6855ca +Description: ROCm library for sparse linear systems +Maintainer: rocALUTION Maintainer +Recommends: rocalution-asan-dev (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 192449 + +Package: rocalution-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 6883b77d5b5918010b3f063c847d824123270e02 ce15a63877802bf9e97efbdcf1b0c85475457460 +Depends: rocalution (= 3.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocalution-dbgsym/rocalution-dbgsym_3.2.0.60200-66~20.04_amd64.deb +Size: 11240698 +SHA256: 3cb4e1e434aa328a825f7aace31515eb7a3ed135673cbd1de1b915f01eceec9f +SHA1: 1c0b5f797d969f1c98e8c6fd4b7156abd74d80dc +MD5sum: c915cc76fe0791269ce266c4928db43c +Description: debug symbols for rocalution +Maintainer: rocALUTION Maintainer +Package-Type: ddeb +Version: 3.2.0.60200-66~20.04 +Installed-Size: 78585 + +Package: rocalution-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 6883b77d5b5918010b3f063c847d824123270e02 ce15a63877802bf9e97efbdcf1b0c85475457460 +Depends: rocalution-rpath6.2.0 (= 3.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocalution-dbgsym-rpath6.2.0/rocalution-dbgsym-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 11237832 +SHA256: f668416821d383d47d5b20564ee7023fb7f3fdcf169a26270896e06e63c9cc57 +SHA1: e07f851a1e71ee042d772224053c686d939a9bdd +MD5sum: 385b65ef8d7a32fc5e454b5aba0632eb +Description: debug symbols for rocalution +Maintainer: rocALUTION Maintainer +Package-Type: ddeb +Version: 3.2.0.60200-66~20.04 +Installed-Size: 78585 + +Package: rocalution-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 6883b77d5b5918010b3f063c847d824123270e02 ce15a63877802bf9e97efbdcf1b0c85475457460 +Depends: rocalution6.2.0 (= 3.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocalution-dbgsym6.2.0/rocalution-dbgsym6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 11235448 +SHA256: 282af05505a9e63a43047717e1a26eecf6e953f0fc3bebe903b6c29a6953c98d +SHA1: da5185c46e201576ae3a4613a5420c39cb3285ac +MD5sum: cebd6785866a613d23714a370e48684c +Description: debug symbols for rocalution +Maintainer: rocALUTION Maintainer +Package-Type: ddeb +Version: 3.2.0.60200-66~20.04 +Installed-Size: 78585 + +Package: rocalution-dev +Architecture: amd64 +Depends: rocalution (>= 3.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocalution-dev/rocalution-dev_3.2.0.60200-66~20.04_amd64.deb +Size: 42966 +SHA256: a12efe90f42d4c3d0a1749c3ff8de76dd6d4dd2906a265a812e8a40441667c0b +SHA1: 5e51eca76a07f921b6938e53474c2f3f07f434b4 +MD5sum: 461ab2bd55f27e12fd848a7d131ad6eb +Description: ROCm library for sparse linear systems +Maintainer: rocALUTION Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 422 + +Package: rocalution-dev-rpath6.2.0 +Architecture: amd64 +Depends: rocalution-rpath6.2.0 (>= 3.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocalution-dev-rpath6.2.0/rocalution-dev-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 42960 +SHA256: 29b6f4c2e2b5feb4c6bfe1eb35b7e3574b835da47b8a4e372508421610c9e077 +SHA1: b4847c0ae6f449b8ef8fe2d0c283b377262468f3 +MD5sum: 39de58c43748267b765e8adc0ea0aff5 +Description: ROCm library for sparse linear systems +Maintainer: rocALUTION Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 422 + +Package: rocalution-dev6.2.0 +Architecture: amd64 +Depends: rocalution6.2.0 (>= 3.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocalution-dev6.2.0/rocalution-dev6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 42932 +SHA256: d7453d8cf368d38f9cfbddb0ff749ff0c0b1a4bb3b81cb91b3bbb427e6f51a76 +SHA1: 000163f509280e37a0c8c9ad81d97319cf27c3d3 +MD5sum: 351e7383cfe841963e52a406239e9bf6 +Description: ROCm library for sparse linear systems +Maintainer: rocALUTION Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 422 + +Package: rocalution-rpath6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd-rpath6.2.0 (>= 4.5.0), rocsparse-rpath6.2.0 (>= 1.12.10), rocblas-rpath6.2.0 (>= 2.22.0), rocrand-rpath6.2.0 (>= 2.1.0), rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocalution-rpath6.2.0/rocalution-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 4573372 +SHA256: 12f16edc286ce669df149eac439d1d1a82a28cf1db213f94d531d3af8c223470 +SHA1: 10103ffd01b5e6e5a3a5d4f1463b8a99defbdb67 +MD5sum: 29f5bf2e0571041fd63f2d6f55fbe1f2 +Description: ROCm library for sparse linear systems +Maintainer: rocALUTION Maintainer +Recommends: rocalution-dev-rpath6.2.0 (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 162424 + +Package: rocalution6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd6.2.0 (>= 4.5.0), rocsparse6.2.0 (>= 1.12.10), rocblas6.2.0 (>= 2.22.0), rocrand6.2.0 (>= 2.1.0), rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocalution6.2.0/rocalution6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 4567572 +SHA256: 2e8a4895f0b98a0b3b7a5f272f05d181b0b38654c1cb1d39c364d3e9c0a4304a +SHA1: 6943780c6406f0f6fe45b0e561f26b0cd7d0e2d4 +MD5sum: b993fcaa126037a02f44b796893be954 +Description: ROCm library for sparse linear systems +Maintainer: rocALUTION Maintainer +Recommends: rocalution-dev6.2.0 (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 162424 + +Package: rocblas +Architecture: amd64 +Depends: hip-runtime-amd (>= 4.5.0), rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocblas/rocblas_4.2.0.60200-66~20.04_amd64.deb +Size: 143756500 +SHA256: c70780f3d1de0e9f3bea397e0ca20be4819339765a66948be54f0137cfeb3a52 +SHA1: 39d6ecba292baaadc72f5b21b956c33512aa98b3 +MD5sum: 701560d31c92525cd9c6963b679439ba +Description: rocBLAS is the AMD library for BLAS in ROCm. Implemented using the HIP language and optimized for AMD GPUs +Maintainer: rocBLAS Maintainer +Recommends: rocblas-dev (>=4.2.0.60200) +Version: 4.2.0.60200-66~20.04 +Installed-Size: 5798309 + +Package: rocblas-asan +Architecture: amd64 +Depends: hip-runtime-amd-asan (>= 4.5.0), rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/r/rocblas-asan/rocblas-asan_4.2.0.60200-66~20.04_amd64.deb +Size: 284205208 +SHA256: 7d2c24feba0f39bd01ea24af04e6e065309f40358a7e7e76ea6d6071f264a31c +SHA1: 2a792117fe224311bc7f76f47004692b6ad881e2 +MD5sum: 29d0ae0b6ae90f234c17e32db46f531d +Description: rocBLAS is the AMD library for BLAS in ROCm. Implemented using the HIP language and optimized for AMD GPUs +Maintainer: rocBLAS Maintainer +Recommends: rocblas-asan-dev (>=4.2.0.60200) +Version: 4.2.0.60200-66~20.04 +Installed-Size: 2848128 + +Package: rocblas-asan-rpath6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd-asan-rpath6.2.0 (>= 4.5.0), rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocblas-asan-rpath6.2.0/rocblas-asan-rpath6.2.0_4.2.0.60200-66~20.04_amd64.deb +Size: 284207072 +SHA256: 122b5e0d225487e7f33f10514f4bbec833b17367c5008456afa85daf220494fd +SHA1: 8f59bf8f06bee218a1359a83c9202bf36f9b263f +MD5sum: 9a5da87b30ba71f5381d51c3cf2d3a17 +Description: rocBLAS is the AMD library for BLAS in ROCm. Implemented using the HIP language and optimized for AMD GPUs +Maintainer: rocBLAS Maintainer +Recommends: rocblas-asan-dev (>=4.2.0.60200) +Version: 4.2.0.60200-66~20.04 +Installed-Size: 2848128 + +Package: rocblas-asan6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd-asan6.2.0 (>= 4.5.0), rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocblas-asan6.2.0/rocblas-asan6.2.0_4.2.0.60200-66~20.04_amd64.deb +Size: 284232568 +SHA256: c083f79a9f3ad40e33f8de8c292c614ddf4f24d91696080153f5ca354494df0f +SHA1: d5bb4391048e2539d56485f24141bcf513d929b1 +MD5sum: f66820f3de5d7d8cc154d149ed9d9606 +Description: rocBLAS is the AMD library for BLAS in ROCm. Implemented using the HIP language and optimized for AMD GPUs +Maintainer: rocBLAS Maintainer +Recommends: rocblas-asan-dev (>=4.2.0.60200) +Version: 4.2.0.60200-66~20.04 +Installed-Size: 2848128 + +Package: rocblas-dev +Architecture: amd64 +Depends: rocblas (>= 4.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocblas-dev/rocblas-dev_4.2.0.60200-66~20.04_amd64.deb +Size: 91604 +SHA256: eaefe5a7d75ef61314b83af5bb85d8e652a730deaa58e1d600b1e9c2e673673c +SHA1: 769fc38f90dbcc35d67a7ae6b5ebb39825cb0658 +MD5sum: 89073be930e4a9275c8a12e14c99bb5e +Description: rocBLAS is the AMD library for BLAS in ROCm. Implemented using the HIP language and optimized for AMD GPUs +Maintainer: rocBLAS Maintainer +Version: 4.2.0.60200-66~20.04 +Installed-Size: 2530 + +Package: rocblas-dev-rpath6.2.0 +Architecture: amd64 +Depends: rocblas-rpath6.2.0 (>= 4.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocblas-dev-rpath6.2.0/rocblas-dev-rpath6.2.0_4.2.0.60200-66~20.04_amd64.deb +Size: 91704 +SHA256: b2edb471078bc66bf0d11eca5a8ada4c8fc7e9e6bde6c87bfd30d9e7ff7c15ba +SHA1: 0ad6279450de54ffbc677df707cfc1612da88fcc +MD5sum: c693562c8aadb7d362c1fa2a961d5634 +Description: rocBLAS is the AMD library for BLAS in ROCm. Implemented using the HIP language and optimized for AMD GPUs +Maintainer: rocBLAS Maintainer +Version: 4.2.0.60200-66~20.04 +Installed-Size: 2530 + +Package: rocblas-dev6.2.0 +Architecture: amd64 +Depends: rocblas6.2.0 (>= 4.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocblas-dev6.2.0/rocblas-dev6.2.0_4.2.0.60200-66~20.04_amd64.deb +Size: 91768 +SHA256: d33c14ff2881f3db25428107ed8e9d9119a40887ea4c18da78117ff420f33c1d +SHA1: a60e0a6e4326b0dd135aba6946784edea9325b0a +MD5sum: df1ac9757303c9ffaf4eff2045fb2018 +Description: rocBLAS is the AMD library for BLAS in ROCm. Implemented using the HIP language and optimized for AMD GPUs +Maintainer: rocBLAS Maintainer +Version: 4.2.0.60200-66~20.04 +Installed-Size: 2530 + +Package: rocblas-rpath6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd-rpath6.2.0 (>= 4.5.0), rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocblas-rpath6.2.0/rocblas-rpath6.2.0_4.2.0.60200-66~20.04_amd64.deb +Size: 143740640 +SHA256: 34d5845236aacfb4a29aff1d65da7f3870cfe096dd1195a22b8b484c04620c3c +SHA1: 109d48049c5807c7041312c02360b3b1e6c0e511 +MD5sum: d7a8f3b7b601571112348ff805cd390a +Description: rocBLAS is the AMD library for BLAS in ROCm. Implemented using the HIP language and optimized for AMD GPUs +Maintainer: rocBLAS Maintainer +Recommends: rocblas-dev-rpath6.2.0 (>=4.2.0.60200) +Version: 4.2.0.60200-66~20.04 +Installed-Size: 5798309 + +Package: rocblas6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd6.2.0 (>= 4.5.0), rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocblas6.2.0/rocblas6.2.0_4.2.0.60200-66~20.04_amd64.deb +Size: 143740696 +SHA256: 6e5b3caeadf592367f8638db67a70b8dd9231a8257dc2012a9c46e2c5974fff5 +SHA1: b9b43aad9025aab5f34ca8d5f810ac155071c365 +MD5sum: ec7db78aeeb126689d21eb425d26e623 +Description: rocBLAS is the AMD library for BLAS in ROCm. Implemented using the HIP language and optimized for AMD GPUs +Maintainer: rocBLAS Maintainer +Recommends: rocblas-dev6.2.0 (>=4.2.0.60200) +Version: 4.2.0.60200-66~20.04 +Installed-Size: 5798309 + +Package: rocdecode +Architecture: amd64 +Depends: rocm-core, rocm-hip-runtime, libva2, libdrm-amdgpu1, mesa-amdgpu-va-drivers +Priority: optional +Section: devel +Filename: pool/main/r/rocdecode/rocdecode_0.6.0.60200-66~20.04_amd64.deb +Size: 164820 +SHA256: a6764d2f616ea524f6093aa6580c154c7a694128b6e6b8d702697c73e6f73699 +SHA1: ee231e45c067d6e10b49337ea784e77e50600f1f +MD5sum: b7c581f28d111b1503ca6fd50822942a +Description: AMD rocDecode is a high performance video decode SDK for AMD GPUs. rocDecode runtime package provides rocDecode library and license.txt +Homepage: https://github.com/ROCm/rocDecode +Maintainer: rocDecode Support +Version: 0.6.0.60200-66~20.04 +Installed-Size: 860 + +Package: rocdecode-dev +Architecture: amd64 +Depends: rocm-core, rocdecode, rocm-hip-runtime-dev, libva-dev, pkg-config, ffmpeg, libavcodec-dev, libavformat-dev, libavutil-dev +Priority: optional +Section: devel +Filename: pool/main/r/rocdecode-dev/rocdecode-dev_0.6.0.60200-66~20.04_amd64.deb +Size: 34708634 +SHA256: ffbeb9a144b82a219a3d58f3a77035b7224a05bce8a82bba24bd11f244dba7e9 +SHA1: 46169c3b94b244615f157c47cf5baf929f683903 +MD5sum: 6e99354dabd51dddf6cc0fc2ffb47f8d +Description: AMD rocDecode is a high performance video decode SDK for AMD GPUs. rocDecode develop package provides rocDecode library, header files, samples, and license.txt +Homepage: https://github.com/ROCm/rocDecode +Maintainer: rocDecode Support +Version: 0.6.0.60200-66~20.04 +Installed-Size: 35012 + +Package: rocdecode-dev-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0, rocdecode-rpath6.2.0, rocm-hip-runtime-dev-rpath6.2.0, libva-dev, pkg-config, ffmpeg, libavcodec-dev, libavformat-dev, libavutil-dev +Priority: optional +Section: devel +Filename: pool/main/r/rocdecode-dev-rpath6.2.0/rocdecode-dev-rpath6.2.0_0.6.0.60200-66~20.04_amd64.deb +Size: 34913460 +SHA256: c95c594bf99797db1f61e0640720d772018bca786a8e794a38c65c42f49d369a +SHA1: c57edea74a16f893ce154fa8dcb932f407d55831 +MD5sum: f82c72462ff035defa664b0d0b2fbc61 +Description: AMD rocDecode is a high performance video decode SDK for AMD GPUs. rocDecode develop package provides rocDecode library, header files, samples, and license.txt +Homepage: https://github.com/ROCm/rocDecode +Maintainer: rocDecode Support +Version: 0.6.0.60200-66~20.04 +Installed-Size: 35012 + +Package: rocdecode-dev6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0, rocdecode6.2.0, rocm-hip-runtime-dev6.2.0, libva-dev, pkg-config, ffmpeg, libavcodec-dev, libavformat-dev, libavutil-dev +Priority: optional +Section: devel +Filename: pool/main/r/rocdecode-dev6.2.0/rocdecode-dev6.2.0_0.6.0.60200-66~20.04_amd64.deb +Size: 34913440 +SHA256: e71bc81899451dde8c43f9a9cbec8861319adca58b21430f6ae34d4489d0ddb5 +SHA1: 9475ab3ec4104ae220ab32a2e20b15c3e584e38b +MD5sum: 8c900ea637d099d3325e1fe214287399 +Description: AMD rocDecode is a high performance video decode SDK for AMD GPUs. rocDecode develop package provides rocDecode library, header files, samples, and license.txt +Homepage: https://github.com/ROCm/rocDecode +Maintainer: rocDecode Support +Version: 0.6.0.60200-66~20.04 +Installed-Size: 35012 + +Package: rocdecode-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0, rocm-hip-runtime-rpath6.2.0, libva2, libdrm-amdgpu1, mesa-amdgpu-va-drivers +Priority: optional +Section: devel +Filename: pool/main/r/rocdecode-rpath6.2.0/rocdecode-rpath6.2.0_0.6.0.60200-66~20.04_amd64.deb +Size: 123048 +SHA256: ee3388357ebbd857ebcde8f29d067300fc6b577746a5a42b8c37df83724ec8e7 +SHA1: 6121dd5ac7d46b2b1538863d131a3c3b7bed901a +MD5sum: 2c81ff84e6ea59ca63a9234474641dda +Description: AMD rocDecode is a high performance video decode SDK for AMD GPUs. rocDecode runtime package provides rocDecode library and license.txt +Homepage: https://github.com/ROCm/rocDecode +Maintainer: rocDecode Support +Version: 0.6.0.60200-66~20.04 +Installed-Size: 860 + +Package: rocdecode-test +Architecture: amd64 +Depends: rocm-core, rocdecode-dev +Priority: optional +Section: devel +Filename: pool/main/r/rocdecode-test/rocdecode-test_0.6.0.60200-66~20.04_amd64.deb +Size: 6624 +SHA256: b0f27fcd6a1b06dde32e46aeb16599667ca8198e36c912a9a5fc1ac00459832a +SHA1: dce642b5cb6eef3d5337552e0b3fbfdd2274780f +MD5sum: d48691ac2ca3211c479981b3de8554cf +Description: AMD rocDecode is a high performance video decode SDK for AMD GPUs. rocDecode Test package provides rocDecode Test Components +Homepage: https://github.com/ROCm/rocDecode +Maintainer: rocDecode Support +Version: 0.6.0.60200-66~20.04 +Installed-Size: 58 + +Package: rocdecode-test-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0, rocdecode-dev-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocdecode-test-rpath6.2.0/rocdecode-test-rpath6.2.0_0.6.0.60200-66~20.04_amd64.deb +Size: 6520 +SHA256: bb716cfad374bbd065128ee20115680c0822d97d31f3dcc9199b378139c459d3 +SHA1: 045994d4c04f7ff2312b99f5d7a94941c5a347f0 +MD5sum: bf51abaf08f2313e6fea7f808366ca15 +Description: AMD rocDecode is a high performance video decode SDK for AMD GPUs. rocDecode Test package provides rocDecode Test Components +Homepage: https://github.com/ROCm/rocDecode +Maintainer: rocDecode Support +Version: 0.6.0.60200-66~20.04 +Installed-Size: 58 + +Package: rocdecode-test6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0, rocdecode-dev6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocdecode-test6.2.0/rocdecode-test6.2.0_0.6.0.60200-66~20.04_amd64.deb +Size: 6520 +SHA256: ed5fa322b102f1cb5cababf9653e060727714a51c4aa61c63101183cf99ab2fd +SHA1: bb057c88e124c74caafe982ccb8c4613e69e6f80 +MD5sum: f2bf1902bc5fd80be0d8955f04f68ccc +Description: AMD rocDecode is a high performance video decode SDK for AMD GPUs. rocDecode Test package provides rocDecode Test Components +Homepage: https://github.com/ROCm/rocDecode +Maintainer: rocDecode Support +Version: 0.6.0.60200-66~20.04 +Installed-Size: 58 + +Package: rocdecode6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0, rocm-hip-runtime6.2.0, libva2, libdrm-amdgpu1, mesa-amdgpu-va-drivers +Priority: optional +Section: devel +Filename: pool/main/r/rocdecode6.2.0/rocdecode6.2.0_0.6.0.60200-66~20.04_amd64.deb +Size: 123104 +SHA256: 3d9657f3fc0dfc48c4e7054b2f277475088ccce98b09c5adbb311489715ebb6b +SHA1: ab486c19317f2c69b948a496902d2fc1ba592335 +MD5sum: 3cb2044d14fe9c295abb4f2df3afb38a +Description: AMD rocDecode is a high performance video decode SDK for AMD GPUs. rocDecode runtime package provides rocDecode library and license.txt +Homepage: https://github.com/ROCm/rocDecode +Maintainer: rocDecode Support +Version: 0.6.0.60200-66~20.04 +Installed-Size: 860 + +Package: rocfft +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocfft/rocfft_1.0.28.60200-66~20.04_amd64.deb +Size: 100484138 +SHA256: 143214682c4416c183fd172a135eb6afaae017e712721286685622d84a3db168 +SHA1: 8dcdd97a670ab168f11d3b0d9af9892ce554d299 +MD5sum: 4ff74fc583b5ecd65d36b2d79e044216 +Description: ROCm FFT library +Maintainer: rocfft-maintainer@amd.com +Recommends: rocfft-dev (>=1.0.28.60200) +Version: 1.0.28.60200-66~20.04 +Installed-Size: 2073370 + +Package: rocfft-asan +Architecture: amd64 +Depends: rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/r/rocfft-asan/rocfft-asan_1.0.28.60200-66~20.04_amd64.deb +Size: 4591994 +SHA256: d5e8383556187ca31d29d7fd53579b2e88b602c19edae40f2d82ea51239a1f39 +SHA1: 67972809ec9a91d586a08352ae7239126e13f41a +MD5sum: d1411b8051f114cef01c11491599da39 +Description: ROCm FFT library +Maintainer: rocfft-maintainer@amd.com +Recommends: rocfft-asan-dev (>=1.0.28.60200) +Version: 1.0.28.60200-66~20.04 +Installed-Size: 39426 + +Package: rocfft-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 25256302e6c8308f89ca92bbbcdb741a39b07dd6 +Depends: rocfft-asan (= 1.0.28.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocfft-asan-dbgsym/rocfft-asan-dbgsym_1.0.28.60200-66~20.04_amd64.deb +Size: 21479514 +SHA256: 938a109c35ec256b21b4b5bf167cff3d6dcb8fb3258d98e2de4058838c7a4772 +SHA1: ad47ce651e0048bcdfba9f1feef3e0a78c284eee +MD5sum: b1d5ac0f64fc1535d4e69444b6d817ac +Description: debug symbols for rocfft-asan +Maintainer: rocfft-maintainer@amd.com +Package-Type: ddeb +Version: 1.0.28.60200-66~20.04 +Installed-Size: 24320 + +Package: rocfft-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 25256302e6c8308f89ca92bbbcdb741a39b07dd6 +Depends: rocfft-asan-rpath6.2.0 (= 1.0.28.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocfft-asan-dbgsym-rpath6.2.0/rocfft-asan-dbgsym-rpath6.2.0_1.0.28.60200-66~20.04_amd64.deb +Size: 21479408 +SHA256: e17de8a75783da16ab10ed9aec2ba0ea49160b4e5e7522909d86c7041e795bed +SHA1: 9156e9f700a3400612c8192e8227dada241e57a8 +MD5sum: 5a0322f0a58ec878e23d44b7bd23d78b +Description: debug symbols for rocfft-asan +Maintainer: rocfft-maintainer@amd.com +Package-Type: ddeb +Version: 1.0.28.60200-66~20.04 +Installed-Size: 24320 + +Package: rocfft-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 25256302e6c8308f89ca92bbbcdb741a39b07dd6 +Depends: rocfft-asan6.2.0 (= 1.0.28.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocfft-asan-dbgsym6.2.0/rocfft-asan-dbgsym6.2.0_1.0.28.60200-66~20.04_amd64.deb +Size: 21479448 +SHA256: 210d47d0688eaff18183499b63170d4e87fc117d0c3caa4ce5cfc1dee3107bcb +SHA1: 0ea56ac2b5005d8320cb00bbb1b228549bdd280c +MD5sum: 43057cb10d8d00f6e3dbff603983a580 +Description: debug symbols for rocfft-asan +Maintainer: rocfft-maintainer@amd.com +Package-Type: ddeb +Version: 1.0.28.60200-66~20.04 +Installed-Size: 24320 + +Package: rocfft-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocfft-asan-rpath6.2.0/rocfft-asan-rpath6.2.0_1.0.28.60200-66~20.04_amd64.deb +Size: 4588536 +SHA256: 53bd3bb74889f494ff200c763478d2ffc2d63022c26f49b34e3186f011c2111b +SHA1: 5d779d46475d17ac9a7e115ce7d60a4a1d3cd41d +MD5sum: a84324820d8ed43dbd3a937015ffbcf1 +Description: ROCm FFT library +Maintainer: rocfft-maintainer@amd.com +Recommends: rocfft-asan-dev (>=1.0.28.60200) +Version: 1.0.28.60200-66~20.04 +Installed-Size: 39426 + +Package: rocfft-asan6.2.0 +Architecture: amd64 +Depends: rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocfft-asan6.2.0/rocfft-asan6.2.0_1.0.28.60200-66~20.04_amd64.deb +Size: 4593552 +SHA256: 8e27041b0a49b0bd15b1dff70840e2594d72e56340e7a1bf32c581ad77789e5d +SHA1: 7c40152b878b5326bd50b9e2571b726024006330 +MD5sum: 83a6f7f9c5352163fad850fef66f55cd +Description: ROCm FFT library +Maintainer: rocfft-maintainer@amd.com +Recommends: rocfft-asan-dev (>=1.0.28.60200) +Version: 1.0.28.60200-66~20.04 +Installed-Size: 39426 + +Package: rocfft-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 9f5755bdd26a5bbc78f0cecf60a8aa3d7c3e7e9e 54537852e8daadea2229ca7e4c8bbf1211257262 +Depends: rocfft (= 1.0.28.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocfft-dbgsym/rocfft-dbgsym_1.0.28.60200-66~20.04_amd64.deb +Size: 9860008 +SHA256: 96309bb42173d7baa334e5b7befb1a26504972dabe62d7a9c6a026bc0b5bd2a9 +SHA1: 0cdb6fc58ae2ad677340671e16e0dfb71c466f7f +MD5sum: 2c8547fcaac4fd46b782e0e761b81529 +Description: debug symbols for rocfft +Maintainer: rocfft-maintainer@amd.com +Package-Type: ddeb +Version: 1.0.28.60200-66~20.04 +Installed-Size: 63940 + +Package: rocfft-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 9f5755bdd26a5bbc78f0cecf60a8aa3d7c3e7e9e 54537852e8daadea2229ca7e4c8bbf1211257262 +Depends: rocfft-rpath6.2.0 (= 1.0.28.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocfft-dbgsym-rpath6.2.0/rocfft-dbgsym-rpath6.2.0_1.0.28.60200-66~20.04_amd64.deb +Size: 9843116 +SHA256: 157e8776651f0a7f7f24d82d5abbf8a1f28c3da9aa901931a44baaed159665c9 +SHA1: f9bd6bd6cff31d9015ccba2ae47b356c633ec5cd +MD5sum: 59c2c96a0d95b28dec00fd5ffa45fa18 +Description: debug symbols for rocfft +Maintainer: rocfft-maintainer@amd.com +Package-Type: ddeb +Version: 1.0.28.60200-66~20.04 +Installed-Size: 63940 + +Package: rocfft-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 9f5755bdd26a5bbc78f0cecf60a8aa3d7c3e7e9e 54537852e8daadea2229ca7e4c8bbf1211257262 +Depends: rocfft6.2.0 (= 1.0.28.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocfft-dbgsym6.2.0/rocfft-dbgsym6.2.0_1.0.28.60200-66~20.04_amd64.deb +Size: 9846708 +SHA256: e569c4b9742f3cea326050028aadb5dd2e47b8cecbe2fb5e0b52d66e9f5ccdb5 +SHA1: 1537e74e5ac988f6b6ec445e6e3313b00cbcefab +MD5sum: 0b65b634ce457f270fcae499776cc6b6 +Description: debug symbols for rocfft +Maintainer: rocfft-maintainer@amd.com +Package-Type: ddeb +Version: 1.0.28.60200-66~20.04 +Installed-Size: 63940 + +Package: rocfft-dev +Architecture: amd64 +Depends: rocfft (>= 1.0.28.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocfft-dev/rocfft-dev_1.0.28.60200-66~20.04_amd64.deb +Size: 10492 +SHA256: 7ee282b30700b3dc3e703a34595afd8fc348b55061dccdcc110e6020fae919cb +SHA1: dce50f8da062b2d8d241f8655d1cea152ecdcf20 +MD5sum: cf6eee8c0306dc188844ea242b37d307 +Description: ROCm FFT library +Maintainer: rocfft-maintainer@amd.com +Version: 1.0.28.60200-66~20.04 +Installed-Size: 70 + +Package: rocfft-dev-rpath6.2.0 +Architecture: amd64 +Depends: rocfft-rpath6.2.0 (>= 1.0.28.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocfft-dev-rpath6.2.0/rocfft-dev-rpath6.2.0_1.0.28.60200-66~20.04_amd64.deb +Size: 10656 +SHA256: b53631b381f455a735febb72d5abd51dfaf6d312483a2b8b69c21495dd2831a0 +SHA1: ac94f92f5d832db364a6b1e035038ad3562527f7 +MD5sum: 0c88e714bddca254339e69c54bb5bad1 +Description: ROCm FFT library +Maintainer: rocfft-maintainer@amd.com +Version: 1.0.28.60200-66~20.04 +Installed-Size: 70 + +Package: rocfft-dev6.2.0 +Architecture: amd64 +Depends: rocfft6.2.0 (>= 1.0.28.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocfft-dev6.2.0/rocfft-dev6.2.0_1.0.28.60200-66~20.04_amd64.deb +Size: 10644 +SHA256: e94d50fd6f24d70649ce046dbfe4dda2587d1d82892d4c126a4c3e91d1570071 +SHA1: ab7aae5dcdf59b5504981446f1077d5620e56cce +MD5sum: 37945f232073cda7fa3aaa121d72f661 +Description: ROCm FFT library +Maintainer: rocfft-maintainer@amd.com +Version: 1.0.28.60200-66~20.04 +Installed-Size: 70 + +Package: rocfft-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocfft-rpath6.2.0/rocfft-rpath6.2.0_1.0.28.60200-66~20.04_amd64.deb +Size: 100484184 +SHA256: 106188063f722e1f53125b4ef20b292d1ae3fa728b84f3bc3af76c420886f01c +SHA1: db4955eabbdccf40c528d183f4fd1adedfe02261 +MD5sum: 89338d01ac3c2b6ab6c43925a9fe4c55 +Description: ROCm FFT library +Maintainer: rocfft-maintainer@amd.com +Recommends: rocfft-dev-rpath6.2.0 (>=1.0.28.60200) +Version: 1.0.28.60200-66~20.04 +Installed-Size: 2073370 + +Package: rocfft6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocfft6.2.0/rocfft6.2.0_1.0.28.60200-66~20.04_amd64.deb +Size: 100483656 +SHA256: b2bfe29ab688781bad5bc067ee682658085e22caaf09b18278f2f4b9905081d3 +SHA1: 36d88afacfe651c911d9622ac5066c3535bba9db +MD5sum: cf74dcec7ced88d05afde907fdcc6be8 +Description: ROCm FFT library +Maintainer: rocfft-maintainer@amd.com +Recommends: rocfft-dev6.2.0 (>=1.0.28.60200) +Version: 1.0.28.60200-66~20.04 +Installed-Size: 2073370 + +Package: rocm +Architecture: amd64 +Depends: rocm-utils (= 6.2.0.60200-66~20.04), rocm-developer-tools (= 6.2.0.60200-66~20.04), rocm-openmp-sdk (= 6.2.0.60200-66~20.04), rocm-opencl-sdk (= 6.2.0.60200-66~20.04), rocm-ml-sdk (= 6.2.0.60200-66~20.04), mivisionx (= 3.0.0.60200-66~20.04), migraphx (= 2.10.0.60200-66~20.04), rpp (= 1.8.0.60200-66~20.04), rocm-core (= 6.2.0.60200-66~20.04), migraphx-dev (= 2.10.0.60200-66~20.04), mivisionx-dev (= 3.0.0.60200-66~20.04), rpp-dev (= 1.8.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm/rocm_6.2.0.60200-66~20.04_amd64.deb +Size: 2066 +SHA256: 1fe7c92a43029e693c2ba1813748ad1506e1abaac1b3c5823e54693fdae76f78 +SHA1: d3d2629c4d563d389395881614c89ca8d5ca14d0 +MD5sum: 216fb4f0c10afd3915e24f9d9855e990 +Description: Radeon Open Compute (ROCm) software stack meta package +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm dev support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-asan +Architecture: amd64 +Depends: rocm (= 6.2.0.60200-66~20.04), rocm-core-asan (= 6.2.0.60200-66~20.04), rocm-developer-tools-asan (= 6.2.0.60200-66~20.04), rocm-language-runtime-asan (= 6.2.0.60200-66~20.04), rocm-opencl-runtime-asan (= 6.2.0.60200-66~20.04), rocm-ml-libraries-asan (= 6.2.0.60200-66~20.04), mivisionx-asan (= 3.0.0.60200-66~20.04), migraphx-asan (= 2.10.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-asan/rocm-asan_6.2.0.60200-66~20.04_amd64.deb +Size: 864 +SHA256: 17c03f23dbcdb6fcef56b8b6494ef3410138fe7f763dcdb515ed02fd94ac3d82 +SHA1: 23ed7faa3ee417881b13e01fce837d5020a596c8 +MD5sum: 214a22caf649f86139199fdbd28ba746 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-developer-tools-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-language-runtime-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl-runtime-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-ml-libraries-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), mivisionx-asan-rpath6.2.0 (= 3.0.0.60200-66~20.04), migraphx-asan-rpath6.2.0 (= 2.10.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-asan-rpath6.2.0/rocm-asan-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1060 +SHA256: 57e9876da680aca1f5a05a736130aef3e1d72ca29fbcb231894b43cd40b263b8 +SHA1: 5a24e1048229281ada670ace6ea2e6250b4a18bb +MD5sum: cdba1516f2e4ba12b7c1ef81a3c2f367 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-asan6.2.0 +Architecture: amd64 +Depends: rocm6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-asan6.2.0 (= 6.2.0.60200-66~20.04), rocm-developer-tools-asan6.2.0 (= 6.2.0.60200-66~20.04), rocm-language-runtime-asan6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl-runtime-asan6.2.0 (= 6.2.0.60200-66~20.04), rocm-ml-libraries-asan6.2.0 (= 6.2.0.60200-66~20.04), mivisionx-asan6.2.0 (= 3.0.0.60200-66~20.04), migraphx-asan6.2.0 (= 2.10.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-asan6.2.0/rocm-asan6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1052 +SHA256: c0c8473c65562693117bdce8df7677768bfdd8f69f7559b45b7a36eb67535ea1 +SHA1: 7661c599739be79b5639063a1d56bfb32e1e0a8a +MD5sum: d89f99ce9697fc96d35c5aed7ddeafd8 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-bandwidth-test +Architecture: amd64 +Depends: libstdc++6, hsa-rocr +Priority: optional +Section: devel +Filename: pool/main/r/rocm-bandwidth-test/rocm-bandwidth-test_1.4.0.60200-66~20.04_amd64.deb +Size: 61128 +SHA256: 445cb33d04a026cb5ee246e2237d1c8cc2f13e317b81bf3b6a630d82902e0b91 +SHA1: c2494e647b7f1fbdedbe593d6e36f3867427b473 +MD5sum: 5d935cfbd827d082c75d096526310100 +Description: Diagnostic utility tool to measure PCIe bandwidth on ROCm platforms +Homepage: https://github.com/RadeonOpenCompute/rocm_bandwidth_test +Maintainer: TODO +Version: 1.4.0.60200-66~20.04 +Installed-Size: 177 + +Package: rocm-bandwidth-test-rpath6.2.0 +Architecture: amd64 +Depends: libstdc++6, hsa-rocr-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-bandwidth-test-rpath6.2.0/rocm-bandwidth-test-rpath6.2.0_1.4.0.60200-66~20.04_amd64.deb +Size: 49720 +SHA256: bb2ede790830fe7c41658c27f193ff63d921f312b49ddd854443a2bdfcbdac85 +SHA1: 622b020e3b9056c028410aafc9a16464711b0f35 +MD5sum: fb254fae56bdf6a89cabdfcab8548a82 +Description: Diagnostic utility tool to measure PCIe bandwidth on ROCm platforms +Homepage: https://github.com/RadeonOpenCompute/rocm_bandwidth_test +Maintainer: TODO +Version: 1.4.0.60200-66~20.04 +Installed-Size: 177 + +Package: rocm-bandwidth-test6.2.0 +Architecture: amd64 +Depends: libstdc++6, hsa-rocr6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-bandwidth-test6.2.0/rocm-bandwidth-test6.2.0_1.4.0.60200-66~20.04_amd64.deb +Size: 49852 +SHA256: 4cf9cddcf03d16d125913bdb8509b53122f5fc7a823c4c91347402e14f01d672 +SHA1: 942fe62d6edc3003026286e2990928441509a3f4 +MD5sum: 08644d449d47161dd8f9b6782a68c453 +Description: Diagnostic utility tool to measure PCIe bandwidth on ROCm platforms +Homepage: https://github.com/RadeonOpenCompute/rocm_bandwidth_test +Maintainer: TODO +Version: 1.4.0.60200-66~20.04 +Installed-Size: 177 + +Package: rocm-cmake +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocm-cmake/rocm-cmake_0.13.0.60200-66~20.04_amd64.deb +Size: 24634 +SHA256: 0211817cf28187f10244fd0a6cfa0b9e2948d6533e6ff7354ccbf29a91e669ea +SHA1: b727b7cfacf880b2f54d3b61db8945f911a21a8b +MD5sum: 6c36ae6b96998d7a8eb0fafdc508f812 +Description: rocm-cmake built using CMake +Maintainer: Paul Fultz II pfultz@amd.com +Version: 0.13.0.60200-66~20.04 +Installed-Size: 157 + +Package: rocm-cmake-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-cmake-rpath6.2.0/rocm-cmake-rpath6.2.0_0.13.0.60200-66~20.04_amd64.deb +Size: 24748 +SHA256: 30263e867bda4fc02e6d6b69aecf259373b2bf9f696ea5d02c8a80598ec4fcf6 +SHA1: 9ff5c898adc3924160733c2477dd2c1393a22360 +MD5sum: cc584d05a1a6255d50c964bc91c9c777 +Description: rocm-cmake built using CMake +Maintainer: Paul Fultz II pfultz@amd.com +Version: 0.13.0.60200-66~20.04 +Installed-Size: 157 + +Package: rocm-cmake6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-cmake6.2.0/rocm-cmake6.2.0_0.13.0.60200-66~20.04_amd64.deb +Size: 24740 +SHA256: 9c7913a50c99493b9b7273f99ff07bc2fd909dd32e7dd931046e638aeec09cb7 +SHA1: 4a1f0fd99b7770d212112729c94b3a0642b90c75 +MD5sum: 42e568ca5f22c119b61837c034f238be +Description: rocm-cmake built using CMake +Maintainer: Paul Fultz II pfultz@amd.com +Version: 0.13.0.60200-66~20.04 +Installed-Size: 157 + +Package: rocm-core +Architecture: amd64 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-core/rocm-core_6.2.0.60200-66~20.04_amd64.deb +Size: 10730 +SHA256: 0e16c9fc58fc904542be4dad63bb2ff34268b5c13957c432e91ec0e4fd149c82 +SHA1: bf50bd931f2990b2c93b350296572bc479d3515c +MD5sum: 2ec934ecc77c1f57a9755a44237925c9 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 110 + +Package: rocm-core-asan +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocm-core-asan/rocm-core-asan_6.2.0.60200-66~20.04_amd64.deb +Size: 22900 +SHA256: 5797b456cc81336f7e702b90e6eda88196235a70b12ce1690f4297c6a9aa2faa +SHA1: 94cc991faca7c3d9f583b6e273f0f0d06b81295a +MD5sum: 1230307961c1ddf8c4ac9b3b59d2fe37 +Description: Radeon Open Compute (ROCm) AddressSanitizer Instrumented Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 263 + +Package: rocm-core-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-core-asan-rpath6.2.0/rocm-core-asan-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 16536 +SHA256: 5ab846c536043a3a5d8574e4160c8992e0b507f22446e9f6862d164e4ac55bdc +SHA1: ae60d04fd026f0383f278fbe5b83596b33ec6396 +MD5sum: 817375db725e8a7de442739bf9de3827 +Description: Radeon Open Compute (ROCm) AddressSanitizer Instrumented Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 263 + +Package: rocm-core-asan6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-core-asan6.2.0/rocm-core-asan6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 16564 +SHA256: 6b4d6ab3b3499ef77ec06d0d81773a72cea842e38a0b323a489a82dbc5542926 +SHA1: f34a2c8d63b850ce15e1d671f61fbe1d19a53cac +MD5sum: bc2bf388599296c357dd9714e4552f88 +Description: Radeon Open Compute (ROCm) AddressSanitizer Instrumented Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 263 + +Package: rocm-core-rpath6.2.0 +Architecture: amd64 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-core-rpath6.2.0/rocm-core-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 9804 +SHA256: cbd2d18b20108ac2ce1c01bf19a860811c9cf191acdc68219e1fb138c0aba002 +SHA1: c1926f175497f628fe49a659d6d202a8e002b41a +MD5sum: f80ce96ed264f63a25e0144f273d17a1 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 110 + +Package: rocm-core6.2.0 +Architecture: amd64 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-core6.2.0/rocm-core6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 9804 +SHA256: 1f7abfefaa53adbca020ab664cbb132d14b3ca5962aefc6a022377549d073780 +SHA1: cc69eee5f66e8852f0159784ae1b83f86e3c1581 +MD5sum: 7dfafa411229267c3cb24d7f51832f1a +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 110 + +Package: rocm-dbgapi +Architecture: amd64 +Depends: comgr(>=1.2.0), rocm-core, pci.ids +Priority: optional +Section: devel +Filename: pool/main/r/rocm-dbgapi/rocm-dbgapi_0.76.0.60200-66~20.04_amd64.deb +Size: 1732500 +SHA256: 7849dae1ac7bb30cd7ecfd6a5954be089b93a5bd40c5784831e759206493832c +SHA1: 28b22fc6aa0340cbd59dcb96c1a6ca0e40cb995e +MD5sum: b2f0dff5616dbbf43b0e000a7a29ce56 +Description: Library to provide AMD GPU debugger API + Non ASAN libraries, include files for the ROCM-DBGAPI +Maintainer: ROCm Debugger Support +Version: 0.76.0.60200-66~20.04 +Installed-Size: 7368 + +Package: rocm-dbgapi-asan +Architecture: amd64 +Depends: comgr-asan(>=1.2.0), rocm-core-asan, pci.ids +Priority: optional +Section: devel +Filename: pool/main/r/rocm-dbgapi-asan/rocm-dbgapi-asan_0.76.0.60200-66~20.04_amd64.deb +Size: 754512 +SHA256: d01d5c6a155e3e366ddbbba7219f76e11b86e0ebfb72aef0db81123fb7744f63 +SHA1: 5daf948c306ccc3ad01b18127c4c185d1919bb85 +MD5sum: 1cfee904ccc9e9f4d393383ae4cf6953 +Description: Library to provide AMD GPU debugger API + ASAN libraries for the ROCM-DBGAPI +Maintainer: ROCm Debugger Support +Version: 0.76.0.60200-66~20.04 +Installed-Size: 7901 + +Package: rocm-dbgapi-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 45300d3a8284abe099ae4528de4a6594b45dac57 +Depends: rocm-dbgapi-asan (= 0.76.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-dbgapi-asan-dbgsym/rocm-dbgapi-asan-dbgsym_0.76.0.60200-66~20.04_amd64.deb +Size: 4740578 +SHA256: c4ea5fd031cbbe91f96c76a464c32065f9b43939f599ef6b24ec43679b6a441f +SHA1: 4d05428f70b47680f9d574de733ab5c7e51ff1fc +MD5sum: e6b14680c526f78c642d5fb55ca2196f +Description: debug symbols for rocm-dbgapi-asan +Maintainer: ROCm Debugger Support +Package-Type: ddeb +Version: 0.76.0.60200-66~20.04 +Installed-Size: 18280 + +Package: rocm-dbgapi-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 45300d3a8284abe099ae4528de4a6594b45dac57 +Depends: rocm-dbgapi-asan-rpath6.2.0 (= 0.76.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-dbgapi-asan-dbgsym-rpath6.2.0/rocm-dbgapi-asan-dbgsym-rpath6.2.0_0.76.0.60200-66~20.04_amd64.deb +Size: 2808584 +SHA256: 312300b1f4abb56bf5a5ddbb4e79990bf586f99c0a51246a23623e5a7f10231f +SHA1: b038a70bfa59f309a05214d9a00f22ea023c4bc2 +MD5sum: 981fa370ecb7d7539b27bd4d36456414 +Description: debug symbols for rocm-dbgapi-asan +Maintainer: ROCm Debugger Support +Package-Type: ddeb +Version: 0.76.0.60200-66~20.04 +Installed-Size: 18280 + +Package: rocm-dbgapi-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 45300d3a8284abe099ae4528de4a6594b45dac57 +Depends: rocm-dbgapi-asan6.2.0 (= 0.76.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-dbgapi-asan-dbgsym6.2.0/rocm-dbgapi-asan-dbgsym6.2.0_0.76.0.60200-66~20.04_amd64.deb +Size: 2809228 +SHA256: 1a02b539f019644a440457e6568a1638ae98f20323f42d1a11893e5d651e3ae5 +SHA1: 18f79f2c89caf7ec71691084192bf4251446db6e +MD5sum: fc54efe36bfc0384e849912e00e37d0d +Description: debug symbols for rocm-dbgapi-asan +Maintainer: ROCm Debugger Support +Package-Type: ddeb +Version: 0.76.0.60200-66~20.04 +Installed-Size: 18280 + +Package: rocm-dbgapi-asan-rpath6.2.0 +Architecture: amd64 +Depends: comgr-asan-rpath6.2.0(>=1.2.0), rocm-core-asan-rpath6.2.0, pci.ids +Priority: optional +Section: devel +Filename: pool/main/r/rocm-dbgapi-asan-rpath6.2.0/rocm-dbgapi-asan-rpath6.2.0_0.76.0.60200-66~20.04_amd64.deb +Size: 451576 +SHA256: 3c02075b4184f1620f002972e3cef935162d93f52fe71556d618c362d25ed121 +SHA1: 52c73f65e40cedf3d2ca15f56d081b7f10443722 +MD5sum: 839913e88ae739d5d2b397d7b9b0d753 +Description: Library to provide AMD GPU debugger API + ASAN libraries for the ROCM-DBGAPI +Maintainer: ROCm Debugger Support +Version: 0.76.0.60200-66~20.04 +Installed-Size: 7901 + +Package: rocm-dbgapi-asan6.2.0 +Architecture: amd64 +Depends: comgr-asan6.2.0(>=1.2.0), rocm-core-asan6.2.0, pci.ids +Priority: optional +Section: devel +Filename: pool/main/r/rocm-dbgapi-asan6.2.0/rocm-dbgapi-asan6.2.0_0.76.0.60200-66~20.04_amd64.deb +Size: 451612 +SHA256: a0bc99bd94928fa404dab82f85b8b089404b4aabc3fdc7ab4e12f029fa237e3f +SHA1: 5566b7b3ea3bd7caaa0612a1b7caad084ebc8b42 +MD5sum: 54f6ede32f508b4ded4f3ea7a180cdc2 +Description: Library to provide AMD GPU debugger API + ASAN libraries for the ROCM-DBGAPI +Maintainer: ROCm Debugger Support +Version: 0.76.0.60200-66~20.04 +Installed-Size: 7901 + +Package: rocm-dbgapi-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: ec5a911d52e71c0f407c1b6a31b1d672c333ff88 +Depends: rocm-dbgapi (= 0.76.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-dbgapi-dbgsym/rocm-dbgapi-dbgsym_0.76.0.60200-66~20.04_amd64.deb +Size: 11620738 +SHA256: cb80d5f249c5cec000fb42ecc09674f39e4bb1e6dfe8d2e8a79e8dc1b4c08995 +SHA1: 6f19aa7c5a9597b2853b31a9c457ce2f1dc53a58 +MD5sum: 2c411fbb26dbd781f9ef53b2d9bed929 +Description: debug symbols for rocm-dbgapi +Maintainer: ROCm Debugger Support +Package-Type: ddeb +Version: 0.76.0.60200-66~20.04 +Installed-Size: 47932 + +Package: rocm-dbgapi-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: ec5a911d52e71c0f407c1b6a31b1d672c333ff88 +Depends: rocm-dbgapi-rpath6.2.0 (= 0.76.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-dbgapi-dbgsym-rpath6.2.0/rocm-dbgapi-dbgsym-rpath6.2.0_0.76.0.60200-66~20.04_amd64.deb +Size: 7260200 +SHA256: 02ae3e99cec32a125d6b9ee415f0fca7c53f6197607ec19d9ca5cefdefd01fb3 +SHA1: ae21335a2105b7776a36897e4d192f7fb2a9a19e +MD5sum: 374a39705e503f332be37c67989fd585 +Description: debug symbols for rocm-dbgapi +Maintainer: ROCm Debugger Support +Package-Type: ddeb +Version: 0.76.0.60200-66~20.04 +Installed-Size: 47932 + +Package: rocm-dbgapi-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: ec5a911d52e71c0f407c1b6a31b1d672c333ff88 +Depends: rocm-dbgapi6.2.0 (= 0.76.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-dbgapi-dbgsym6.2.0/rocm-dbgapi-dbgsym6.2.0_0.76.0.60200-66~20.04_amd64.deb +Size: 7260928 +SHA256: bc0934061d2c00f0d622a3cd7222b032a2439fd78784c09392659b270082b2d1 +SHA1: 38ee3ed956018d0621b45f34e34e29961202e04e +MD5sum: 225d0b1bf2f96fd9868820d685986b70 +Description: debug symbols for rocm-dbgapi +Maintainer: ROCm Debugger Support +Package-Type: ddeb +Version: 0.76.0.60200-66~20.04 +Installed-Size: 47932 + +Package: rocm-dbgapi-rpath6.2.0 +Architecture: amd64 +Depends: comgr-rpath6.2.0(>=1.2.0), rocm-core-rpath6.2.0, pci.ids +Priority: optional +Section: devel +Filename: pool/main/r/rocm-dbgapi-rpath6.2.0/rocm-dbgapi-rpath6.2.0_0.76.0.60200-66~20.04_amd64.deb +Size: 1351292 +SHA256: c487b454cd33342fae88fbe7aa9cd385eea53b1ecb760f128bffbdb67bd6b05c +SHA1: c2079e91a7e9449303304658ecacf2aa4489da39 +MD5sum: ca349b6b2743e0ed11971ee00fb9d6ac +Description: Library to provide AMD GPU debugger API + Non ASAN libraries, include files for the ROCM-DBGAPI +Maintainer: ROCm Debugger Support +Version: 0.76.0.60200-66~20.04 +Installed-Size: 7368 + +Package: rocm-dbgapi6.2.0 +Architecture: amd64 +Depends: comgr6.2.0(>=1.2.0), rocm-core6.2.0, pci.ids +Priority: optional +Section: devel +Filename: pool/main/r/rocm-dbgapi6.2.0/rocm-dbgapi6.2.0_0.76.0.60200-66~20.04_amd64.deb +Size: 1352296 +SHA256: bb03e3ca0fb737f656e64066dbeb22ad803cb1d15e341a1133d17f202ca67969 +SHA1: 7b976607128bee7b91312f55c383590638af5473 +MD5sum: f7e5458727643407bade3c00a5c61b48 +Description: Library to provide AMD GPU debugger API + Non ASAN libraries, include files for the ROCM-DBGAPI +Maintainer: ROCm Debugger Support +Version: 0.76.0.60200-66~20.04 +Installed-Size: 7368 + +Package: rocm-debug-agent +Architecture: amd64 +Depends: rocm-dbgapi, rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocm-debug-agent/rocm-debug-agent_2.0.3.60200-66~20.04_amd64.deb +Size: 54122 +SHA256: 298528258fdd5eac07b72b04a85a541abfcdef048b328c3bad71bf285315582d +SHA1: a7e7e577a6276ece060990760fc3ca76034f520c +MD5sum: 1551591bb3216c5c42b31ae4b39e3d14 +Description: Radeon Open Compute Debug Agent (ROCdebug-agent) + Dynamic libraries for the ROCdebug-agent +Maintainer: ROCm Debugger Support +Version: 2.0.3.60200-66~20.04 +Installed-Size: 263 + +Package: rocm-debug-agent-asan +Architecture: amd64 +Depends: rocm-dbgapi-asan, rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/r/rocm-debug-agent-asan/rocm-debug-agent-asan_2.0.3.60200-66~20.04_amd64.deb +Size: 88608 +SHA256: 0676a2f20e649514d78978f8e6c685adf2db3a7f68644815badbfecb61b61053 +SHA1: 559f289475d8dcafc36a6cdb3ca7527b6cfa2eb9 +MD5sum: b85581207ba489132b829df45c12fbde +Description: Radeon Open Compute Debug Agent (ROCdebug-agent) + AddressSanitizer libraries for the ROCdebug-agent +Maintainer: ROCm Debugger Support +Version: 2.0.3.60200-66~20.04 +Installed-Size: 499 + +Package: rocm-debug-agent-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 6a74c1ce952e12c98762111ed8b07286faaa305e +Depends: rocm-debug-agent-asan (= 2.0.3.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-debug-agent-asan-dbgsym/rocm-debug-agent-asan-dbgsym_2.0.3.60200-66~20.04_amd64.deb +Size: 439180 +SHA256: 449aa347a19c4f5ddab968023edb3c98ce957bdbb51dc6657b96138bcc8f93d7 +SHA1: 66233bfe4247f5dbc6fcc3916a7e2c4cacc376e9 +MD5sum: cee900514fa458f941c523e832440e37 +Description: debug symbols for rocm-debug-agent-asan +Maintainer: ROCm Debugger Support +Package-Type: ddeb +Version: 2.0.3.60200-66~20.04 +Installed-Size: 1436 + +Package: rocm-debug-agent-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 6a74c1ce952e12c98762111ed8b07286faaa305e +Depends: rocm-debug-agent-asan-rpath6.2.0 (= 2.0.3.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-debug-agent-asan-dbgsym-rpath6.2.0/rocm-debug-agent-asan-dbgsym-rpath6.2.0_2.0.3.60200-66~20.04_amd64.deb +Size: 325692 +SHA256: 69254bb983f2ba27e90905038d7f69d6b8c27b2dcf2e45577a0b7fda323b09ac +SHA1: e09f5033032a21e4fe3304d4e21ea2dedd165863 +MD5sum: 53203a4b2ee21343ed10ac043f44344f +Description: debug symbols for rocm-debug-agent-asan +Maintainer: ROCm Debugger Support +Package-Type: ddeb +Version: 2.0.3.60200-66~20.04 +Installed-Size: 1436 + +Package: rocm-debug-agent-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 6a74c1ce952e12c98762111ed8b07286faaa305e +Depends: rocm-debug-agent-asan6.2.0 (= 2.0.3.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-debug-agent-asan-dbgsym6.2.0/rocm-debug-agent-asan-dbgsym6.2.0_2.0.3.60200-66~20.04_amd64.deb +Size: 325724 +SHA256: 4c8862f17c880131ebb09734fa506f2c538c50320fc24376bbb3a426a4aa10b4 +SHA1: 2674b0ea1e85f62af30f2c35747c1007f02141dd +MD5sum: 0a7736b29e25d9f8da3f5834d1c90b1b +Description: debug symbols for rocm-debug-agent-asan +Maintainer: ROCm Debugger Support +Package-Type: ddeb +Version: 2.0.3.60200-66~20.04 +Installed-Size: 1436 + +Package: rocm-debug-agent-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-dbgapi-asan-rpath6.2.0, rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-debug-agent-asan-rpath6.2.0/rocm-debug-agent-asan-rpath6.2.0_2.0.3.60200-66~20.04_amd64.deb +Size: 71016 +SHA256: 0aee6a14fa2d4f4220f387171d05efc49567ea4ee0408f422cc05d6e5602dbce +SHA1: cfa14f44d0b008bd8975508ad7558ae8d8af20ca +MD5sum: 606f7c950c6e2c429c0a603797caf7ad +Description: Radeon Open Compute Debug Agent (ROCdebug-agent) + AddressSanitizer libraries for the ROCdebug-agent +Maintainer: ROCm Debugger Support +Version: 2.0.3.60200-66~20.04 +Installed-Size: 499 + +Package: rocm-debug-agent-asan6.2.0 +Architecture: amd64 +Depends: rocm-dbgapi-asan6.2.0, rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-debug-agent-asan6.2.0/rocm-debug-agent-asan6.2.0_2.0.3.60200-66~20.04_amd64.deb +Size: 70944 +SHA256: e75a18ac7e9cf6428184611e67e844016e2a28729b5c0cc57b1cebdc918c01fe +SHA1: d6ed53fe7c4a237a3cc991f6aa95fd41ac248038 +MD5sum: 3ca89495421335374533c4633a0f3f15 +Description: Radeon Open Compute Debug Agent (ROCdebug-agent) + AddressSanitizer libraries for the ROCdebug-agent +Maintainer: ROCm Debugger Support +Version: 2.0.3.60200-66~20.04 +Installed-Size: 499 + +Package: rocm-debug-agent-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: af8b821da1331fa8985c330bcb5e90124dcbc5da +Depends: rocm-debug-agent (= 2.0.3.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-debug-agent-dbgsym/rocm-debug-agent-dbgsym_2.0.3.60200-66~20.04_amd64.deb +Size: 706068 +SHA256: 666b990e49109ed45fa6a950ef33ced8f51143985848fed5042efafceff0702b +SHA1: 6e8fe04d32827572ec79c6a18a5b3d500a492259 +MD5sum: 519c64ba0fd120a39b8a18718495d14d +Description: debug symbols for rocm-debug-agent +Maintainer: ROCm Debugger Support +Package-Type: ddeb +Version: 2.0.3.60200-66~20.04 +Installed-Size: 2552 + +Package: rocm-debug-agent-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: af8b821da1331fa8985c330bcb5e90124dcbc5da +Depends: rocm-debug-agent-rpath6.2.0 (= 2.0.3.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-debug-agent-dbgsym-rpath6.2.0/rocm-debug-agent-dbgsym-rpath6.2.0_2.0.3.60200-66~20.04_amd64.deb +Size: 530068 +SHA256: 9edced7fb99ed11902108fe7c4f560a41c173b109831c17de28f7e19d3885191 +SHA1: e12a3c5944e8eb2eb4e0561a3272e3db6bbaf53b +MD5sum: 88311e34b759e067218408f7fa85baa9 +Description: debug symbols for rocm-debug-agent +Maintainer: ROCm Debugger Support +Package-Type: ddeb +Version: 2.0.3.60200-66~20.04 +Installed-Size: 2552 + +Package: rocm-debug-agent-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: af8b821da1331fa8985c330bcb5e90124dcbc5da +Depends: rocm-debug-agent6.2.0 (= 2.0.3.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-debug-agent-dbgsym6.2.0/rocm-debug-agent-dbgsym6.2.0_2.0.3.60200-66~20.04_amd64.deb +Size: 530132 +SHA256: dc99a4cec89ae45107153e725db39c90ee818f6142442f5919af4a17cb9e4df3 +SHA1: 843f6523e0c812f35775425a233652c20cab1530 +MD5sum: a5986b88d65041f7d938e3c0b90b6447 +Description: debug symbols for rocm-debug-agent +Maintainer: ROCm Debugger Support +Package-Type: ddeb +Version: 2.0.3.60200-66~20.04 +Installed-Size: 2552 + +Package: rocm-debug-agent-rpath6.2.0 +Architecture: amd64 +Depends: rocm-dbgapi-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-debug-agent-rpath6.2.0/rocm-debug-agent-rpath6.2.0_2.0.3.60200-66~20.04_amd64.deb +Size: 44876 +SHA256: c24d168a7bdfcbf127c5d7dcfcdbabfbb9882b0150ec979ed5cb26a1aa2dafb7 +SHA1: 449cd91b6460d92b7275e0701111baf1b0fe485a +MD5sum: 2bfe12813712734f9d445b2504f60d7f +Description: Radeon Open Compute Debug Agent (ROCdebug-agent) + Dynamic libraries for the ROCdebug-agent +Maintainer: ROCm Debugger Support +Version: 2.0.3.60200-66~20.04 +Installed-Size: 263 + +Package: rocm-debug-agent6.2.0 +Architecture: amd64 +Depends: rocm-dbgapi6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-debug-agent6.2.0/rocm-debug-agent6.2.0_2.0.3.60200-66~20.04_amd64.deb +Size: 44812 +SHA256: f6024adaf53bd2c95b26017de5c318aed97a21f2834b8c1c8808fc164e7567fd +SHA1: 2a8788d1bd4fb1f5d7cdb4df14dbbbcccccc44f1 +MD5sum: 0d8ca5460b9a1439f43a3e93b378a3b3 +Description: Radeon Open Compute Debug Agent (ROCdebug-agent) + Dynamic libraries for the ROCdebug-agent +Maintainer: ROCm Debugger Support +Version: 2.0.3.60200-66~20.04 +Installed-Size: 263 + +Package: rocm-dev +Architecture: amd64 +Depends: amd-smi-lib (= 24.6.2.60200-66~20.04), comgr (= 2.8.0.60200-66~20.04), hip-doc (= 6.2.41133.60200-66~20.04), hipify-clang (= 18.0.0.60200-66~20.04), hip-runtime-amd (= 6.2.41133.60200-66~20.04), hip-samples (= 6.2.41133.60200-66~20.04), hipcc (= 1.1.1.60200-66~20.04), hsa-rocr (= 1.14.0.60200-66~20.04), hsa-amd-aqlprofile (= 1.0.0.60200.60200-66~20.04), rocm-llvm (= 18.0.0.24292.60200-66~20.04), openmp-extras-runtime (= 18.62.0.60200-66~20.04), rocm-cmake (= 0.13.0.60200-66~20.04), rocm-dbgapi (= 0.76.0.60200-66~20.04), rocm-debug-agent (= 2.0.3.60200-66~20.04), rocm-device-libs (= 1.0.0.60200-66~20.04), rocm-gdb (= 14.2.60200-66~20.04), rocm-smi-lib (= 7.3.0.60200-66~20.04), rocm-utils (= 6.2.0.60200-66~20.04), rocm-core (= 6.2.0.60200-66~20.04), rocm-opencl (= 2.0.0.60200-66~20.04), rocm-opencl-icd-loader (= 1.2.60200-66~20.04), rocprofiler-register (= 0.4.0.60200-66~20.04), rocprofiler (= 2.0.60200.60200-66~20.04), rocprofiler-plugins (= 2.0.60200.60200-66~20.04), roctracer (= 4.1.60200.60200-66~20.04), rocprofiler-sdk (= 0.4.0-66~20.04), rocprofiler-sdk-roctx (= 0.4.0-66~20.04), hip-dev (= 6.2.41133.60200-66~20.04), hsa-rocr-dev (= 1.14.0.60200-66~20.04), hsakmt-roct-dev (= 20240607.3.8.60200-66~20.04), rocprofiler-register (= 0.4.0.60200-66~20.04), rocprofiler-dev (= 2.0.60200.60200-66~20.04), roctracer-dev (= 4.1.60200.60200-66~20.04), openmp-extras-dev (= 18.62.0.60200-66~20.04), rocm-opencl-dev (= 2.0.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-dev/rocm-dev_6.2.0.60200-66~20.04_amd64.deb +Size: 2480 +SHA256: 6406e5a80ba68b5230f7bf1c092f8201955c94b36e7d7239dbc24489a14abe4d +SHA1: 064fdd5eeb6388f48d5881cedb8b41f025b3f320 +MD5sum: fbee31ddbb971902916961b991302892 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-dev-asan +Architecture: amd64 +Depends: rocm-dev (= 6.2.0.60200-66~20.04), comgr-asan (= 2.8.0.60200-66~20.04), hip-runtime-amd-asan (= 6.2.41133.60200-66~20.04), hsa-rocr-asan (= 1.14.0.60200-66~20.04), hsa-amd-aqlprofile-asan (= 1.0.0.60200.60200-66~20.04), openmp-extras-asan (= 18.62.0.60200-66~20.04), rocm-dbgapi-asan (= 0.76.0.60200-66~20.04), rocm-debug-agent-asan (= 2.0.3.60200-66~20.04), rocm-smi-lib-asan (= 7.3.0.60200-66~20.04), rocm-core-asan (= 6.2.0.60200-66~20.04), rocm-opencl-asan (= 2.0.0.60200-66~20.04), rocprofiler-asan (= 2.0.60200.60200-66~20.04), roctracer-asan (= 4.1.60200.60200-66~20.04), hsakmt-roct-asan (= 20240607.3.8.60200-66~20.04), amd-smi-lib-asan (= 24.6.2.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-dev-asan/rocm-dev-asan_6.2.0.60200-66~20.04_amd64.deb +Size: 970 +SHA256: 6b810d1c7a7ad006fa702df90dc5c9af3296b45168f4676072b9bebe82bc1880 +SHA1: a4301bb6991ca9a713eac79422ade1bb8f503bbf +MD5sum: f19cdc12163a8c36d2110fb814dda42e +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-dev-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-dev-rpath6.2.0 (= 6.2.0.60200-66~20.04), comgr-asan-rpath6.2.0 (= 2.8.0.60200-66~20.04), hip-runtime-amd-asan-rpath6.2.0 (= 6.2.41133.60200-66~20.04), hsa-rocr-asan-rpath6.2.0 (= 1.14.0.60200-66~20.04), hsa-amd-aqlprofile-asan-rpath6.2.0 (= 1.0.0.60200.60200-66~20.04), openmp-extras-asan-rpath6.2.0 (= 18.62.0.60200-66~20.04), rocm-dbgapi-asan-rpath6.2.0 (= 0.76.0.60200-66~20.04), rocm-debug-agent-asan-rpath6.2.0 (= 2.0.3.60200-66~20.04), rocm-smi-lib-asan-rpath6.2.0 (= 7.3.0.60200-66~20.04), rocm-core-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl-asan-rpath6.2.0 (= 2.0.0.60200-66~20.04), rocprofiler-asan-rpath6.2.0 (= 2.0.60200.60200-66~20.04), roctracer-asan-rpath6.2.0 (= 4.1.60200.60200-66~20.04), hsakmt-roct-asan-rpath6.2.0 (= 20240607.3.8.60200-66~20.04), amd-smi-lib-asan-rpath6.2.0 (= 24.6.2.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-dev-asan-rpath6.2.0/rocm-dev-asan-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1176 +SHA256: 8c0bd06ddbc6c87ceb56bc7aa77fe2e7d16c5cf20fd0532fdb4b022c5889ffe2 +SHA1: 36f4484ba6bd9c6a961da03379d077728aabc634 +MD5sum: 1940cc0cf0f3e9cbcd85f7b94f77e788 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-dev-asan6.2.0 +Architecture: amd64 +Depends: rocm-dev6.2.0 (= 6.2.0.60200-66~20.04), comgr-asan6.2.0 (= 2.8.0.60200-66~20.04), hip-runtime-amd-asan6.2.0 (= 6.2.41133.60200-66~20.04), hsa-rocr-asan6.2.0 (= 1.14.0.60200-66~20.04), hsa-amd-aqlprofile-asan6.2.0 (= 1.0.0.60200.60200-66~20.04), openmp-extras-asan6.2.0 (= 18.62.0.60200-66~20.04), rocm-dbgapi-asan6.2.0 (= 0.76.0.60200-66~20.04), rocm-debug-agent-asan6.2.0 (= 2.0.3.60200-66~20.04), rocm-smi-lib-asan6.2.0 (= 7.3.0.60200-66~20.04), rocm-core-asan6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl-asan6.2.0 (= 2.0.0.60200-66~20.04), rocprofiler-asan6.2.0 (= 2.0.60200.60200-66~20.04), roctracer-asan6.2.0 (= 4.1.60200.60200-66~20.04), hsakmt-roct-asan6.2.0 (= 20240607.3.8.60200-66~20.04), amd-smi-lib-asan6.2.0 (= 24.6.2.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-dev-asan6.2.0/rocm-dev-asan6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1168 +SHA256: 57e73c390f5ee49ac95cf1f5e9f07413bac8d59950cf0a9bfd269a814226fde1 +SHA1: 71d73b869305958d77dcb2cfc554fba5abb6cc1b +MD5sum: 21aa7704ee68fd71ed4596532bbe3829 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-dev-rpath6.2.0 +Architecture: amd64 +Depends: amd-smi-lib-rpath6.2.0 (= 24.6.2.60200-66~20.04), comgr-rpath6.2.0 (= 2.8.0.60200-66~20.04), hip-doc-rpath6.2.0 (= 6.2.41133.60200-66~20.04), hipify-clang-rpath6.2.0 (= 18.0.0.60200-66~20.04), hip-runtime-amd-rpath6.2.0 (= 6.2.41133.60200-66~20.04), hip-samples-rpath6.2.0 (= 6.2.41133.60200-66~20.04), hipcc-rpath6.2.0 (= 1.1.1.60200-66~20.04), hsa-rocr-rpath6.2.0 (= 1.14.0.60200-66~20.04), hsa-amd-aqlprofile-rpath6.2.0 (= 1.0.0.60200.60200-66~20.04), rocm-llvm-rpath6.2.0 (= 18.0.0.24292.60200-66~20.04), openmp-extras-runtime-rpath6.2.0 (= 18.62.0.60200-66~20.04), rocm-cmake-rpath6.2.0 (= 0.13.0.60200-66~20.04), rocm-dbgapi-rpath6.2.0 (= 0.76.0.60200-66~20.04), rocm-debug-agent-rpath6.2.0 (= 2.0.3.60200-66~20.04), rocm-device-libs-rpath6.2.0 (= 1.0.0.60200-66~20.04), rocm-gdb-rpath6.2.0 (= 14.2.60200-66~20.04), rocm-smi-lib-rpath6.2.0 (= 7.3.0.60200-66~20.04), rocm-utils-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl-rpath6.2.0 (= 2.0.0.60200-66~20.04), rocm-opencl-icd-loader-rpath6.2.0 (= 1.2.60200-66~20.04), rocprofiler-register-rpath6.2.0 (= 0.4.0.60200-66~20.04), rocprofiler-rpath6.2.0 (= 2.0.60200.60200-66~20.04), rocprofiler-plugins-rpath6.2.0 (= 2.0.60200.60200-66~20.04), roctracer-rpath6.2.0 (= 4.1.60200.60200-66~20.04), rocprofiler-sdk-rpath6.2.0 (= 0.4.0-66~20.04), rocprofiler-sdk-roctx-rpath6.2.0 (= 0.4.0-66~20.04), hip-dev-rpath6.2.0 (= 6.2.41133.60200-66~20.04), hsa-rocr-dev-rpath6.2.0 (= 1.14.0.60200-66~20.04), hsakmt-roct-dev-rpath6.2.0 (= 20240607.3.8.60200-66~20.04), rocprofiler-register-rpath6.2.0 (= 0.4.0.60200-66~20.04), rocprofiler-dev-rpath6.2.0 (= 2.0.60200.60200-66~20.04), roctracer-dev-rpath6.2.0 (= 4.1.60200.60200-66~20.04), openmp-extras-dev-rpath6.2.0 (= 18.62.0.60200-66~20.04), rocm-opencl-dev-rpath6.2.0 (= 2.0.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-dev-rpath6.2.0/rocm-dev-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 2644 +SHA256: 32d20c9417e51e24cd7ce0ab40f23eb7bdd122a7cdbe7d2cb38a6127d2d11fa5 +SHA1: ba1d43f8d4e87ee04fe5835a4aee11a03b0f3e4e +MD5sum: bf4caeb60b27e89da35f8cb15e1eb029 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-dev6.2.0 +Architecture: amd64 +Depends: amd-smi-lib6.2.0 (= 24.6.2.60200-66~20.04), comgr6.2.0 (= 2.8.0.60200-66~20.04), hip-doc6.2.0 (= 6.2.41133.60200-66~20.04), hipify-clang6.2.0 (= 18.0.0.60200-66~20.04), hip-runtime-amd6.2.0 (= 6.2.41133.60200-66~20.04), hip-samples6.2.0 (= 6.2.41133.60200-66~20.04), hipcc6.2.0 (= 1.1.1.60200-66~20.04), hsa-rocr6.2.0 (= 1.14.0.60200-66~20.04), hsa-amd-aqlprofile6.2.0 (= 1.0.0.60200.60200-66~20.04), rocm-llvm6.2.0 (= 18.0.0.24292.60200-66~20.04), openmp-extras-runtime6.2.0 (= 18.62.0.60200-66~20.04), rocm-cmake6.2.0 (= 0.13.0.60200-66~20.04), rocm-dbgapi6.2.0 (= 0.76.0.60200-66~20.04), rocm-debug-agent6.2.0 (= 2.0.3.60200-66~20.04), rocm-device-libs6.2.0 (= 1.0.0.60200-66~20.04), rocm-gdb6.2.0 (= 14.2.60200-66~20.04), rocm-smi-lib6.2.0 (= 7.3.0.60200-66~20.04), rocm-utils6.2.0 (= 6.2.0.60200-66~20.04), rocm-core6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl6.2.0 (= 2.0.0.60200-66~20.04), rocm-opencl-icd-loader6.2.0 (= 1.2.60200-66~20.04), rocprofiler-register6.2.0 (= 0.4.0.60200-66~20.04), rocprofiler6.2.0 (= 2.0.60200.60200-66~20.04), rocprofiler-plugins6.2.0 (= 2.0.60200.60200-66~20.04), roctracer6.2.0 (= 4.1.60200.60200-66~20.04), rocprofiler-sdk6.2.0 (= 0.4.0-66~20.04), rocprofiler-sdk-roctx6.2.0 (= 0.4.0-66~20.04), hip-dev6.2.0 (= 6.2.41133.60200-66~20.04), hsa-rocr-dev6.2.0 (= 1.14.0.60200-66~20.04), hsakmt-roct-dev6.2.0 (= 20240607.3.8.60200-66~20.04), rocprofiler-register6.2.0 (= 0.4.0.60200-66~20.04), rocprofiler-dev6.2.0 (= 2.0.60200.60200-66~20.04), roctracer-dev6.2.0 (= 4.1.60200.60200-66~20.04), openmp-extras-dev6.2.0 (= 18.62.0.60200-66~20.04), rocm-opencl-dev6.2.0 (= 2.0.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-dev6.2.0/rocm-dev6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 2632 +SHA256: fc3c9e6654494c515a2bffe874fde6736b52ea69fd1f3c918f6ad59d0a9cd8d5 +SHA1: 28985d10fd2f7c91c9dc7c9c490afc435905c991 +MD5sum: 7f5ecf5514461573d7ebe8a394bd41e6 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-developer-tools +Architecture: amd64 +Depends: amd-smi-lib (= 24.6.2.60200-66~20.04), rocm-core (= 6.2.0.60200-66~20.04), rocm-language-runtime (= 6.2.0.60200-66~20.04), rocm-dbgapi (= 0.76.0.60200-66~20.04), rocm-debug-agent (= 2.0.3.60200-66~20.04), rocm-gdb (= 14.2.60200-66~20.04), hsa-amd-aqlprofile (= 1.0.0.60200.60200-66~20.04), rocm-smi-lib (= 7.3.0.60200-66~20.04), rocprofiler-register (= 0.4.0.60200-66~20.04), rocprofiler (= 2.0.60200.60200-66~20.04), rocprofiler-plugins (= 2.0.60200.60200-66~20.04), roctracer (= 4.1.60200.60200-66~20.04), rocprofiler-sdk (= 0.4.0-66~20.04), rocprofiler-sdk-roctx (= 0.4.0-66~20.04), rocprofiler-dev (= 2.0.60200.60200-66~20.04), roctracer-dev (= 4.1.60200.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-developer-tools/rocm-developer-tools_6.2.0.60200-66~20.04_amd64.deb +Size: 2174 +SHA256: fb77edfd5d606f8e61e96b739a7230f69b1f17192385f1efae2e207648be4464 +SHA1: 2a65a7684dccdc1c4c6ad8aa6e15e62e526771ff +MD5sum: a1831f061d44b99a1a288de50c26e26b +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-developer-tools-asan +Architecture: amd64 +Depends: rocm-developer-tools (= 6.2.0.60200-66~20.04), rocm-core-asan (= 6.2.0.60200-66~20.04), rocm-language-runtime-asan (= 6.2.0.60200-66~20.04), rocm-dbgapi-asan (= 0.76.0.60200-66~20.04), rocm-debug-agent-asan (= 2.0.3.60200-66~20.04), hsa-amd-aqlprofile-asan (= 1.0.0.60200.60200-66~20.04), rocm-smi-lib-asan (= 7.3.0.60200-66~20.04), amd-smi-lib-asan (= 24.6.2.60200-66~20.04), rocprofiler-asan (= 2.0.60200.60200-66~20.04), roctracer-asan (= 4.1.60200.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-developer-tools-asan/rocm-developer-tools-asan_6.2.0.60200-66~20.04_amd64.deb +Size: 918 +SHA256: 8a2ce2bab89de1f09403181c97a563afe248a3cb5c104f468df0af5cab15c7e4 +SHA1: 35cdfb1d8ad455c338402cbbf16d12585fccc599 +MD5sum: 9d1b027ff517d0b46c4eb0123216e5a6 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-developer-tools-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-developer-tools-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-language-runtime-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-dbgapi-asan-rpath6.2.0 (= 0.76.0.60200-66~20.04), rocm-debug-agent-asan-rpath6.2.0 (= 2.0.3.60200-66~20.04), hsa-amd-aqlprofile-asan-rpath6.2.0 (= 1.0.0.60200.60200-66~20.04), rocm-smi-lib-asan-rpath6.2.0 (= 7.3.0.60200-66~20.04), amd-smi-lib-asan-rpath6.2.0 (= 24.6.2.60200-66~20.04), rocprofiler-asan-rpath6.2.0 (= 2.0.60200.60200-66~20.04), roctracer-asan-rpath6.2.0 (= 4.1.60200.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-developer-tools-asan-rpath6.2.0/rocm-developer-tools-asan-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1124 +SHA256: 52f6bad1c0d0cf1518493780794f4b005cbe862d0c3193a2fb256546f41fbd9a +SHA1: 5540a799d5c7d26723ee8b5d53aae970bf0f091f +MD5sum: 3454833c29d34797a2c9959957e0f2cd +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-developer-tools-asan6.2.0 +Architecture: amd64 +Depends: rocm-developer-tools6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-asan6.2.0 (= 6.2.0.60200-66~20.04), rocm-language-runtime-asan6.2.0 (= 6.2.0.60200-66~20.04), rocm-dbgapi-asan6.2.0 (= 0.76.0.60200-66~20.04), rocm-debug-agent-asan6.2.0 (= 2.0.3.60200-66~20.04), hsa-amd-aqlprofile-asan6.2.0 (= 1.0.0.60200.60200-66~20.04), rocm-smi-lib-asan6.2.0 (= 7.3.0.60200-66~20.04), amd-smi-lib-asan6.2.0 (= 24.6.2.60200-66~20.04), rocprofiler-asan6.2.0 (= 2.0.60200.60200-66~20.04), roctracer-asan6.2.0 (= 4.1.60200.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-developer-tools-asan6.2.0/rocm-developer-tools-asan6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1116 +SHA256: 2619a046d8735e12fe9d9a5dd0565bd3e858af95b21efc0e419ca514925f0ff8 +SHA1: edbf4c665310184e3ada6dc63f57798e582e8751 +MD5sum: 9d4e65836bfe5cc39e8e6d578b3185bb +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-developer-tools-rpath6.2.0 +Architecture: amd64 +Depends: amd-smi-lib-rpath6.2.0 (= 24.6.2.60200-66~20.04), rocm-core-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-language-runtime-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-dbgapi-rpath6.2.0 (= 0.76.0.60200-66~20.04), rocm-debug-agent-rpath6.2.0 (= 2.0.3.60200-66~20.04), rocm-gdb-rpath6.2.0 (= 14.2.60200-66~20.04), hsa-amd-aqlprofile-rpath6.2.0 (= 1.0.0.60200.60200-66~20.04), rocm-smi-lib-rpath6.2.0 (= 7.3.0.60200-66~20.04), rocprofiler-register-rpath6.2.0 (= 0.4.0.60200-66~20.04), rocprofiler-rpath6.2.0 (= 2.0.60200.60200-66~20.04), rocprofiler-plugins-rpath6.2.0 (= 2.0.60200.60200-66~20.04), roctracer-rpath6.2.0 (= 4.1.60200.60200-66~20.04), rocprofiler-sdk-rpath6.2.0 (= 0.4.0-66~20.04), rocprofiler-sdk-roctx-rpath6.2.0 (= 0.4.0-66~20.04), rocprofiler-dev-rpath6.2.0 (= 2.0.60200.60200-66~20.04), roctracer-dev-rpath6.2.0 (= 4.1.60200.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-developer-tools-rpath6.2.0/rocm-developer-tools-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 2332 +SHA256: fe794990bff4a9c283d539329094b850f7de9a71e9f5186c4d5e89b4b51ccbe2 +SHA1: a1af2ac3c66f9b9da41de609d5d2614452a2f91d +MD5sum: f2166f5c0bf47b439b1a898b05965148 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-developer-tools6.2.0 +Architecture: amd64 +Depends: amd-smi-lib6.2.0 (= 24.6.2.60200-66~20.04), rocm-core6.2.0 (= 6.2.0.60200-66~20.04), rocm-language-runtime6.2.0 (= 6.2.0.60200-66~20.04), rocm-dbgapi6.2.0 (= 0.76.0.60200-66~20.04), rocm-debug-agent6.2.0 (= 2.0.3.60200-66~20.04), rocm-gdb6.2.0 (= 14.2.60200-66~20.04), hsa-amd-aqlprofile6.2.0 (= 1.0.0.60200.60200-66~20.04), rocm-smi-lib6.2.0 (= 7.3.0.60200-66~20.04), rocprofiler-register6.2.0 (= 0.4.0.60200-66~20.04), rocprofiler6.2.0 (= 2.0.60200.60200-66~20.04), rocprofiler-plugins6.2.0 (= 2.0.60200.60200-66~20.04), roctracer6.2.0 (= 4.1.60200.60200-66~20.04), rocprofiler-sdk6.2.0 (= 0.4.0-66~20.04), rocprofiler-sdk-roctx6.2.0 (= 0.4.0-66~20.04), rocprofiler-dev6.2.0 (= 2.0.60200.60200-66~20.04), roctracer-dev6.2.0 (= 4.1.60200.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-developer-tools6.2.0/rocm-developer-tools6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 2324 +SHA256: f07eaa377f0e25b9eea9937b2afecaade6dc1c358cc73bb015d736ebad76215b +SHA1: ba76059161d2feaa52a64c2881a72a537f8d5e3f +MD5sum: 66fd857e30b65eebb7f028c1bef007f0 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-device-libs +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocm-device-libs/rocm-device-libs_1.0.0.60200-66~20.04_amd64.deb +Size: 717742 +SHA256: 9caa5f4dc8e7d3bbb3b6f45f7e10d653415061b5b24e64d9e40a66975e44914a +SHA1: 4bbc84c5bf66189c9485bdfb9d77c3e0531eef7c +MD5sum: 978d635cedfd5f42d2a8330c4056ae80 +Description: Radeon Open Compute - device libraries + This package includes LLVM bitcode libraries. +Homepage: https://github.com/RadeonOpenCompute/ROCm-Device-Libs +Maintainer: ROCm Compiler Support +Version: 1.0.0.60200-66~20.04 +Installed-Size: 3326 + +Package: rocm-device-libs-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-device-libs-rpath6.2.0/rocm-device-libs-rpath6.2.0_1.0.0.60200-66~20.04_amd64.deb +Size: 467728 +SHA256: f53bfd4dc539152a71ea294675162ba25039aa761a2b465bdc846c0690f55f3b +SHA1: 43f898826327ff6853fcb597bdcefa33ccda6491 +MD5sum: 16374777ae614ae4c32cf562b358e111 +Description: Radeon Open Compute - device libraries + This package includes LLVM bitcode libraries. +Homepage: https://github.com/RadeonOpenCompute/ROCm-Device-Libs +Maintainer: ROCm Compiler Support +Version: 1.0.0.60200-66~20.04 +Installed-Size: 3326 + +Package: rocm-device-libs6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-device-libs6.2.0/rocm-device-libs6.2.0_1.0.0.60200-66~20.04_amd64.deb +Size: 470672 +SHA256: ae055b579d319e1a779783ba774f119fb0e1a731d058a03b36dc5c15214d210a +SHA1: 08c735c60bb262aa757c60af0abb9562976364af +MD5sum: c2862192ffb76b5c31bd76770868e72c +Description: Radeon Open Compute - device libraries + This package includes LLVM bitcode libraries. +Homepage: https://github.com/RadeonOpenCompute/ROCm-Device-Libs +Maintainer: ROCm Compiler Support +Version: 1.0.0.60200-66~20.04 +Installed-Size: 3326 + +Package: rocm-gdb +Version: 14.2.60200-66~20.04 +Maintainer: ROCm Debugger Support +Priority: optional +Section: utils +Filename: pool/main/r/rocm-gdb/rocm-gdb_14.2.60200-66~20.04_amd64.deb +Size: 110133170 +SHA256: a32cd0e7e745f51847f92b9f142e6ccd8a1e0acccd5a749bff829298e4f18749 +SHA1: 4539832f3def7f42f1f4f6febbfed65dc0c91863 +MD5sum: 11dcfb6dcaedad67afa8ce5075f6068c +Description: ROCgdb + This is ROCgdb, the AMD ROCm source-level debugger for Linux, + based on GDB, the GNU source-level debugger. +Architecture: amd64 +Essential: no +Depends: libc6 (>= 2.29), libexpat1 (>= 2.0.1), libgcc-s1 (>= 4.2), libgmp10, liblzma5 (>= 5.1.1alpha+20110809), libmpfr6 (>= 3.1.3), libncursesw6 (>= 6), libpython3.8 (>= 3.8.2), libstdc++6 (>= 7), libtinfo6 (>= 6), zlib1g (>= 1:1.2.0), rocm-dbgapi, rocm-core + +Package: rocm-gdb-rpath6.2.0 +Version: 14.2.60200-66~20.04 +Maintainer: ROCm Debugger Support +Priority: optional +Section: utils +Filename: pool/main/r/rocm-gdb-rpath6.2.0/rocm-gdb-rpath6.2.0_14.2.60200-66~20.04_amd64.deb +Size: 66409464 +SHA256: c1e2a2c156e34cbbddf1896c2a1b9bdbba37fc1f26a9ee9331edc6c3e434770d +SHA1: e31bd505314412977be66566a68a5554237b4e62 +MD5sum: 12c8dbc343b5501b1353d9900039852e +Description: ROCgdb + This is ROCgdb, the AMD ROCm source-level debugger for Linux, + based on GDB, the GNU source-level debugger. +Architecture: amd64 +Essential: no +Depends: libc6 (>= 2.29), libexpat1 (>= 2.0.1), libgcc-s1 (>= 4.2), libgmp10, liblzma5 (>= 5.1.1alpha+20110809), libmpfr6 (>= 3.1.3), libncursesw6 (>= 6), libpython3.8 (>= 3.8.2), libstdc++6 (>= 7), libtinfo6 (>= 6), zlib1g (>= 1:1.2.0), rocm-dbgapi-rpath6.2.0, rocm-core-rpath6.2.0 + +Package: rocm-gdb6.2.0 +Version: 14.2.60200-66~20.04 +Maintainer: ROCm Debugger Support +Priority: optional +Section: utils +Filename: pool/main/r/rocm-gdb6.2.0/rocm-gdb6.2.0_14.2.60200-66~20.04_amd64.deb +Size: 66411488 +SHA256: 41f3476b5e62bee6b85f97b1019f8213b1c1dee9a8a205fd6405a15d35a1f3f5 +SHA1: 1cd7cb2e4fa1a3200879711ec39146fc5ed37f4d +MD5sum: 2e0fd19deb491447feea12e5c7f171fc +Description: ROCgdb + This is ROCgdb, the AMD ROCm source-level debugger for Linux, + based on GDB, the GNU source-level debugger. +Architecture: amd64 +Essential: no +Depends: libc6 (>= 2.29), libexpat1 (>= 2.0.1), libgcc-s1 (>= 4.2), libgmp10, liblzma5 (>= 5.1.1alpha+20110809), libmpfr6 (>= 3.1.3), libncursesw6 (>= 6), libpython3.8 (>= 3.8.2), libstdc++6 (>= 7), libtinfo6 (>= 6), zlib1g (>= 1:1.2.0), rocm-dbgapi6.2.0, rocm-core6.2.0 + +Package: rocm-hip-libraries +Architecture: amd64 +Depends: rocm-core (= 6.2.0.60200-66~20.04), rocm-smi-lib (= 7.3.0.60200-66~20.04), rocm-hip-runtime (= 6.2.0.60200-66~20.04), hipblas (= 2.2.0.60200-66~20.04), hipblaslt (= 0.8.0.60200-66~20.04), hipfft (= 1.0.14.60200-66~20.04), hipsparse (= 3.1.1.60200-66~20.04), hipsolver (= 2.2.0.60200-66~20.04), hiptensor (= 1.3.0.60200-66~20.04), rccl (= 2.20.5.60200-66~20.04), rocalution (= 3.2.0.60200-66~20.04), rocblas (= 4.2.0.60200-66~20.04), rocfft (= 1.0.28.60200-66~20.04), rocrand (= 3.1.0.60200-66~20.04), hiprand (= 2.11.0.60200-66~20.04), rocsolver (= 3.26.0.60200-66~20.04), rocsparse (= 3.2.0.60200-66~20.04), hipsparselt (= 0.2.1.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-libraries/rocm-hip-libraries_6.2.0.60200-66~20.04_amd64.deb +Size: 940 +SHA256: 14f47d79b508eb259bfe4e0e5f360edb5721b908caf3bb981a4eee4181783be9 +SHA1: d2e16e010d1354bc3ac28ff4f5ef5440fbe00d46 +MD5sum: 37f1555cccc653ef0ebf955928474b27 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-libraries-asan +Architecture: amd64 +Depends: rocm-hip-libraries (= 6.2.0.60200-66~20.04), rocm-core-asan (= 6.2.0.60200-66~20.04), rocm-smi-lib-asan (= 7.3.0.60200-66~20.04), rocm-hip-runtime-asan (= 6.2.0.60200-66~20.04), hipblas-asan (= 2.2.0.60200-66~20.04), hipblaslt-asan (= 0.8.0.60200-66~20.04), hipfft-asan (= 1.0.14.60200-66~20.04), hipsparse-asan (= 3.1.1.60200-66~20.04), hipsolver-asan (= 2.2.0.60200-66~20.04), rocalution-asan (= 3.2.0.60200-66~20.04), rocblas-asan (= 4.2.0.60200-66~20.04), rocfft-asan (= 1.0.28.60200-66~20.04), rocsolver-asan (= 3.26.0.60200-66~20.04), rocsparse-asan (= 3.2.0.60200-66~20.04), hipsparselt-asan (= 0.2.1.60200-66~20.04), rocrand-asan (= 3.1.0.60200-66~20.04), hiprand-asan (= 2.11.0.60200-66~20.04), hiptensor-asan (= 1.3.0.60200-66~20.04), rccl-asan (= 2.20.5.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-libraries-asan/rocm-hip-libraries-asan_6.2.0.60200-66~20.04_amd64.deb +Size: 960 +SHA256: 1fdd4d6cd1dd5ae722815f691d03a54ae12cd94b7b64f609a21f306df24de107 +SHA1: 00d4819f8f7f5cdb10cd85d4a7c3c3dfe4e01cba +MD5sum: 505d320ccec21ad3649e3f237fb16f9f +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-libraries-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-hip-libraries-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-smi-lib-asan-rpath6.2.0 (= 7.3.0.60200-66~20.04), rocm-hip-runtime-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), hipblas-asan-rpath6.2.0 (= 2.2.0.60200-66~20.04), hipblaslt-asan-rpath6.2.0 (= 0.8.0.60200-66~20.04), hipfft-asan-rpath6.2.0 (= 1.0.14.60200-66~20.04), hipsparse-asan-rpath6.2.0 (= 3.1.1.60200-66~20.04), hipsolver-asan-rpath6.2.0 (= 2.2.0.60200-66~20.04), rocalution-asan-rpath6.2.0 (= 3.2.0.60200-66~20.04), rocblas-asan-rpath6.2.0 (= 4.2.0.60200-66~20.04), rocfft-asan-rpath6.2.0 (= 1.0.28.60200-66~20.04), rocsolver-asan-rpath6.2.0 (= 3.26.0.60200-66~20.04), rocsparse-asan-rpath6.2.0 (= 3.2.0.60200-66~20.04), hipsparselt-asan-rpath6.2.0 (= 0.2.1.60200-66~20.04), rocrand-asan-rpath6.2.0 (= 3.1.0.60200-66~20.04), hiprand-asan-rpath6.2.0 (= 2.11.0.60200-66~20.04), hiptensor-asan-rpath6.2.0 (= 1.3.0.60200-66~20.04), rccl-asan-rpath6.2.0 (= 2.20.5.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-libraries-asan-rpath6.2.0/rocm-hip-libraries-asan-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1164 +SHA256: 792f95d6f69ad2f224dbeb6649a1043c4d887e8b76d7d5f5e2482d9e57c7eddb +SHA1: 6f97be7653b9642984ea41eabc6ac2f00ffba5df +MD5sum: a8d2654a7b7c304d8fcd20a80f835beb +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-libraries-asan6.2.0 +Architecture: amd64 +Depends: rocm-hip-libraries6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-asan6.2.0 (= 6.2.0.60200-66~20.04), rocm-smi-lib-asan6.2.0 (= 7.3.0.60200-66~20.04), rocm-hip-runtime-asan6.2.0 (= 6.2.0.60200-66~20.04), hipblas-asan6.2.0 (= 2.2.0.60200-66~20.04), hipblaslt-asan6.2.0 (= 0.8.0.60200-66~20.04), hipfft-asan6.2.0 (= 1.0.14.60200-66~20.04), hipsparse-asan6.2.0 (= 3.1.1.60200-66~20.04), hipsolver-asan6.2.0 (= 2.2.0.60200-66~20.04), rocalution-asan6.2.0 (= 3.2.0.60200-66~20.04), rocblas-asan6.2.0 (= 4.2.0.60200-66~20.04), rocfft-asan6.2.0 (= 1.0.28.60200-66~20.04), rocsolver-asan6.2.0 (= 3.26.0.60200-66~20.04), rocsparse-asan6.2.0 (= 3.2.0.60200-66~20.04), hipsparselt-asan6.2.0 (= 0.2.1.60200-66~20.04), rocrand-asan6.2.0 (= 3.1.0.60200-66~20.04), hiprand-asan6.2.0 (= 2.11.0.60200-66~20.04), hiptensor-asan6.2.0 (= 1.3.0.60200-66~20.04), rccl-asan6.2.0 (= 2.20.5.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-libraries-asan6.2.0/rocm-hip-libraries-asan6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1156 +SHA256: a5c5683a90b34daa59214f6d2bca41a27611f6af45fcfc378b6c4e701692bccc +SHA1: 2445c84673c507d0eecdb91cadf1de5a363e8b3b +MD5sum: 0e8ce096097b8992b0bd84cbbfe5fa54 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-libraries-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-smi-lib-rpath6.2.0 (= 7.3.0.60200-66~20.04), rocm-hip-runtime-rpath6.2.0 (= 6.2.0.60200-66~20.04), hipblas-rpath6.2.0 (= 2.2.0.60200-66~20.04), hipblaslt-rpath6.2.0 (= 0.8.0.60200-66~20.04), hipfft-rpath6.2.0 (= 1.0.14.60200-66~20.04), hipsparse-rpath6.2.0 (= 3.1.1.60200-66~20.04), hipsolver-rpath6.2.0 (= 2.2.0.60200-66~20.04), hiptensor-rpath6.2.0 (= 1.3.0.60200-66~20.04), rccl-rpath6.2.0 (= 2.20.5.60200-66~20.04), rocalution-rpath6.2.0 (= 3.2.0.60200-66~20.04), rocblas-rpath6.2.0 (= 4.2.0.60200-66~20.04), rocfft-rpath6.2.0 (= 1.0.28.60200-66~20.04), rocrand-rpath6.2.0 (= 3.1.0.60200-66~20.04), hiprand-rpath6.2.0 (= 2.11.0.60200-66~20.04), rocsolver-rpath6.2.0 (= 3.26.0.60200-66~20.04), rocsparse-rpath6.2.0 (= 3.2.0.60200-66~20.04), hipsparselt-rpath6.2.0 (= 0.2.1.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-libraries-rpath6.2.0/rocm-hip-libraries-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1144 +SHA256: 82371f56b80f97b16358b793633123790f0124f7292adf1623ef634b3ade74d8 +SHA1: 65c81c7772d24c1972275890f481cc1c4c6fbf15 +MD5sum: 43be5d05534b7f907a2ff8d77fb44345 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-libraries6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 (= 6.2.0.60200-66~20.04), rocm-smi-lib6.2.0 (= 7.3.0.60200-66~20.04), rocm-hip-runtime6.2.0 (= 6.2.0.60200-66~20.04), hipblas6.2.0 (= 2.2.0.60200-66~20.04), hipblaslt6.2.0 (= 0.8.0.60200-66~20.04), hipfft6.2.0 (= 1.0.14.60200-66~20.04), hipsparse6.2.0 (= 3.1.1.60200-66~20.04), hipsolver6.2.0 (= 2.2.0.60200-66~20.04), hiptensor6.2.0 (= 1.3.0.60200-66~20.04), rccl6.2.0 (= 2.20.5.60200-66~20.04), rocalution6.2.0 (= 3.2.0.60200-66~20.04), rocblas6.2.0 (= 4.2.0.60200-66~20.04), rocfft6.2.0 (= 1.0.28.60200-66~20.04), rocrand6.2.0 (= 3.1.0.60200-66~20.04), hiprand6.2.0 (= 2.11.0.60200-66~20.04), rocsolver6.2.0 (= 3.26.0.60200-66~20.04), rocsparse6.2.0 (= 3.2.0.60200-66~20.04), hipsparselt6.2.0 (= 0.2.1.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-libraries6.2.0/rocm-hip-libraries6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1136 +SHA256: cc926d92de2a3458afd5c430eb9ed731f46542f2fff5d664a7593bed7761a782 +SHA1: 4dbc863b66414f6f41c95a0252d6b9cd9a0adde1 +MD5sum: 513b116c76897c9e886e12a2ee1941af +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-runtime +Architecture: amd64 +Depends: rocm-core (= 6.2.0.60200-66~20.04), rocm-language-runtime (= 6.2.0.60200-66~20.04), rocminfo (= 1.0.0.60200-66~20.04), hip-runtime-amd (= 6.2.41133.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-runtime/rocm-hip-runtime_6.2.0.60200-66~20.04_amd64.deb +Size: 2032 +SHA256: 3d1632b0b989ae3376a9c19afd08044ab501f6a634997893caa4ee656e772c2d +SHA1: f9bd47632db69597ee2c6790a781e70f2b788ba2 +MD5sum: fcea5396740db2b3172aa519e4019e74 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-runtime-asan +Architecture: amd64 +Depends: rocm-hip-runtime (= 6.2.0.60200-66~20.04), rocm-core-asan (= 6.2.0.60200-66~20.04), rocm-language-runtime-asan (= 6.2.0.60200-66~20.04), hip-runtime-amd-asan (= 6.2.41133.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-runtime-asan/rocm-hip-runtime-asan_6.2.0.60200-66~20.04_amd64.deb +Size: 832 +SHA256: 7d44db5797a7eadc4d9d992dacdafddc0d1ad6904556e100186a154ab1ad4efc +SHA1: 5578cd1a6962e7abc9f5d7d768567ae5e38b4bc6 +MD5sum: 684f8bb8f13827525418e9507430df63 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-runtime-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-hip-runtime-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-language-runtime-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), hip-runtime-amd-asan-rpath6.2.0 (= 6.2.41133.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-runtime-asan-rpath6.2.0/rocm-hip-runtime-asan-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1044 +SHA256: 07020d050b3e48717b42ddb933fd3d309cc25aed8a948917bba440525e09bdbe +SHA1: 20fa16e835b6cea7a247925f6aea9a55a62123cc +MD5sum: 4147c9cac9dc1db7e9ee55d1ae5c067f +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-runtime-asan6.2.0 +Architecture: amd64 +Depends: rocm-hip-runtime6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-asan6.2.0 (= 6.2.0.60200-66~20.04), rocm-language-runtime-asan6.2.0 (= 6.2.0.60200-66~20.04), hip-runtime-amd-asan6.2.0 (= 6.2.41133.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-runtime-asan6.2.0/rocm-hip-runtime-asan6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1040 +SHA256: cdfa0062c1f80592f97788d3a6a28f256cb9a164e4f564c3b0b6026b3b852605 +SHA1: 357e75eb24330cbd8e678b2a0aca6ae55803584f +MD5sum: 3fd05b1478fd6afeac8025628d7e7730 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-runtime-dev +Architecture: amd64 +Depends: rocm-core (= 6.2.0.60200-66~20.04), rocm-device-libs (= 1.0.0.60200-66~20.04), rocm-hip-runtime (= 6.2.0.60200-66~20.04), rocm-cmake (= 0.13.0.60200-66~20.04), rocm-llvm (= 18.0.0.24292.60200-66~20.04), hipcc (= 1.1.1.60200-66~20.04), hipify-clang (= 18.0.0.60200-66~20.04), hip-doc (= 6.2.41133.60200-66~20.04), hip-samples (= 6.2.41133.60200-66~20.04), hip-dev (= 6.2.41133.60200-66~20.04), hsa-rocr-dev (= 1.14.0.60200-66~20.04), hsakmt-roct-dev (= 20240607.3.8.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-runtime-dev/rocm-hip-runtime-dev_6.2.0.60200-66~20.04_amd64.deb +Size: 2220 +SHA256: e025d72bf6047c9f1a11149ef89818f9942127f85f837258d43d6dfdbdad180c +SHA1: 1b525838dd4c94414e5ae085ae3818e12e217145 +MD5sum: 62a7bce39abd7a64c60c31050229bbc6 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-runtime-dev-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-device-libs-rpath6.2.0 (= 1.0.0.60200-66~20.04), rocm-hip-runtime-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-cmake-rpath6.2.0 (= 0.13.0.60200-66~20.04), rocm-llvm-rpath6.2.0 (= 18.0.0.24292.60200-66~20.04), hipcc-rpath6.2.0 (= 1.1.1.60200-66~20.04), hipify-clang-rpath6.2.0 (= 18.0.0.60200-66~20.04), hip-doc-rpath6.2.0 (= 6.2.41133.60200-66~20.04), hip-samples-rpath6.2.0 (= 6.2.41133.60200-66~20.04), hip-dev-rpath6.2.0 (= 6.2.41133.60200-66~20.04), hsa-rocr-dev-rpath6.2.0 (= 1.14.0.60200-66~20.04), hsakmt-roct-dev-rpath6.2.0 (= 20240607.3.8.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-runtime-dev-rpath6.2.0/rocm-hip-runtime-dev-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 2380 +SHA256: ab0499f975fcbc4f39e39c0f5b77abaa55de36f17df6a2c7e572091e4e1ec735 +SHA1: 4ccfc4c85d20c94a0efda3720335a990f8529455 +MD5sum: 4e7e54eb4256f7838bf469af1f58eb86 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-runtime-dev6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 (= 6.2.0.60200-66~20.04), rocm-device-libs6.2.0 (= 1.0.0.60200-66~20.04), rocm-hip-runtime6.2.0 (= 6.2.0.60200-66~20.04), rocm-cmake6.2.0 (= 0.13.0.60200-66~20.04), rocm-llvm6.2.0 (= 18.0.0.24292.60200-66~20.04), hipcc6.2.0 (= 1.1.1.60200-66~20.04), hipify-clang6.2.0 (= 18.0.0.60200-66~20.04), hip-doc6.2.0 (= 6.2.41133.60200-66~20.04), hip-samples6.2.0 (= 6.2.41133.60200-66~20.04), hip-dev6.2.0 (= 6.2.41133.60200-66~20.04), hsa-rocr-dev6.2.0 (= 1.14.0.60200-66~20.04), hsakmt-roct-dev6.2.0 (= 20240607.3.8.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-runtime-dev6.2.0/rocm-hip-runtime-dev6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 2376 +SHA256: 82aa3259483611f3e621e02f16f65b3cd36bddd1bb0a7458e35b1cb577524f85 +SHA1: 7e44c0d96d9e09719c0a5b0502c0bd4ac3cf4bb9 +MD5sum: 65b35d1cdc58d81d312559d936857e90 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-runtime-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-language-runtime-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocminfo-rpath6.2.0 (= 1.0.0.60200-66~20.04), hip-runtime-amd-rpath6.2.0 (= 6.2.41133.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-runtime-rpath6.2.0/rocm-hip-runtime-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 2204 +SHA256: 87f3dde3bd487e167b0347cf1e6588414a45f33c036b0811fc5bd6b9ec0a1255 +SHA1: 9bc3997463f9bcb8d1015a8d431a86fbc63045f1 +MD5sum: 28a47474443ad6af7cc5ce3feb32552f +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-runtime6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 (= 6.2.0.60200-66~20.04), rocm-language-runtime6.2.0 (= 6.2.0.60200-66~20.04), rocminfo6.2.0 (= 1.0.0.60200-66~20.04), hip-runtime-amd6.2.0 (= 6.2.41133.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-runtime6.2.0/rocm-hip-runtime6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 2192 +SHA256: 45fdba8b881d2ef752fefbae403f8360cc4aaf1273c31d9bb19cfe3f7baa52f9 +SHA1: 89e19f4aa9ca7d25d75dc8661fd12af57f6b9fe5 +MD5sum: 0eeab48f62cde9133385987578ea4f1b +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-sdk +Architecture: amd64 +Depends: rocm-hip-libraries (= 6.2.0.60200-66~20.04), rocm-core (= 6.2.0.60200-66~20.04), rocm-hip-runtime-dev (= 6.2.0.60200-66~20.04), composablekernel-dev (= 1.1.0.60200-66~20.04), hipblas-dev (= 2.2.0.60200-66~20.04), hipblaslt-dev (= 0.8.0.60200-66~20.04), hipcub-dev (= 3.2.0.60200-66~20.04), hipfft-dev (= 1.0.14.60200-66~20.04), hipsparse-dev (= 3.1.1.60200-66~20.04), hipsolver-dev (= 2.2.0.60200-66~20.04), hipfort-dev (= 0.4.0.60200-66~20.04), hiptensor-dev (= 1.3.0.60200-66~20.04), rccl-dev (= 2.20.5.60200-66~20.04), rocalution-dev (= 3.2.0.60200-66~20.04), rocblas-dev (= 4.2.0.60200-66~20.04), rocfft-dev (= 1.0.28.60200-66~20.04), rocprim-dev (= 3.2.0.60200-66~20.04), rocrand-dev (= 3.1.0.60200-66~20.04), hiprand-dev (= 2.11.0.60200-66~20.04), rocsolver-dev (= 3.26.0.60200-66~20.04), rocsparse-dev (= 3.2.0.60200-66~20.04), rocthrust-dev (= 3.0.1.60200-66~20.04), rocwmma-dev (= 1.5.0.60200-66~20.04), hipsparselt-dev (= 0.2.1.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-sdk/rocm-hip-sdk_6.2.0.60200-66~20.04_amd64.deb +Size: 2194 +SHA256: f272de1457c872e7f7ee61fcda3b7d8af992a876eb9ea81621e4182b3f35bab0 +SHA1: ba359dadc65a23779b33443bbcbe8a936c126fc5 +MD5sum: f50b30939d08b41b2e744febb4696c98 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-sdk-rpath6.2.0 +Architecture: amd64 +Depends: rocm-hip-libraries-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-hip-runtime-dev-rpath6.2.0 (= 6.2.0.60200-66~20.04), composablekernel-dev-rpath6.2.0 (= 1.1.0.60200-66~20.04), hipblas-dev-rpath6.2.0 (= 2.2.0.60200-66~20.04), hipblaslt-dev-rpath6.2.0 (= 0.8.0.60200-66~20.04), hipcub-dev-rpath6.2.0 (= 3.2.0.60200-66~20.04), hipfft-dev-rpath6.2.0 (= 1.0.14.60200-66~20.04), hipsparse-dev-rpath6.2.0 (= 3.1.1.60200-66~20.04), hipsolver-dev-rpath6.2.0 (= 2.2.0.60200-66~20.04), hipfort-dev-rpath6.2.0 (= 0.4.0.60200-66~20.04), hiptensor-dev-rpath6.2.0 (= 1.3.0.60200-66~20.04), rccl-dev-rpath6.2.0 (= 2.20.5.60200-66~20.04), rocalution-dev-rpath6.2.0 (= 3.2.0.60200-66~20.04), rocblas-dev-rpath6.2.0 (= 4.2.0.60200-66~20.04), rocfft-dev-rpath6.2.0 (= 1.0.28.60200-66~20.04), rocprim-dev-rpath6.2.0 (= 3.2.0.60200-66~20.04), rocrand-dev-rpath6.2.0 (= 3.1.0.60200-66~20.04), hiprand-dev-rpath6.2.0 (= 2.11.0.60200-66~20.04), rocsolver-dev-rpath6.2.0 (= 3.26.0.60200-66~20.04), rocsparse-dev-rpath6.2.0 (= 3.2.0.60200-66~20.04), rocthrust-dev-rpath6.2.0 (= 3.0.1.60200-66~20.04), rocwmma-dev-rpath6.2.0 (= 1.5.0.60200-66~20.04), hipsparselt-dev-rpath6.2.0 (= 0.2.1.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-sdk-rpath6.2.0/rocm-hip-sdk-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 2336 +SHA256: 7fd11e14545782b86a949e34ecec40fc6b9f358f76d20953efba8e0b1a189264 +SHA1: 6b20d9c95af6ac4636fe626c400f7feb397ee5d0 +MD5sum: 89327ce4a05ca489a15be81ca3ec138a +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-hip-sdk6.2.0 +Architecture: amd64 +Depends: rocm-hip-libraries6.2.0 (= 6.2.0.60200-66~20.04), rocm-core6.2.0 (= 6.2.0.60200-66~20.04), rocm-hip-runtime-dev6.2.0 (= 6.2.0.60200-66~20.04), composablekernel-dev6.2.0 (= 1.1.0.60200-66~20.04), hipblas-dev6.2.0 (= 2.2.0.60200-66~20.04), hipblaslt-dev6.2.0 (= 0.8.0.60200-66~20.04), hipcub-dev6.2.0 (= 3.2.0.60200-66~20.04), hipfft-dev6.2.0 (= 1.0.14.60200-66~20.04), hipsparse-dev6.2.0 (= 3.1.1.60200-66~20.04), hipsolver-dev6.2.0 (= 2.2.0.60200-66~20.04), hipfort-dev6.2.0 (= 0.4.0.60200-66~20.04), hiptensor-dev6.2.0 (= 1.3.0.60200-66~20.04), rccl-dev6.2.0 (= 2.20.5.60200-66~20.04), rocalution-dev6.2.0 (= 3.2.0.60200-66~20.04), rocblas-dev6.2.0 (= 4.2.0.60200-66~20.04), rocfft-dev6.2.0 (= 1.0.28.60200-66~20.04), rocprim-dev6.2.0 (= 3.2.0.60200-66~20.04), rocrand-dev6.2.0 (= 3.1.0.60200-66~20.04), hiprand-dev6.2.0 (= 2.11.0.60200-66~20.04), rocsolver-dev6.2.0 (= 3.26.0.60200-66~20.04), rocsparse-dev6.2.0 (= 3.2.0.60200-66~20.04), rocthrust-dev6.2.0 (= 3.0.1.60200-66~20.04), rocwmma-dev6.2.0 (= 1.5.0.60200-66~20.04), hipsparselt-dev6.2.0 (= 0.2.1.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-hip-sdk6.2.0/rocm-hip-sdk6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 2336 +SHA256: e05cf4a9694951723b0bd9b911e7e43da097450cf0c19862e4a8a70f794fd23d +SHA1: 9fc35b34a4afc6fdc595b7df70319296332a4370 +MD5sum: fe5a93b9e6a7addc49b856e70d2e95ba +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-khronos-cts +Architecture: amd64 +Depends: rocm-core, rocm-opencl-icd-loader +Priority: optional +Section: devel +Filename: pool/main/r/rocm-khronos-cts/rocm-khronos-cts_3.0.0.60200-66~20.04_amd64.deb +Size: 8309280 +SHA256: 6c941ad43ed3da82232fcb71424752b728441aa8db5ba71f104ccaccb8f615a7 +SHA1: a19c3d7923096ddfca3ac1d7c75f234bb2386a76 +MD5sum: be05567a38499a518ecf9c659270d8ec +Description: CLConform built using CMake +Maintainer: ROCm OpenCL Support +Version: 3.0.0.60200-66~20.04 +Installed-Size: 24079 + +Package: rocm-khronos-cts-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 94e9917906b3ce3d0ca64e31e75247644c9a46ce 9c37af5c1c6d62d20844a1f13b33c45e415a3055 98b06959a1d9de91d7c65a6491d461280d524b60 5366c00d77471b19badf16b8538bd8b74bdbbb91 c8cc61352a916478de98236803c6ca44605b3a66 68f4f8a8bf9bb317c67ac1322f1aa41680422df8 732d242066175d6f183fcc01caf1637e7f136be6 1bbdf6e4ce5a5d854e5f1b472af2c0ce58a4cba5 45b66ce9dc4a938fb93e94f69741581a24422784 045693d56269ce19aadf568552f22d46133f9632 714b4d6b129ba80811ebf5f449c238fbe5912f93 7cda9e0482c9280818978a5d1cba225c00ccb645 857a0dbc0d5684074269ba2862d9e7b9d00a45d0 e75fb162b1b7ceeae1e8dad92ed7ede977e05c8b 81bb62eb33d0952e982828c06eac7281ec35ca33 56a8425f61d034eddd7a3bdbb479038f135b9b96 b0bfdc5b73ebb8005b9148ee759b16033b458290 5267465a18ef8ff7bb24554a0e0ed4470fb3d0a6 2a4c642ffe919adb48a4f2058ad08f88bf335f57 489e092eb67f21cd078a326726ee0f36d726b1dc 7f9613c11119ee83427dd12fb45138f633261e89 fe5cbfece7bf1615b428255aa71b11fc6b4ecfcd b58a7f822e726b70acc4e7823edefd820514b25a 564610a456f0f4ab8d493a2b12f1ae13231caded 5db3a42379e42caa7f744437084aed5d19760566 7781e23422823e38e19bad64b995826e1c429363 4c9dfa4efe2d5ecfbce8b7ff8b1dff1d6cbd4f84 727fa19224b7e5305f20fdf1713a32e35acc1b49 f6cc343dd946f75d1c31a33cf674adbd93ae402a b88b5d1a1820aab4fa1b841584b60c5ed11b89c4 80b6e472fb5ad023ba99a5ba97205bdcfc99f7c5 99e52da9e711c4a0ba4a8d4183817af6c6c46d32 a2b170517b8425c8abdd3aa628405c0b753d6ce7 bb2af8446cf57726e4a900ca63e7bf9f82ad5639 9491e7c8905060234d37707cf00d0e74e455c26b fb33d11866ac9fc0e291ee3f0039c39970ba5bb6 1eea99c5cda0bdffbec92ce946e42699b8e147d7 1ffd33ddd7b7e8a58a28c12ff664e1963faf399d 10c268330940980c139aad706c6268cf8d85c3d3 49970265e0f28910457feadfe07424d8e1702eae 6863af6c17608d60c16868b35e7ef477a64260d3 2a5e889f9d3e7ae8d584e986a1c63844bf9b0ddb b55b56eda641a927ec21309b8d209f75fe373ac3 b916b3ba12c8268c2dd0d4174aa9c8417a207a7c 7ffe5de18e09db0356896173c72e081c75cde566 828ba05644f03f264b6a5419ecec7f00b1cbfdb2 +Depends: rocm-khronos-cts (= 3.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-khronos-cts-dbgsym/rocm-khronos-cts-dbgsym_3.0.0.60200-66~20.04_amd64.deb +Size: 85609136 +SHA256: 20498cdb5ad5249d9e68c6291501adacab3ad1be00cb3ecb00ade1e5dda155ed +SHA1: 283c2a495abe22d630b85a9a00adac2c1c00ee6a +MD5sum: 9f86b7bda88e965ae2fc06acefc80867 +Description: debug symbols for rocm-khronos-cts +Maintainer: ROCm OpenCL Support +Package-Type: ddeb +Version: 3.0.0.60200-66~20.04 +Installed-Size: 341286 + +Package: rocm-khronos-cts-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 94e9917906b3ce3d0ca64e31e75247644c9a46ce 9c37af5c1c6d62d20844a1f13b33c45e415a3055 98b06959a1d9de91d7c65a6491d461280d524b60 5366c00d77471b19badf16b8538bd8b74bdbbb91 c8cc61352a916478de98236803c6ca44605b3a66 68f4f8a8bf9bb317c67ac1322f1aa41680422df8 732d242066175d6f183fcc01caf1637e7f136be6 1bbdf6e4ce5a5d854e5f1b472af2c0ce58a4cba5 45b66ce9dc4a938fb93e94f69741581a24422784 045693d56269ce19aadf568552f22d46133f9632 714b4d6b129ba80811ebf5f449c238fbe5912f93 7cda9e0482c9280818978a5d1cba225c00ccb645 857a0dbc0d5684074269ba2862d9e7b9d00a45d0 e75fb162b1b7ceeae1e8dad92ed7ede977e05c8b 81bb62eb33d0952e982828c06eac7281ec35ca33 56a8425f61d034eddd7a3bdbb479038f135b9b96 b0bfdc5b73ebb8005b9148ee759b16033b458290 5267465a18ef8ff7bb24554a0e0ed4470fb3d0a6 2a4c642ffe919adb48a4f2058ad08f88bf335f57 489e092eb67f21cd078a326726ee0f36d726b1dc 7f9613c11119ee83427dd12fb45138f633261e89 fe5cbfece7bf1615b428255aa71b11fc6b4ecfcd b58a7f822e726b70acc4e7823edefd820514b25a 564610a456f0f4ab8d493a2b12f1ae13231caded 5db3a42379e42caa7f744437084aed5d19760566 7781e23422823e38e19bad64b995826e1c429363 4c9dfa4efe2d5ecfbce8b7ff8b1dff1d6cbd4f84 727fa19224b7e5305f20fdf1713a32e35acc1b49 f6cc343dd946f75d1c31a33cf674adbd93ae402a b88b5d1a1820aab4fa1b841584b60c5ed11b89c4 80b6e472fb5ad023ba99a5ba97205bdcfc99f7c5 99e52da9e711c4a0ba4a8d4183817af6c6c46d32 a2b170517b8425c8abdd3aa628405c0b753d6ce7 bb2af8446cf57726e4a900ca63e7bf9f82ad5639 9491e7c8905060234d37707cf00d0e74e455c26b fb33d11866ac9fc0e291ee3f0039c39970ba5bb6 1eea99c5cda0bdffbec92ce946e42699b8e147d7 1ffd33ddd7b7e8a58a28c12ff664e1963faf399d 10c268330940980c139aad706c6268cf8d85c3d3 49970265e0f28910457feadfe07424d8e1702eae 6863af6c17608d60c16868b35e7ef477a64260d3 2a5e889f9d3e7ae8d584e986a1c63844bf9b0ddb b55b56eda641a927ec21309b8d209f75fe373ac3 b916b3ba12c8268c2dd0d4174aa9c8417a207a7c 7ffe5de18e09db0356896173c72e081c75cde566 828ba05644f03f264b6a5419ecec7f00b1cbfdb2 +Depends: rocm-khronos-cts-rpath6.2.0 (= 3.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-khronos-cts-dbgsym-rpath6.2.0/rocm-khronos-cts-dbgsym-rpath6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 46602780 +SHA256: e826cd64f65e8dbbd28b01aaa99ac14437ce9715c1ced9ed6779f5596a5633cf +SHA1: f6b026e93eff5710c0f9011b3b7cb07f413515c8 +MD5sum: 413deeb7e60b237ea2a5b8e6cde34980 +Description: debug symbols for rocm-khronos-cts +Maintainer: ROCm OpenCL Support +Package-Type: ddeb +Version: 3.0.0.60200-66~20.04 +Installed-Size: 341286 + +Package: rocm-khronos-cts-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 94e9917906b3ce3d0ca64e31e75247644c9a46ce 9c37af5c1c6d62d20844a1f13b33c45e415a3055 98b06959a1d9de91d7c65a6491d461280d524b60 5366c00d77471b19badf16b8538bd8b74bdbbb91 c8cc61352a916478de98236803c6ca44605b3a66 68f4f8a8bf9bb317c67ac1322f1aa41680422df8 732d242066175d6f183fcc01caf1637e7f136be6 1bbdf6e4ce5a5d854e5f1b472af2c0ce58a4cba5 45b66ce9dc4a938fb93e94f69741581a24422784 045693d56269ce19aadf568552f22d46133f9632 714b4d6b129ba80811ebf5f449c238fbe5912f93 7cda9e0482c9280818978a5d1cba225c00ccb645 857a0dbc0d5684074269ba2862d9e7b9d00a45d0 e75fb162b1b7ceeae1e8dad92ed7ede977e05c8b 81bb62eb33d0952e982828c06eac7281ec35ca33 56a8425f61d034eddd7a3bdbb479038f135b9b96 b0bfdc5b73ebb8005b9148ee759b16033b458290 5267465a18ef8ff7bb24554a0e0ed4470fb3d0a6 2a4c642ffe919adb48a4f2058ad08f88bf335f57 489e092eb67f21cd078a326726ee0f36d726b1dc 7f9613c11119ee83427dd12fb45138f633261e89 fe5cbfece7bf1615b428255aa71b11fc6b4ecfcd b58a7f822e726b70acc4e7823edefd820514b25a 564610a456f0f4ab8d493a2b12f1ae13231caded 5db3a42379e42caa7f744437084aed5d19760566 7781e23422823e38e19bad64b995826e1c429363 4c9dfa4efe2d5ecfbce8b7ff8b1dff1d6cbd4f84 727fa19224b7e5305f20fdf1713a32e35acc1b49 f6cc343dd946f75d1c31a33cf674adbd93ae402a b88b5d1a1820aab4fa1b841584b60c5ed11b89c4 80b6e472fb5ad023ba99a5ba97205bdcfc99f7c5 99e52da9e711c4a0ba4a8d4183817af6c6c46d32 a2b170517b8425c8abdd3aa628405c0b753d6ce7 bb2af8446cf57726e4a900ca63e7bf9f82ad5639 9491e7c8905060234d37707cf00d0e74e455c26b fb33d11866ac9fc0e291ee3f0039c39970ba5bb6 1eea99c5cda0bdffbec92ce946e42699b8e147d7 1ffd33ddd7b7e8a58a28c12ff664e1963faf399d 10c268330940980c139aad706c6268cf8d85c3d3 49970265e0f28910457feadfe07424d8e1702eae 6863af6c17608d60c16868b35e7ef477a64260d3 2a5e889f9d3e7ae8d584e986a1c63844bf9b0ddb b55b56eda641a927ec21309b8d209f75fe373ac3 b916b3ba12c8268c2dd0d4174aa9c8417a207a7c 7ffe5de18e09db0356896173c72e081c75cde566 828ba05644f03f264b6a5419ecec7f00b1cbfdb2 +Depends: rocm-khronos-cts6.2.0 (= 3.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-khronos-cts-dbgsym6.2.0/rocm-khronos-cts-dbgsym6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 46597360 +SHA256: 5657663d287d76e5315f850e1c747eedc8daf12f184af700f28a393f531f16e0 +SHA1: 56c73a49e34304e387adcb2d196ef5b8917b2780 +MD5sum: d3b27049c146905e4f6d9696d78e341d +Description: debug symbols for rocm-khronos-cts +Maintainer: ROCm OpenCL Support +Package-Type: ddeb +Version: 3.0.0.60200-66~20.04 +Installed-Size: 341286 + +Package: rocm-khronos-cts-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0, rocm-opencl-icd-loader-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-khronos-cts-rpath6.2.0/rocm-khronos-cts-rpath6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 3528836 +SHA256: 2e7e31ad68b7154bc3512f693fdca93d134804956136915f6ac473921aa36f4d +SHA1: 807965e8714cb94182e270ba6a16e28ffa403d8b +MD5sum: bdc62e72fb0e34d864da0aff94be4e13 +Description: CLConform built using CMake +Maintainer: ROCm OpenCL Support +Version: 3.0.0.60200-66~20.04 +Installed-Size: 24079 + +Package: rocm-khronos-cts6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0, rocm-opencl-icd-loader6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-khronos-cts6.2.0/rocm-khronos-cts6.2.0_3.0.0.60200-66~20.04_amd64.deb +Size: 3529148 +SHA256: 0541b9b24c7283e6dd29f08aa8bac25a4f0d93f393704895ecaa026441ce6bf3 +SHA1: 3b7e6adddcab87070be275f8f3c23ac4f974fb65 +MD5sum: faf9be552c6e93436035fc2a96281515 +Description: CLConform built using CMake +Maintainer: ROCm OpenCL Support +Version: 3.0.0.60200-66~20.04 +Installed-Size: 24079 + +Package: rocm-language-runtime +Architecture: amd64 +Depends: comgr (= 2.8.0.60200-66~20.04), hsa-rocr (= 1.14.0.60200-66~20.04), rocm-core (= 6.2.0.60200-66~20.04), openmp-extras-runtime (= 18.62.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-language-runtime/rocm-language-runtime_6.2.0.60200-66~20.04_amd64.deb +Size: 838 +SHA256: 7d590c8ccc30ae4344671d390b195c473283de7fac82ac09e524e65ba9ee39ca +SHA1: 8b688ff6c27217a2601f30df37540d4aab0297a9 +MD5sum: 19b2163f22af0410d155934fb6098eab +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-language-runtime-asan +Architecture: amd64 +Depends: rocm-language-runtime (= 6.2.0.60200-66~20.04), comgr-asan (= 2.8.0.60200-66~20.04), hsakmt-roct-asan (= 20240607.3.8.60200-66~20.04), hsa-rocr-asan (= 1.14.0.60200-66~20.04), openmp-extras-asan (= 18.62.0.60200-66~20.04), rocm-core-asan (= 6.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-language-runtime-asan/rocm-language-runtime-asan_6.2.0.60200-66~20.04_amd64.deb +Size: 870 +SHA256: 14ea5bcd5bcf82eca39f3d40774a168604b1570852c302cbbc2d7e494be65808 +SHA1: 1a3cba1a4da6dc868c076144fff96e26a7242755 +MD5sum: d5f82f86cbde0d4868393efba0416cbe +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-language-runtime-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-language-runtime-rpath6.2.0 (= 6.2.0.60200-66~20.04), comgr-asan-rpath6.2.0 (= 2.8.0.60200-66~20.04), hsakmt-roct-asan-rpath6.2.0 (= 20240607.3.8.60200-66~20.04), hsa-rocr-asan-rpath6.2.0 (= 1.14.0.60200-66~20.04), openmp-extras-asan-rpath6.2.0 (= 18.62.0.60200-66~20.04), rocm-core-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-language-runtime-asan-rpath6.2.0/rocm-language-runtime-asan-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1080 +SHA256: 6a04af9d2c878fe8edd6eee1affd9db442ce04af583396a70969fc1e06806c3c +SHA1: f9b4877d920085159559a0dbe6e420e6e1cc97cc +MD5sum: ed1877d746ea52c09e6bc96cd5df356a +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-language-runtime-asan6.2.0 +Architecture: amd64 +Depends: rocm-language-runtime6.2.0 (= 6.2.0.60200-66~20.04), comgr-asan6.2.0 (= 2.8.0.60200-66~20.04), hsakmt-roct-asan6.2.0 (= 20240607.3.8.60200-66~20.04), hsa-rocr-asan6.2.0 (= 1.14.0.60200-66~20.04), openmp-extras-asan6.2.0 (= 18.62.0.60200-66~20.04), rocm-core-asan6.2.0 (= 6.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-language-runtime-asan6.2.0/rocm-language-runtime-asan6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1076 +SHA256: b8743daf2b95279b54a7dcd1c6192a0ccd03b94f8cbc69745589c0c2863995b7 +SHA1: 595b041fc0d1e6114be3d1719b15001d599d9f19 +MD5sum: db994ee0a50e779e2ea8561b971d0838 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-language-runtime-rpath6.2.0 +Architecture: amd64 +Depends: comgr-rpath6.2.0 (= 2.8.0.60200-66~20.04), hsa-rocr-rpath6.2.0 (= 1.14.0.60200-66~20.04), rocm-core-rpath6.2.0 (= 6.2.0.60200-66~20.04), openmp-extras-runtime-rpath6.2.0 (= 18.62.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-language-runtime-rpath6.2.0/rocm-language-runtime-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1048 +SHA256: 4f11f01838878b74681e08ee2409ce57ff97751409107631d4aabc668fd1654f +SHA1: 795ecccba3d5e005b6d3feb2dace7c7686a85604 +MD5sum: 655d0c4cadaa9a48edc6056433cbd1b6 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-language-runtime6.2.0 +Architecture: amd64 +Depends: comgr6.2.0 (= 2.8.0.60200-66~20.04), hsa-rocr6.2.0 (= 1.14.0.60200-66~20.04), rocm-core6.2.0 (= 6.2.0.60200-66~20.04), openmp-extras-runtime6.2.0 (= 18.62.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-language-runtime6.2.0/rocm-language-runtime6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1028 +SHA256: 5e8d61bd1ecdf67dfafa318296abba34a2afaea49ca6a6cb0ba5c065ec105a0b +SHA1: de42876e3770771ecdeb3f17710930714b33f764 +MD5sum: f1e75113d62a59b5ac55cbaa5bdace7e +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-libs +Architecture: amd64 +Depends: hipblas (= 2.2.0.60200-66~20.04), hipblaslt (= 0.8.0.60200-66~20.04), hipfft (= 1.0.14.60200-66~20.04), hipsolver (= 2.2.0.60200-66~20.04), hipsparse (= 3.1.1.60200-66~20.04), hiptensor (= 1.3.0.60200-66~20.04), miopen-hip (= 3.2.0.60200-66~20.04), half (= 1.12.0.60200-66~20.04), rccl (= 2.20.5.60200-66~20.04), rocalution (= 3.2.0.60200-66~20.04), rocblas (= 4.2.0.60200-66~20.04), rocfft (= 1.0.28.60200-66~20.04), rocrand (= 3.1.0.60200-66~20.04), hiprand (= 2.11.0.60200-66~20.04), rocsolver (= 3.26.0.60200-66~20.04), rocsparse (= 3.2.0.60200-66~20.04), rocm-core (= 6.2.0.60200-66~20.04), hipsparselt (= 0.2.1.60200-66~20.04), composablekernel-dev (= 1.1.0.60200-66~20.04), hipblas-dev (= 2.2.0.60200-66~20.04), hipblaslt-dev (= 0.8.0.60200-66~20.04), hipcub-dev (= 3.2.0.60200-66~20.04), hipfft-dev (= 1.0.14.60200-66~20.04), hipsolver-dev (= 2.2.0.60200-66~20.04), hipsparse-dev (= 3.1.1.60200-66~20.04), hiptensor-dev (= 1.3.0.60200-66~20.04), miopen-hip-dev (= 3.2.0.60200-66~20.04), rccl-dev (= 2.20.5.60200-66~20.04), rocalution-dev (= 3.2.0.60200-66~20.04), rocblas-dev (= 4.2.0.60200-66~20.04), rocfft-dev (= 1.0.28.60200-66~20.04), rocprim-dev (= 3.2.0.60200-66~20.04), rocrand-dev (= 3.1.0.60200-66~20.04), hiprand-dev (= 2.11.0.60200-66~20.04), rocsolver-dev (= 3.26.0.60200-66~20.04), rocsparse-dev (= 3.2.0.60200-66~20.04), rocthrust-dev (= 3.0.1.60200-66~20.04), rocwmma-dev (= 1.5.0.60200-66~20.04), hipsparselt-dev (= 0.2.1.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-libs/rocm-libs_6.2.0.60200-66~20.04_amd64.deb +Size: 1054 +SHA256: cecab73a5a9f10d2d80c1c90a9b0e34a992edc9f4f6b0e68d335d72e1dbc7231 +SHA1: 7f61a9d87ab0b742833894a6aa898119e4b9b0ee +MD5sum: 6887b42b7fdf7520b921ec464e898158 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-libs-rpath6.2.0 +Architecture: amd64 +Depends: hipblas-rpath6.2.0 (= 2.2.0.60200-66~20.04), hipblaslt-rpath6.2.0 (= 0.8.0.60200-66~20.04), hipfft-rpath6.2.0 (= 1.0.14.60200-66~20.04), hipsolver-rpath6.2.0 (= 2.2.0.60200-66~20.04), hipsparse-rpath6.2.0 (= 3.1.1.60200-66~20.04), hiptensor-rpath6.2.0 (= 1.3.0.60200-66~20.04), miopen-hip-rpath6.2.0 (= 3.2.0.60200-66~20.04), half-rpath6.2.0 (= 1.12.0.60200-66~20.04), rccl-rpath6.2.0 (= 2.20.5.60200-66~20.04), rocalution-rpath6.2.0 (= 3.2.0.60200-66~20.04), rocblas-rpath6.2.0 (= 4.2.0.60200-66~20.04), rocfft-rpath6.2.0 (= 1.0.28.60200-66~20.04), rocrand-rpath6.2.0 (= 3.1.0.60200-66~20.04), hiprand-rpath6.2.0 (= 2.11.0.60200-66~20.04), rocsolver-rpath6.2.0 (= 3.26.0.60200-66~20.04), rocsparse-rpath6.2.0 (= 3.2.0.60200-66~20.04), rocm-core-rpath6.2.0 (= 6.2.0.60200-66~20.04), hipsparselt-rpath6.2.0 (= 0.2.1.60200-66~20.04), composablekernel-dev-rpath6.2.0 (= 1.1.0.60200-66~20.04), hipblas-dev-rpath6.2.0 (= 2.2.0.60200-66~20.04), hipblaslt-dev-rpath6.2.0 (= 0.8.0.60200-66~20.04), hipcub-dev-rpath6.2.0 (= 3.2.0.60200-66~20.04), hipfft-dev-rpath6.2.0 (= 1.0.14.60200-66~20.04), hipsolver-dev-rpath6.2.0 (= 2.2.0.60200-66~20.04), hipsparse-dev-rpath6.2.0 (= 3.1.1.60200-66~20.04), hiptensor-dev-rpath6.2.0 (= 1.3.0.60200-66~20.04), miopen-hip-dev-rpath6.2.0 (= 3.2.0.60200-66~20.04), rccl-dev-rpath6.2.0 (= 2.20.5.60200-66~20.04), rocalution-dev-rpath6.2.0 (= 3.2.0.60200-66~20.04), rocblas-dev-rpath6.2.0 (= 4.2.0.60200-66~20.04), rocfft-dev-rpath6.2.0 (= 1.0.28.60200-66~20.04), rocprim-dev-rpath6.2.0 (= 3.2.0.60200-66~20.04), rocrand-dev-rpath6.2.0 (= 3.1.0.60200-66~20.04), hiprand-dev-rpath6.2.0 (= 2.11.0.60200-66~20.04), rocsolver-dev-rpath6.2.0 (= 3.26.0.60200-66~20.04), rocsparse-dev-rpath6.2.0 (= 3.2.0.60200-66~20.04), rocthrust-dev-rpath6.2.0 (= 3.0.1.60200-66~20.04), rocwmma-dev-rpath6.2.0 (= 1.5.0.60200-66~20.04), hipsparselt-dev-rpath6.2.0 (= 0.2.1.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-libs-rpath6.2.0/rocm-libs-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1248 +SHA256: a40922f589f51c4bb54b89db71942d5c869dc37cb18dc9f47d9e8b9f89c6afef +SHA1: 3bce8671c0873c8f19ed6bee8315314a319fdfe1 +MD5sum: adcd5c35341ad8c45ae1d4acb9401165 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-libs6.2.0 +Architecture: amd64 +Depends: hipblas6.2.0 (= 2.2.0.60200-66~20.04), hipblaslt6.2.0 (= 0.8.0.60200-66~20.04), hipfft6.2.0 (= 1.0.14.60200-66~20.04), hipsolver6.2.0 (= 2.2.0.60200-66~20.04), hipsparse6.2.0 (= 3.1.1.60200-66~20.04), hiptensor6.2.0 (= 1.3.0.60200-66~20.04), miopen-hip6.2.0 (= 3.2.0.60200-66~20.04), half6.2.0 (= 1.12.0.60200-66~20.04), rccl6.2.0 (= 2.20.5.60200-66~20.04), rocalution6.2.0 (= 3.2.0.60200-66~20.04), rocblas6.2.0 (= 4.2.0.60200-66~20.04), rocfft6.2.0 (= 1.0.28.60200-66~20.04), rocrand6.2.0 (= 3.1.0.60200-66~20.04), hiprand6.2.0 (= 2.11.0.60200-66~20.04), rocsolver6.2.0 (= 3.26.0.60200-66~20.04), rocsparse6.2.0 (= 3.2.0.60200-66~20.04), rocm-core6.2.0 (= 6.2.0.60200-66~20.04), hipsparselt6.2.0 (= 0.2.1.60200-66~20.04), composablekernel-dev6.2.0 (= 1.1.0.60200-66~20.04), hipblas-dev6.2.0 (= 2.2.0.60200-66~20.04), hipblaslt-dev6.2.0 (= 0.8.0.60200-66~20.04), hipcub-dev6.2.0 (= 3.2.0.60200-66~20.04), hipfft-dev6.2.0 (= 1.0.14.60200-66~20.04), hipsolver-dev6.2.0 (= 2.2.0.60200-66~20.04), hipsparse-dev6.2.0 (= 3.1.1.60200-66~20.04), hiptensor-dev6.2.0 (= 1.3.0.60200-66~20.04), miopen-hip-dev6.2.0 (= 3.2.0.60200-66~20.04), rccl-dev6.2.0 (= 2.20.5.60200-66~20.04), rocalution-dev6.2.0 (= 3.2.0.60200-66~20.04), rocblas-dev6.2.0 (= 4.2.0.60200-66~20.04), rocfft-dev6.2.0 (= 1.0.28.60200-66~20.04), rocprim-dev6.2.0 (= 3.2.0.60200-66~20.04), rocrand-dev6.2.0 (= 3.1.0.60200-66~20.04), hiprand-dev6.2.0 (= 2.11.0.60200-66~20.04), rocsolver-dev6.2.0 (= 3.26.0.60200-66~20.04), rocsparse-dev6.2.0 (= 3.2.0.60200-66~20.04), rocthrust-dev6.2.0 (= 3.0.1.60200-66~20.04), rocwmma-dev6.2.0 (= 1.5.0.60200-66~20.04), hipsparselt-dev6.2.0 (= 0.2.1.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-libs6.2.0/rocm-libs6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1240 +SHA256: e0f3ca5b13dc0b3e5ef20f167119aee55c826ef4fe3afe787935f2bcdfededb5 +SHA1: 3de9b7e2d8ee585cf291d6f9a9c9d87d2e5f5a75 +MD5sum: 0759e42b093543ffda8007386acd1dd8 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-llvm +Architecture: amd64 +Maintainer: ROCm Compiler Support +Version: 18.0.0.24292.60200-66~20.04 +Release: 66~20.04 +Depends: python3, libc6, libstdc++6|libstdc++8, libstdc++-5-dev|libstdc++-7-dev|libstdc++-11-dev, libgcc-5-dev|libgcc-7-dev|libgcc-11-dev, rocm-core +Recommends: gcc, g++, gcc-multilib, g++-multilib +Priority: optional +Section: devel +Filename: pool/main/r/rocm-llvm/rocm-llvm_18.0.0.24292.60200-66~20.04_amd64.deb +Size: 327523948 +SHA256: 3a0da5e3a42aa3c76e8cfbb1919d2196905e0a186375f35a8d60b93d70823406 +SHA1: 3e035b55b9c678dc47ad16917c1b7d302a4ef5d3 +MD5sum: 42a7fe3981635e91041f43206bd1d4bb +Description: ROCm core compiler + ROCm core compiler based on LLVM 18.0.0 + +Package: rocm-llvm-dev +Architecture: amd64 +Maintainer: ROCm Compiler Support +Version: 18.0.0.24292.60200-66~20.04 +Release: 66~20.04 +Depends: python3, libc6, libstdc++6|libstdc++8, libstdc++-5-dev|libstdc++-7-dev|libstdc++-11-dev, libgcc-5-dev|libgcc-7-dev|libgcc-11-dev, rocm-core, rocm-llvm +Recommends: gcc, g++, gcc-multilib, g++-multilib +Priority: optional +Section: devel +Filename: pool/main/r/rocm-llvm-dev/rocm-llvm-dev_18.0.0.24292.60200-66~20.04_amd64.deb +Size: 1012346986 +SHA256: 322ca8425c3a8f2ec17c551bad606b96d957b0c1eea07196dd66ac9f15460ed5 +SHA1: aaac186876fe685a1a2abd247ff6e464039112bd +MD5sum: e73d1a323a936ffb9292e93c4ca68bbf +Description: ROCm compiler dev tools + ROCm compiler dev tools and documentation, based on LLVM 18.0.0 + +Package: rocm-llvm-dev-rpath6.2.0 +Architecture: amd64 +Maintainer: ROCm Compiler Support +Version: 18.0.0.24292.60200-66~20.04 +Release: 66~20.04 +Depends: python3, libc6, libstdc++6|libstdc++8, libstdc++-5-dev|libstdc++-7-dev|libstdc++-11-dev, libgcc-5-dev|libgcc-7-dev|libgcc-11-dev, rocm-core-rpath6.2.0, rocm-llvm-rpath6.2.0 +Recommends: gcc, g++, gcc-multilib, g++-multilib +Priority: optional +Section: devel +Filename: pool/main/r/rocm-llvm-dev-rpath6.2.0/rocm-llvm-dev-rpath6.2.0_18.0.0.24292.60200-66~20.04_amd64.deb +Size: 653579032 +SHA256: db68c90bc36f5052139a21612186fec613111b1d261fa940c0202c3af78bcf34 +SHA1: 4adad9c5a7d4e3773022040068b037d05851fec1 +MD5sum: 7b607b311eb3c66c377a42ddc3890e26 +Description: ROCm compiler dev tools + ROCm compiler dev tools and documentation, based on LLVM 18.0.0 + +Package: rocm-llvm-dev6.2.0 +Architecture: amd64 +Maintainer: ROCm Compiler Support +Version: 18.0.0.24292.60200-66~20.04 +Release: 66~20.04 +Depends: python3, libc6, libstdc++6|libstdc++8, libstdc++-5-dev|libstdc++-7-dev|libstdc++-11-dev, libgcc-5-dev|libgcc-7-dev|libgcc-11-dev, rocm-core6.2.0, rocm-llvm6.2.0 +Recommends: gcc, g++, gcc-multilib, g++-multilib +Priority: optional +Section: devel +Filename: pool/main/r/rocm-llvm-dev6.2.0/rocm-llvm-dev6.2.0_18.0.0.24292.60200-66~20.04_amd64.deb +Size: 653627832 +SHA256: 51011892a666a3ce5f3334649c33c21c516ae07fab3af15dc2659e8510129d96 +SHA1: b2a0f7b84c93d7d071df640740222719193cdfb1 +MD5sum: 1edbcd711830dd3c73e049517e22bcdb +Description: ROCm compiler dev tools + ROCm compiler dev tools and documentation, based on LLVM 18.0.0 + +Package: rocm-llvm-docs +Architecture: amd64 +Maintainer: ROCm Compiler Support +Version: 18.0.0.24292.60200-66~20.04 +Release: 66~20.04 +Depends: rocm-core +Recommends: +Priority: optional +Section: devel +Filename: pool/main/r/rocm-llvm-docs/rocm-llvm-docs_18.0.0.24292.60200-66~20.04_amd64.deb +Size: 12961012 +SHA256: c972be4ad39207681332a500337261375306aad2030d66c8ba3756496c6bc5eb +SHA1: d8fb6b9cdcc55421f3f5dd001f010b14570e3779 +MD5sum: a97ce123c29d13e58d8a7f22c9645ea8 +Description: ROCm LLVM compiler documentation + Documenation for LLVM 18.0.0 + +Package: rocm-llvm-docs-rpath6.2.0 +Architecture: amd64 +Maintainer: ROCm Compiler Support +Version: 18.0.0.24292.60200-66~20.04 +Release: 66~20.04 +Depends: rocm-core-rpath6.2.0 +Recommends: +Priority: optional +Section: devel +Filename: pool/main/r/rocm-llvm-docs-rpath6.2.0/rocm-llvm-docs-rpath6.2.0_18.0.0.24292.60200-66~20.04_amd64.deb +Size: 9543288 +SHA256: 1fd792a3ae1744483e970ca4ac8c6eb26e2833cf9269025e833fb1b302a8a88b +SHA1: 1b7b912259654819c969ccede53cd5ce7222d546 +MD5sum: 16291cf5cf94abc096b77668b90abfca +Description: ROCm LLVM compiler documentation + Documenation for LLVM 18.0.0 + +Package: rocm-llvm-docs6.2.0 +Architecture: amd64 +Maintainer: ROCm Compiler Support +Version: 18.0.0.24292.60200-66~20.04 +Release: 66~20.04 +Depends: rocm-core6.2.0 +Recommends: +Priority: optional +Section: devel +Filename: pool/main/r/rocm-llvm-docs6.2.0/rocm-llvm-docs6.2.0_18.0.0.24292.60200-66~20.04_amd64.deb +Size: 9543348 +SHA256: 326cd2dc5759ca03ea711c227ae35e4b2e3e0e9195da412de336a86cf4ee24f9 +SHA1: 607e17f2dc726f055e251a8ae31a0c2ddd502ec2 +MD5sum: 8c48bb2371ba318f206bbec75baa5f8f +Description: ROCm LLVM compiler documentation + Documenation for LLVM 18.0.0 + +Package: rocm-llvm-rpath6.2.0 +Architecture: amd64 +Maintainer: ROCm Compiler Support +Version: 18.0.0.24292.60200-66~20.04 +Release: 66~20.04 +Depends: python3, libc6, libstdc++6|libstdc++8, libstdc++-5-dev|libstdc++-7-dev|libstdc++-11-dev, libgcc-5-dev|libgcc-7-dev|libgcc-11-dev, rocm-core-rpath6.2.0 +Recommends: gcc, g++, gcc-multilib, g++-multilib +Priority: optional +Section: devel +Filename: pool/main/r/rocm-llvm-rpath6.2.0/rocm-llvm-rpath6.2.0_18.0.0.24292.60200-66~20.04_amd64.deb +Size: 215448184 +SHA256: 87cd444a4b34f028c070f0485d17fd6c2c4c65e6e90332cbb5ac10366aa0dd3a +SHA1: e96ebcf3954f6b55c23587f9f331be25b79fc767 +MD5sum: 2be98da5070d8a142e0c62e6a05a2643 +Description: ROCm core compiler + ROCm core compiler based on LLVM 18.0.0 + +Package: rocm-llvm6.2.0 +Architecture: amd64 +Maintainer: ROCm Compiler Support +Version: 18.0.0.24292.60200-66~20.04 +Release: 66~20.04 +Depends: python3, libc6, libstdc++6|libstdc++8, libstdc++-5-dev|libstdc++-7-dev|libstdc++-11-dev, libgcc-5-dev|libgcc-7-dev|libgcc-11-dev, rocm-core6.2.0 +Recommends: gcc, g++, gcc-multilib, g++-multilib +Priority: optional +Section: devel +Filename: pool/main/r/rocm-llvm6.2.0/rocm-llvm6.2.0_18.0.0.24292.60200-66~20.04_amd64.deb +Size: 215430404 +SHA256: ce17d2b85407b9539e0feda513fd360a48ebfd971c19af122dda21d60448c9fc +SHA1: b05aecd55c820e3ce91d55f25c78542e4d65757a +MD5sum: 2e3f35b246d71c39653ecb43762f8182 +Description: ROCm core compiler + ROCm core compiler based on LLVM 18.0.0 + +Package: rocm-ml-libraries +Architecture: amd64 +Depends: rocm-hip-libraries (= 6.2.0.60200-66~20.04), miopen-hip (= 3.2.0.60200-66~20.04), half (= 1.12.0.60200-66~20.04), rocm-llvm (= 18.0.0.24292.60200-66~20.04), rocm-core (= 6.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-ml-libraries/rocm-ml-libraries_6.2.0.60200-66~20.04_amd64.deb +Size: 846 +SHA256: 922f5257dcdda35a2e26b2e8688f5c843fc80089a18279b23072ea59224bb273 +SHA1: 0bde5bd26bbf1fcc4ffbdc9e621b57da9185184d +MD5sum: 41d63efeaf658b1d52a7d0d783467edf +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-ml-libraries-asan +Architecture: amd64 +Depends: rocm-ml-libraries (= 6.2.0.60200-66~20.04), rocm-core-asan (= 6.2.0.60200-66~20.04), rocm-hip-libraries-asan (= 6.2.0.60200-66~20.04), miopen-hip-asan (= 3.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-ml-libraries-asan/rocm-ml-libraries-asan_6.2.0.60200-66~20.04_amd64.deb +Size: 838 +SHA256: 68330b8f333f49de9a6b086c04e48f094ec7e1a629973e14074240a8d52fe4ea +SHA1: e829899c68faad6f5892a8b625aec995746b19e9 +MD5sum: cd11b75b283ca7621620236668477de8 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-ml-libraries-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-ml-libraries-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-hip-libraries-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), miopen-hip-asan-rpath6.2.0 (= 3.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-ml-libraries-asan-rpath6.2.0/rocm-ml-libraries-asan-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1040 +SHA256: 90d0ac876b07360663bd33917b39f61dfdab16382436b919115c252dd13ec42b +SHA1: 74876963060c4385026ede4ec45838a25645351f +MD5sum: fefe0411364c3a33d5413f813218c412 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-ml-libraries-asan6.2.0 +Architecture: amd64 +Depends: rocm-ml-libraries6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-asan6.2.0 (= 6.2.0.60200-66~20.04), rocm-hip-libraries-asan6.2.0 (= 6.2.0.60200-66~20.04), miopen-hip-asan6.2.0 (= 3.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-ml-libraries-asan6.2.0/rocm-ml-libraries-asan6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1040 +SHA256: 4cf10e8f9137d44cbd01e8feb632afeffab3bf7eb01f54254d1348b5efeec8c3 +SHA1: e1020d69065a1c1ff85b2f338c738956e6fc8f9f +MD5sum: 1744b09e68e5e2d506d5f29ee5eaf6f1 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-ml-libraries-rpath6.2.0 +Architecture: amd64 +Depends: rocm-hip-libraries-rpath6.2.0 (= 6.2.0.60200-66~20.04), miopen-hip-rpath6.2.0 (= 3.2.0.60200-66~20.04), half-rpath6.2.0 (= 1.12.0.60200-66~20.04), rocm-llvm-rpath6.2.0 (= 18.0.0.24292.60200-66~20.04), rocm-core-rpath6.2.0 (= 6.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-ml-libraries-rpath6.2.0/rocm-ml-libraries-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1048 +SHA256: a8fab4b9a094dea922481e0a6bf780b07e9f7cc3b01608c3d896ef7e481f3d3f +SHA1: 4c76f87c6af75b862caa6ea495a5b9a3f0c92c3c +MD5sum: 51690354eb4bb93a39f775f84bfac136 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-ml-libraries6.2.0 +Architecture: amd64 +Depends: rocm-hip-libraries6.2.0 (= 6.2.0.60200-66~20.04), miopen-hip6.2.0 (= 3.2.0.60200-66~20.04), half6.2.0 (= 1.12.0.60200-66~20.04), rocm-llvm6.2.0 (= 18.0.0.24292.60200-66~20.04), rocm-core6.2.0 (= 6.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-ml-libraries6.2.0/rocm-ml-libraries6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1044 +SHA256: ff21f393f0e4e0f4ea3141ddd2f7f3dfd11bce876a04d4c84aeacc732e724132 +SHA1: e1932cafaded272c14370e4373c72f8a349373cb +MD5sum: 4015ac31a4ab220f598b9d7bc6ea892f +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-ml-sdk +Architecture: amd64 +Depends: rocm-ml-libraries (= 6.2.0.60200-66~20.04), rocm-hip-sdk (= 6.2.0.60200-66~20.04), rocm-core (= 6.2.0.60200-66~20.04), miopen-hip-dev (= 3.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-ml-sdk/rocm-ml-sdk_6.2.0.60200-66~20.04_amd64.deb +Size: 828 +SHA256: e9b03bfa0eecfae6f34d9bef6e57208e5e6c02e2858ba7dfd3b96154c853d5c1 +SHA1: baefb7ee9560cd874bc79d0fcbf139a17d389693 +MD5sum: 2a23dc1f5422c35ff2ec875039290eb7 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-ml-sdk-asan +Architecture: amd64 +Depends: rocm-ml-sdk (= 6.2.0.60200-66~20.04), rocm-core-asan (= 6.2.0.60200-66~20.04), rocm-ml-libraries-asan (= 6.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-ml-sdk-asan/rocm-ml-sdk-asan_6.2.0.60200-66~20.04_amd64.deb +Size: 820 +SHA256: 41e10d34b02a0843e7402b5b7c27160c986171ec038c02efdfb03a3290b3ffbd +SHA1: 115f661f04e0327a782dcff3929dd11e3ea3f2ee +MD5sum: b93b4101b80ae774fe4fc642babc78f3 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-ml-sdk-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-ml-sdk-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-ml-libraries-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-ml-sdk-asan-rpath6.2.0/rocm-ml-sdk-asan-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1008 +SHA256: 2fa5ee5ef092f64e86df1b6bd1fe512f15d8ed8e56c5d2b9da5c2574ab7b1a4b +SHA1: ec4b2831de2398987dde23949ef8eb737150f8e3 +MD5sum: 9b5e7b50a3913dd26947ffecca333d77 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-ml-sdk-asan6.2.0 +Architecture: amd64 +Depends: rocm-ml-sdk6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-asan6.2.0 (= 6.2.0.60200-66~20.04), rocm-ml-libraries-asan6.2.0 (= 6.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-ml-sdk-asan6.2.0/rocm-ml-sdk-asan6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1012 +SHA256: 81c416ad946d33ffc6ead95d0cda5628c9bf087a22090d49b6e91b71be065806 +SHA1: fa36aac348267e4c783a1da7b43fba006fe32e48 +MD5sum: c16ef91ee229d4b4727c3f90f99a7954 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-ml-sdk-rpath6.2.0 +Architecture: amd64 +Depends: rocm-ml-libraries-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-hip-sdk-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-rpath6.2.0 (= 6.2.0.60200-66~20.04), miopen-hip-dev-rpath6.2.0 (= 3.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-ml-sdk-rpath6.2.0/rocm-ml-sdk-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1032 +SHA256: f500dbb98866460a3a28c6785358c08ce51f96bf562b7fda4da02723dceea1c8 +SHA1: f97497a7740bfbc322af458f1daec5a5a45e9997 +MD5sum: 922136148e4d77ae40c1f77af75196b4 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-ml-sdk6.2.0 +Architecture: amd64 +Depends: rocm-ml-libraries6.2.0 (= 6.2.0.60200-66~20.04), rocm-hip-sdk6.2.0 (= 6.2.0.60200-66~20.04), rocm-core6.2.0 (= 6.2.0.60200-66~20.04), miopen-hip-dev6.2.0 (= 3.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-ml-sdk6.2.0/rocm-ml-sdk6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1012 +SHA256: 3e78e37d2e9d028c92e3b409c620f0ae2967a27e537f1949d3f7b0c373882123 +SHA1: 7777b717f3fa9ba4efbda28a57d75d3c1144f973 +MD5sum: a6934d65b50986650dcf281b95a1fd59 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-ocltst +Architecture: amd64 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-ocltst/rocm-ocltst_2.0.0.60200-66~20.04_amd64.deb +Size: 677806 +SHA256: 6c45517c8a64a3f99b3553a47fa2bc1369af87848e053871c0b28ff68c6c4685 +SHA1: 69c6c7c6fae05eed5df38ede504381a603c5da34 +MD5sum: a29a0ec0fa99b1f9bd91f7b42c480e7e +Description: clr built using CMake +Maintainer: ROCm OpenCL Support +Version: 2.0.0.60200-66~20.04 +Installed-Size: 2209 + +Package: rocm-ocltst-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 88eac27ecf913d2dafb1e0cf04f07faa27d387d0 850a78bd342cba3874866688e36da00099d18f2e b317745ccf101a1dc27b6537b3a2a2902db4f6a6 1885f1eb2d0542bcde963ad539b296b1e47888e1 +Depends: rocm-ocltst (= 2.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-ocltst-dbgsym/rocm-ocltst-dbgsym_2.0.0.60200-66~20.04_amd64.deb +Size: 8649442 +SHA256: 3ee07de32c3a2adfdf0cbe579faf65385aa7921ef072305eaf537208a8cadc7a +SHA1: 801252d60fbd509be37ff3c3de080bbb4eaf1c9f +MD5sum: 700a207f6a9da5c162fd48830bb316ed +Description: debug symbols for rocm-ocltst +Maintainer: ROCm OpenCL Support +Package-Type: ddeb +Version: 2.0.0.60200-66~20.04 +Installed-Size: 29495 + +Package: rocm-ocltst-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 88eac27ecf913d2dafb1e0cf04f07faa27d387d0 850a78bd342cba3874866688e36da00099d18f2e b317745ccf101a1dc27b6537b3a2a2902db4f6a6 1885f1eb2d0542bcde963ad539b296b1e47888e1 +Depends: rocm-ocltst-rpath6.2.0 (= 2.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-ocltst-dbgsym-rpath6.2.0/rocm-ocltst-dbgsym-rpath6.2.0_2.0.0.60200-66~20.04_amd64.deb +Size: 4887720 +SHA256: 6b854f10dbddf774890a3f0d591ad1eb3d63b897328987800d956f8f34dbd357 +SHA1: 63a104238143721c221868badf4730c0b7cd465a +MD5sum: 623913608c73612debe2e1c9d177870b +Description: debug symbols for rocm-ocltst +Maintainer: ROCm OpenCL Support +Package-Type: ddeb +Version: 2.0.0.60200-66~20.04 +Installed-Size: 29495 + +Package: rocm-ocltst-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 88eac27ecf913d2dafb1e0cf04f07faa27d387d0 850a78bd342cba3874866688e36da00099d18f2e b317745ccf101a1dc27b6537b3a2a2902db4f6a6 1885f1eb2d0542bcde963ad539b296b1e47888e1 +Depends: rocm-ocltst6.2.0 (= 2.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-ocltst-dbgsym6.2.0/rocm-ocltst-dbgsym6.2.0_2.0.0.60200-66~20.04_amd64.deb +Size: 4889088 +SHA256: 7500ec560876ab23781f0109b8f30ae6663a30daf237e10b954d4dfd2c4099de +SHA1: 71c192c9613bb488593add8d9dcdb11259a754e6 +MD5sum: 32fe0bdccf039e66878e720a5095a89e +Description: debug symbols for rocm-ocltst +Maintainer: ROCm OpenCL Support +Package-Type: ddeb +Version: 2.0.0.60200-66~20.04 +Installed-Size: 29495 + +Package: rocm-ocltst-rpath6.2.0 +Architecture: amd64 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-ocltst-rpath6.2.0/rocm-ocltst-rpath6.2.0_2.0.0.60200-66~20.04_amd64.deb +Size: 453564 +SHA256: c61351863fc48aca2398d72fe07b100f3fd760c3313627bc3876fc3ad3822765 +SHA1: d1a60f20c933fcb4c616ff6274eaea6134440896 +MD5sum: e35a9a1c80f6fb1f3396fbdbe062e4e5 +Description: clr built using CMake +Maintainer: ROCm OpenCL Support +Version: 2.0.0.60200-66~20.04 +Installed-Size: 2209 + +Package: rocm-ocltst6.2.0 +Architecture: amd64 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-ocltst6.2.0/rocm-ocltst6.2.0_2.0.0.60200-66~20.04_amd64.deb +Size: 452816 +SHA256: 7dc8c43521512d4527fe4592c1610188433a57d47160da51d11fade9f8448dd1 +SHA1: c122d67e40303c1e5a49cebb5cafb960bd75737c +MD5sum: 6b239e4d7e0d4a226c53ca998b7b3afd +Description: clr built using CMake +Maintainer: ROCm OpenCL Support +Version: 2.0.0.60200-66~20.04 +Installed-Size: 2209 + +Package: rocm-opencl +Architecture: amd64 +Depends: libelf-dev, comgr, hsa-rocr, rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl/rocm-opencl_2.0.0.60200-66~20.04_amd64.deb +Size: 588934 +SHA256: d6ddfee18e4b498e4546db6ff18dc2145c626faa91fca8cdc78ed0c447ee1a2f +SHA1: 6f5d8df876417bb43fbaedf5b2a4120312903ebd +MD5sum: 65e58ee4802faad82ed43a6500a46451 +Description: clr built using CMake +Maintainer: ROCm OpenCL Support +Version: 2.0.0.60200-66~20.04 +Installed-Size: 4350 + +Package: rocm-opencl-asan +Architecture: amd64 +Depends: libelf-dev, comgr-asan, hsa-rocr-asan, rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-asan/rocm-opencl-asan_2.0.0.60200-66~20.04_amd64.deb +Size: 1542614 +SHA256: acca065aa019da995daf4c44b56350afecce07bd3d311b8622ffd3b6c4d14ae9 +SHA1: ed14e11ab0db07027a4a74dce47b7ee97b203675 +MD5sum: 969d96261972b22a964db049fe3194b4 +Description: clr built using CMake +Maintainer: ROCm OpenCL Support +Version: 2.0.0.60200-66~20.04 +Installed-Size: 15340 + +Package: rocm-opencl-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 60407f1573526522c6d4960933c22cfbac13dacf +Depends: rocm-opencl-asan (= 2.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-opencl-asan-dbgsym/rocm-opencl-asan-dbgsym_2.0.0.60200-66~20.04_amd64.deb +Size: 8195676 +SHA256: d9cc3a4b24a74fcc5a9d0b540b8e7f0ee018e3d5918c4bc5dabeb2714a6c31c3 +SHA1: 82a618a4f01f6cc398814d162f80e7f79e776098 +MD5sum: 3f6818b8741035ac40ebb7c4218ffa11 +Description: debug symbols for rocm-opencl-asan +Maintainer: ROCm OpenCL Support +Package-Type: ddeb +Version: 2.0.0.60200-66~20.04 +Installed-Size: 24932 + +Package: rocm-opencl-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 60407f1573526522c6d4960933c22cfbac13dacf +Depends: rocm-opencl-asan-rpath6.2.0 (= 2.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-opencl-asan-dbgsym-rpath6.2.0/rocm-opencl-asan-dbgsym-rpath6.2.0_2.0.0.60200-66~20.04_amd64.deb +Size: 4669192 +SHA256: db5214dd389da1be4906af30af8441f988bbc0b9db0d95ae2e6b63018b495712 +SHA1: e30987b69ca955133054bd034489b5c0492df8ac +MD5sum: 2caa06c2875199669013df7c99b498ca +Description: debug symbols for rocm-opencl-asan +Maintainer: ROCm OpenCL Support +Package-Type: ddeb +Version: 2.0.0.60200-66~20.04 +Installed-Size: 24932 + +Package: rocm-opencl-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 60407f1573526522c6d4960933c22cfbac13dacf +Depends: rocm-opencl-asan6.2.0 (= 2.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-opencl-asan-dbgsym6.2.0/rocm-opencl-asan-dbgsym6.2.0_2.0.0.60200-66~20.04_amd64.deb +Size: 4669068 +SHA256: 1f2137a44fe2b7d01c796491362e46282d2c4ea799729e62baea94d2fce3b870 +SHA1: 7fc4f2a031588aa4dfba8eaad6494cf408df33b3 +MD5sum: 8fc6ab3042ba3cb4207d5262501fa0f7 +Description: debug symbols for rocm-opencl-asan +Maintainer: ROCm OpenCL Support +Package-Type: ddeb +Version: 2.0.0.60200-66~20.04 +Installed-Size: 24932 + +Package: rocm-opencl-asan-rpath6.2.0 +Architecture: amd64 +Depends: libelf-dev, comgr-asan-rpath6.2.0, hsa-rocr-asan-rpath6.2.0, rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-asan-rpath6.2.0/rocm-opencl-asan-rpath6.2.0_2.0.0.60200-66~20.04_amd64.deb +Size: 938764 +SHA256: c984cb411910d1d0e5fde5c0a6066a6e615206a2d662fc72339b9b927d83cb43 +SHA1: 281d272421fecf8d4356eb5c3545df47311f1772 +MD5sum: a72279dea3ffcbb9ba965f74aece286c +Description: clr built using CMake +Maintainer: ROCm OpenCL Support +Version: 2.0.0.60200-66~20.04 +Installed-Size: 15340 + +Package: rocm-opencl-asan6.2.0 +Architecture: amd64 +Depends: libelf-dev, comgr-asan6.2.0, hsa-rocr-asan6.2.0, rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-asan6.2.0/rocm-opencl-asan6.2.0_2.0.0.60200-66~20.04_amd64.deb +Size: 939760 +SHA256: 1ec120860457f90d9ab3a1bd3bf1450da4afc479b5752ab90edd69c5dda29c13 +SHA1: 37f6d0a005cf915a1bfff89771eedc56f5d13c43 +MD5sum: f0e47c114283df467f7ad97bafb029fa +Description: clr built using CMake +Maintainer: ROCm OpenCL Support +Version: 2.0.0.60200-66~20.04 +Installed-Size: 15340 + +Package: rocm-opencl-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 74bfbcdf3c4647145afc9309e9cbcfda1af4163b a35db2b28bab107fe1691f02550847f7e594f29a +Depends: rocm-opencl (= 2.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-opencl-dbgsym/rocm-opencl-dbgsym_2.0.0.60200-66~20.04_amd64.deb +Size: 15212512 +SHA256: 925d40402d989162ccb454397b30711d8cb3f8ce3ff76f193cad8c11ae3b774c +SHA1: e24f57147dfbaa2ecaee877e7fe9133f14afd134 +MD5sum: b94bdc65d8db3e5bbba4352a36c63c27 +Description: debug symbols for rocm-opencl +Maintainer: ROCm OpenCL Support +Package-Type: ddeb +Version: 2.0.0.60200-66~20.04 +Installed-Size: 47983 + +Package: rocm-opencl-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 74bfbcdf3c4647145afc9309e9cbcfda1af4163b a35db2b28bab107fe1691f02550847f7e594f29a +Depends: rocm-opencl-rpath6.2.0 (= 2.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-opencl-dbgsym-rpath6.2.0/rocm-opencl-dbgsym-rpath6.2.0_2.0.0.60200-66~20.04_amd64.deb +Size: 9380284 +SHA256: a7e381a70cfd6e6ddd58ce54aa1f5441a0bab59c94c8e5a38aae0d2ead2642a3 +SHA1: 04e6b5bc527caa5af1630e367c8bb3e8fcaf0acc +MD5sum: 04e655369e5f420eacc4b19169a69bf7 +Description: debug symbols for rocm-opencl +Maintainer: ROCm OpenCL Support +Package-Type: ddeb +Version: 2.0.0.60200-66~20.04 +Installed-Size: 47983 + +Package: rocm-opencl-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 74bfbcdf3c4647145afc9309e9cbcfda1af4163b a35db2b28bab107fe1691f02550847f7e594f29a +Depends: rocm-opencl6.2.0 (= 2.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-opencl-dbgsym6.2.0/rocm-opencl-dbgsym6.2.0_2.0.0.60200-66~20.04_amd64.deb +Size: 9379108 +SHA256: ef1fc10ed151791d4f5c3a7ae9fe42b8f6e7e9b074d45fb1d18680304832a2e3 +SHA1: 229133c0de42960794103e48815e179dc3821cbf +MD5sum: 9d111870a42f8d31a48849a3ff7e0cfd +Description: debug symbols for rocm-opencl +Maintainer: ROCm OpenCL Support +Package-Type: ddeb +Version: 2.0.0.60200-66~20.04 +Installed-Size: 47983 + +Package: rocm-opencl-dev +Architecture: amd64 +Depends: mesa-common-dev, rocm-opencl, hsa-rocr-dev, rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-dev/rocm-opencl-dev_2.0.0.60200-66~20.04_amd64.deb +Size: 121370 +SHA256: 0f0f3d8f36a7d3f7921611ac51457840e19849a77cc41045d35c891823e4eac8 +SHA1: c23fa0e6ea54b3f84840573fcdb6faa7ac507a0d +MD5sum: fbb46c23cba2dd870afdda8a316bbbc5 +Description: clr built using CMake +Maintainer: ROCm OpenCL Support +Version: 2.0.0.60200-66~20.04 +Installed-Size: 854 + +Package: rocm-opencl-dev-rpath6.2.0 +Architecture: amd64 +Depends: mesa-common-dev, rocm-opencl-rpath6.2.0, hsa-rocr-dev-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-dev-rpath6.2.0/rocm-opencl-dev-rpath6.2.0_2.0.0.60200-66~20.04_amd64.deb +Size: 77044 +SHA256: 6edff9e4ca52bb55c1f7096c327ae4d46d885421c7e7cc016e0d410ac317517f +SHA1: e73a4d00656f328082b272bcc763de833d7d32ac +MD5sum: 3cc5236e1599240054cb0e08a78df8ec +Description: clr built using CMake +Maintainer: ROCm OpenCL Support +Version: 2.0.0.60200-66~20.04 +Installed-Size: 854 + +Package: rocm-opencl-dev6.2.0 +Architecture: amd64 +Depends: mesa-common-dev, rocm-opencl6.2.0, hsa-rocr-dev6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-dev6.2.0/rocm-opencl-dev6.2.0_2.0.0.60200-66~20.04_amd64.deb +Size: 77056 +SHA256: 470755205015b01beb2271e8526baf71debf01a93d60c6dccf6ce5816e9d72ca +SHA1: 68395f87073c7c06471fe2b6281a624a7139e623 +MD5sum: b2b61e8482a69b9f5b9e8e83ff581678 +Description: clr built using CMake +Maintainer: ROCm OpenCL Support +Version: 2.0.0.60200-66~20.04 +Installed-Size: 854 + +Package: rocm-opencl-icd-loader +Architecture: amd64 +Conflicts: rocm-ocl-icd +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-icd-loader/rocm-opencl-icd-loader_1.2.60200-66~20.04_amd64.deb +Size: 17138 +SHA256: b339f8eceb4a60c508f291dea2f5eceb9c42cd7e98404625a46bd7a414abd15a +SHA1: e1f520b32a32bfad294ab74a5d5ad130ceae4f29 +MD5sum: c95a6e9ee9fafe27249ac3c86bda8b1f +Description: OpenCL-ICD-Loader built using CMake +Maintainer: ROCm OpenCL Support +Provides: rocm-ocl-icd +Replaces: rocm-ocl-icd +Version: 1.2.60200-66~20.04 +Installed-Size: 139 + +Package: rocm-opencl-icd-loader-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: e6d2e7b5acb9ca5975340c9cc608bb78d14dd90c +Depends: rocm-opencl-icd-loader (= 1.2.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-opencl-icd-loader-dbgsym/rocm-opencl-icd-loader-dbgsym_1.2.60200-66~20.04_amd64.deb +Size: 56178 +SHA256: 50dd1c9c25750c1996ff3fd9b82236f7f0dc7d078434ecff74ebeab18dea6db4 +SHA1: 7dc7994f8addeb554317dc6e4f248c9b2de4e44e +MD5sum: 97eea45f219f28804df0dc70a55ddbb5 +Description: debug symbols for rocm-opencl-icd-loader +Maintainer: ROCm OpenCL Support +Package-Type: ddeb +Version: 1.2.60200-66~20.04 +Installed-Size: 197 + +Package: rocm-opencl-icd-loader-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: e6d2e7b5acb9ca5975340c9cc608bb78d14dd90c +Depends: rocm-opencl-icd-loader-rpath6.2.0 (= 1.2.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-opencl-icd-loader-dbgsym-rpath6.2.0/rocm-opencl-icd-loader-dbgsym-rpath6.2.0_1.2.60200-66~20.04_amd64.deb +Size: 39092 +SHA256: ec13a70aa5f0e001ff3158f1de2c1ffe8171116fdc430fee6353083ff8c88127 +SHA1: 22cfc8c410575eaa28f84359a2aeb3edfdf4da40 +MD5sum: b28bebfcf975157c4645da94787b18c0 +Description: debug symbols for rocm-opencl-icd-loader +Maintainer: ROCm OpenCL Support +Package-Type: ddeb +Version: 1.2.60200-66~20.04 +Installed-Size: 197 + +Package: rocm-opencl-icd-loader-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: e6d2e7b5acb9ca5975340c9cc608bb78d14dd90c +Depends: rocm-opencl-icd-loader6.2.0 (= 1.2.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-opencl-icd-loader-dbgsym6.2.0/rocm-opencl-icd-loader-dbgsym6.2.0_1.2.60200-66~20.04_amd64.deb +Size: 39072 +SHA256: 0f1f20861733b4cd1c80f38fe57ddb88195237fab5d5bfe6c3b9130fe7a8a9f6 +SHA1: 1891712d10ae73731b0b99801e13a17f5949d37e +MD5sum: fb793c54a3df9ee69154d928e9ef7f83 +Description: debug symbols for rocm-opencl-icd-loader +Maintainer: ROCm OpenCL Support +Package-Type: ddeb +Version: 1.2.60200-66~20.04 +Installed-Size: 197 + +Package: rocm-opencl-icd-loader-rpath6.2.0 +Architecture: amd64 +Conflicts: rocm-ocl-icd-rpath6.2.0 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-icd-loader-rpath6.2.0/rocm-opencl-icd-loader-rpath6.2.0_1.2.60200-66~20.04_amd64.deb +Size: 14340 +SHA256: 6f1bd04a5734b8f162468037b4108494ac99f43405f71a9f8cb246a24740f8ed +SHA1: 8b1f5832ccf2dfe2114fd6560e789c9912b73b54 +MD5sum: bbefa1e22860d0017d42ea8ba6e71a31 +Description: OpenCL-ICD-Loader built using CMake +Maintainer: ROCm OpenCL Support +Provides: rocm-ocl-icd-rpath6.2.0 +Replaces: rocm-ocl-icd-rpath6.2.0 +Version: 1.2.60200-66~20.04 +Installed-Size: 139 + +Package: rocm-opencl-icd-loader6.2.0 +Architecture: amd64 +Conflicts: rocm-ocl-icd6.2.0 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-icd-loader6.2.0/rocm-opencl-icd-loader6.2.0_1.2.60200-66~20.04_amd64.deb +Size: 14376 +SHA256: b0d2a974bbeef05c3b309881049f027143dfaaa84c9a405d4a657b614b065bf2 +SHA1: 646d1e821531b12703ec6184f3be995b5534ea54 +MD5sum: e0c8849af275067f6d83feaa3d52f68e +Description: OpenCL-ICD-Loader built using CMake +Maintainer: ROCm OpenCL Support +Provides: rocm-ocl-icd6.2.0 +Replaces: rocm-ocl-icd6.2.0 +Version: 1.2.60200-66~20.04 +Installed-Size: 139 + +Package: rocm-opencl-rpath6.2.0 +Architecture: amd64 +Depends: libelf-dev, comgr-rpath6.2.0, hsa-rocr-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-rpath6.2.0/rocm-opencl-rpath6.2.0_2.0.0.60200-66~20.04_amd64.deb +Size: 452212 +SHA256: 96a332a4a83fee78f61fbf5b6eecfe17749bb478d16a8229441e8ef2ccdf6bf9 +SHA1: 392c07a32bf83591a4caeafc886f33dfc4fdd32b +MD5sum: b92009c1bea14dbae37bdc4ad931b24f +Description: clr built using CMake +Maintainer: ROCm OpenCL Support +Version: 2.0.0.60200-66~20.04 +Installed-Size: 4350 + +Package: rocm-opencl-runtime +Architecture: amd64 +Depends: rocm-core (= 6.2.0.60200-66~20.04), rocm-language-runtime (= 6.2.0.60200-66~20.04), rocm-opencl (= 2.0.0.60200-66~20.04), rocm-opencl-icd-loader (= 1.2.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-runtime/rocm-opencl-runtime_6.2.0.60200-66~20.04_amd64.deb +Size: 2018 +SHA256: 931f192c074bc76d4b8309892b22e26f4b128e5826c9be771bed536c91720b1e +SHA1: 361a20f64d8779da5f326f8d50ddf5af764237e4 +MD5sum: dcee21394a8defd62d97f91869ef68c8 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-opencl-runtime-asan +Architecture: amd64 +Depends: rocm-opencl-runtime (= 6.2.0.60200-66~20.04), rocm-core-asan (= 6.2.0.60200-66~20.04), rocm-language-runtime-asan (= 6.2.0.60200-66~20.04), rocm-opencl-asan (= 2.0.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-runtime-asan/rocm-opencl-runtime-asan_6.2.0.60200-66~20.04_amd64.deb +Size: 830 +SHA256: 718e007dc6b8bb12380b420ba42a29b9907c276fe4a1e3ca63ac1680a8d7954a +SHA1: 106d8d556b0e84d081e7cca9a093ce71b363d953 +MD5sum: eb7cb101167e9fdaa449108fbcea6434 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-opencl-runtime-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-opencl-runtime-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-language-runtime-asan-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl-asan-rpath6.2.0 (= 2.0.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-runtime-asan-rpath6.2.0/rocm-opencl-runtime-asan-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1036 +SHA256: c5a0b7f870de59e367df713cb5194b2314227d6b02297e600ad04e2043ec952b +SHA1: 0d0b0f6023a011c1aeaf977b08d998b4ffbd1669 +MD5sum: 76fc0b2618315e70d53110be78a7b0c4 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-opencl-runtime-asan6.2.0 +Architecture: amd64 +Depends: rocm-opencl-runtime6.2.0 (= 6.2.0.60200-66~20.04), rocm-core-asan6.2.0 (= 6.2.0.60200-66~20.04), rocm-language-runtime-asan6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl-asan6.2.0 (= 2.0.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-runtime-asan6.2.0/rocm-opencl-runtime-asan6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1028 +SHA256: 64b9fc2e20c547666c6d6b261c446c442a4aa9769bf990f6345ebfc10c53ba5a +SHA1: 923924e22cc1d078175053db8befa7782f5c1d26 +MD5sum: 3970e83750a60260caba7c5715a91f47 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-opencl-runtime-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-language-runtime-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl-rpath6.2.0 (= 2.0.0.60200-66~20.04), rocm-opencl-icd-loader-rpath6.2.0 (= 1.2.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-runtime-rpath6.2.0/rocm-opencl-runtime-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 2184 +SHA256: 8cc5ac3dfe830187a7a0e756fe17ac56a0ca49bbd2ad03587f31ad15a21f0c89 +SHA1: f00fcd8fdfd355f5dcd77499860ecfb62807675b +MD5sum: a29248984a281365173b14e9e9c6a459 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-opencl-runtime6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 (= 6.2.0.60200-66~20.04), rocm-language-runtime6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl6.2.0 (= 2.0.0.60200-66~20.04), rocm-opencl-icd-loader6.2.0 (= 1.2.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-runtime6.2.0/rocm-opencl-runtime6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 2176 +SHA256: 2e32d1b59969df779eb34c5d0c85b0375f5b2b86fecd1d3e4e3fb500a8bc2422 +SHA1: d7f266570e27f01982d5c88e60800bd67f7a3ac2 +MD5sum: 5291c3542166cc1dd55724eff9dbf6cc +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-opencl-sdk +Architecture: amd64 +Depends: rocm-core (= 6.2.0.60200-66~20.04), rocm-opencl-runtime (= 6.2.0.60200-66~20.04), rocm-opencl-dev (= 2.0.0.60200-66~20.04), hsa-rocr-dev (= 1.14.0.60200-66~20.04), hsakmt-roct-dev (= 20240607.3.8.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-sdk/rocm-opencl-sdk_6.2.0.60200-66~20.04_amd64.deb +Size: 848 +SHA256: 48d773c9b01914b5121c47b723706f8e7aa054ca1bdc30cf2b6d93f2c4023921 +SHA1: e5c93821b81ec33c52a0bc15011c7c358ab46af1 +MD5sum: e0a1dca7f5a7d6039a4edaf0b58db155 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-opencl-sdk-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl-runtime-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl-dev-rpath6.2.0 (= 2.0.0.60200-66~20.04), hsa-rocr-dev-rpath6.2.0 (= 1.14.0.60200-66~20.04), hsakmt-roct-dev-rpath6.2.0 (= 20240607.3.8.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-sdk-rpath6.2.0/rocm-opencl-sdk-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1044 +SHA256: bc92c1654b2c6b52d5db3a73a350e929c8a75b6df4446194130a93a2474f60ee +SHA1: 1b3961b7f9fcb7dab2a694ff849d1896e01270c2 +MD5sum: 71af1ad9f49b7bb6bb2ba4132f746e1c +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-opencl-sdk6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl-runtime6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl-dev6.2.0 (= 2.0.0.60200-66~20.04), hsa-rocr-dev6.2.0 (= 1.14.0.60200-66~20.04), hsakmt-roct-dev6.2.0 (= 20240607.3.8.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl-sdk6.2.0/rocm-opencl-sdk6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1036 +SHA256: ebe80a7b6654058e1c01af79d58448004e2c5420b33fdb12e2fd29e9ae408fb2 +SHA1: 5f394413b62357711079f514d2a37db13ab84346 +MD5sum: 49427d6f3b029fba895af0758d121482 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-opencl6.2.0 +Architecture: amd64 +Depends: libelf-dev, comgr6.2.0, hsa-rocr6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-opencl6.2.0/rocm-opencl6.2.0_2.0.0.60200-66~20.04_amd64.deb +Size: 452452 +SHA256: 50c1a7f28d0286bac45fbfce84ec6903d541b8cb539e3346936aaf2550be750d +SHA1: 36cb4b2d341b0d09af2c2963eef1bed5381292c5 +MD5sum: 6c34f05ce2cb286f62b729eb80662fc4 +Description: clr built using CMake +Maintainer: ROCm OpenCL Support +Version: 2.0.0.60200-66~20.04 +Installed-Size: 4350 + +Package: rocm-openmp-sdk +Architecture: amd64 +Depends: rocm-language-runtime (= 6.2.0.60200-66~20.04), rocm-device-libs (= 1.0.0.60200-66~20.04), rocm-llvm (= 18.0.0.24292.60200-66~20.04), rocm-core (= 6.2.0.60200-66~20.04), openmp-extras-dev (= 18.62.0.60200-66~20.04), hsa-rocr-dev (= 1.14.0.60200-66~20.04), hsakmt-roct-dev (= 20240607.3.8.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-openmp-sdk/rocm-openmp-sdk_6.2.0.60200-66~20.04_amd64.deb +Size: 892 +SHA256: 6ff73142468078b6e0c523baa5fdbe8d8e8509574f74000dc866cf65025dc833 +SHA1: c84b5523c06dc817eef32e3b74cf469411334c2e +MD5sum: 279d95f53229b401ae8c7ffab1d39f87 +Description: Radeon Open Compute (ROCm) OpenMP Software development Kit. +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-openmp-sdk-rpath6.2.0 +Architecture: amd64 +Depends: rocm-language-runtime-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-device-libs-rpath6.2.0 (= 1.0.0.60200-66~20.04), rocm-llvm-rpath6.2.0 (= 18.0.0.24292.60200-66~20.04), rocm-core-rpath6.2.0 (= 6.2.0.60200-66~20.04), openmp-extras-dev-rpath6.2.0 (= 18.62.0.60200-66~20.04), hsa-rocr-dev-rpath6.2.0 (= 1.14.0.60200-66~20.04), hsakmt-roct-dev-rpath6.2.0 (= 20240607.3.8.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-openmp-sdk-rpath6.2.0/rocm-openmp-sdk-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1096 +SHA256: f5ef51c4256c22704832ecf15398081bc8bfdd581600b2cfddb21dc436ae38f2 +SHA1: 0595904f1ea362740aee2a2edd9f81566378122c +MD5sum: 30fe93a81549c374e199b71fe71ee0ed +Description: Radeon Open Compute (ROCm) OpenMP Software development Kit. +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-openmp-sdk6.2.0 +Architecture: amd64 +Depends: rocm-language-runtime6.2.0 (= 6.2.0.60200-66~20.04), rocm-device-libs6.2.0 (= 1.0.0.60200-66~20.04), rocm-llvm6.2.0 (= 18.0.0.24292.60200-66~20.04), rocm-core6.2.0 (= 6.2.0.60200-66~20.04), openmp-extras-dev6.2.0 (= 18.62.0.60200-66~20.04), hsa-rocr-dev6.2.0 (= 1.14.0.60200-66~20.04), hsakmt-roct-dev6.2.0 (= 20240607.3.8.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-openmp-sdk6.2.0/rocm-openmp-sdk6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1092 +SHA256: 3ab53256e6e42d6b36b52385144fe2abfd6abae00b5f1050687fdf6574e8fe51 +SHA1: c70392aaa5219df5e04bb0f8ec8eea87f4ed6d68 +MD5sum: 8f7f1b2ea51d4fd4b833613c11b4b8da +Description: Radeon Open Compute (ROCm) OpenMP Software development Kit. +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-rpath6.2.0 +Architecture: amd64 +Depends: rocm-utils-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-developer-tools-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-openmp-sdk-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl-sdk-rpath6.2.0 (= 6.2.0.60200-66~20.04), rocm-ml-sdk-rpath6.2.0 (= 6.2.0.60200-66~20.04), mivisionx-rpath6.2.0 (= 3.0.0.60200-66~20.04), migraphx-rpath6.2.0 (= 2.10.0.60200-66~20.04), rpp-rpath6.2.0 (= 1.8.0.60200-66~20.04), rocm-core-rpath6.2.0 (= 6.2.0.60200-66~20.04), migraphx-dev-rpath6.2.0 (= 2.10.0.60200-66~20.04), mivisionx-dev-rpath6.2.0 (= 3.0.0.60200-66~20.04), rpp-dev-rpath6.2.0 (= 1.8.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-rpath6.2.0/rocm-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 2224 +SHA256: 5a84e602e0cf109737886362374ebecb11ed890b8b899ee07c7fcd818da50278 +SHA1: 61b752ec8e6d9bec38daa700993fb49bbd59fa4f +MD5sum: 6612ab1687b1946761db5ec1d308c4b0 +Description: Radeon Open Compute (ROCm) software stack meta package +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm dev support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-smi-lib +Architecture: amd64 +Depends: python3, rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocm-smi-lib/rocm-smi-lib_7.3.0.60200-66~20.04_amd64.deb +Size: 1002008 +SHA256: 8f607a4312139a727056fa9e28dd34b0f343bb99559fd9bc32ef24ebe9c13f8f +SHA1: 955054f61ca5765a669cd579d3d2884e6fd95aad +MD5sum: 2e84603a2947edd43fe955c5e11f771e +Description: AMD System Management libraries + Development needed header files for ROCM-SMI +Maintainer: RocmSMILib Support +Suggests: sudo +Version: 7.3.0.60200-66~20.04 +Installed-Size: 8302 + +Package: rocm-smi-lib-asan +Architecture: amd64 +Depends: python3, rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/r/rocm-smi-lib-asan/rocm-smi-lib-asan_7.3.0.60200-66~20.04_amd64.deb +Size: 1943830 +SHA256: b2cbb7baa4f002bfdbd454a918bb5ca1b3024a6ef0c4ad6c9335d2a4d2560720 +SHA1: 29d78dfdd3d7b2ad17ae254d422232538c707c8c +MD5sum: 9323d0f4acf74c5eee9799127a1cf7e6 +Description: AMD System Management libraries + ASAN libraries for the ROCM-SMI +Maintainer: RocmSMILib Support +Suggests: sudo +Version: 7.3.0.60200-66~20.04 +Installed-Size: 18451 + +Package: rocm-smi-lib-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 6a8296a61a8b08394b59d27a3fda04fe05d24101 3577815c2fad3c023c2083e02aa8220083035119 +Depends: rocm-smi-lib-asan (= 7.3.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-smi-lib-asan-dbgsym/rocm-smi-lib-asan-dbgsym_7.3.0.60200-66~20.04_amd64.deb +Size: 9100076 +SHA256: b9c53c08037a64868943b7fd94caa35dfe0bfd96e5a9831f89d7705f7db2b96d +SHA1: 2f5f5a0a08037f8685efd3947f2def150bc23495 +MD5sum: 0810ccf86522b83bb45cbb85825f8cc2 +Description: debug symbols for rocm-smi-lib-asan +Maintainer: RocmSMILib Support +Package-Type: ddeb +Version: 7.3.0.60200-66~20.04 +Installed-Size: 29935 + +Package: rocm-smi-lib-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 6a8296a61a8b08394b59d27a3fda04fe05d24101 3577815c2fad3c023c2083e02aa8220083035119 +Depends: rocm-smi-lib-asan-rpath6.2.0 (= 7.3.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-smi-lib-asan-dbgsym-rpath6.2.0/rocm-smi-lib-asan-dbgsym-rpath6.2.0_7.3.0.60200-66~20.04_amd64.deb +Size: 5596640 +SHA256: 8f10d1ce5d1ffc1b8801e4b9d1b7701e55e39bce47f9503cddd9da630ff801fc +SHA1: 4ccad9e3089e0c13b8584cff0b2886b7564c19c9 +MD5sum: dced26a4fde737ea37ecff0daa807fc9 +Description: debug symbols for rocm-smi-lib-asan +Maintainer: RocmSMILib Support +Package-Type: ddeb +Version: 7.3.0.60200-66~20.04 +Installed-Size: 29935 + +Package: rocm-smi-lib-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 6a8296a61a8b08394b59d27a3fda04fe05d24101 3577815c2fad3c023c2083e02aa8220083035119 +Depends: rocm-smi-lib-asan6.2.0 (= 7.3.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-smi-lib-asan-dbgsym6.2.0/rocm-smi-lib-asan-dbgsym6.2.0_7.3.0.60200-66~20.04_amd64.deb +Size: 5605844 +SHA256: bb6c284b32b24dec140376c7abbda7d730610d56cf7345240c4deb45674d73a0 +SHA1: 4ac13423ced4cd572c4ab7649f0f621be7e2bd8c +MD5sum: 7e6933f5518eb65aeb86080f544e09c7 +Description: debug symbols for rocm-smi-lib-asan +Maintainer: RocmSMILib Support +Package-Type: ddeb +Version: 7.3.0.60200-66~20.04 +Installed-Size: 29935 + +Package: rocm-smi-lib-asan-rpath6.2.0 +Architecture: amd64 +Depends: python3, rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-smi-lib-asan-rpath6.2.0/rocm-smi-lib-asan-rpath6.2.0_7.3.0.60200-66~20.04_amd64.deb +Size: 882976 +SHA256: 1da0d9e382e97707584961fabbae66bd0902fce3ef989b29a399def4804f8c26 +SHA1: 950e193fa346af4a4a95fda07403b810fed692c0 +MD5sum: f36fe8697b20bfc6260c95fb9f48ae6e +Description: AMD System Management libraries + ASAN libraries for the ROCM-SMI +Maintainer: RocmSMILib Support +Suggests: sudo +Version: 7.3.0.60200-66~20.04 +Installed-Size: 18451 + +Package: rocm-smi-lib-asan6.2.0 +Architecture: amd64 +Depends: python3, rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-smi-lib-asan6.2.0/rocm-smi-lib-asan6.2.0_7.3.0.60200-66~20.04_amd64.deb +Size: 883560 +SHA256: 6b45151eb58bce42c111b07d9979b7b4370483e2e4ad109440b603817ac74d5d +SHA1: 4a238456e71e7137939a19e5e57c7728202620eb +MD5sum: 25a03ee34e96bd983dfe916039dc1533 +Description: AMD System Management libraries + ASAN libraries for the ROCM-SMI +Maintainer: RocmSMILib Support +Suggests: sudo +Version: 7.3.0.60200-66~20.04 +Installed-Size: 18451 + +Package: rocm-smi-lib-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: e736ecddecbf1488cf53c283cba00ef64b3e01fb 9210c855bcea4aa551c9e7e245fc54a178fcf0b4 +Depends: rocm-smi-lib (= 7.3.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-smi-lib-dbgsym/rocm-smi-lib-dbgsym_7.3.0.60200-66~20.04_amd64.deb +Size: 16069224 +SHA256: be9ff9c655ddaabd7440c6211275db0c44cbcaa566ab2e50e493b6ca5a1f0601 +SHA1: ff005b08ac4981f2a5491d83351a12c47fe268b0 +MD5sum: 61fb72894c1ad8d0902f13510c1cd7f3 +Description: debug symbols for rocm-smi-lib +Maintainer: RocmSMILib Support +Package-Type: ddeb +Version: 7.3.0.60200-66~20.04 +Installed-Size: 63561 + +Package: rocm-smi-lib-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: e736ecddecbf1488cf53c283cba00ef64b3e01fb 9210c855bcea4aa551c9e7e245fc54a178fcf0b4 +Depends: rocm-smi-lib-rpath6.2.0 (= 7.3.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-smi-lib-dbgsym-rpath6.2.0/rocm-smi-lib-dbgsym-rpath6.2.0_7.3.0.60200-66~20.04_amd64.deb +Size: 10507208 +SHA256: 0d938371509d4ca50506c9788ccfc2884ab220de81d3272fa08be1b46fe16676 +SHA1: 8d98d76fb59997ed9e08569ca03586e22abb9aca +MD5sum: 922e3fc6b8598e6b43ef85596d01d5f0 +Description: debug symbols for rocm-smi-lib +Maintainer: RocmSMILib Support +Package-Type: ddeb +Version: 7.3.0.60200-66~20.04 +Installed-Size: 63561 + +Package: rocm-smi-lib-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: e736ecddecbf1488cf53c283cba00ef64b3e01fb 9210c855bcea4aa551c9e7e245fc54a178fcf0b4 +Depends: rocm-smi-lib6.2.0 (= 7.3.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-smi-lib-dbgsym6.2.0/rocm-smi-lib-dbgsym6.2.0_7.3.0.60200-66~20.04_amd64.deb +Size: 10508076 +SHA256: 0487145a72ee8e91321146ab82567dcaeb3f59baccb46c1bcd5d958bc5755503 +SHA1: 4bf16e0aba8c58cb6ac2e475f56edd0278afa272 +MD5sum: 8f444c5bda8801b6464a8a31c4032446 +Description: debug symbols for rocm-smi-lib +Maintainer: RocmSMILib Support +Package-Type: ddeb +Version: 7.3.0.60200-66~20.04 +Installed-Size: 63561 + +Package: rocm-smi-lib-rpath6.2.0 +Architecture: amd64 +Depends: python3, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-smi-lib-rpath6.2.0/rocm-smi-lib-rpath6.2.0_7.3.0.60200-66~20.04_amd64.deb +Size: 523584 +SHA256: b6f93bd93e74752f57be1fa222196f804889300c3f1407ce8ddce5af6ff09354 +SHA1: 106e67b78af73654b3899446aab82746f6d17c89 +MD5sum: 63a140559226fb66605f5777f6625236 +Description: AMD System Management libraries + Development needed header files for ROCM-SMI +Maintainer: RocmSMILib Support +Suggests: sudo +Version: 7.3.0.60200-66~20.04 +Installed-Size: 8302 + +Package: rocm-smi-lib6.2.0 +Architecture: amd64 +Depends: python3, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocm-smi-lib6.2.0/rocm-smi-lib6.2.0_7.3.0.60200-66~20.04_amd64.deb +Size: 524020 +SHA256: 1bbdb32d21dbc12bf9a736f6ca8726df9673e4401465d2b9b537c47b358b67f1 +SHA1: ddc74142d9645a05df290db04e89bd4093839ae3 +MD5sum: 97db6b16964c05a0cd990fb6ab0da15f +Description: AMD System Management libraries + Development needed header files for ROCM-SMI +Maintainer: RocmSMILib Support +Suggests: sudo +Version: 7.3.0.60200-66~20.04 +Installed-Size: 8302 + +Package: rocm-utils +Architecture: amd64 +Depends: rocminfo (= 1.0.0.60200-66~20.04), rocm-cmake (= 0.13.0.60200-66~20.04), rocm-core (= 6.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-utils/rocm-utils_6.2.0.60200-66~20.04_amd64.deb +Size: 812 +SHA256: 11ef8ac5642a9a67c3b0524b659a26beccb42a986c380623de10a8069ca25425 +SHA1: a53fdf21068ed57c42bb6be01bb904e183e7b267 +MD5sum: 491e82ec89d1c322c8da9bca73dac07c +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-utils-rpath6.2.0 +Architecture: amd64 +Depends: rocminfo-rpath6.2.0 (= 1.0.0.60200-66~20.04), rocm-cmake-rpath6.2.0 (= 0.13.0.60200-66~20.04), rocm-core-rpath6.2.0 (= 6.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-utils-rpath6.2.0/rocm-utils-rpath6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1008 +SHA256: afe176f5fc8781998a7406e82c32fb20222a5bc4ceb3c620f664509b2e56fe74 +SHA1: e2a8b847c54317b6f11005a9252dff764621c0f9 +MD5sum: 444cf7ae78aeb03f6a56905d7aef3952 +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-utils6.2.0 +Architecture: amd64 +Depends: rocminfo6.2.0 (= 1.0.0.60200-66~20.04), rocm-cmake6.2.0 (= 0.13.0.60200-66~20.04), rocm-core6.2.0 (= 6.2.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm-utils6.2.0/rocm-utils6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 1004 +SHA256: 928b8129e3c90c5da1b11497d04aac01cc7231846a5787c371df88dda838104b +SHA1: 2862540bb6198bd6ede6d4403875560b59e6b1d5 +MD5sum: 8dfbf0e9113e957e622eb7ec8d9ed9cd +Description: Radeon Open Compute (ROCm) Runtime software stack +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm Dev Support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocm-validation-suite +Architecture: amd64 +Depends: hip-runtime-amd, comgr, hsa-rocr, rocblas, rocm-smi-lib, rocm-core, libpci3, libyaml-cpp-dev +Priority: optional +Section: devel +Filename: pool/main/r/rocm-validation-suite/rocm-validation-suite_1.0.60200.60200-66~20.04_amd64.deb +Size: 1594192 +SHA256: d9112eb328f5470bc985f9b32535cd559f483023e929f3cdbd47fc8c77b596ce +SHA1: bce2fd6c55ef68156841878708701c8c9a90d74a +MD5sum: 47fae9ca6cc8a7c9faabe32e7be62bd3 +Description: The ROCm Validation Suite (RVS) is a system validation and diagnostics tool for monitoring, stress testing, detecting and troubleshooting issues that affects the functionality and performance of AMD GPU(s) operating in a high-performance/AI/ML computing environment. + ROCm Validation Suite +Maintainer: ROCM Validation Suite Support +Version: 1.0.60200.60200-66~20.04 +Installed-Size: 13412 + +Package: rocm-validation-suite-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 84f6eb4a1aecb79c2ae878fe9bfb431dfee39a81 e70a1b937f9f68d294a71c25a9f304995363807f 9d535030ed58e791afb9708ee5119b157803bdfb 310ebbbf8db6880946d4f88c5b0ae74f46a8a892 8602a67dcd8db3020499b0ed453412c9c5cedcbd c80f3042d614a6937742e3180188f8f190615072 3e6304013f2b010fe9da856dfcd7993bdefd1267 c4126bcc5c7449c803ea213e2621eab3f25d5531 607f7275ee22c74a86eb1f43c6f02d1be9cbcfaa ccf7e267bce48e1910520b98bb940f6ebca19286 835967db887086c01cdc76f14660554d9dedd458 4c94ff8b0a7eb94aef6e8b1211f2a715d6542e85 f76a3d709871cbbf8e80d1b4cbe30142443a405a 22f280cac681dc72e97cb02c8a6c9efdaec8ba76 88766f56a121fd39e3f7429b5555646f541cf1d1 0a0f991040d9c00a2c3fa3fcab3ff35e04f23ddf +Depends: rocm-validation-suite (= 1.0.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-validation-suite-dbgsym/rocm-validation-suite-dbgsym_1.0.60200.60200-66~20.04_amd64.deb +Size: 5027330 +SHA256: 94d066a07a590b8532d2870093366eadd95eddefe327be583d535572aa243976 +SHA1: 9fa5beeec9b9a7af0f70e16101581b5b1dcb767f +MD5sum: 4bab2022d20246ab2d1b78dba943f7f5 +Description: debug symbols for rocm-validation-suite +Maintainer: ROCM Validation Suite Support +Package-Type: ddeb +Version: 1.0.60200.60200-66~20.04 +Installed-Size: 16445 + +Package: rocm-validation-suite-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 84f6eb4a1aecb79c2ae878fe9bfb431dfee39a81 e70a1b937f9f68d294a71c25a9f304995363807f 9d535030ed58e791afb9708ee5119b157803bdfb 310ebbbf8db6880946d4f88c5b0ae74f46a8a892 8602a67dcd8db3020499b0ed453412c9c5cedcbd c80f3042d614a6937742e3180188f8f190615072 3e6304013f2b010fe9da856dfcd7993bdefd1267 c4126bcc5c7449c803ea213e2621eab3f25d5531 607f7275ee22c74a86eb1f43c6f02d1be9cbcfaa ccf7e267bce48e1910520b98bb940f6ebca19286 835967db887086c01cdc76f14660554d9dedd458 4c94ff8b0a7eb94aef6e8b1211f2a715d6542e85 f76a3d709871cbbf8e80d1b4cbe30142443a405a 22f280cac681dc72e97cb02c8a6c9efdaec8ba76 88766f56a121fd39e3f7429b5555646f541cf1d1 0a0f991040d9c00a2c3fa3fcab3ff35e04f23ddf +Depends: rocm-validation-suite-rpath6.2.0 (= 1.0.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-validation-suite-dbgsym-rpath6.2.0/rocm-validation-suite-dbgsym-rpath6.2.0_1.0.60200.60200-66~20.04_amd64.deb +Size: 3127408 +SHA256: c9d29e3fc21a882e1bb9a7f9675020f8d7884d006e66d58884f59be51a174c84 +SHA1: fd9d41bf5511590edb59ff8d4f05b7f2973ea544 +MD5sum: 2f3f333770d8aaac48adbb604a0ec6a9 +Description: debug symbols for rocm-validation-suite +Maintainer: ROCM Validation Suite Support +Package-Type: ddeb +Version: 1.0.60200.60200-66~20.04 +Installed-Size: 16445 + +Package: rocm-validation-suite-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 84f6eb4a1aecb79c2ae878fe9bfb431dfee39a81 e70a1b937f9f68d294a71c25a9f304995363807f 9d535030ed58e791afb9708ee5119b157803bdfb 310ebbbf8db6880946d4f88c5b0ae74f46a8a892 8602a67dcd8db3020499b0ed453412c9c5cedcbd c80f3042d614a6937742e3180188f8f190615072 3e6304013f2b010fe9da856dfcd7993bdefd1267 c4126bcc5c7449c803ea213e2621eab3f25d5531 607f7275ee22c74a86eb1f43c6f02d1be9cbcfaa ccf7e267bce48e1910520b98bb940f6ebca19286 835967db887086c01cdc76f14660554d9dedd458 4c94ff8b0a7eb94aef6e8b1211f2a715d6542e85 f76a3d709871cbbf8e80d1b4cbe30142443a405a 22f280cac681dc72e97cb02c8a6c9efdaec8ba76 88766f56a121fd39e3f7429b5555646f541cf1d1 0a0f991040d9c00a2c3fa3fcab3ff35e04f23ddf +Depends: rocm-validation-suite6.2.0 (= 1.0.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocm-validation-suite-dbgsym6.2.0/rocm-validation-suite-dbgsym6.2.0_1.0.60200.60200-66~20.04_amd64.deb +Size: 3122456 +SHA256: 395cbba9b491244870cf4c01ff643854912b13d9460852034631651bf0357039 +SHA1: 5f8ec6428392caa395873fc62059bea6131cc75f +MD5sum: 9b7269794c91efae17e225b18fc5ee50 +Description: debug symbols for rocm-validation-suite +Maintainer: ROCM Validation Suite Support +Package-Type: ddeb +Version: 1.0.60200.60200-66~20.04 +Installed-Size: 16445 + +Package: rocm-validation-suite-rpath6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd-rpath6.2.0, comgr-rpath6.2.0, hsa-rocr-rpath6.2.0, rocblas-rpath6.2.0, rocm-smi-lib-rpath6.2.0, rocm-core-rpath6.2.0, libpci3, libyaml-cpp-dev +Priority: optional +Section: devel +Filename: pool/main/r/rocm-validation-suite-rpath6.2.0/rocm-validation-suite-rpath6.2.0_1.0.60200.60200-66~20.04_amd64.deb +Size: 741064 +SHA256: 9bc29aa7b7d2c659c710aa4e6661c778f5142264f456da99dc364bc9d3eaa362 +SHA1: cb7c4be2bfbc9363b93f04b55c41989e5b55486b +MD5sum: 0e6c845594562e5a733fb9c7c2c01c5b +Description: The ROCm Validation Suite (RVS) is a system validation and diagnostics tool for monitoring, stress testing, detecting and troubleshooting issues that affects the functionality and performance of AMD GPU(s) operating in a high-performance/AI/ML computing environment. + ROCm Validation Suite +Maintainer: ROCM Validation Suite Support +Version: 1.0.60200.60200-66~20.04 +Installed-Size: 13412 + +Package: rocm-validation-suite6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd6.2.0, comgr6.2.0, hsa-rocr6.2.0, rocblas6.2.0, rocm-smi-lib6.2.0, rocm-core6.2.0, libpci3, libyaml-cpp-dev +Priority: optional +Section: devel +Filename: pool/main/r/rocm-validation-suite6.2.0/rocm-validation-suite6.2.0_1.0.60200.60200-66~20.04_amd64.deb +Size: 741900 +SHA256: e9f9dc143899ee29bd4b556dfefe1f650cbcf09c5559cfa71dfe8214de1f47aa +SHA1: 5bd81043f0112b001f6d2675f204a9475f22257c +MD5sum: db6337db23ad8006696339d658d6bce5 +Description: The ROCm Validation Suite (RVS) is a system validation and diagnostics tool for monitoring, stress testing, detecting and troubleshooting issues that affects the functionality and performance of AMD GPU(s) operating in a high-performance/AI/ML computing environment. + ROCm Validation Suite +Maintainer: ROCM Validation Suite Support +Version: 1.0.60200.60200-66~20.04 +Installed-Size: 13412 + +Package: rocm6.2.0 +Architecture: amd64 +Depends: rocm-utils6.2.0 (= 6.2.0.60200-66~20.04), rocm-developer-tools6.2.0 (= 6.2.0.60200-66~20.04), rocm-openmp-sdk6.2.0 (= 6.2.0.60200-66~20.04), rocm-opencl-sdk6.2.0 (= 6.2.0.60200-66~20.04), rocm-ml-sdk6.2.0 (= 6.2.0.60200-66~20.04), mivisionx6.2.0 (= 3.0.0.60200-66~20.04), migraphx6.2.0 (= 2.10.0.60200-66~20.04), rpp6.2.0 (= 1.8.0.60200-66~20.04), rocm-core6.2.0 (= 6.2.0.60200-66~20.04), migraphx-dev6.2.0 (= 2.10.0.60200-66~20.04), mivisionx-dev6.2.0 (= 3.0.0.60200-66~20.04), rpp-dev6.2.0 (= 1.8.0.60200-66~20.04) +Priority: optional +Section: devel +Filename: pool/main/r/rocm6.2.0/rocm6.2.0_6.2.0.60200-66~20.04_amd64.deb +Size: 2216 +SHA256: 93efd47d4b259000ac9a3b6b3ea4613dde22c1dd60b75487123978e8af189c26 +SHA1: d6e44840b58f7e37f2705ab304ab8b37e5b77aed +MD5sum: 57ded833d99301589ba0d5aba02521b8 +Description: Radeon Open Compute (ROCm) software stack meta package +Homepage: https://github.com/RadeonOpenCompute/ROCm +Maintainer: ROCm dev support +Version: 6.2.0.60200-66~20.04 +Installed-Size: 13 + +Package: rocminfo +Architecture: amd64 +Depends: hsa-rocr, kmod, pciutils, python3, libc6, libgcc-s1, libstdc++6, rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocminfo/rocminfo_1.0.0.60200-66~20.04_amd64.deb +Size: 28982 +SHA256: 70081fcb255e05de87c28de816cb6b3108f544a8b9d481b51daf1cfd35040a89 +SHA1: f11a7d85e528023b087a1ad600e6756d609f77c6 +MD5sum: b1014116562a4d62ea5a0fd4e31fc418 +Description: Radeon Open Compute (ROCm) Runtime rocminfo tool +Maintainer: AMD Rocminfo Support +Version: 1.0.0.60200-66~20.04 +Installed-Size: 106 + +Package: rocminfo-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: a8a777bdb53d47bdd18f064e15e7f10e2a670f50 +Depends: rocminfo (= 1.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocminfo-dbgsym/rocminfo-dbgsym_1.0.0.60200-66~20.04_amd64.deb +Size: 57238 +SHA256: 5e8e66884e56181d75fddd5c315b8d0cba2b3899100b46b2ee1660b5c9de6a65 +SHA1: 0c91161e7f6133f88957bab1273b5935ae578afc +MD5sum: ace9c886ac903ab9792dd70ba4f302a7 +Description: debug symbols for rocminfo +Maintainer: AMD Rocminfo Support +Package-Type: ddeb +Version: 1.0.0.60200-66~20.04 +Installed-Size: 192 + +Package: rocminfo-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: a8a777bdb53d47bdd18f064e15e7f10e2a670f50 +Depends: rocminfo-rpath6.2.0 (= 1.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocminfo-dbgsym-rpath6.2.0/rocminfo-dbgsym-rpath6.2.0_1.0.0.60200-66~20.04_amd64.deb +Size: 47868 +SHA256: 0736ba7582ab5d7f32d0faad40d543ea4db2783e1a12f4ac2f98f3f3259abe49 +SHA1: 2c3a54361b848211ca95ef0fa79895ea8f0e490e +MD5sum: 81fb7220dc37aa9946d4cb6410c01db4 +Description: debug symbols for rocminfo +Maintainer: AMD Rocminfo Support +Package-Type: ddeb +Version: 1.0.0.60200-66~20.04 +Installed-Size: 192 + +Package: rocminfo-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: a8a777bdb53d47bdd18f064e15e7f10e2a670f50 +Depends: rocminfo6.2.0 (= 1.0.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocminfo-dbgsym6.2.0/rocminfo-dbgsym6.2.0_1.0.0.60200-66~20.04_amd64.deb +Size: 47876 +SHA256: d4593ddf2e146abdbd2258a7fb2a58c3e3006531cc70c8fee817da673639f232 +SHA1: 8412f70d4754331d617ca71a884da2a02e025719 +MD5sum: f688aaf9818979173a05caddb75cdf51 +Description: debug symbols for rocminfo +Maintainer: AMD Rocminfo Support +Package-Type: ddeb +Version: 1.0.0.60200-66~20.04 +Installed-Size: 192 + +Package: rocminfo-rpath6.2.0 +Architecture: amd64 +Depends: hsa-rocr-rpath6.2.0, kmod, pciutils, python3, libc6, libgcc-s1, libstdc++6, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocminfo-rpath6.2.0/rocminfo-rpath6.2.0_1.0.0.60200-66~20.04_amd64.deb +Size: 23160 +SHA256: 649dfe865ee6a177474c9abb51616458752a61e989bd3c8ae65446682a8e3e93 +SHA1: 170980de56aa53b77181c2002dae30308eb83e37 +MD5sum: 2208983a83cfcb0ba058206e424a7b8a +Description: Radeon Open Compute (ROCm) Runtime rocminfo tool +Maintainer: AMD Rocminfo Support +Version: 1.0.0.60200-66~20.04 +Installed-Size: 106 + +Package: rocminfo6.2.0 +Architecture: amd64 +Depends: hsa-rocr6.2.0, kmod, pciutils, python3, libc6, libgcc-s1, libstdc++6, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocminfo6.2.0/rocminfo6.2.0_1.0.0.60200-66~20.04_amd64.deb +Size: 23172 +SHA256: 3bcf3dc22dbede7da70299cde1484776827808b967d371441f6cf6d3fe8af30d +SHA1: d8def853e8984d966dda0a41a15db96546e9fab7 +MD5sum: e61cdbdd0bfc9d408a061d32db46d071 +Description: Radeon Open Compute (ROCm) Runtime rocminfo tool +Maintainer: AMD Rocminfo Support +Version: 1.0.0.60200-66~20.04 +Installed-Size: 106 + +Package: rocprim-dev +Architecture: amd64 +Depends: hip-runtime-amd (>= 4.5.0), rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocprim-dev/rocprim-dev_3.2.0.60200-66~20.04_amd64.deb +Size: 211380 +SHA256: ff51538bdb29b6d5c59fbd714e5fa6253fd8901701d355ec082b53c4553e97c5 +SHA1: b51d5e200c2d666894572e448e4dd5c0028254f7 +MD5sum: 96e26a11d09aa658bc0cf89ecbf227fd +Description: Radeon Open Compute Parallel Primitives Library +Maintainer: rocPRIM Maintainer +Provides: CPACK_DEBIAN_PACKAGE_PROVIDES, rocprim (= 3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 3787 + +Package: rocprim-dev-rpath6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd-rpath6.2.0 (>= 4.5.0), rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocprim-dev-rpath6.2.0/rocprim-dev-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 210968 +SHA256: 49a7792ffed75750eeeb6a37d62ddf1688fbee6a6caa95af7954ffcef42ac9be +SHA1: 0d2dd3bfa59c0e42c1b3c1e7d7547a3b86a39a59 +MD5sum: cea50f39e9f7c46c6e5c80bfc4ec424d +Description: Radeon Open Compute Parallel Primitives Library +Maintainer: rocPRIM Maintainer +Provides: CPACK_DEBIAN_PACKAGE_PROVIDES, rocprim-rpath6.2.0 (= 3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 3787 + +Package: rocprim-dev6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd6.2.0 (>= 4.5.0), rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocprim-dev6.2.0/rocprim-dev6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 210944 +SHA256: e74e1907eb90a692344626e881cb88eeed5565ac3b487eb94ad4ac02ffd838ed +SHA1: 63972d918570ddcccb7f5ede492a87045f8b77da +MD5sum: 6fe3f13f6129fc3bfce5a19e795c9801 +Description: Radeon Open Compute Parallel Primitives Library +Maintainer: rocPRIM Maintainer +Provides: CPACK_DEBIAN_PACKAGE_PROVIDES, rocprim6.2.0 (= 3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 3787 + +Package: rocprofiler +Architecture: amd64 +Depends: rocminfo, hsa-rocr, rocm-core, libsystemd-dev, libelf-dev, libnuma-dev, libpciaccess-dev, libxml2-dev +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler/rocprofiler_2.0.60200.60200-66~20.04_amd64.deb +Size: 905540 +SHA256: 2e06c471826d4e2c30fbd712d262599106e18150605f16d537e8f5aa1b99ce60 +SHA1: f0b3d0c0f89434e502859028732f0319d71ecd49 +MD5sum: 4aaaa9eb78227ba13d7294d796fa9edb +Description: ROCPROFILER library for AMD HSA runtime API extension support + Dynamic libraries for the ROCProfiler +Maintainer: ROCm Profiler Support +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 4105 + +Package: rocprofiler-asan +Architecture: amd64 +Depends: hsa-rocr-asan, rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-asan/rocprofiler-asan_2.0.60200.60200-66~20.04_amd64.deb +Size: 1513246 +SHA256: 53f3e8eaf27e990b239119089f9e52c31e92081f08b962351f4c95cf960b513b +SHA1: 6164c9183d1d4d1a2e9564e2818dcba8f78c0a4e +MD5sum: 4692df36c6ec9ce866ddfb135bea8ef8 +Description: ROCPROFILER library for AMD HSA runtime API extension support + ASAN libraries for the ROCPROFILER +Maintainer: ROCm Profiler Support +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 10589 + +Package: rocprofiler-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 071432e2e53212d906bc2efa8d4d4ecf07a6f68b 1ee3fa6296df77591eccb8ed00b28b485faecc73 72564bac369cb0beece327214b51915e6168f16c fbbb10beaaa2b87b3be603ea9335ee7e9c295879 ab2ad07ff8818febbb32b178bb959ece12f3238e 44b10987d45f1ca170ef625ac15837c0d5ed1adb 06d855b79697ad116a1769832be0da9de82863cc 33bcaf0f26d508751b83f179b56a7f812744b612 +Depends: rocprofiler-asan (= 2.0.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocprofiler-asan-dbgsym/rocprofiler-asan-dbgsym_2.0.60200.60200-66~20.04_amd64.deb +Size: 7697758 +SHA256: 9d37d0368a24f6d0b27ec7af150c6628bc66afd9b584f465124dc94577791ea4 +SHA1: 8fa9ee98cce075dae571981b8451747c606f7830 +MD5sum: a4c7eff684f6ce53eff3369ad2b95ebb +Description: debug symbols for rocprofiler-asan +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 23460 + +Package: rocprofiler-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 071432e2e53212d906bc2efa8d4d4ecf07a6f68b 1ee3fa6296df77591eccb8ed00b28b485faecc73 72564bac369cb0beece327214b51915e6168f16c fbbb10beaaa2b87b3be603ea9335ee7e9c295879 ab2ad07ff8818febbb32b178bb959ece12f3238e 44b10987d45f1ca170ef625ac15837c0d5ed1adb 06d855b79697ad116a1769832be0da9de82863cc 33bcaf0f26d508751b83f179b56a7f812744b612 +Depends: rocprofiler-asan-rpath6.2.0 (= 2.0.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocprofiler-asan-dbgsym-rpath6.2.0/rocprofiler-asan-dbgsym-rpath6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 4605692 +SHA256: 85031c9fd64583e41175f407b8c77a000c352faa1d59c8d149c5e9cf1dec2ce9 +SHA1: c1338f69ee8a43232a29b4ee77585b1576fec444 +MD5sum: a3b07c71de6a2f5bda384b66c91d44e7 +Description: debug symbols for rocprofiler-asan +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 23460 + +Package: rocprofiler-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 071432e2e53212d906bc2efa8d4d4ecf07a6f68b 1ee3fa6296df77591eccb8ed00b28b485faecc73 72564bac369cb0beece327214b51915e6168f16c fbbb10beaaa2b87b3be603ea9335ee7e9c295879 ab2ad07ff8818febbb32b178bb959ece12f3238e 44b10987d45f1ca170ef625ac15837c0d5ed1adb 06d855b79697ad116a1769832be0da9de82863cc 33bcaf0f26d508751b83f179b56a7f812744b612 +Depends: rocprofiler-asan6.2.0 (= 2.0.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocprofiler-asan-dbgsym6.2.0/rocprofiler-asan-dbgsym6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 4609856 +SHA256: f01548c3a33b0cb5f14e9be93187b27d650af2f3dadde14d9553fdaaec277d13 +SHA1: 9733cc635df48672b5465627700d3c64604fa141 +MD5sum: 11444411215fb22005024ba08c00f852 +Description: debug symbols for rocprofiler-asan +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 23460 + +Package: rocprofiler-asan-rpath6.2.0 +Architecture: amd64 +Depends: hsa-rocr-asan-rpath6.2.0, rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-asan-rpath6.2.0/rocprofiler-asan-rpath6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 882892 +SHA256: 977321ce8b5c19919ddf9915bc6e8aed8b098a9845cf583c447db6ba143979ed +SHA1: 76ca31ab9c4354b5353a8d11d975e1d1eb9932d5 +MD5sum: bac15b85fab6d11c54644c37e8c0fcd3 +Description: ROCPROFILER library for AMD HSA runtime API extension support + ASAN libraries for the ROCPROFILER +Maintainer: ROCm Profiler Support +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 10589 + +Package: rocprofiler-asan6.2.0 +Architecture: amd64 +Depends: hsa-rocr-asan6.2.0, rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-asan6.2.0/rocprofiler-asan6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 884028 +SHA256: 31165e390b3efae3195646c36d013a958802ac6b8ebecada78283fac2da3dbf3 +SHA1: daa0673966ab0f4c8b0bd867c7f44ea727d1a749 +MD5sum: 85861f49930d391be1e229f8c4e164a5 +Description: ROCPROFILER library for AMD HSA runtime API extension support + ASAN libraries for the ROCPROFILER +Maintainer: ROCm Profiler Support +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 10589 + +Package: rocprofiler-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: c9e42ae8ffb417b7c0c5da2e5d28c47a1cdfb839 c7b9d9de6c308543192fcc65636fc4ccf5597ee0 52436d9d75060d77f5bb9b49b263193d1672d343 b3c85a030f35730caa18f3b47127e84b35a30005 6c2e62d5285e11145636a49eb4e68a7134ee428c 37a50b648704f30b434e1d9f2db34b604cf9b8a4 adc407c1e7e3fa9cabd7fcbe59c9e7a6ce67f593 4c6982a96be8e8df7a612e7045903c1bfbcf12f5 54dd58939e40be2d838d471eea70d25ec2bad55b 7ee42c6f6de1be65634f47166897f5912ef6bdc0 890365625bba4c2ad6759d6569d4ed792902687e +Depends: rocprofiler (= 2.0.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocprofiler-dbgsym/rocprofiler-dbgsym_2.0.60200.60200-66~20.04_amd64.deb +Size: 19048396 +SHA256: aedf6df24891e4d1ae4375e411be52cd2d02c64a4462295379bb9258ffd15bd9 +SHA1: 64bff6781bd378343fa83bd6a4fd68cac67fa1a7 +MD5sum: 3c5940f1f6eed63764cee05e806ed637 +Description: debug symbols for rocprofiler +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 65533 + +Package: rocprofiler-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: c9e42ae8ffb417b7c0c5da2e5d28c47a1cdfb839 c7b9d9de6c308543192fcc65636fc4ccf5597ee0 52436d9d75060d77f5bb9b49b263193d1672d343 b3c85a030f35730caa18f3b47127e84b35a30005 6c2e62d5285e11145636a49eb4e68a7134ee428c 37a50b648704f30b434e1d9f2db34b604cf9b8a4 adc407c1e7e3fa9cabd7fcbe59c9e7a6ce67f593 4c6982a96be8e8df7a612e7045903c1bfbcf12f5 54dd58939e40be2d838d471eea70d25ec2bad55b 7ee42c6f6de1be65634f47166897f5912ef6bdc0 890365625bba4c2ad6759d6569d4ed792902687e +Depends: rocprofiler-rpath6.2.0 (= 2.0.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocprofiler-dbgsym-rpath6.2.0/rocprofiler-dbgsym-rpath6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 12185500 +SHA256: b3f1bab3e5e862366436e38fd3443a1f1682bf12eb79d9c1f36d996b6176c008 +SHA1: 73cddbe5e2570115142130da18696eafe8bb8f79 +MD5sum: 1268f3b9a92622eed737ee82db233356 +Description: debug symbols for rocprofiler +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 65533 + +Package: rocprofiler-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: c9e42ae8ffb417b7c0c5da2e5d28c47a1cdfb839 c7b9d9de6c308543192fcc65636fc4ccf5597ee0 52436d9d75060d77f5bb9b49b263193d1672d343 b3c85a030f35730caa18f3b47127e84b35a30005 6c2e62d5285e11145636a49eb4e68a7134ee428c 37a50b648704f30b434e1d9f2db34b604cf9b8a4 adc407c1e7e3fa9cabd7fcbe59c9e7a6ce67f593 4c6982a96be8e8df7a612e7045903c1bfbcf12f5 54dd58939e40be2d838d471eea70d25ec2bad55b 7ee42c6f6de1be65634f47166897f5912ef6bdc0 890365625bba4c2ad6759d6569d4ed792902687e +Depends: rocprofiler6.2.0 (= 2.0.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocprofiler-dbgsym6.2.0/rocprofiler-dbgsym6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 12180784 +SHA256: 9452c0c65545fb4e84e1ece761e007014b1d1d4e4edcbdffd5d4df7e3ef8ced7 +SHA1: 94e0cd1836e8a0ff61b767174b988d7e5821d70a +MD5sum: 878bb4134bb0d872a7bcc03f8a8ccfaa +Description: debug symbols for rocprofiler +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 65533 + +Package: rocprofiler-dev +Architecture: amd64 +Depends: rocprofiler, hsa-rocr-dev, rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-dev/rocprofiler-dev_2.0.60200.60200-66~20.04_amd64.deb +Size: 23882 +SHA256: e4bb699ce214d2bfe1bca8422c123f538657cf48d971dc7824429b799ed96ab2 +SHA1: f832b92be223493be7d01476988914419a411762 +MD5sum: a4c8a16aeb907b4f60d702757a52fd9a +Description: ROCPROFILER library for AMD HSA runtime API extension support + Development needed header files for ROCProfiler +Maintainer: ROCm Profiler Support +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 133 + +Package: rocprofiler-dev-rpath6.2.0 +Architecture: amd64 +Depends: rocprofiler-rpath6.2.0, hsa-rocr-dev-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-dev-rpath6.2.0/rocprofiler-dev-rpath6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 21040 +SHA256: 82648ed42c1905f194828b4bfc81b84f465783effaf6ff269eec87de1c796788 +SHA1: fef4df17942485d59331daa504a336da0f4da525 +MD5sum: 6022cfa4ea05a59213d624d83a0a3d43 +Description: ROCPROFILER library for AMD HSA runtime API extension support + Development needed header files for ROCProfiler +Maintainer: ROCm Profiler Support +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 133 + +Package: rocprofiler-dev6.2.0 +Architecture: amd64 +Depends: rocprofiler6.2.0, hsa-rocr-dev6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-dev6.2.0/rocprofiler-dev6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 21040 +SHA256: 7b8c864749a82900066163c5278df15c6f74bf86b50860b05f8013acfec62d9c +SHA1: e4c7c96cfd39757226c8b3503807cd48c4d596a0 +MD5sum: 096be62222845cb8be69a85e26086826 +Description: ROCPROFILER library for AMD HSA runtime API extension support + Development needed header files for ROCProfiler +Maintainer: ROCm Profiler Support +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 133 + +Package: rocprofiler-docs +Architecture: amd64 +Depends: rocprofiler-dev, hsa-rocr-dev, rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-docs/rocprofiler-docs_2.0.60200.60200-66~20.04_amd64.deb +Size: 732 +SHA256: 228b10039cd0b1374230f6bf4ab98412752020b5b9bc999fb649049beaf02b9b +SHA1: a49f78fdba8fccfce76c7b7f0f15788b8f9d76f1 +MD5sum: da8f5aa190be823ff3a3efe1855e921f +Description: ROCPROFILER library for AMD HSA runtime API extension support + Documentation for the ROCProfiler API +Maintainer: ROCm Profiler Support +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 20 + +Package: rocprofiler-docs-rpath6.2.0 +Architecture: amd64 +Depends: rocprofiler-dev-rpath6.2.0, hsa-rocr-dev-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-docs-rpath6.2.0/rocprofiler-docs-rpath6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 940 +SHA256: 9e331ff671c95d4696644124a3a4fbc2faa7dd3e843f46e2c9abdcb0242095ab +SHA1: f4b2899f1d843b0e6585e6e0c6d59efc8727e599 +MD5sum: c4b88824bd80c6cc13a19d3ff54bad37 +Description: ROCPROFILER library for AMD HSA runtime API extension support + Documentation for the ROCProfiler API +Maintainer: ROCm Profiler Support +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 20 + +Package: rocprofiler-docs6.2.0 +Architecture: amd64 +Depends: rocprofiler-dev6.2.0, hsa-rocr-dev6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-docs6.2.0/rocprofiler-docs6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 932 +SHA256: 9dcf71f4f401796e535463b6660e03533b8beddc637662538b933d25d8149ca4 +SHA1: febe4914d3a562e0abf2044856c4fe6d5a4f983d +MD5sum: 0510350b838ec3d7c4345dfc0e13593c +Description: ROCPROFILER library for AMD HSA runtime API extension support + Documentation for the ROCProfiler API +Maintainer: ROCm Profiler Support +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 20 + +Package: rocprofiler-plugins +Architecture: amd64 +Depends: rocprofiler, hsa-rocr-dev, rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-plugins/rocprofiler-plugins_2.0.60200.60200-66~20.04_amd64.deb +Size: 1031260 +SHA256: d01fd4034c817dca264617a2d04819ccd5a26a177a20457ea1f8accaff236dcb +SHA1: aaf1803f116e8d7fbd9b4a893ab9e7e9f0adbd60 +MD5sum: f1f5f3d06e17490400956607cafc55fd +Description: ROCPROFILER library for AMD HSA runtime API extension support + Plugins for handling ROCProfiler data output +Maintainer: ROCm Profiler Support +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 4258 + +Package: rocprofiler-plugins-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: e47d8022e2aa9fb1bf7fb9811785e655e11778ff 34ce2b9ed800c13e489b14e10faca6e54c865059 17612dc3ce9f1b662cc2e71851fa46c629831867 +Depends: rocprofiler-plugins (= 2.0.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocprofiler-plugins-dbgsym/rocprofiler-plugins-dbgsym_2.0.60200.60200-66~20.04_amd64.deb +Size: 20624186 +SHA256: b80f225efe699353e4ac6f9e20c22dd971972e2c4d508d8696333036ff5ea68a +SHA1: fa359819b5cafd3ced184a44ee86f70a2f1ae6b1 +MD5sum: f857ad5a53c628f35a88dc03f2601fc3 +Description: debug symbols for rocprofiler-plugins +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 84014 + +Package: rocprofiler-plugins-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: e47d8022e2aa9fb1bf7fb9811785e655e11778ff 34ce2b9ed800c13e489b14e10faca6e54c865059 17612dc3ce9f1b662cc2e71851fa46c629831867 +Depends: rocprofiler-plugins-rpath6.2.0 (= 2.0.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocprofiler-plugins-dbgsym-rpath6.2.0/rocprofiler-plugins-dbgsym-rpath6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 13513168 +SHA256: b47f20ec91c49853166214c6d1d1c74559104a418c07fb6bb68640c606b773f1 +SHA1: 996490f50600b668f1bdbc7333ad14eafdeed4bf +MD5sum: f014b5bb055b435c346d1f6c0c3a3ce1 +Description: debug symbols for rocprofiler-plugins +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 84014 + +Package: rocprofiler-plugins-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: e47d8022e2aa9fb1bf7fb9811785e655e11778ff 34ce2b9ed800c13e489b14e10faca6e54c865059 17612dc3ce9f1b662cc2e71851fa46c629831867 +Depends: rocprofiler-plugins6.2.0 (= 2.0.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocprofiler-plugins-dbgsym6.2.0/rocprofiler-plugins-dbgsym6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 13512916 +SHA256: 511d3e84eb3026de098c8c0968a352f3a8c67406cb429b7ec9ba79c745347f83 +SHA1: cf2f7ff4bd879c6a61dfb77b2c94bcb7cfdf3854 +MD5sum: e76d9c937fae82df4175e066914bf8d3 +Description: debug symbols for rocprofiler-plugins +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 84014 + +Package: rocprofiler-plugins-rpath6.2.0 +Architecture: amd64 +Depends: rocprofiler-rpath6.2.0, hsa-rocr-dev-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-plugins-rpath6.2.0/rocprofiler-plugins-rpath6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 713624 +SHA256: 21db0c737c0936b1bcaa208bef4d5a5d174b2b53a606705e7eefd8a0ea6a1fcb +SHA1: 886483e9438648a7b56eb82706ffb0295752cff3 +MD5sum: 08c9bff2213a08b30ff6038a05594515 +Description: ROCPROFILER library for AMD HSA runtime API extension support + Plugins for handling ROCProfiler data output +Maintainer: ROCm Profiler Support +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 4258 + +Package: rocprofiler-plugins6.2.0 +Architecture: amd64 +Depends: rocprofiler6.2.0, hsa-rocr-dev6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-plugins6.2.0/rocprofiler-plugins6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 713144 +SHA256: 59e1dde17c937cf98e3f0bdfa978d4673fa1e521c9900c89b39800c7e724a7f1 +SHA1: 3e446fd3e246fc3acf1962e85dad575d7f38d2c9 +MD5sum: 6ef28745b70c9e4e5f59acbff9c9bc41 +Description: ROCPROFILER library for AMD HSA runtime API extension support + Plugins for handling ROCProfiler data output +Maintainer: ROCm Profiler Support +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 4258 + +Package: rocprofiler-register +Architecture: amd64 +Depends: rocm-core, libc6 (>= 2.14), libgcc-s1 (>= 3.3), libstdc++6 (>= 9) +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-register/rocprofiler-register_0.4.0.60200-66~20.04_amd64.deb +Size: 221068 +SHA256: 0ca16d311c5254c1cff5a6998e30046faeaa5c161ed63505e6ca0b6d0d3909ea +SHA1: d23804654233cabfd55d1345f129bbb92479ecb2 +MD5sum: 41fc06f3653f92927ec3367569367418 +Description: Registration library for rocprofiler +Homepage: https://github.com/ROCm/rocprofiler-register-internal +Maintainer: ROCm Profiler Support +Version: 0.4.0.60200-66~20.04 +Installed-Size: 1713 + +Package: rocprofiler-register-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0, libc6 (>= 2.14), libgcc-s1 (>= 3.3), libstdc++6 (>= 9) +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-register-rpath6.2.0/rocprofiler-register-rpath6.2.0_0.4.0.60200-66~20.04_amd64.deb +Size: 179048 +SHA256: 374acfe26c63d37c126e68c20aeebb9ec9c73769398b5ba335a6a00f48caef10 +SHA1: c51d165ed8d95d8c62b26ae9bfab34c92080a507 +MD5sum: f45045e6990d95e31d1899e3905cc0fb +Description: Registration library for rocprofiler +Homepage: https://github.com/ROCm/rocprofiler-register-internal +Maintainer: ROCm Profiler Support +Version: 0.4.0.60200-66~20.04 +Installed-Size: 1713 + +Package: rocprofiler-register6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0, libc6 (>= 2.14), libgcc-s1 (>= 3.3), libstdc++6 (>= 9) +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-register6.2.0/rocprofiler-register6.2.0_0.4.0.60200-66~20.04_amd64.deb +Size: 179084 +SHA256: 4be88c5010c2cf0223c1dd7dc9d4a430fc54ee401ca093de2dcca60dabea763a +SHA1: a79fc6a8b18724f01874ddde1693e3dc6f2d43fd +MD5sum: 37a5cbcb8e69a4854fd2d9b5d68994e1 +Description: Registration library for rocprofiler +Homepage: https://github.com/ROCm/rocprofiler-register-internal +Maintainer: ROCm Profiler Support +Version: 0.4.0.60200-66~20.04 +Installed-Size: 1713 + +Package: rocprofiler-rpath6.2.0 +Architecture: amd64 +Depends: rocminfo-rpath6.2.0, hsa-rocr-rpath6.2.0, rocm-core-rpath6.2.0, libsystemd-dev, libelf-dev, libnuma-dev, libpciaccess-dev, libxml2-dev +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-rpath6.2.0/rocprofiler-rpath6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 574136 +SHA256: 40e6dca3c85a4c96101c98e557d653d325516aaedd9a4d4bac4201f46e164f93 +SHA1: ce51e20f670a9e229cecca9b8026b953df44faa0 +MD5sum: 68b6d03828d1f3c55e2da97b4bd7f523 +Description: ROCPROFILER library for AMD HSA runtime API extension support + Dynamic libraries for the ROCProfiler +Maintainer: ROCm Profiler Support +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 4105 + +Package: rocprofiler-sdk +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-sdk/rocprofiler-sdk_0.4.0-66~20.04_amd64.deb +Size: 2963082 +SHA256: e22b4f30a45c18b9e90fe1abd032c102e1c706d119084d1ca8a48bcd5a1f7baa +SHA1: 04abcc1bf8ed6cb32d2aa347c1f8c76e0b86fc4a +MD5sum: 53b879c40bd12f86bb5013f0a2d16211 +Description: ROCm GPU performance analysis SDK +Homepage: https://github.com/ROCm/rocprofiler-sdk +Maintainer: ROCm Profiler Support +Version: 0.4.0-66~20.04 +Installed-Size: 28487 + +Package: rocprofiler-sdk-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 38e6257938f10da32c05533e8eb65fe0cf85c3d2 218c5538bcb92b9283609b5357303e54bb3df8e0 a33250ccdd3ea97312c4eba02f85041201e43ec6 +Depends: rocprofiler-sdk (= 0.4.0-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocprofiler-sdk-dbgsym/rocprofiler-sdk-dbgsym_0.4.0-66~20.04_amd64.deb +Size: 60252378 +SHA256: ef3ef33efffc4148193d9a2db9869a117ad52c89b5b1b8fbc5e51b6d1d9c8593 +SHA1: cd9bbe67f595dabee33dab77e88f29f024f0f386 +MD5sum: 627e8f588ba94ad720f322b1b0a3548b +Description: debug symbols for rocprofiler-sdk +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 0.4.0-66~20.04 +Installed-Size: 248893 + +Package: rocprofiler-sdk-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 38e6257938f10da32c05533e8eb65fe0cf85c3d2 218c5538bcb92b9283609b5357303e54bb3df8e0 a33250ccdd3ea97312c4eba02f85041201e43ec6 +Depends: rocprofiler-sdk-rpath6.2.0 (= 0.4.0-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocprofiler-sdk-dbgsym-rpath6.2.0/rocprofiler-sdk-dbgsym-rpath6.2.0_0.4.0-66~20.04_amd64.deb +Size: 38861336 +SHA256: 92082fe822452f6f0df75e60ebcc0615193db9a16d2bdcc90322ea5d7dc3ea7e +SHA1: 71b32fd36aee4be8cd4e42a82cd836ce740ee8c9 +MD5sum: 5d4b98b2db7b3cd6c0324559a0badad0 +Description: debug symbols for rocprofiler-sdk +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 0.4.0-66~20.04 +Installed-Size: 248893 + +Package: rocprofiler-sdk-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 38e6257938f10da32c05533e8eb65fe0cf85c3d2 218c5538bcb92b9283609b5357303e54bb3df8e0 a33250ccdd3ea97312c4eba02f85041201e43ec6 +Depends: rocprofiler-sdk6.2.0 (= 0.4.0-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocprofiler-sdk-dbgsym6.2.0/rocprofiler-sdk-dbgsym6.2.0_0.4.0-66~20.04_amd64.deb +Size: 38862704 +SHA256: ac69f66435b096b46be7bdd36fefc91f6562773218678bab4655ed5cc2e310ad +SHA1: 24559b7e3edd2e6947e3cf975518d12c128f2973 +MD5sum: 603c3d879530321a677dd583553e96bb +Description: debug symbols for rocprofiler-sdk +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 0.4.0-66~20.04 +Installed-Size: 248893 + +Package: rocprofiler-sdk-roctx +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-sdk-roctx/rocprofiler-sdk-roctx_0.4.0-66~20.04_amd64.deb +Size: 204780 +SHA256: db5682fc99e92f13780a1460f1c8082abf0fe2af8f0420aa4ae69bc4169b1383 +SHA1: 9117e180b15740ee9c7055ac259dd0440e43cc1c +MD5sum: 453380cbdfbf527fda1d1feba268d224 +Description: ROCm GPU performance analysis SDK +Homepage: https://github.com/ROCm/rocprofiler-sdk +Maintainer: ROCm Profiler Support +Version: 0.4.0-66~20.04 +Installed-Size: 1513 + +Package: rocprofiler-sdk-roctx-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 52f2816547ce2ffdf95eaba29f521c88707c2cc4 +Depends: rocprofiler-sdk-roctx (= 0.4.0-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocprofiler-sdk-roctx-dbgsym/rocprofiler-sdk-roctx-dbgsym_0.4.0-66~20.04_amd64.deb +Size: 2585786 +SHA256: add4a40af35487192e43541013196da446662dcba902566bb895bb9bdda8551e +SHA1: 7ca1936cda721f32f3322653a6be733b6747dedc +MD5sum: 662ec4468167bbb7f6c31f61c2ee5f21 +Description: debug symbols for rocprofiler-sdk-roctx +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 0.4.0-66~20.04 +Installed-Size: 9277 + +Package: rocprofiler-sdk-roctx-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 52f2816547ce2ffdf95eaba29f521c88707c2cc4 +Depends: rocprofiler-sdk-roctx-rpath6.2.0 (= 0.4.0-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocprofiler-sdk-roctx-dbgsym-rpath6.2.0/rocprofiler-sdk-roctx-dbgsym-rpath6.2.0_0.4.0-66~20.04_amd64.deb +Size: 1793104 +SHA256: 3c94fd7e23417dc9a045f4a4bfd1b9a2b85bcfa69fc9187ddbe4b45b88eb5e9d +SHA1: 9d10c244586fb19a3d55fadaa821e64e30a17230 +MD5sum: 1923153cf1a9a68e07004e045a9aa241 +Description: debug symbols for rocprofiler-sdk-roctx +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 0.4.0-66~20.04 +Installed-Size: 9277 + +Package: rocprofiler-sdk-roctx-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 52f2816547ce2ffdf95eaba29f521c88707c2cc4 +Depends: rocprofiler-sdk-roctx6.2.0 (= 0.4.0-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocprofiler-sdk-roctx-dbgsym6.2.0/rocprofiler-sdk-roctx-dbgsym6.2.0_0.4.0-66~20.04_amd64.deb +Size: 1792880 +SHA256: 17070ad1f0c7ccefd0bdce879609a1232669b44cf14a61b90088f1a43ad99218 +SHA1: c365e8af1edadcea7379bdb04ee8fe72919c45bb +MD5sum: a60d26aca18663bacf62436fd531e034 +Description: debug symbols for rocprofiler-sdk-roctx +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 0.4.0-66~20.04 +Installed-Size: 9277 + +Package: rocprofiler-sdk-roctx-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-sdk-roctx-rpath6.2.0/rocprofiler-sdk-roctx-rpath6.2.0_0.4.0-66~20.04_amd64.deb +Size: 168292 +SHA256: 42bedde8eb48c4040a4cfad502d9eb92bae94c2478dbb6a591a1166ff74ba3bf +SHA1: 17cc5050bd124ae57ffa650d17b9b921f2baf6f0 +MD5sum: 5d4634a9ef24454688823e06d6df73c9 +Description: ROCm GPU performance analysis SDK +Homepage: https://github.com/ROCm/rocprofiler-sdk +Maintainer: ROCm Profiler Support +Version: 0.4.0-66~20.04 +Installed-Size: 1513 + +Package: rocprofiler-sdk-roctx6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-sdk-roctx6.2.0/rocprofiler-sdk-roctx6.2.0_0.4.0-66~20.04_amd64.deb +Size: 168248 +SHA256: 5e3a52e0df465a73304681556d9aa9c64aaf1587eb328ed261deb7ed7329aa54 +SHA1: e344d886aa32af9de5d2e0d33182857bf365883f +MD5sum: 4c9870cb4e53ff3a581a383f5f7018b8 +Description: ROCm GPU performance analysis SDK +Homepage: https://github.com/ROCm/rocprofiler-sdk +Maintainer: ROCm Profiler Support +Version: 0.4.0-66~20.04 +Installed-Size: 1513 + +Package: rocprofiler-sdk-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-sdk-rpath6.2.0/rocprofiler-sdk-rpath6.2.0_0.4.0-66~20.04_amd64.deb +Size: 1920032 +SHA256: 18c08b3f4b3a472147554a87210bae1e8681af5d48a101eb453812aece7e066c +SHA1: ce241c74117b6bd5747fea7e8b4f0c6a5575715f +MD5sum: 0eb98da8d6d8e9d10d091631934d046c +Description: ROCm GPU performance analysis SDK +Homepage: https://github.com/ROCm/rocprofiler-sdk +Maintainer: ROCm Profiler Support +Version: 0.4.0-66~20.04 +Installed-Size: 28487 + +Package: rocprofiler-sdk6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler-sdk6.2.0/rocprofiler-sdk6.2.0_0.4.0-66~20.04_amd64.deb +Size: 1919736 +SHA256: 84e8128c238af454df470a23eac86e45cb7b0ba83dc58d39daa654bacf43f8ac +SHA1: 8c75f91f88812705c0037a5049f6b1ee1fcdfaad +MD5sum: 31adde36153acf1fe8bbd72f8480c98c +Description: ROCm GPU performance analysis SDK +Homepage: https://github.com/ROCm/rocprofiler-sdk +Maintainer: ROCm Profiler Support +Version: 0.4.0-66~20.04 +Installed-Size: 28487 + +Package: rocprofiler6.2.0 +Architecture: amd64 +Depends: rocminfo6.2.0, hsa-rocr6.2.0, rocm-core6.2.0, libsystemd-dev, libelf-dev, libnuma-dev, libpciaccess-dev, libxml2-dev +Priority: optional +Section: devel +Filename: pool/main/r/rocprofiler6.2.0/rocprofiler6.2.0_2.0.60200.60200-66~20.04_amd64.deb +Size: 573436 +SHA256: 5541020902f83c90a3be4a89ce2b5418e2350f4771333d016072f91a95f85dca +SHA1: 4b41012c55d8960f7b83eed408e9de235c87fc37 +MD5sum: 4d1f8ce1f632a540d1ac9f8e0f919c6b +Description: ROCPROFILER library for AMD HSA runtime API extension support + Dynamic libraries for the ROCProfiler +Maintainer: ROCm Profiler Support +Version: 2.0.60200.60200-66~20.04 +Installed-Size: 4105 + +Package: rocrand +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocrand/rocrand_3.1.0.60200-66~20.04_amd64.deb +Size: 21596938 +SHA256: d3a89fa47ce981c0daa44a09392f62828ec95bff256efbd6a99253946fd0e0f6 +SHA1: 26d97e0e4cc696f1ba742c34dd97f1f1197d58c6 +MD5sum: c4b3797308a14bf14356ffc8d569edb0 +Description: Radeon Open Compute RAND library +Maintainer: rocRAND Maintainer +Recommends: rocrand-dev (>=3.1.0.60200) +Version: 3.1.0.60200-66~20.04 +Installed-Size: 298946 + +Package: rocrand-asan +Architecture: amd64 +Depends: rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/r/rocrand-asan/rocrand-asan_3.1.0.60200-66~20.04_amd64.deb +Size: 28698234 +SHA256: 50438be42b8882559aa70cef4f6784665d494def5c30feb3435ebee772b4f9a3 +SHA1: a9a8951ca678e17a82619a8e0177f97c137a0aab +MD5sum: 76d8c7a8d1f2679bd3872e202985a019 +Description: Radeon Open Compute RAND library +Maintainer: rocRAND Maintainer +Recommends: rocrand-asan-dev (>=3.1.0.60200) +Version: 3.1.0.60200-66~20.04 +Installed-Size: 227169 + +Package: rocrand-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: aa5ef3f6d63f944f233dddcb90f1799236ce59a8 +Depends: rocrand-asan (= 3.1.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocrand-asan-dbgsym/rocrand-asan-dbgsym_3.1.0.60200-66~20.04_amd64.deb +Size: 4507178 +SHA256: 7306fc23c30c04406f797918db79e3ccbf9be55d0745ac0af19e6b4c9c112e76 +SHA1: e854ca6ba44b93d4c477afe430b729af5a754785 +MD5sum: 04a9e42292ba530c56f3f6ff7d0c111c +Description: debug symbols for rocrand-asan +Maintainer: rocRAND Maintainer +Package-Type: ddeb +Version: 3.1.0.60200-66~20.04 +Installed-Size: 5760 + +Package: rocrand-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: aa5ef3f6d63f944f233dddcb90f1799236ce59a8 +Depends: rocrand-asan-rpath6.2.0 (= 3.1.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocrand-asan-dbgsym-rpath6.2.0/rocrand-asan-dbgsym-rpath6.2.0_3.1.0.60200-66~20.04_amd64.deb +Size: 4507492 +SHA256: db2ab16e702c9297ea13f29fc7557d52836d93d7558cab206def9aa28072c51c +SHA1: 0f22fb82c3afd468d29b26af7b18e9029077acb6 +MD5sum: 1301bce097d84fd4b4c984096ee7151a +Description: debug symbols for rocrand-asan +Maintainer: rocRAND Maintainer +Package-Type: ddeb +Version: 3.1.0.60200-66~20.04 +Installed-Size: 5760 + +Package: rocrand-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: aa5ef3f6d63f944f233dddcb90f1799236ce59a8 +Depends: rocrand-asan6.2.0 (= 3.1.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocrand-asan-dbgsym6.2.0/rocrand-asan-dbgsym6.2.0_3.1.0.60200-66~20.04_amd64.deb +Size: 4507112 +SHA256: 1d98e83e9b7455a379f86733a88ceb6b51a28105c0f0b6d00da21e0cc1bca615 +SHA1: 77b2ecaffffe6016a3916f514358ee0d94963874 +MD5sum: 23f653733177f3e19c18dc7d55cfd4e6 +Description: debug symbols for rocrand-asan +Maintainer: rocRAND Maintainer +Package-Type: ddeb +Version: 3.1.0.60200-66~20.04 +Installed-Size: 5760 + +Package: rocrand-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocrand-asan-rpath6.2.0/rocrand-asan-rpath6.2.0_3.1.0.60200-66~20.04_amd64.deb +Size: 28704540 +SHA256: 5391f5bdd9fec88b3adf0826ada2d9d0e1db3382a0c7cfa89ae49e378a117da5 +SHA1: ff3069482f646f66682a3fd6bd82567bc904c103 +MD5sum: b39ebfaae701140619eeb15991ba4dca +Description: Radeon Open Compute RAND library +Maintainer: rocRAND Maintainer +Recommends: rocrand-asan-dev (>=3.1.0.60200) +Version: 3.1.0.60200-66~20.04 +Installed-Size: 227169 + +Package: rocrand-asan6.2.0 +Architecture: amd64 +Depends: rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocrand-asan6.2.0/rocrand-asan6.2.0_3.1.0.60200-66~20.04_amd64.deb +Size: 28704440 +SHA256: 70e72a3f516a9c01b4eb933f3ceb3c911d04b51f8e6914e135dd0e3226b782cb +SHA1: 112b6b62b603c198488b009caff352bde2656bcb +MD5sum: 6bc884fbabdc4deae22e75cae93434bf +Description: Radeon Open Compute RAND library +Maintainer: rocRAND Maintainer +Recommends: rocrand-asan-dev (>=3.1.0.60200) +Version: 3.1.0.60200-66~20.04 +Installed-Size: 227169 + +Package: rocrand-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: d677e1e1d2fe63663b8312247220e8b01f27cecd +Depends: rocrand (= 3.1.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocrand-dbgsym/rocrand-dbgsym_3.1.0.60200-66~20.04_amd64.deb +Size: 1930248 +SHA256: 27fc9db9c03e07386449ef9dd91e4bedeb2f8d826b0c9380474d3aa358ad4860 +SHA1: a162a02c943cc57f2102a5786fbf26d7d9cef1b8 +MD5sum: 6bc4cefb4dcadc26e460315be4e75fd6 +Description: debug symbols for rocrand +Maintainer: rocRAND Maintainer +Package-Type: ddeb +Version: 3.1.0.60200-66~20.04 +Installed-Size: 14848 + +Package: rocrand-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: d677e1e1d2fe63663b8312247220e8b01f27cecd +Depends: rocrand-rpath6.2.0 (= 3.1.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocrand-dbgsym-rpath6.2.0/rocrand-dbgsym-rpath6.2.0_3.1.0.60200-66~20.04_amd64.deb +Size: 1925016 +SHA256: c367bff3fed83f5d3201ac2f99a793a79278f7d2c9b97dcf8e39c90b9eb92bd1 +SHA1: e47928fb1bf70d4d1aa294587a394f46479ab203 +MD5sum: e55e1c5900787e78349ba6e1ebeea523 +Description: debug symbols for rocrand +Maintainer: rocRAND Maintainer +Package-Type: ddeb +Version: 3.1.0.60200-66~20.04 +Installed-Size: 14848 + +Package: rocrand-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: d677e1e1d2fe63663b8312247220e8b01f27cecd +Depends: rocrand6.2.0 (= 3.1.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocrand-dbgsym6.2.0/rocrand-dbgsym6.2.0_3.1.0.60200-66~20.04_amd64.deb +Size: 1929516 +SHA256: 5d6728a3fcda0d306de1d413f1736ebc77a349494f2571643db4c40c95a971b6 +SHA1: 6a2a5ad38beb800d1a5736eac0a5e53119c2c1cc +MD5sum: 83b3dba206b297cf1c4fb35c9768a3db +Description: debug symbols for rocrand +Maintainer: rocRAND Maintainer +Package-Type: ddeb +Version: 3.1.0.60200-66~20.04 +Installed-Size: 14848 + +Package: rocrand-dev +Architecture: amd64 +Depends: rocrand (>= 3.1.0.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocrand-dev/rocrand-dev_3.1.0.60200-66~20.04_amd64.deb +Size: 544426 +SHA256: ddd0ac44b08470dfc128d6f6d2598a9728879f5a78bc5290645baebf22433b63 +SHA1: ae627286346b1dfac9b3f54dcba61af37f2c0abc +MD5sum: 47cbe7d56ed024767b1274901d22e1eb +Description: Radeon Open Compute RAND library +Maintainer: rocRAND Maintainer +Version: 3.1.0.60200-66~20.04 +Installed-Size: 3794 + +Package: rocrand-dev-rpath6.2.0 +Architecture: amd64 +Depends: rocrand-rpath6.2.0 (>= 3.1.0.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocrand-dev-rpath6.2.0/rocrand-dev-rpath6.2.0_3.1.0.60200-66~20.04_amd64.deb +Size: 543284 +SHA256: 3695efa92e8109babcc00447fff61978d2a1275fab8eef195135aa25181c93d5 +SHA1: 9b69819290a4f7dcec7facb00edaa91a27751ea3 +MD5sum: 2a6281e6a89c8ea34d1e9ddc8957cd27 +Description: Radeon Open Compute RAND library +Maintainer: rocRAND Maintainer +Version: 3.1.0.60200-66~20.04 +Installed-Size: 3794 + +Package: rocrand-dev6.2.0 +Architecture: amd64 +Depends: rocrand6.2.0 (>= 3.1.0.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocrand-dev6.2.0/rocrand-dev6.2.0_3.1.0.60200-66~20.04_amd64.deb +Size: 544844 +SHA256: 1ead9edbf095aeb30beb67150408eaa3c6bfd7903e37f886f8a65d185db90416 +SHA1: 809ad7fab5aa95b713369887befdf5f2925dd7c8 +MD5sum: 815136df7947706c8acbc650f658bd26 +Description: Radeon Open Compute RAND library +Maintainer: rocRAND Maintainer +Version: 3.1.0.60200-66~20.04 +Installed-Size: 3794 + +Package: rocrand-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocrand-rpath6.2.0/rocrand-rpath6.2.0_3.1.0.60200-66~20.04_amd64.deb +Size: 21676520 +SHA256: 9d0daddb6263eeba21c97132af5ddb594b5b53c7fd7b73984e92c1205a30fe10 +SHA1: cbc7d573be9cb00c7a5b6dfa6995a93b8c7c4fd9 +MD5sum: 871c033232ceb287865b456177566e65 +Description: Radeon Open Compute RAND library +Maintainer: rocRAND Maintainer +Recommends: rocrand-dev-rpath6.2.0 (>=3.1.0.60200) +Version: 3.1.0.60200-66~20.04 +Installed-Size: 298946 + +Package: rocrand6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocrand6.2.0/rocrand6.2.0_3.1.0.60200-66~20.04_amd64.deb +Size: 21611932 +SHA256: 3b82887f165832070d6236324b95b14d216b250031ee07cf648636c4f1ead8da +SHA1: 7d7382cbf49356cdf49806ea5b835a9c484fc6fc +MD5sum: ba45a56eed6deb107adcc610c009a0cd +Description: Radeon Open Compute RAND library +Maintainer: rocRAND Maintainer +Recommends: rocrand-dev6.2.0 (>=3.1.0.60200) +Version: 3.1.0.60200-66~20.04 +Installed-Size: 298946 + +Package: rocsolver +Architecture: amd64 +Depends: rocblas (>= 4.2), rocsparse (>= 2.2), rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocsolver/rocsolver_3.26.0.60200-66~20.04_amd64.deb +Size: 244653970 +SHA256: 4051dd06738653cdd73ab3ab51fe012c61ccb54a89a5268a05365791111120bd +SHA1: 07cf99b5a30e3749b4f0e29f3d36b920091f08dc +MD5sum: 8c5a05f206994c6672ed28b93cf80871 +Description: AMD ROCm SOLVER library +Maintainer: RocSOLVER maintainer +Recommends: rocsolver-dev (>=3.26.0.60200) +Version: 3.26.0.60200-66~20.04 +Installed-Size: 3304337 + +Package: rocsolver-asan +Architecture: amd64 +Depends: rocblas (>= 4.2), rocsparse (>= 2.2), rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/r/rocsolver-asan/rocsolver-asan_3.26.0.60200-66~20.04_amd64.deb +Size: 261168116 +SHA256: 8d3c695587d2566bd98eaf1741e2c2cfc2e4e3174cad19db885cdd87410e1bec +SHA1: 8ed01aed5311aa78b637d60382e7d5ef0a79790d +MD5sum: ba883798ab9ea4874e78fc4b7e8c2c39 +Description: AMD ROCm SOLVER library +Maintainer: RocSOLVER maintainer +Recommends: rocsolver-asan-dev (>=3.26.0.60200) +Version: 3.26.0.60200-66~20.04 +Installed-Size: 3558884 + +Package: rocsolver-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 470dd4382404f3ae1363e9f1c062f2b73ac6e5b6 +Depends: rocsolver-asan (= 3.26.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocsolver-asan-dbgsym/rocsolver-asan-dbgsym_3.26.0.60200-66~20.04_amd64.deb +Size: 126673082 +SHA256: 3a63a7240eda4ee29d1983f8efa25dc382eca3188917561adee88d414f4c44c3 +SHA1: cee9de4ab2f2e0cb967a836b5f81b9c539f18a2d +MD5sum: edcc7fdb22f8b524a0afffd01e5ec983 +Description: debug symbols for rocsolver-asan +Maintainer: RocSOLVER maintainer +Package-Type: ddeb +Version: 3.26.0.60200-66~20.04 +Installed-Size: 140471 + +Package: rocsolver-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 470dd4382404f3ae1363e9f1c062f2b73ac6e5b6 +Depends: rocsolver-asan-rpath6.2.0 (= 3.26.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocsolver-asan-dbgsym-rpath6.2.0/rocsolver-asan-dbgsym-rpath6.2.0_3.26.0.60200-66~20.04_amd64.deb +Size: 126678272 +SHA256: 1af3ff2792833f24a38b7eed308d17b617b5cea7452260202268ab54aaee2eaa +SHA1: 8fd19ef8a553fabac80d89fb95d59fd75d9f8829 +MD5sum: 17a1c4639fb1e742a9fac3c74fd12381 +Description: debug symbols for rocsolver-asan +Maintainer: RocSOLVER maintainer +Package-Type: ddeb +Version: 3.26.0.60200-66~20.04 +Installed-Size: 140471 + +Package: rocsolver-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 470dd4382404f3ae1363e9f1c062f2b73ac6e5b6 +Depends: rocsolver-asan6.2.0 (= 3.26.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocsolver-asan-dbgsym6.2.0/rocsolver-asan-dbgsym6.2.0_3.26.0.60200-66~20.04_amd64.deb +Size: 126678588 +SHA256: c2beb369a7598e8dcccb263190b4646f8025b6a6e0b0d0f58453ce4a0679f36f +SHA1: a775cb4e8976ef5d9bcff6f502bb2f3f7191319e +MD5sum: c0695a19abf19fde584c714407956d0f +Description: debug symbols for rocsolver-asan +Maintainer: RocSOLVER maintainer +Package-Type: ddeb +Version: 3.26.0.60200-66~20.04 +Installed-Size: 140471 + +Package: rocsolver-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocblas-rpath6.2.0 (>= 4.2), rocsparse-rpath6.2.0 (>= 2.2), rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocsolver-asan-rpath6.2.0/rocsolver-asan-rpath6.2.0_3.26.0.60200-66~20.04_amd64.deb +Size: 261170204 +SHA256: e3a3c3fe281a84662babc5c6146e6174dce9865a9e0bc2a78355fa190d5a7dd6 +SHA1: 7fd11fc2f2f8c01caacf8f83ab167b2584967471 +MD5sum: 383a7a7d81adbfcfebe6182e6f514256 +Description: AMD ROCm SOLVER library +Maintainer: RocSOLVER maintainer +Recommends: rocsolver-asan-dev (>=3.26.0.60200) +Version: 3.26.0.60200-66~20.04 +Installed-Size: 3558884 + +Package: rocsolver-asan6.2.0 +Architecture: amd64 +Depends: rocblas6.2.0 (>= 4.2), rocsparse6.2.0 (>= 2.2), rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocsolver-asan6.2.0/rocsolver-asan6.2.0_3.26.0.60200-66~20.04_amd64.deb +Size: 261186288 +SHA256: b0403b347deaf0bcb559dbec7eb744d5056801aa56ae604244074b1003e3cd85 +SHA1: 67c20d91f4bae24af072cfb9160209f302095b3b +MD5sum: 53b18dad0549c385c50fcfb9163bdf87 +Description: AMD ROCm SOLVER library +Maintainer: RocSOLVER maintainer +Recommends: rocsolver-asan-dev (>=3.26.0.60200) +Version: 3.26.0.60200-66~20.04 +Installed-Size: 3558884 + +Package: rocsolver-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 8b27bf32cba1ec530c457e25b24ec8564b8e7b73 +Depends: rocsolver (= 3.26.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocsolver-dbgsym/rocsolver-dbgsym_3.26.0.60200-66~20.04_amd64.deb +Size: 34745486 +SHA256: 8a94b75af937eb154adf2a37e80e34d9457eb46142a3f39da711093633066624 +SHA1: de43315d8d370d451ddcce750483e36c275bfd11 +MD5sum: 041ad4f9d5d9314ec83cba032bcf5e19 +Description: debug symbols for rocsolver +Maintainer: RocSOLVER maintainer +Package-Type: ddeb +Version: 3.26.0.60200-66~20.04 +Installed-Size: 304262 + +Package: rocsolver-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 8b27bf32cba1ec530c457e25b24ec8564b8e7b73 +Depends: rocsolver-rpath6.2.0 (= 3.26.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocsolver-dbgsym-rpath6.2.0/rocsolver-dbgsym-rpath6.2.0_3.26.0.60200-66~20.04_amd64.deb +Size: 34746700 +SHA256: c331b6b8db5509d6aaefb2923c33ea675558e3d6a258aa7a1c15a9d3694257df +SHA1: 89b54c22d6da04c211a735d0f1209480e79d9e72 +MD5sum: 07c13e80fa52875b913c4270ec2d5143 +Description: debug symbols for rocsolver +Maintainer: RocSOLVER maintainer +Package-Type: ddeb +Version: 3.26.0.60200-66~20.04 +Installed-Size: 304262 + +Package: rocsolver-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 8b27bf32cba1ec530c457e25b24ec8564b8e7b73 +Depends: rocsolver6.2.0 (= 3.26.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocsolver-dbgsym6.2.0/rocsolver-dbgsym6.2.0_3.26.0.60200-66~20.04_amd64.deb +Size: 34745916 +SHA256: d0fb2d9e6ca93f8ae7f5b792480dd6472fc8b87c41590e0a367a2bdc48de38a9 +SHA1: 5966003422b542928ea8a184fbc441da1b2cb8aa +MD5sum: 2a9f20a5edb89b75ef0cca53822968f8 +Description: debug symbols for rocsolver +Maintainer: RocSOLVER maintainer +Package-Type: ddeb +Version: 3.26.0.60200-66~20.04 +Installed-Size: 304262 + +Package: rocsolver-dev +Architecture: amd64 +Depends: rocsolver (>= 3.26.0.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocsolver-dev/rocsolver-dev_3.26.0.60200-66~20.04_amd64.deb +Size: 50980 +SHA256: c695620f1c1ab6682f8df7d5c0634eeac9e4b632503c1edf459b47949f1788d1 +SHA1: 7adc3cd2ed2bfb33455a41b67572abf1588ab9e0 +MD5sum: d92de96466db003fa4022e6ca6a3a30e +Description: AMD ROCm SOLVER library +Maintainer: RocSOLVER maintainer +Version: 3.26.0.60200-66~20.04 +Installed-Size: 1572 + +Package: rocsolver-dev-rpath6.2.0 +Architecture: amd64 +Depends: rocsolver-rpath6.2.0 (>= 3.26.0.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocsolver-dev-rpath6.2.0/rocsolver-dev-rpath6.2.0_3.26.0.60200-66~20.04_amd64.deb +Size: 51124 +SHA256: 104cc4aedcfcfa56b5d67790dfe33ae834a5f61a8bd53a663c5692345c3a0649 +SHA1: 0a53161a15cfcd5fe87897a3cb588f73c4bde0de +MD5sum: 5a1a35c2062e4194b3f1db028e7cdb0b +Description: AMD ROCm SOLVER library +Maintainer: RocSOLVER maintainer +Version: 3.26.0.60200-66~20.04 +Installed-Size: 1572 + +Package: rocsolver-dev6.2.0 +Architecture: amd64 +Depends: rocsolver6.2.0 (>= 3.26.0.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocsolver-dev6.2.0/rocsolver-dev6.2.0_3.26.0.60200-66~20.04_amd64.deb +Size: 51092 +SHA256: 21e4aa1957e7bc5d293a418a983d9b3c3917fb78eb79d3d4d55a253b9bae7743 +SHA1: c4fb9a43c40d341c684fbe42005d4f7b444bd823 +MD5sum: 095ea41bed156272aa888ff3159e5741 +Description: AMD ROCm SOLVER library +Maintainer: RocSOLVER maintainer +Version: 3.26.0.60200-66~20.04 +Installed-Size: 1572 + +Package: rocsolver-rpath6.2.0 +Architecture: amd64 +Depends: rocblas-rpath6.2.0 (>= 4.2), rocsparse-rpath6.2.0 (>= 2.2), rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocsolver-rpath6.2.0/rocsolver-rpath6.2.0_3.26.0.60200-66~20.04_amd64.deb +Size: 244654248 +SHA256: 0716ebe505306cfc0b033da101747959ae46a78c70fd75e41d9d5bbe4d5e829b +SHA1: 869ed4ad31aa557cd6cc0c007bd4eb90613dce4d +MD5sum: 5384f00f1eb55350478a2eda9de24cdd +Description: AMD ROCm SOLVER library +Maintainer: RocSOLVER maintainer +Recommends: rocsolver-dev-rpath6.2.0 (>=3.26.0.60200) +Version: 3.26.0.60200-66~20.04 +Installed-Size: 3304337 + +Package: rocsolver6.2.0 +Architecture: amd64 +Depends: rocblas6.2.0 (>= 4.2), rocsparse6.2.0 (>= 2.2), rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocsolver6.2.0/rocsolver6.2.0_3.26.0.60200-66~20.04_amd64.deb +Size: 244654860 +SHA256: 87dcd34a9b50f46161ecdb7781ab03c2b311fb7e13aa167c4a9c5e3bcf24b473 +SHA1: 51bd647973d297944fab5bcf58942579142c6edd +MD5sum: 2e2ea7f10f81830edece2c6e957e9cf7 +Description: AMD ROCm SOLVER library +Maintainer: RocSOLVER maintainer +Recommends: rocsolver-dev6.2.0 (>=3.26.0.60200) +Version: 3.26.0.60200-66~20.04 +Installed-Size: 3304337 + +Package: rocsparse +Architecture: amd64 +Depends: hip-runtime-amd (>= 4.5.0), rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocsparse/rocsparse_3.2.0.60200-66~20.04_amd64.deb +Size: 169430710 +SHA256: 95544ede8cbd87107e3337ef9bb485b4c82afa6e92f78593ccf0ed0958273c9e +SHA1: 450f2ef46842fc8819cdebf7cff6fefdfb10268b +MD5sum: 2412a131af39b972dfa230d7f8b803da +Description: Radeon Open Compute SPARSE library +Maintainer: rocSPARSE Maintainer +Recommends: rocsparse-dev (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 2755048 + +Package: rocsparse-asan +Architecture: amd64 +Depends: hip-runtime-amd-asan (>= 4.5.0), rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/r/rocsparse-asan/rocsparse-asan_3.2.0.60200-66~20.04_amd64.deb +Size: 194504320 +SHA256: 31d8b337fe0a68274524cb68c2b01d08271c076f44a7c932c2811fd7ca90e7d7 +SHA1: 06dcd27607ebec9e11b1b2fb7974cdd35b2f084a +MD5sum: 85dc0a867f019655e7df4e643b77b946 +Description: Radeon Open Compute SPARSE library +Maintainer: rocSPARSE Maintainer +Recommends: rocsparse-asan-dev (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 3171459 + +Package: rocsparse-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 574884f268b7515be449051ef063948b2377d5ef +Depends: rocsparse-asan (= 3.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocsparse-asan-dbgsym/rocsparse-asan-dbgsym_3.2.0.60200-66~20.04_amd64.deb +Size: 40848266 +SHA256: f2a4e9468046a8adc579adaef9eff9c0dc5e2e923c061a0156cfad0299b22ad4 +SHA1: 91f12b202ef0c7c4f6a2c99e33f0cc62c065367c +MD5sum: 7acb47bdc3204561156286597d38f71c +Description: debug symbols for rocsparse-asan +Maintainer: rocSPARSE Maintainer +Package-Type: ddeb +Version: 3.2.0.60200-66~20.04 +Installed-Size: 56488 + +Package: rocsparse-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 574884f268b7515be449051ef063948b2377d5ef +Depends: rocsparse-asan-rpath6.2.0 (= 3.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocsparse-asan-dbgsym-rpath6.2.0/rocsparse-asan-dbgsym-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 40842028 +SHA256: 72afdbb0cd2761a52db4cfe0ad89c0c377b81d78f40544b029acfadc1e2d4030 +SHA1: 1ef593675a868aab06c3006f811ac6741279e027 +MD5sum: b0e88bc6f4a253ca7837e93662d3fba5 +Description: debug symbols for rocsparse-asan +Maintainer: rocSPARSE Maintainer +Package-Type: ddeb +Version: 3.2.0.60200-66~20.04 +Installed-Size: 56488 + +Package: rocsparse-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 574884f268b7515be449051ef063948b2377d5ef +Depends: rocsparse-asan6.2.0 (= 3.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocsparse-asan-dbgsym6.2.0/rocsparse-asan-dbgsym6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 40842024 +SHA256: 70106435e16819e544db27b0f7c581224387a5cef0deefd76ca3d7ebddd48866 +SHA1: 1534f96eb1262ff0bdf0f0110764c526a6fe5879 +MD5sum: d910d592124d3c0e6980cd37f154eb88 +Description: debug symbols for rocsparse-asan +Maintainer: rocSPARSE Maintainer +Package-Type: ddeb +Version: 3.2.0.60200-66~20.04 +Installed-Size: 56488 + +Package: rocsparse-asan-rpath6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd-asan-rpath6.2.0 (>= 4.5.0), rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocsparse-asan-rpath6.2.0/rocsparse-asan-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 194487732 +SHA256: 9a31b7a62ffc4fb1951cd5266af8c07e46dfa9e85ffc880b3b40eca2542b5254 +SHA1: e35cabc13d95ad1c2a555b90dbf28062981b8ff3 +MD5sum: bbfdf126b79bdb642b821f0748c8db28 +Description: Radeon Open Compute SPARSE library +Maintainer: rocSPARSE Maintainer +Recommends: rocsparse-asan-dev (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 3171459 + +Package: rocsparse-asan6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd-asan6.2.0 (>= 4.5.0), rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocsparse-asan6.2.0/rocsparse-asan6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 194488804 +SHA256: 00a510c0479af9c5f9e64381f66998abb8217e73c01801949832d5931bcb6a1e +SHA1: 1db235bbd53c986f77966c907c0839a9c6f0ebae +MD5sum: b55d0408aa38e5df8d341d513cde53b3 +Description: Radeon Open Compute SPARSE library +Maintainer: rocSPARSE Maintainer +Recommends: rocsparse-asan-dev (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 3171459 + +Package: rocsparse-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 82bc8b44bba0b83c077491bd7576848c717acbb5 +Depends: rocsparse (= 3.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocsparse-dbgsym/rocsparse-dbgsym_3.2.0.60200-66~20.04_amd64.deb +Size: 16611874 +SHA256: af6ad4873dba8720c943f744dd5a9f92957706c4a064c332f2254519b5a0f492 +SHA1: 830a60ddc414706ee2b94b417428e09b9587a136 +MD5sum: a4a10cf4c55aff34696d096b4231247d +Description: debug symbols for rocsparse +Maintainer: rocSPARSE Maintainer +Package-Type: ddeb +Version: 3.2.0.60200-66~20.04 +Installed-Size: 135539 + +Package: rocsparse-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 82bc8b44bba0b83c077491bd7576848c717acbb5 +Depends: rocsparse-rpath6.2.0 (= 3.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocsparse-dbgsym-rpath6.2.0/rocsparse-dbgsym-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 16616188 +SHA256: 093a7269b9fbc05f03fd993cbedb568cdf598203628e68ee3e5433c5088916ea +SHA1: d14b0e05a6a0d0065cbbba8960ce091ac7cae878 +MD5sum: 7cc26e68e30de5f8332fb71e167aea8b +Description: debug symbols for rocsparse +Maintainer: rocSPARSE Maintainer +Package-Type: ddeb +Version: 3.2.0.60200-66~20.04 +Installed-Size: 135539 + +Package: rocsparse-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 82bc8b44bba0b83c077491bd7576848c717acbb5 +Depends: rocsparse6.2.0 (= 3.2.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rocsparse-dbgsym6.2.0/rocsparse-dbgsym6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 16613768 +SHA256: 7c860698acb50a0dfa35c4122a9addada546d8a7530d22ffc593cba5cc120e7a +SHA1: d6e848f9c227470d071cce96e599c4771b428d75 +MD5sum: c900e8b2d3f4b48621fe594ba9231eec +Description: debug symbols for rocsparse +Maintainer: rocSPARSE Maintainer +Package-Type: ddeb +Version: 3.2.0.60200-66~20.04 +Installed-Size: 135539 + +Package: rocsparse-dev +Architecture: amd64 +Depends: rocsparse (>= 3.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocsparse-dev/rocsparse-dev_3.2.0.60200-66~20.04_amd64.deb +Size: 93000 +SHA256: 8bf5d9f3a59ffae251792a115ff41f0ba080c11e0266ca8616ebd13f2aeed9d5 +SHA1: eaec36cf02813db280c590ba4c139380bd61c41e +MD5sum: c4049960a87f553989c3325dbb7802b5 +Description: Radeon Open Compute SPARSE library +Maintainer: rocSPARSE Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 1932 + +Package: rocsparse-dev-rpath6.2.0 +Architecture: amd64 +Depends: rocsparse-rpath6.2.0 (>= 3.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocsparse-dev-rpath6.2.0/rocsparse-dev-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 92744 +SHA256: f3882c31949fef65bdf703a656e668def3d5b687bb2a3d41a3930803ef8551b3 +SHA1: d14d163d0b88a3ec13f48a749b8d69cb6422334d +MD5sum: 947dd686f178cd53fb1dddf392b4e221 +Description: Radeon Open Compute SPARSE library +Maintainer: rocSPARSE Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 1932 + +Package: rocsparse-dev6.2.0 +Architecture: amd64 +Depends: rocsparse6.2.0 (>= 3.2.0.60200) +Priority: optional +Section: devel +Filename: pool/main/r/rocsparse-dev6.2.0/rocsparse-dev6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 92692 +SHA256: 1cb5a05e9e88850992eb08c33cc54e4104713a8a2fdf71f5021024e438fef2b4 +SHA1: 0993d417cd9b635e7160fd58531bc38beda17ccd +MD5sum: 27dc9035ee3422080921a9c204c63a28 +Description: Radeon Open Compute SPARSE library +Maintainer: rocSPARSE Maintainer +Version: 3.2.0.60200-66~20.04 +Installed-Size: 1932 + +Package: rocsparse-rpath6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd-rpath6.2.0 (>= 4.5.0), rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocsparse-rpath6.2.0/rocsparse-rpath6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 169431648 +SHA256: 573cf461b022c3af31f387b2aa18dde420d3c4df4c903b418c1b5933c4253876 +SHA1: 8148a51a4afaef15f8b60ba27e48b91f17c6acc4 +MD5sum: 5ca834173fb8c54d90a49cc491ffb3bb +Description: Radeon Open Compute SPARSE library +Maintainer: rocSPARSE Maintainer +Recommends: rocsparse-dev-rpath6.2.0 (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 2755048 + +Package: rocsparse6.2.0 +Architecture: amd64 +Depends: hip-runtime-amd6.2.0 (>= 4.5.0), rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocsparse6.2.0/rocsparse6.2.0_3.2.0.60200-66~20.04_amd64.deb +Size: 169428716 +SHA256: dacc13278f2be1cd847fca30ce409dcf95749df5f1a27635bc6dbd61be488d14 +SHA1: c1013819dbeab2884927086ee982facfe4ac1e82 +MD5sum: b3a3ba8cfbfa172ba8de7e48f5235d9e +Description: Radeon Open Compute SPARSE library +Maintainer: rocSPARSE Maintainer +Recommends: rocsparse-dev6.2.0 (>=3.2.0.60200) +Version: 3.2.0.60200-66~20.04 +Installed-Size: 2755048 + +Package: rocthrust-dev +Architecture: amd64 +Conflicts: hip-thrust, thrust +Depends: rocprim-dev (>= 2.10.1), rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocthrust-dev/rocthrust-dev_3.0.1.60200-66~20.04_amd64.deb +Size: 416486 +SHA256: d6061ede613609eb7b22d415e5f1509f9c57c887715f8249a6addd62d451ee98 +SHA1: a829239b971617f691a86356b1e943f6ef41c45f +MD5sum: adf5addd7e0d95d8ee5bb5cd8adc9697 +Description: Radeon Open Compute Thrust library +Maintainer: rocthrust-maintainer@amd.com +Provides: hipstdpar, CPACK_DEBIAN_PACKAGE_PROVIDES, rocthrust (= 3.0.1.60200) +Version: 3.0.1.60200-66~20.04 +Installed-Size: 5630 + +Package: rocthrust-dev-rpath6.2.0 +Architecture: amd64 +Conflicts: hip-thrust-rpath6.2.0, thrust-rpath6.2.0 +Depends: rocprim-dev-rpath6.2.0 (>= 2.10.1), rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocthrust-dev-rpath6.2.0/rocthrust-dev-rpath6.2.0_3.0.1.60200-66~20.04_amd64.deb +Size: 412980 +SHA256: 7632259839d182ed6346d43048a4ba51e2162267362be17b35f018ffd0f66e09 +SHA1: d1e560d55e31ee90eacb2fea4c3bd59317f06b9d +MD5sum: 41f68247b23ec7c8cb3216e863854194 +Description: Radeon Open Compute Thrust library +Maintainer: rocthrust-maintainer@amd.com +Provides: hipstdpar, CPACK_DEBIAN_PACKAGE_PROVIDES, rocthrust-rpath6.2.0 (= 3.0.1.60200) +Version: 3.0.1.60200-66~20.04 +Installed-Size: 5630 + +Package: rocthrust-dev6.2.0 +Architecture: amd64 +Conflicts: hip-thrust6.2.0, thrust6.2.0 +Depends: rocprim-dev6.2.0 (>= 2.10.1), rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocthrust-dev6.2.0/rocthrust-dev6.2.0_3.0.1.60200-66~20.04_amd64.deb +Size: 412996 +SHA256: 6d9aa5446169126cfd9b57ab3c1a62c224b7480aa6538229d322e00734970996 +SHA1: c84d5b046c3f072acfb4e1f0ebade3fd4e254a87 +MD5sum: 52bfdb4e6d15fd929568920b1c56fa6a +Description: Radeon Open Compute Thrust library +Maintainer: rocthrust-maintainer@amd.com +Provides: hipstdpar, CPACK_DEBIAN_PACKAGE_PROVIDES, rocthrust6.2.0 (= 3.0.1.60200) +Version: 3.0.1.60200-66~20.04 +Installed-Size: 5630 + +Package: roctracer +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/roctracer/roctracer_4.1.60200.60200-66~20.04_amd64.deb +Size: 451932 +SHA256: 1fae27f536ecacfdd48c4748ce5f802aa49103bfd9eaf97819599dc23bf9b9b2 +SHA1: 1cd8eb7bde5d07c52f2e6b9e717688f51321d40a +MD5sum: ec6fab671adfe3084a300500e022a6c0 +Description: AMD ROCTRACER library + Dynamic libraries for the ROCtracer +Maintainer: ROCm Profiler Support +Version: 4.1.60200.60200-66~20.04 +Installed-Size: 1481 + +Package: roctracer-asan +Architecture: amd64 +Depends: rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/r/roctracer-asan/roctracer-asan_4.1.60200.60200-66~20.04_amd64.deb +Size: 565560 +SHA256: 188aae4b21301bdc02d5fd310eb9d95839eaa97f197ecea72665e7cb021b2fd0 +SHA1: 45abcd59dc93552b3cc1771ae828b7e0f7639404 +MD5sum: 5cc0fb946b8a8e4e40073637661c311e +Description: AMD ROCTRACER library + ASAN libraries for the ROCtracer +Maintainer: ROCm Profiler Support +Version: 4.1.60200.60200-66~20.04 +Installed-Size: 3119 + +Package: roctracer-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 8a83ec0dcd341e1c14dc88c5cc291e905bf45fa4 ce345663ae62f224484b2cdd3bdf2ef387277f5e ed55917e3aa0cd819e78f665ec0e1e5788a9639f 94d20542da41ad5e295bc022a86d7e0c0f1bf329 57250455fbca71b6ef2fe08db6914f2861a8b878 +Depends: roctracer-asan (= 4.1.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/roctracer-asan-dbgsym/roctracer-asan-dbgsym_4.1.60200.60200-66~20.04_amd64.deb +Size: 1741678 +SHA256: 1715a0fd7fa066a23e34122d91494912980a5fe0b2bf029f725ad673d67799fd +SHA1: 9ba8f3a60dfdac429d2cb876aa96172132438148 +MD5sum: 05c512b801352136f2c912f4b62fde99 +Description: debug symbols for roctracer-asan +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 4.1.60200.60200-66~20.04 +Installed-Size: 5642 + +Package: roctracer-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 8a83ec0dcd341e1c14dc88c5cc291e905bf45fa4 ce345663ae62f224484b2cdd3bdf2ef387277f5e ed55917e3aa0cd819e78f665ec0e1e5788a9639f 94d20542da41ad5e295bc022a86d7e0c0f1bf329 57250455fbca71b6ef2fe08db6914f2861a8b878 +Depends: roctracer-asan-rpath6.2.0 (= 4.1.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/roctracer-asan-dbgsym-rpath6.2.0/roctracer-asan-dbgsym-rpath6.2.0_4.1.60200.60200-66~20.04_amd64.deb +Size: 1105352 +SHA256: 6fa9e137cd52cce0ffb48b5b630d599ece22e246b74f9f20a62792a83dddafbf +SHA1: 31d3b2406ac2018f60539dcd5ffa10040c4c1c0a +MD5sum: f0e1d36eccc48396fa9d1032fa525a0e +Description: debug symbols for roctracer-asan +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 4.1.60200.60200-66~20.04 +Installed-Size: 5642 + +Package: roctracer-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 8a83ec0dcd341e1c14dc88c5cc291e905bf45fa4 ce345663ae62f224484b2cdd3bdf2ef387277f5e ed55917e3aa0cd819e78f665ec0e1e5788a9639f 94d20542da41ad5e295bc022a86d7e0c0f1bf329 57250455fbca71b6ef2fe08db6914f2861a8b878 +Depends: roctracer-asan6.2.0 (= 4.1.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/roctracer-asan-dbgsym6.2.0/roctracer-asan-dbgsym6.2.0_4.1.60200.60200-66~20.04_amd64.deb +Size: 1105580 +SHA256: 7510abbad8a4fbb548cb953a3f970b7a069bf21416d3d83fa75bc9f75c5e961a +SHA1: 1a05dcd46e46e28fd605ea36255e3356c56250be +MD5sum: 70537c4b43341abbba32660104b76f08 +Description: debug symbols for roctracer-asan +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 4.1.60200.60200-66~20.04 +Installed-Size: 5642 + +Package: roctracer-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/roctracer-asan-rpath6.2.0/roctracer-asan-rpath6.2.0_4.1.60200.60200-66~20.04_amd64.deb +Size: 350156 +SHA256: 327af2b734abf25110b96c759614f15568964cc53ca0dee00058c7434cf4d7e2 +SHA1: c83a5bea4a5f8e2776e26e78e2204c9f7bffbf3f +MD5sum: 445749ab265f6d94d96110482155defb +Description: AMD ROCTRACER library + ASAN libraries for the ROCtracer +Maintainer: ROCm Profiler Support +Version: 4.1.60200.60200-66~20.04 +Installed-Size: 3119 + +Package: roctracer-asan6.2.0 +Architecture: amd64 +Depends: rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/roctracer-asan6.2.0/roctracer-asan6.2.0_4.1.60200.60200-66~20.04_amd64.deb +Size: 349188 +SHA256: 6f340ebb905e05cbac08ed9a6db7a2c7cc23fc02258770c581e0d8708418d923 +SHA1: cb85b8a97403699f42ea91f7ef34d21098485a8a +MD5sum: 10e4d2f22378eef3195448d386983310 +Description: AMD ROCTRACER library + ASAN libraries for the ROCtracer +Maintainer: ROCm Profiler Support +Version: 4.1.60200.60200-66~20.04 +Installed-Size: 3119 + +Package: roctracer-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: f88a6a3f1a05124c3673662c15fcb1a909b7e2a2 c4a7b146ad8b0028be1a054c72e2b50260ca10ad a50f8b42ffed6f80f2692b671f4672dbc0121781 cd2f25ebcab889ebc21626d4e3299b8f860b80b4 ccf2d4c6a5562d231a10d9236eeb02283f447c64 +Depends: roctracer (= 4.1.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/roctracer-dbgsym/roctracer-dbgsym_4.1.60200.60200-66~20.04_amd64.deb +Size: 2987526 +SHA256: d0e9d83bd103b059970fb9d1ec8475c620234bdb6f8e5ebb4dbcce12d66b2b50 +SHA1: c18e06e95bbe4f87123bf63ed8b82fb32884e5cd +MD5sum: ebdaa2f92e2b56536ba58ec93990d77f +Description: debug symbols for roctracer +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 4.1.60200.60200-66~20.04 +Installed-Size: 11493 + +Package: roctracer-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: f88a6a3f1a05124c3673662c15fcb1a909b7e2a2 c4a7b146ad8b0028be1a054c72e2b50260ca10ad a50f8b42ffed6f80f2692b671f4672dbc0121781 cd2f25ebcab889ebc21626d4e3299b8f860b80b4 ccf2d4c6a5562d231a10d9236eeb02283f447c64 +Depends: roctracer-rpath6.2.0 (= 4.1.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/roctracer-dbgsym-rpath6.2.0/roctracer-dbgsym-rpath6.2.0_4.1.60200.60200-66~20.04_amd64.deb +Size: 1976268 +SHA256: 095daf0c42444f510819d5064057649b91ffd0ac3526d416d50984cd4849d07a +SHA1: 24908a8e3b2206cccd4abee2567cc3e920c95d49 +MD5sum: 004c275d65b43e8f26a8545df1bef292 +Description: debug symbols for roctracer +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 4.1.60200.60200-66~20.04 +Installed-Size: 11493 + +Package: roctracer-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: f88a6a3f1a05124c3673662c15fcb1a909b7e2a2 c4a7b146ad8b0028be1a054c72e2b50260ca10ad a50f8b42ffed6f80f2692b671f4672dbc0121781 cd2f25ebcab889ebc21626d4e3299b8f860b80b4 ccf2d4c6a5562d231a10d9236eeb02283f447c64 +Depends: roctracer6.2.0 (= 4.1.60200.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/roctracer-dbgsym6.2.0/roctracer-dbgsym6.2.0_4.1.60200.60200-66~20.04_amd64.deb +Size: 1976308 +SHA256: 01e676cf50e04231e5d7bf0cc50a732c66ea3de440f9cb4742274b146a2f5725 +SHA1: 814833ee6b3324e11cc90ca20df203efee2d940f +MD5sum: 6d68ad5d8ebfd1444a7e2ceb73cad334 +Description: debug symbols for roctracer +Maintainer: ROCm Profiler Support +Package-Type: ddeb +Version: 4.1.60200.60200-66~20.04 +Installed-Size: 11493 + +Package: roctracer-dev +Architecture: amd64 +Depends: roctracer, rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/roctracer-dev/roctracer-dev_4.1.60200.60200-66~20.04_amd64.deb +Size: 454658 +SHA256: e5394a7971d3e91a992859cfc62eae5c4b72d95b21a1a5199b70175809ca9f1a +SHA1: a02fa93e9239f63fb9514354b23ed49f1c922232 +MD5sum: 1d34c88620e578553a2f71551fd37c85 +Description: AMD ROCTRACER library + Header files and documentation for ROCtracer +Maintainer: ROCm Profiler Support +Version: 4.1.60200.60200-66~20.04 +Installed-Size: 1447 + +Package: roctracer-dev-rpath6.2.0 +Architecture: amd64 +Depends: roctracer-rpath6.2.0, rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/roctracer-dev-rpath6.2.0/roctracer-dev-rpath6.2.0_4.1.60200.60200-66~20.04_amd64.deb +Size: 395820 +SHA256: 8c599ba3b26a514445fdfc930c855eaf4bfc6d3fc06cd95e315f5c09681905b4 +SHA1: 6e46ad852adf34b87ce3f553616c85bb4ddb5c07 +MD5sum: cbb7f33950c9f9a01a501f4c38fe8c0e +Description: AMD ROCTRACER library + Header files and documentation for ROCtracer +Maintainer: ROCm Profiler Support +Version: 4.1.60200.60200-66~20.04 +Installed-Size: 1447 + +Package: roctracer-dev6.2.0 +Architecture: amd64 +Depends: roctracer6.2.0, rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/roctracer-dev6.2.0/roctracer-dev6.2.0_4.1.60200.60200-66~20.04_amd64.deb +Size: 395752 +SHA256: 9a85b57eea3790432eae06421081b3e59d3c9841d59646364ecd174f9ed4821a +SHA1: a7a97af139f26200155935bbc7cb19eaa6a99da3 +MD5sum: 0f6f73a07acd607750832d8c9e685d9c +Description: AMD ROCTRACER library + Header files and documentation for ROCtracer +Maintainer: ROCm Profiler Support +Version: 4.1.60200.60200-66~20.04 +Installed-Size: 1447 + +Package: roctracer-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/roctracer-rpath6.2.0/roctracer-rpath6.2.0_4.1.60200.60200-66~20.04_amd64.deb +Size: 262504 +SHA256: e2fe122d669ea870a165edf1a68dc99a4ef6e2b88de8365147694b14aad5db72 +SHA1: a71727a602e34939fbfb00815503970fb826887a +MD5sum: 9604d86610486fe8457fd26f19f8f18f +Description: AMD ROCTRACER library + Dynamic libraries for the ROCtracer +Maintainer: ROCm Profiler Support +Version: 4.1.60200.60200-66~20.04 +Installed-Size: 1481 + +Package: roctracer6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/roctracer6.2.0/roctracer6.2.0_4.1.60200.60200-66~20.04_amd64.deb +Size: 262168 +SHA256: b94cdf230b372ebcaf97085cf67f01ef7977f814280fdaf1886797f39899ef41 +SHA1: 16f96758bf592c1f009f6e35d30d4dff8418fe51 +MD5sum: 2cea5906bd53f24fe3023813dc6aba81 +Description: AMD ROCTRACER library + Dynamic libraries for the ROCtracer +Maintainer: ROCm Profiler Support +Version: 4.1.60200.60200-66~20.04 +Installed-Size: 1481 + +Package: rocwmma-dev +Architecture: amd64 +Depends: rocm-core +Priority: optional +Section: devel +Filename: pool/main/r/rocwmma-dev/rocwmma-dev_1.5.0.60200-66~20.04_amd64.deb +Size: 71886 +SHA256: c8d555a2b50e47d4ac8cf6dfcfe666f6c9e6ad3155eaa45729915d421bb55265 +SHA1: f75642689df5604b320f2f3e16739738cf282ea6 +MD5sum: 22fd60bedb2cbf52583f41a5aad9e275 +Description: AMD C++ library for facilitating GEMM, or GEMM-like 2D matrix multiplications on GPU leveraging MFMA instructions executing on matrix cores. +Maintainer: rocWMMA Maintainer +Provides: CPACK_DEBIAN_PACKAGE_PROVIDES, rocwmma (= 1.5.0.60200) +Version: 1.5.0.60200-66~20.04 +Installed-Size: 817 + +Package: rocwmma-dev-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocwmma-dev-rpath6.2.0/rocwmma-dev-rpath6.2.0_1.5.0.60200-66~20.04_amd64.deb +Size: 71840 +SHA256: 877598fd6b575c30d40298d3cf1ed99db56c69380b7f49ee9c7c75984b388be6 +SHA1: 17d5cf20f845d086d7167bed668229dd506b11d5 +MD5sum: fb0da50713785baf51dffef737e8faca +Description: AMD C++ library for facilitating GEMM, or GEMM-like 2D matrix multiplications on GPU leveraging MFMA instructions executing on matrix cores. +Maintainer: rocWMMA Maintainer +Provides: CPACK_DEBIAN_PACKAGE_PROVIDES, rocwmma-rpath6.2.0 (= 1.5.0.60200) +Version: 1.5.0.60200-66~20.04 +Installed-Size: 817 + +Package: rocwmma-dev6.2.0 +Architecture: amd64 +Depends: rocm-core6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rocwmma-dev6.2.0/rocwmma-dev6.2.0_1.5.0.60200-66~20.04_amd64.deb +Size: 71832 +SHA256: 385bfc8930ad8e08bf4049c4aed1891ee7fad48483b78aa9071bd537f33d5ed0 +SHA1: 1254422cf9ffedf8b32cda38f50bd5f43bf7106b +MD5sum: e1e98c0033a89f923b200f472ed8022c +Description: AMD C++ library for facilitating GEMM, or GEMM-like 2D matrix multiplications on GPU leveraging MFMA instructions executing on matrix cores. +Maintainer: rocWMMA Maintainer +Provides: CPACK_DEBIAN_PACKAGE_PROVIDES, rocwmma6.2.0 (= 1.5.0.60200) +Version: 1.5.0.60200-66~20.04 +Installed-Size: 817 + +Package: rpp +Architecture: amd64 +Depends: rocm-hip-runtime +Priority: optional +Section: devel +Filename: pool/main/r/rpp/rpp_1.8.0.60200-66~20.04_amd64.deb +Size: 79025358 +SHA256: 9d4476f432190e194d17fd0eecbd7257a5be8baed25f10fcaea283be33c27f0b +SHA1: 4bb29f96f5e969f30477c2dc788edb7d23dae463 +MD5sum: 5eacd1f4695ab8ec340a4e94d366c81b +Description: ROCm Performance Primitives library is a comprehensive high performance computer vision library for AMD CPUs and GPUs with HOST/HIP/OpenCL back-ends. + RPP runtime package provides rpp library and license.txt +Homepage: https://github.com/ROCm/rpp +Maintainer: mivisionx support +Version: 1.8.0.60200-66~20.04 +Installed-Size: 542283 + +Package: rpp-asan +Architecture: amd64 +Depends: rocm-core-asan +Priority: optional +Section: devel +Filename: pool/main/r/rpp-asan/rpp-asan_1.8.0.60200-66~20.04_amd64.deb +Size: 82578296 +SHA256: cc87ce677e656791b20dbbbf1baee5fe87989ad4d1fc4ea150f39de564e91eea +SHA1: 652a9b8c119833c78249ed6b1c1292ac908c6f97 +MD5sum: 107afa7674335980b253e7aa710050e9 +Description: ROCm Performance Primitives library is a comprehensive high performance computer vision library for AMD CPUs and GPUs with HOST/HIP/OpenCL back-ends. RPP ASAN package provides rpp ASAN libraries +Homepage: https://github.com/ROCm/rpp +Maintainer: mivisionx support +Version: 1.8.0.60200-66~20.04 +Installed-Size: 532345 + +Package: rpp-asan-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 831b45600415cccb5ffcc2d1e4975c8b974e7273 +Depends: rpp-asan (= 1.8.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rpp-asan-dbgsym/rpp-asan-dbgsym_1.8.0.60200-66~20.04_amd64.deb +Size: 8212004 +SHA256: 20fad2a4917adf6f9887d393b494be897a9dfe145fec4af4756eb96038155733 +SHA1: 9c5a082f0a77fecdd2b7e7c022979e7fdc5edd69 +MD5sum: c6a2099bdd75bb63f8140a44696d6d31 +Description: debug symbols for rpp-asan +Maintainer: mivisionx support +Package-Type: ddeb +Version: 1.8.0.60200-66~20.04 +Installed-Size: 9264 + +Package: rpp-asan-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 831b45600415cccb5ffcc2d1e4975c8b974e7273 +Depends: rpp-asan-rpath6.2.0 (= 1.8.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rpp-asan-dbgsym-rpath6.2.0/rpp-asan-dbgsym-rpath6.2.0_1.8.0.60200-66~20.04_amd64.deb +Size: 8079424 +SHA256: b330c233a490277c9500ad7defab9072a58f4c33659ec11e00184ba22f0aa0ec +SHA1: 2d78cc53df5aced51129563eb590cab8ddcd050a +MD5sum: f4fec80bdcf1d8ed49d253f3ee228fcb +Description: debug symbols for rpp-asan +Maintainer: mivisionx support +Package-Type: ddeb +Version: 1.8.0.60200-66~20.04 +Installed-Size: 9264 + +Package: rpp-asan-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 831b45600415cccb5ffcc2d1e4975c8b974e7273 +Depends: rpp-asan6.2.0 (= 1.8.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rpp-asan-dbgsym6.2.0/rpp-asan-dbgsym6.2.0_1.8.0.60200-66~20.04_amd64.deb +Size: 8079440 +SHA256: dcbef8e6736574861b8ca5a9c0e6dad13a14130c9e00f3bb2d9662d5e4c569a2 +SHA1: e3bd172abbe726b8ea3050cdb249153122aa764a +MD5sum: fd0f88ee5b93ff8611dd884cd13e8eb6 +Description: debug symbols for rpp-asan +Maintainer: mivisionx support +Package-Type: ddeb +Version: 1.8.0.60200-66~20.04 +Installed-Size: 9264 + +Package: rpp-asan-rpath6.2.0 +Architecture: amd64 +Depends: rocm-core-asan-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rpp-asan-rpath6.2.0/rpp-asan-rpath6.2.0_1.8.0.60200-66~20.04_amd64.deb +Size: 36796952 +SHA256: df4a92d3569ff38ac39eeb4dec30a600e7b041b7879b75f8bd750b0fb2283fa2 +SHA1: 1741da7524ed1dbfd44f2dc9d52586214524442f +MD5sum: 3a29898ef3815464b13fd5640b98f8fd +Description: ROCm Performance Primitives library is a comprehensive high performance computer vision library for AMD CPUs and GPUs with HOST/HIP/OpenCL back-ends. RPP ASAN package provides rpp ASAN libraries +Homepage: https://github.com/ROCm/rpp +Maintainer: mivisionx support +Version: 1.8.0.60200-66~20.04 +Installed-Size: 532345 + +Package: rpp-asan6.2.0 +Architecture: amd64 +Depends: rocm-core-asan6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rpp-asan6.2.0/rpp-asan6.2.0_1.8.0.60200-66~20.04_amd64.deb +Size: 36792672 +SHA256: 7f6f40c89bdc401d6ad587414cb8d9254c6379456cf81d8fc99a9f5a79506d4c +SHA1: 1cfd908d64e1aad84acc3efb6c4f839aec7d050d +MD5sum: bf6b4436ceaa1224ccffa566c5af1b65 +Description: ROCm Performance Primitives library is a comprehensive high performance computer vision library for AMD CPUs and GPUs with HOST/HIP/OpenCL back-ends. RPP ASAN package provides rpp ASAN libraries +Homepage: https://github.com/ROCm/rpp +Maintainer: mivisionx support +Version: 1.8.0.60200-66~20.04 +Installed-Size: 532345 + +Package: rpp-dbgsym +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 9d958b43e63673d85d69c54e1d61ddbf422ea780 +Depends: rpp (= 1.8.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rpp-dbgsym/rpp-dbgsym_1.8.0.60200-66~20.04_amd64.deb +Size: 5388638 +SHA256: ad074aaec3276dfea08981ad3670750ecc3455cb7451b4f732b402f77959f27d +SHA1: 47dd89092dc8b914a1e6b315fb05349e92923240 +MD5sum: 2ee11a6c0e71fdb04f272314aeac591e +Description: debug symbols for rpp +Maintainer: mivisionx support +Package-Type: ddeb +Version: 1.8.0.60200-66~20.04 +Installed-Size: 15857 + +Package: rpp-dbgsym-rpath6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 9d958b43e63673d85d69c54e1d61ddbf422ea780 +Depends: rpp-rpath6.2.0 (= 1.8.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rpp-dbgsym-rpath6.2.0/rpp-dbgsym-rpath6.2.0_1.8.0.60200-66~20.04_amd64.deb +Size: 3404424 +SHA256: bd1ce4b39573d9e28e91563bce33e81cf9e998ceefe5f4642846a66d588d1699 +SHA1: 9c65b4826b9a772dec4008c9b566e5d97e7864c8 +MD5sum: cd7d6abeb8119f3fdea9e5db6ac7dce9 +Description: debug symbols for rpp +Maintainer: mivisionx support +Package-Type: ddeb +Version: 1.8.0.60200-66~20.04 +Installed-Size: 15857 + +Package: rpp-dbgsym6.2.0 +Architecture: amd64 +Auto-Built-Package: debug-symbols +Build-Ids: 9d958b43e63673d85d69c54e1d61ddbf422ea780 +Depends: rpp6.2.0 (= 1.8.0.60200-66~20.04) +Priority: optional +Section: debug +Filename: pool/main/r/rpp-dbgsym6.2.0/rpp-dbgsym6.2.0_1.8.0.60200-66~20.04_amd64.deb +Size: 3402816 +SHA256: 3de5ed6a1d39980f74b66579d5c79e8425168d847a08f5805505346e53ec23dc +SHA1: b5522fbf138c93696f4767f7f1beff0ce0a3dd0e +MD5sum: 04ffaf25635fa25891d0b447216dc133 +Description: debug symbols for rpp +Maintainer: mivisionx support +Package-Type: ddeb +Version: 1.8.0.60200-66~20.04 +Installed-Size: 15857 + +Package: rpp-dev +Architecture: amd64 +Depends: rpp, rocm-hip-runtime-dev, half +Priority: optional +Section: devel +Filename: pool/main/r/rpp-dev/rpp-dev_1.8.0.60200-66~20.04_amd64.deb +Size: 45868 +SHA256: 7d54ec59b817e641f27a71ef644124e20cec527a11ac34449d73b129529f8af4 +SHA1: ee77dea7d0b38fa567198a583fa6b98f30ae1c83 +MD5sum: 1ff19798d53f543d4ebf505f7886dbaa +Description: ROCm Performance Primitives library is a comprehensive high performance computer vision library for AMD CPUs and GPUs with HOST/HIP/OpenCL back-ends. RPP develop package provides rpp library, header files, and license.txt +Homepage: https://github.com/ROCm/rpp +Maintainer: mivisionx support +Version: 1.8.0.60200-66~20.04 +Installed-Size: 601 + +Package: rpp-dev-rpath6.2.0 +Architecture: amd64 +Depends: rpp-rpath6.2.0, rocm-hip-runtime-dev-rpath6.2.0, half-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rpp-dev-rpath6.2.0/rpp-dev-rpath6.2.0_1.8.0.60200-66~20.04_amd64.deb +Size: 33600 +SHA256: 8b526fbf390eddd136a9860b2fed7b2ee01d41c30564f1d2ad8929f6517b19b4 +SHA1: 08f5d9195c3d8a737eaed97654aa44f16bc4353b +MD5sum: 2b56a032263471d9a8da2b7fb5d3a7de +Description: ROCm Performance Primitives library is a comprehensive high performance computer vision library for AMD CPUs and GPUs with HOST/HIP/OpenCL back-ends. RPP develop package provides rpp library, header files, and license.txt +Homepage: https://github.com/ROCm/rpp +Maintainer: mivisionx support +Version: 1.8.0.60200-66~20.04 +Installed-Size: 601 + +Package: rpp-dev6.2.0 +Architecture: amd64 +Depends: rpp6.2.0, rocm-hip-runtime-dev6.2.0, half6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rpp-dev6.2.0/rpp-dev6.2.0_1.8.0.60200-66~20.04_amd64.deb +Size: 33596 +SHA256: ae1a9b1b272c45519b4fe89d31ab5afbaf69fff0f62a185356f823e27f67a96c +SHA1: 0b36ad8634262ff0b94763ef525e60d9c0664d90 +MD5sum: c7efea9cbe44f92c7e7e6278106d3fd7 +Description: ROCm Performance Primitives library is a comprehensive high performance computer vision library for AMD CPUs and GPUs with HOST/HIP/OpenCL back-ends. RPP develop package provides rpp library, header files, and license.txt +Homepage: https://github.com/ROCm/rpp +Maintainer: mivisionx support +Version: 1.8.0.60200-66~20.04 +Installed-Size: 601 + +Package: rpp-rpath6.2.0 +Architecture: amd64 +Depends: rocm-hip-runtime-rpath6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rpp-rpath6.2.0/rpp-rpath6.2.0_1.8.0.60200-66~20.04_amd64.deb +Size: 22277172 +SHA256: b46173267bd8ebc327b723a94838f86f34f966dfdad717e359601f740c8086fa +SHA1: 64ae6e7089ed148b390a94b780e72fe369a07ffe +MD5sum: 1318650c917b2d35cf0c24fc29ef1df1 +Description: ROCm Performance Primitives library is a comprehensive high performance computer vision library for AMD CPUs and GPUs with HOST/HIP/OpenCL back-ends. + RPP runtime package provides rpp library and license.txt +Homepage: https://github.com/ROCm/rpp +Maintainer: mivisionx support +Version: 1.8.0.60200-66~20.04 +Installed-Size: 542283 + +Package: rpp-test +Architecture: amd64 +Depends: rpp-dev, clang +Priority: optional +Section: devel +Filename: pool/main/r/rpp-test/rpp-test_1.8.0.60200-66~20.04_amd64.deb +Size: 30003696 +SHA256: ef9101ec07e5212f7eec1bef7a39453ef9a05e207e59508adfb59df7fb8ddd10 +SHA1: cef997f9fdc90209c0cd80c3435ab5a2798be380 +MD5sum: 5477a20e88fb2235ba7a097d44f0db06 +Description: ROCm Performance Primitives library is a comprehensive high performance computer vision library for AMD CPUs and GPUs with HOST/HIP/OpenCL back-ends. RPP test package provides rpp test suite +Homepage: https://github.com/ROCm/rpp +Maintainer: mivisionx support +Version: 1.8.0.60200-66~20.04 +Installed-Size: 84560 + +Package: rpp-test-rpath6.2.0 +Architecture: amd64 +Depends: rpp-dev-rpath6.2.0, clang +Priority: optional +Section: devel +Filename: pool/main/r/rpp-test-rpath6.2.0/rpp-test-rpath6.2.0_1.8.0.60200-66~20.04_amd64.deb +Size: 24214664 +SHA256: b25a1a93e6cf1fc68a42c461c4c2ce1f2353dd042e2a5db90f463ea11f972795 +SHA1: 5c93f26edf848cfe5f145579de406d30408681e3 +MD5sum: 5c5c80883f981e0c98a93bd7a5106b63 +Description: ROCm Performance Primitives library is a comprehensive high performance computer vision library for AMD CPUs and GPUs with HOST/HIP/OpenCL back-ends. RPP test package provides rpp test suite +Homepage: https://github.com/ROCm/rpp +Maintainer: mivisionx support +Version: 1.8.0.60200-66~20.04 +Installed-Size: 84560 + +Package: rpp-test6.2.0 +Architecture: amd64 +Depends: rpp-dev6.2.0, clang +Priority: optional +Section: devel +Filename: pool/main/r/rpp-test6.2.0/rpp-test6.2.0_1.8.0.60200-66~20.04_amd64.deb +Size: 24205060 +SHA256: f10fa117a56d923934460ebfbd75f760b46e62b6006584999046cdcd9b0e00fb +SHA1: 151bb1d3c0ad93b2299c0f016e7a96cb147652c4 +MD5sum: 6282b066aeb7c8a83602a74b27f5e3a7 +Description: ROCm Performance Primitives library is a comprehensive high performance computer vision library for AMD CPUs and GPUs with HOST/HIP/OpenCL back-ends. RPP test package provides rpp test suite +Homepage: https://github.com/ROCm/rpp +Maintainer: mivisionx support +Version: 1.8.0.60200-66~20.04 +Installed-Size: 84560 + +Package: rpp6.2.0 +Architecture: amd64 +Depends: rocm-hip-runtime6.2.0 +Priority: optional +Section: devel +Filename: pool/main/r/rpp6.2.0/rpp6.2.0_1.8.0.60200-66~20.04_amd64.deb +Size: 22279152 +SHA256: fe70b996c6071eb18eeee5ded84434a37d7a4211ffae5bf8ffbfdbedc7211803 +SHA1: 108f8b104301097d78239d015c2d2db06056c52c +MD5sum: 595e93db187a8b6f611d36c901f01689 +Description: ROCm Performance Primitives library is a comprehensive high performance computer vision library for AMD CPUs and GPUs with HOST/HIP/OpenCL back-ends. + RPP runtime package provides rpp library and license.txt +Homepage: https://github.com/ROCm/rpp +Maintainer: mivisionx support +Version: 1.8.0.60200-66~20.04 +Installed-Size: 542283 + diff --git a/runtimes/rocm/rocm.bzl b/runtimes/rocm/rocm.bzl new file mode 100644 index 0000000..603095b --- /dev/null +++ b/runtimes/rocm/rocm.bzl @@ -0,0 +1,242 @@ +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load("//bazel:http_deb_archive.bzl", "http_deb_archive") + +ROCM_VERSION = "6.2" +BASE_URL = "https://repo.radeon.com/rocm/apt/{}".format(ROCM_VERSION) +STRIP_PREFIX = "opt/rocm-6.2.0" + +def pkg_kwargs(pkg, packages): + return { + "name": pkg, + "urls": [BASE_URL + "/" + packages[pkg]["Filename"]], + "sha256": packages[pkg]["SHA256"], + "strip_prefix": STRIP_PREFIX, + } + +def _ubuntu_package(path, deb_path, sha256, name, shared_library): + return { + "urls": ["http://archive.ubuntu.com/ubuntu/pool/main/{}".format(path)], + "sha256": sha256, + "build_file_content": """\ +cc_import( + name = {name}, + shared_library = "{deb_path}{shared_library}", + visibility = ["//visibility:public"], +) +""".format(name = repr(name), shared_library = shared_library, deb_path = deb_path), + } + +_UBUNTU_PACKAGES = { + "libdrm": _ubuntu_package( + path = "libd/libdrm/libdrm2_2.4.107-8ubuntu1~20.04.2_amd64.deb", + deb_path = "usr/lib/x86_64-linux-gnu/", + sha256 = "9b01d73313841abe8e3f24c2715edced675fbe329bbd10be912a5b135cd51fb6", + name = "libdrm", + shared_library = "libdrm.so.2", + ), + "libelf": _ubuntu_package( + path = "e/elfutils/libelf1_0.176-1.1build1_amd64.deb", + deb_path = "usr/lib/x86_64-linux-gnu/", + sha256 = "78a8761227efc04a1e37527f2f33ba608c6fb5d6c911616346ada5d7b9b72ee3", + name = "libelf", + shared_library = "libelf.so.1", + ), + "libnuma": _ubuntu_package( + path = "n/numactl/libnuma1_2.0.12-1_amd64.deb", + deb_path = "usr/lib/x86_64-linux-gnu/", + sha256 = "0b1edf08cf9befecd21fe94e298ac25e476f87fd876ddd4adf42ef713449e637", + name = "libnuma", + shared_library = "libnuma.so.1", + ), + "libzstd": _ubuntu_package( + path = "libz/libzstd/libzstd1_1.4.4+dfsg-3ubuntu0.1_amd64.deb", + deb_path = "usr/lib/x86_64-linux-gnu/", + sha256 = "7a4422dadb90510dc90765c308d65e61a3e244ceb3886394335e48cff7559e69", + name = "libzstd", + shared_library = "libzstd.so.1", + ), + "libdrm-amdgpu": _ubuntu_package( + path = "libd/libdrm/libdrm-amdgpu1_2.4.107-8ubuntu1~20.04.2_amd64.deb", + deb_path = "usr/lib/x86_64-linux-gnu/", + sha256 = "0d95779b581f344e3d658e0f21f6e4b57da6eb3606c0bcb8cb874c12f5754bf2", + name = "libdrm-amdgpu", + shared_library = "libdrm_amdgpu.so.1", + ), + "libtinfo": _ubuntu_package( + path = "n/ncurses/libtinfo6_6.2-0ubuntu2.1_amd64.deb", + deb_path = "lib/x86_64-linux-gnu/", + sha256 = "711a3a901c3a71561565558865699efa9c07a99fdc810ffe086a5636f89c6431", + name = "libtinfo", + shared_library = "libtinfo.so.6", + ), + "zlib1g": _ubuntu_package( + path = "z/zlib/zlib1g_1.2.11.dfsg-2ubuntu1.5_amd64.deb", + deb_path = "lib/x86_64-linux-gnu/", + sha256 = "bf67018f5303466eb468680b637a5d3f3bb17b9d44decf3d82d40b35babcd3e0", + name = "zlib1g", + shared_library = "libz.so.1", + ), +} + +_CC_IMPORT_TPL = """\ +cc_import( + name = "{name}", + shared_library = "lib/{shared_library}", + visibility = ["@libpjrt_rocm//:__subpackages__"], +) +""" + +_RUNFILES_TPL = """\ +filegroup( + name = "{name}", + srcs = glob({glob}), + visibility = ["@libpjrt_rocm//:__subpackages__"], +) +""" + +_PACKAGES = { + "rocm-core": _CC_IMPORT_TPL.format(name = "rocm-core", shared_library = "librocm-core.so.1"), + "rocm-smi-lib": _CC_IMPORT_TPL.format(name = "rocm_smi", shared_library = "librocm_smi64.so.7"), + "hsa-rocr": _CC_IMPORT_TPL.format(name = "hsa-runtime", shared_library = "libhsa-runtime64.so.1"), + "hsa-amd-aqlprofile": _CC_IMPORT_TPL.format(name = "hsa-amd-aqlprofile", shared_library = "libhsa-amd-aqlprofile64.so.1"), + "comgr": _CC_IMPORT_TPL.format(name = "amd_comgr", shared_library = "libamd_comgr.so.2"), + "rocprofiler-register": _CC_IMPORT_TPL.format(name = "rocprofiler-register", shared_library = "librocprofiler-register.so.0"), + "miopen-hip": "".join([ + _CC_IMPORT_TPL.format(name = "MIOpen", shared_library = "libMIOpen.so.1"), + _RUNFILES_TPL.format(name = "runfiles", glob = repr(["share/miopen/**"])), + ]), + "rccl": "".join([ + _CC_IMPORT_TPL.format(name = "rccl", shared_library = "librccl.so.1"), + _RUNFILES_TPL.format(name = "runfiles", glob = repr(["share/rccl/msccl-algorithms/**"])), + ]), + "rocm-device-libs": _RUNFILES_TPL.format(name = "runfiles", glob = repr(["amdgcn/**"])), + "hip-dev": _RUNFILES_TPL.format(name = "runfiles", glob = repr(["share/**"])), + "rocblas": """\ +load("@zml//bazel:cc_import.bzl", "cc_import") +load("@zml//runtimes/rocm:gfx.bzl", "bytecode_select") + +cc_import( + name = "rocblas", + shared_library = "lib/librocblas.so.4", + add_needed = ["libzmlrocmhooks.so.0"], + visibility = ["@libpjrt_rocm//:__subpackages__"], +) + +bytecode_select( + name = "runfiles", + bytecodes = glob(["lib/rocblas/library/*"]), + enabled_gfx = "@libpjrt_rocm//:gfx", + visibility = ["@libpjrt_rocm//:__subpackages__"], +) +""", + "roctracer": """\ +cc_import( + name = "roctracer", + shared_library = "lib/libroctracer64.so.4", + visibility = ["@libpjrt_rocm//:__subpackages__"], + deps = [":roctx"], +) + +cc_import( + name = "roctx", + shared_library = "lib/libroctx64.so.4", +) +""", + "hipblaslt": """\ +load("@zml//bazel:cc_import.bzl", "cc_import") +cc_import( + name = "hipblaslt", + shared_library = "lib/libhipblaslt.so.0", + add_needed = ["libzmlrocmhooks.so.0"], + visibility = ["@libpjrt_rocm//:__subpackages__"], +) +""", + "hipblaslt-dev": """\ +load("@zml//runtimes/rocm:gfx.bzl", "bytecode_select") + +bytecode_select( + name = "bytecodes", + bytecodes = glob( + include = ["lib/hipblaslt/library/*"], + exclude = ["lib/hipblaslt/library/hipblasltExtOpLibrary.dat"], + ), + enabled_gfx = "@libpjrt_rocm//:gfx", +) + +filegroup( + name = "runfiles", + srcs = [ + "lib/hipblaslt/library/hipblasltExtOpLibrary.dat", + ":bytecodes", + ], + visibility = ["@libpjrt_rocm//:__subpackages__"], +) +""", + "hip-runtime-amd": """\ +cc_import( + name = "amdhip", + shared_library = "lib/libamdhip64.so.6", + visibility = ["@libpjrt_rocm//:__subpackages__"], + deps = [":hiprtc"], +) +cc_import( + name = "hiprtc", + shared_library = "lib/libhiprtc.so.6", +) +""", + "rocm-llvm": """\ +filegroup( + name = "lld", + srcs = ["llvm/bin/ld.lld"], + visibility = ["@libpjrt_rocm//:__subpackages__"], +) +""", +} + +def _packages_to_dict(txt): + packages = {} + current_pkg = {} + for line in txt.splitlines(): + if line == "": + if current_pkg: + packages[current_pkg["Package"]] = current_pkg + current_pkg = {} + continue + if line.startswith(" "): + current_pkg[key] += line + continue + split = line.split(": ", 1) + key = split[0] + value = len(split) > 1 and split[1] or "" + current_pkg[key] = value + return packages + +def _rocm_impl(mctx): + data = mctx.read(Label("@zml//runtimes/rocm:packages.amd64.txt")) + PACKAGES = _packages_to_dict(data) + + for pkg, build_file_content in _PACKAGES.items(): + http_deb_archive( + build_file_content = build_file_content, + **pkg_kwargs(pkg, PACKAGES) + ) + + for repository, kwargs in _UBUNTU_PACKAGES.items(): + http_deb_archive(name = repository, **kwargs) + + http_archive( + name = "libpjrt_rocm", + build_file = "libpjrt_rocm.BUILD.bazel", + url = "https://github.com/zml/pjrt-artifacts/releases/download/v0.1.13/pjrt-rocm_linux-amd64.tar.gz", + sha256 = "5900cec41274e80ab799bc13f31cdc87202f8e168d7e753b1c10796912f5ebef", + ) + + return mctx.extension_metadata( + reproducible = True, + root_module_direct_deps = ["libpjrt_rocm"], + root_module_direct_dev_deps = [], + ) + +rocm_packages = module_extension( + implementation = _rocm_impl, +) diff --git a/runtimes/rocm/zmlrocmhooks.cc b/runtimes/rocm/zmlrocmhooks.cc new file mode 100644 index 0000000..0c0fc60 --- /dev/null +++ b/runtimes/rocm/zmlrocmhooks.cc @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include "tools/cpp/runfiles/runfiles.h" + +namespace zml +{ + using bazel::tools::cpp::runfiles::Runfiles; + + std::unique_ptr runfiles; + std::string ROCBLAS_TENSILE_LIBPATH; + std::string HIPBLASLT_TENSILE_LIBPATH; + std::string HIPBLASLT_EXT_OP_LIBRARY_PATH; + std::string ROCM_PATH; + + typedef void *(*dlopen_func)(const char *filename, int flags); + dlopen_func dlopen_orig = nullptr; + + __attribute__((constructor)) static void setup(int argc, char **argv) + { + runfiles = std::unique_ptr(Runfiles::Create(argv[0], BAZEL_CURRENT_REPOSITORY)); + + HIPBLASLT_EXT_OP_LIBRARY_PATH = runfiles->Rlocation("hipblaslt-dev/lib/hipblaslt/library/hipblasltExtOpLibrary.dat"); + if (HIPBLASLT_EXT_OP_LIBRARY_PATH != "") + { + setenv("HIPBLASLT_EXT_OP_LIBRARY_PATH", HIPBLASLT_EXT_OP_LIBRARY_PATH.c_str(), 1); + } + + HIPBLASLT_TENSILE_LIBPATH = runfiles->Rlocation("hipblaslt-dev/lib/hipblaslt/library"); + if (HIPBLASLT_TENSILE_LIBPATH != "") + { + setenv("HIPBLASLT_TENSILE_LIBPATH", HIPBLASLT_TENSILE_LIBPATH.c_str(), 1); + } + + ROCBLAS_TENSILE_LIBPATH = runfiles->Rlocation("rocblas/lib/rocblas/library"); + setenv("ROCBLAS_TENSILE_LIBPATH", ROCBLAS_TENSILE_LIBPATH.c_str(), 1); + + ROCM_PATH = runfiles->Rlocation("libpjrt_rocm/sandbox"); + setenv("ROCM_PATH", ROCM_PATH.c_str(), 1); + } + + static void *rocm_dlopen(const char *filename, int flags) + { + if (filename != NULL) + { + char *replacements[] = { + "librocm-core.so", + "librocm-core.so.1", + "librocm_smi64.so", + "librocm_smi64.so.7", + "libhsa-runtime64.so", + "libhsa-runtime64.so.1", + "libhsa-amd-aqlprofile64.so", + "libhsa-amd-aqlprofile64.so.1", + "libamd_comgr.so", + "libamd_comgr.so.2", + "librocprofiler-register.so", + "librocprofiler-register.so.0", + "libMIOpen.so", + "libMIOpen.so.1", + "librccl.so", + "librccl.so.1", + "librocblas.so", + "librocblas.so.4", + "libroctracer64.so", + "libroctracer64.so.4", + "libroctx64.so", + "libroctx64.so.4", + "libhipblaslt.so", + "libhipblaslt.so.0", + "libamdhip64.so", + "libamdhip64.so.6", + "libhiprtc.so", + "libhiprtc.so.6", + NULL, + NULL, + }; + for (int i = 0; replacements[i] != NULL; i += 2) + { + if (strcmp(filename, replacements[i]) == 0) + { + filename = replacements[i + 1]; + break; + } + } + } + return dlopen_orig(filename, flags); + } +} + +extern "C" +{ + zml::dlopen_func _zml_rocm_resolve_dlopen() + { + zml::dlopen_orig = (zml::dlopen_func)dlsym(RTLD_NEXT, "dlopen"); + return zml::rocm_dlopen; + } + + extern void *dlopen(const char *filename, int flags) __attribute__((ifunc("_zml_rocm_resolve_dlopen"))); +} diff --git a/runtimes/tpu/BUILD.bazel b/runtimes/tpu/BUILD.bazel new file mode 100644 index 0000000..6bda66e --- /dev/null +++ b/runtimes/tpu/BUILD.bazel @@ -0,0 +1,5 @@ +alias( + name = "tpu", + actual = "@libpjrt_tpu", + visibility = ["//visibility:public"], +) diff --git a/runtimes/tpu/libpjrt_tpu.BUILD.bazel b/runtimes/tpu/libpjrt_tpu.BUILD.bazel new file mode 100644 index 0000000..b4385aa --- /dev/null +++ b/runtimes/tpu/libpjrt_tpu.BUILD.bazel @@ -0,0 +1,14 @@ +load("@bazel_skylib//rules:copy_file.bzl", "copy_file") + +copy_file( + name = "libpjrt_tpu_so", + src = "libtpu/libtpu.so", + out = "libpjrt_tpu.so", + allow_symlink = True, +) + +cc_import( + name = "libpjrt_tpu", + shared_library = ":libpjrt_tpu_so", + visibility = ["@zml//runtimes/tpu:__subpackages__"], +) diff --git a/runtimes/tpu/tpu.bzl b/runtimes/tpu/tpu.bzl new file mode 100644 index 0000000..23b484b --- /dev/null +++ b/runtimes/tpu/tpu.bzl @@ -0,0 +1,20 @@ +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +def _tpu_impl(mctx): + # https://storage.googleapis.com/jax-releases/libtpu_releases.html + http_archive( + name = "libpjrt_tpu", + url = "https://storage.googleapis.com/libtpu-nightly-releases/wheels/libtpu-nightly/libtpu_nightly-0.1.dev20240915+nightly-py3-none-any.whl", + type = "zip", + sha256 = "4eee6c7dc92e7e60334c5b0261308a0a07c2f5b6235c7c60f465263576c602bf", + build_file = "libpjrt_tpu.BUILD.bazel", + ) + return mctx.extension_metadata( + reproducible = True, + root_module_direct_deps = ["libpjrt_tpu"], + root_module_direct_dev_deps = [], + ) + +tpu_packages = module_extension( + implementation = _tpu_impl, +) diff --git a/third_party/bazel_registry.json b/third_party/bazel_registry.json new file mode 100644 index 0000000..ed6904f --- /dev/null +++ b/third_party/bazel_registry.json @@ -0,0 +1,6 @@ +{ + "mirrors": [ + "https://storage.googleapis.com/mirror.tensorflow.org/" + ], + "module_base_path": "." +} diff --git a/third_party/modules/aspect_bazel_lib/2.8.1.1/MODULE.bazel b/third_party/modules/aspect_bazel_lib/2.8.1.1/MODULE.bazel new file mode 100644 index 0000000..7f1750b --- /dev/null +++ b/third_party/modules/aspect_bazel_lib/2.8.1.1/MODULE.bazel @@ -0,0 +1,78 @@ +"aspect-build/bazel-lib" + +module( + name = "aspect_bazel_lib", + version = "2.8.1.1", + bazel_compatibility = [">=6.0.0"], + compatibility_level = 1, +) + +# Lower-bounds (minimum) versions for direct runtime dependencies +bazel_dep(name = "bazel_skylib", version = "1.5.0") +bazel_dep(name = "platforms", version = "0.0.8") + +# 0.5.4 is the first version with bzlmod support +bazel_dep(name = "stardoc", version = "0.6.2", repo_name = "io_bazel_stardoc") + +bazel_lib_toolchains = use_extension("@aspect_bazel_lib//lib:extensions.bzl", "toolchains") +bazel_lib_toolchains.copy_directory() +bazel_lib_toolchains.copy_to_directory() +bazel_lib_toolchains.jq() +bazel_lib_toolchains.yq() +bazel_lib_toolchains.coreutils() +bazel_lib_toolchains.tar() +bazel_lib_toolchains.zstd() +bazel_lib_toolchains.expand_template() +bazel_lib_toolchains.bats() +use_repo(bazel_lib_toolchains, "bats_toolchains", "bsd_tar_toolchains", "copy_directory_toolchains", "copy_to_directory_toolchains", "coreutils_toolchains", "expand_template_toolchains", "jq_toolchains", "yq_toolchains", "zstd_toolchains") + +register_toolchains( + "@copy_directory_toolchains//:all", + "@copy_to_directory_toolchains//:all", + "@jq_toolchains//:all", + "@yq_toolchains//:all", + "@coreutils_toolchains//:all", + "@expand_template_toolchains//:all", + "@bats_toolchains//:all", + "@bsd_tar_toolchains//:all", + "@zstd_toolchains//:all", +) + +####### Dev dependencies ######## + +# To allow /tools to be built from source +# NOTE: when publishing to BCR, we patch this to be dev_dependency, as we publish pre-built binaries +# along with our releases. + +bazel_dep( + name = "gazelle", + version = "0.36.0", + dev_dependency = True, +) +bazel_dep( + name = "rules_go", + version = "0.46.0", + repo_name = "io_bazel_rules_go", + dev_dependency = True, +) + +go_deps = use_extension( + "@gazelle//:extensions.bzl", + "go_deps", + dev_dependency = True, +) +go_deps.from_file(go_mod = "//:go.mod") +use_repo( + go_deps, + "com_github_bmatcuk_doublestar_v4", + "org_golang_x_exp", + "org_golang_x_sys", +) + +host = use_extension("@aspect_bazel_lib//lib:extensions.bzl", "host", dev_dependency = True) +host.host() +use_repo(host, "aspect_bazel_lib_host") + +bazel_dep(name = "bazel_skylib_gazelle_plugin", version = "1.5.0", dev_dependency = True) +bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True) +bazel_dep(name = "bazel_features", version = "0.2.0", dev_dependency = True) diff --git a/third_party/modules/aspect_bazel_lib/2.8.1.1/patches/0001-fix-add-repo-mapping-to-tar-archive.patch b/third_party/modules/aspect_bazel_lib/2.8.1.1/patches/0001-fix-add-repo-mapping-to-tar-archive.patch new file mode 100644 index 0000000..96aa8df --- /dev/null +++ b/third_party/modules/aspect_bazel_lib/2.8.1.1/patches/0001-fix-add-repo-mapping-to-tar-archive.patch @@ -0,0 +1,50 @@ +From 5dbe6a2604e440b684add7b44531898acc8631b4 Mon Sep 17 00:00:00 2001 +From: Steeve Morin +Date: Sun, 8 Sep 2024 21:17:29 +0200 +Subject: [PATCH] fix: add repo mapping to tar archive + +When using bzlmod, runfiles lookup will fail without it. +--- + lib/private/tar.bzl | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/lib/private/tar.bzl b/lib/private/tar.bzl +index 733ff60..29434f6 100644 +--- a/lib/private/tar.bzl ++++ b/lib/private/tar.bzl +@@ -147,12 +147,19 @@ def _tar_impl(ctx): + args.add(ctx.file.mtree, format = "@%s") + inputs.append(ctx.file.mtree) + ++ src_runfiles = [] ++ for src in ctx.attr.srcs: ++ src_di = src[DefaultInfo] ++ if getattr(src_di.files_to_run, "repo_mapping_manifest", None) != None: ++ src_runfiles.append(depset( ++ direct = [src_di.files_to_run.repo_mapping_manifest], ++ transitive = [src_di.default_runfiles.files], ++ )) ++ else: ++ src_runfiles.append(src_di.default_runfiles.files) + ctx.actions.run( + executable = bsdtar.tarinfo.binary, +- inputs = depset(direct = inputs, transitive = [bsdtar.default.files] + [ +- src[DefaultInfo].default_runfiles.files +- for src in ctx.attr.srcs +- ]), ++ inputs = depset(direct = inputs, transitive = [bsdtar.default.files] + src_runfiles), + outputs = [out], + arguments = [args], + mnemonic = "Tar", +@@ -234,6 +241,8 @@ def _mtree_impl(ctx): + workspace_name = str(ctx.workspace_name) + + content.add(_mtree_line(runfiles_dir, type = "dir")) ++ if getattr(default_info.files_to_run, "repo_mapping_manifest", None) != None: ++ content.add(_mtree_line("{}/_repo_mapping".format(runfiles_dir), type = "file", content = default_info.files_to_run.repo_mapping_manifest.path)) + content.add_all( + s.default_runfiles.files, + expand_directories = True, +-- +2.39.3 (Apple Git-146) + diff --git a/third_party/modules/aspect_bazel_lib/2.8.1.1/patches/go_dev_dep.patch b/third_party/modules/aspect_bazel_lib/2.8.1.1/patches/go_dev_dep.patch new file mode 100644 index 0000000..ffe1c1d --- /dev/null +++ b/third_party/modules/aspect_bazel_lib/2.8.1.1/patches/go_dev_dep.patch @@ -0,0 +1,27 @@ +diff --git a/MODULE.bazel b/MODULE.bazel +index e63fa5b..9d78a88 100644 +--- a/MODULE.bazel ++++ b/MODULE.bazel +@@ -50,19 +50,19 @@ use_repo(host, "aspect_bazel_lib_host") + bazel_dep( + name = "gazelle", + version = "0.36.0", +- # In released versions: dev_dependency = True ++ dev_dependency = True, + ) + bazel_dep( + name = "rules_go", + version = "0.46.0", + repo_name = "io_bazel_rules_go", +- # In released versions: dev_dependency = True ++ dev_dependency = True, + ) + + go_deps = use_extension( + "@gazelle//:extensions.bzl", + "go_deps", +- # In released versions: dev_dependency = True ++ dev_dependency = True, + ) + go_deps.from_file(go_mod = "//:go.mod") + use_repo( diff --git a/third_party/modules/aspect_bazel_lib/2.8.1.1/patches/module_dot_bazel_version.patch b/third_party/modules/aspect_bazel_lib/2.8.1.1/patches/module_dot_bazel_version.patch new file mode 100644 index 0000000..fe11475 --- /dev/null +++ b/third_party/modules/aspect_bazel_lib/2.8.1.1/patches/module_dot_bazel_version.patch @@ -0,0 +1,14 @@ +=================================================================== +--- a/MODULE.bazel ++++ b/MODULE.bazel +@@ -1,9 +1,9 @@ + "aspect-build/bazel-lib" + + module( + name = "aspect_bazel_lib", +- version = "0.0.0", ++ version = "2.8.1", + bazel_compatibility = [">=6.0.0"], + compatibility_level = 1, + ) + diff --git a/third_party/modules/aspect_bazel_lib/2.8.1.1/source.json b/third_party/modules/aspect_bazel_lib/2.8.1.1/source.json new file mode 100644 index 0000000..3b7d500 --- /dev/null +++ b/third_party/modules/aspect_bazel_lib/2.8.1.1/source.json @@ -0,0 +1,11 @@ +{ + "integrity": "sha256-aINU7mvuunGUJD1z6wmSuaEujt7u7FtlRPS1MaMRIjc=", + "strip_prefix": "bazel-lib-2.8.1", + "url": "https://github.com/aspect-build/bazel-lib/releases/download/v2.8.1/bazel-lib-v2.8.1.tar.gz", + "patches": { + "go_dev_dep.patch": "sha256-DTc/hk+etl4D50M0BLRik2vHbrgDb6rds+Dj4xphWb4=", + "module_dot_bazel_version.patch": "sha256-cEMv6bY7Sc5dERv8YG0lq45zuZCsVPNn4oAN9aOkf40=", + "0001-fix-add-repo-mapping-to-tar-archive.patch": "" + }, + "patch_strip": 1 +} diff --git a/third_party/modules/aspect_bazel_lib/metadata.json b/third_party/modules/aspect_bazel_lib/metadata.json new file mode 100644 index 0000000..db6bde1 --- /dev/null +++ b/third_party/modules/aspect_bazel_lib/metadata.json @@ -0,0 +1,25 @@ +{ + "homepage": "https://docs.aspect.build/rules/aspect_bazel_lib", + "maintainers": [ + { + "name": "Alex Eagle", + "email": "alex@aspect.dev", + "github": "alexeagle" + }, + { + "name": "Derek Cormier", + "email": "derek@aspect.dev", + "github": "kormide" + } + ], + "repository": [ + "github:aspect-build/bazel-lib" + ], + "versions": [ + "2.8.1.1" + ], + "yanked_versions": { + "1.31.0": "1.31.0 has a breaking change to the default yq version", + "1.34.2": "The version field has a leading 'v' due to a release automation bug" + } +} diff --git a/third_party/modules/libxev/20240825.0-dbe2291/MODULE.bazel b/third_party/modules/libxev/20240825.0-dbe2291/MODULE.bazel new file mode 100644 index 0000000..8f8806c --- /dev/null +++ b/third_party/modules/libxev/20240825.0-dbe2291/MODULE.bazel @@ -0,0 +1,7 @@ +module( + name = "libxev", + version = "20240825.0-dbe2291", + compatibility_level = 1, +) + +bazel_dep(name = "rules_zig", version = "20240904.0-010da15") diff --git a/third_party/modules/libxev/20240825.0-dbe2291/overlay/BUILD.bazel b/third_party/modules/libxev/20240825.0-dbe2291/overlay/BUILD.bazel new file mode 100644 index 0000000..872ef7f --- /dev/null +++ b/third_party/modules/libxev/20240825.0-dbe2291/overlay/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_zig//zig:defs.bzl", "zig_library") + +zig_library( + name = "xev", + srcs = glob([ + "src/*.zig", + "src/backend/*.zig", + "src/linux/*.zig", + "src/watcher/*.zig", + ]), + main = "src/main.zig", + visibility = ["//visibility:public"], +) diff --git a/third_party/modules/libxev/20240825.0-dbe2291/overlay/MODULE.bazel b/third_party/modules/libxev/20240825.0-dbe2291/overlay/MODULE.bazel new file mode 100644 index 0000000..8f8806c --- /dev/null +++ b/third_party/modules/libxev/20240825.0-dbe2291/overlay/MODULE.bazel @@ -0,0 +1,7 @@ +module( + name = "libxev", + version = "20240825.0-dbe2291", + compatibility_level = 1, +) + +bazel_dep(name = "rules_zig", version = "20240904.0-010da15") diff --git a/third_party/modules/libxev/20240825.0-dbe2291/source.json b/third_party/modules/libxev/20240825.0-dbe2291/source.json new file mode 100644 index 0000000..8195028 --- /dev/null +++ b/third_party/modules/libxev/20240825.0-dbe2291/source.json @@ -0,0 +1,9 @@ +{ + "strip_prefix": "libxev-dbe22910a43e9e8ec9948d3cbd73d8488a074967", + "url": "https://github.com/mitchellh/libxev/archive/dbe22910a43e9e8ec9948d3cbd73d8488a074967.tar.gz", + "integrity": "sha256-JM70bkRUyuAQXKV1piJ6I0IClzCrXV43sdLfIKVC9Lo=", + "overlay": { + "MODULE.bazel": "", + "BUILD.bazel": "" + } +} diff --git a/third_party/modules/libxev/20240910.0-a2d9b31/MODULE.bazel b/third_party/modules/libxev/20240910.0-a2d9b31/MODULE.bazel new file mode 100644 index 0000000..99daae7 --- /dev/null +++ b/third_party/modules/libxev/20240910.0-a2d9b31/MODULE.bazel @@ -0,0 +1,7 @@ +module( + name = "libxev", + version = "20240910.0-a2d9b31", + compatibility_level = 1, +) + +bazel_dep(name = "rules_zig", version = "20240904.0-010da15") diff --git a/third_party/modules/libxev/20240910.0-a2d9b31/overlay/BUILD.bazel b/third_party/modules/libxev/20240910.0-a2d9b31/overlay/BUILD.bazel new file mode 100644 index 0000000..872ef7f --- /dev/null +++ b/third_party/modules/libxev/20240910.0-a2d9b31/overlay/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_zig//zig:defs.bzl", "zig_library") + +zig_library( + name = "xev", + srcs = glob([ + "src/*.zig", + "src/backend/*.zig", + "src/linux/*.zig", + "src/watcher/*.zig", + ]), + main = "src/main.zig", + visibility = ["//visibility:public"], +) diff --git a/third_party/modules/libxev/20240910.0-a2d9b31/overlay/MODULE.bazel b/third_party/modules/libxev/20240910.0-a2d9b31/overlay/MODULE.bazel new file mode 100644 index 0000000..99daae7 --- /dev/null +++ b/third_party/modules/libxev/20240910.0-a2d9b31/overlay/MODULE.bazel @@ -0,0 +1,7 @@ +module( + name = "libxev", + version = "20240910.0-a2d9b31", + compatibility_level = 1, +) + +bazel_dep(name = "rules_zig", version = "20240904.0-010da15") diff --git a/third_party/modules/libxev/20240910.0-a2d9b31/source.json b/third_party/modules/libxev/20240910.0-a2d9b31/source.json new file mode 100644 index 0000000..c56bc6a --- /dev/null +++ b/third_party/modules/libxev/20240910.0-a2d9b31/source.json @@ -0,0 +1,9 @@ +{ + "strip_prefix": "libxev-a2d9b3154f1e5ed463c9f2fb98a0d739057796ce", + "url": "https://github.com/zml/libxev/archive/a2d9b3154f1e5ed463c9f2fb98a0d739057796ce.tar.gz", + "integrity": "sha256-xdMjrGSB3telt52iRqHgem0WSRPjfGlTKBRyDMXLlaQ=", + "overlay": { + "MODULE.bazel": "", + "BUILD.bazel": "" + } +} diff --git a/third_party/modules/libxev/metadata.json b/third_party/modules/libxev/metadata.json new file mode 100644 index 0000000..3b334be --- /dev/null +++ b/third_party/modules/libxev/metadata.json @@ -0,0 +1,18 @@ +{ + "homepage": "https://github.com/mitchellh/libxev", + "maintainers": [ + { + "email": "bzlmod@zml.ai", + "github": "zml", + "name": "ZML Engineering Team" + } + ], + "repository": [ + "github:mitchellh/libxev" + ], + "versions": [ + "20240825.0-dbe2291", + "20240910.0-a2d9b31" + ], + "yanked_versions": {} +} diff --git a/third_party/modules/llvm-raw/20240823.0-f142f8a/MODULE.bazel b/third_party/modules/llvm-raw/20240823.0-f142f8a/MODULE.bazel new file mode 100644 index 0000000..6bf421a --- /dev/null +++ b/third_party/modules/llvm-raw/20240823.0-f142f8a/MODULE.bazel @@ -0,0 +1,10 @@ +module( + name = "llvm-raw", + version = "20240823.0-f142f8a", + compatibility_level = 1, +) + +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "platforms", version = "0.0.10") +bazel_dep(name = "zstd", version = "1.5.6", repo_name = "llvm_zstd") +bazel_dep(name = "zlib", version = "1.3.1.bcr.3", repo_name = "llvm_zlib") diff --git a/third_party/modules/llvm-raw/20240823.0-f142f8a/overlay/BUILD.bazel b/third_party/modules/llvm-raw/20240823.0-f142f8a/overlay/BUILD.bazel new file mode 100644 index 0000000..e69de29 diff --git a/third_party/modules/llvm-raw/20240823.0-f142f8a/overlay/MODULE.bazel b/third_party/modules/llvm-raw/20240823.0-f142f8a/overlay/MODULE.bazel new file mode 100644 index 0000000..6bf421a --- /dev/null +++ b/third_party/modules/llvm-raw/20240823.0-f142f8a/overlay/MODULE.bazel @@ -0,0 +1,10 @@ +module( + name = "llvm-raw", + version = "20240823.0-f142f8a", + compatibility_level = 1, +) + +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "platforms", version = "0.0.10") +bazel_dep(name = "zstd", version = "1.5.6", repo_name = "llvm_zstd") +bazel_dep(name = "zlib", version = "1.3.1.bcr.3", repo_name = "llvm_zlib") diff --git a/third_party/modules/llvm-raw/20240823.0-f142f8a/overlay/utils/bazel/extension.bzl b/third_party/modules/llvm-raw/20240823.0-f142f8a/overlay/utils/bazel/extension.bzl new file mode 100644 index 0000000..f247ed4 --- /dev/null +++ b/third_party/modules/llvm-raw/20240823.0-f142f8a/overlay/utils/bazel/extension.bzl @@ -0,0 +1,28 @@ +load("//utils/bazel:configure.bzl", _llvm_configure = "llvm_configure") + +def _llvm_impl(mctx): + _targets = {} + for mod in mctx.modules: + for conf in mod.tags.configure: + for target in conf.targets: + _targets[target] = True + _llvm_configure( + name = "llvm-project", + targets = _targets.keys(), + ) + return mctx.extension_metadata( + reproducible = True, + root_module_direct_deps = "all", + root_module_direct_dev_deps = [], + ) + +llvm = module_extension( + implementation = _llvm_impl, + tag_classes = { + "configure": tag_class( + attrs = { + "targets": attr.string_list(mandatory = True), + }, + ), + }, +) diff --git a/third_party/modules/llvm-raw/20240823.0-f142f8a/source.json b/third_party/modules/llvm-raw/20240823.0-f142f8a/source.json new file mode 100644 index 0000000..6edc73d --- /dev/null +++ b/third_party/modules/llvm-raw/20240823.0-f142f8a/source.json @@ -0,0 +1,10 @@ +{ + "strip_prefix": "llvm-project-f142f8afe21bceb00fb495468aa0b5043e98c419", + "url": "https://github.com/llvm/llvm-project/archive/f142f8afe21bceb00fb495468aa0b5043e98c419.tar.gz", + "integrity": "sha256-8ftYOnMGq99igt2I1n9SOZpYLq79+F7HiKL/7lOwcHs=", + "overlay": { + "BUILD.bazel": "", + "MODULE.bazel": "", + "utils/bazel/extension.bzl": "" + } +} diff --git a/third_party/modules/llvm-raw/metadata.json b/third_party/modules/llvm-raw/metadata.json new file mode 100644 index 0000000..e32ca27 --- /dev/null +++ b/third_party/modules/llvm-raw/metadata.json @@ -0,0 +1,17 @@ +{ + "homepage": "https://github.com/llvm/llvm-project", + "maintainers": [ + { + "email": "bzlmod@zml.ai", + "github": "zml", + "name": "ZML Engineering Team" + } + ], + "repository": [ + "github:llvm/llvm-project" + ], + "versions": [ + "20240823.0-f142f8a" + ], + "yanked_versions": {} +} diff --git a/third_party/modules/rules_zig/20240904.0-010da15/MODULE.bazel b/third_party/modules/rules_zig/20240904.0-010da15/MODULE.bazel new file mode 100644 index 0000000..723c6a9 --- /dev/null +++ b/third_party/modules/rules_zig/20240904.0-010da15/MODULE.bazel @@ -0,0 +1,68 @@ +module( + name = "rules_zig", + version = "20240904.0-010da15", + compatibility_level = 1, +) + +bazel_dep(name = "aspect_bazel_lib", version = "2.8.1") +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "platforms", version = "0.0.10") + +zig = use_extension("//zig:extensions.bzl", "zig") +zig.index(file = "//zig/private:versions.json") +use_repo(zig, "zig_toolchains") + +register_toolchains("@rules_zig//zig/target:all") + +register_toolchains("@zig_toolchains//:all") + +zig_dev = use_extension( + "//zig:extensions.bzl", + "zig", + dev_dependency = True, +) +zig_dev.toolchain(zig_version = "0.13.0") +zig_dev.toolchain(zig_version = "0.12.1") +zig_dev.toolchain(zig_version = "0.12.0") +zig_dev.toolchain(zig_version = "0.11.0") + +bazel_dep(name = "rules_cc", version = "0.0.9", dev_dependency = True) +bazel_dep(name = "stardoc", version = "0.7.0", dev_dependency = True, repo_name = "io_bazel_stardoc") +bazel_dep(name = "gazelle", version = "0.38.0", dev_dependency = True, repo_name = "bazel_gazelle") +bazel_dep(name = "bazel_skylib_gazelle_plugin", version = "1.7.1", dev_dependency = True) +bazel_dep( + name = "buildifier_prebuilt", + version = "7.3.1", + dev_dependency = True, +) +bazel_dep(name = "rules_multirun", version = "0.9.0", dev_dependency = True) +bazel_dep(name = "rules_python", version = "0.35.0", dev_dependency = True) +bazel_dep( + name = "rules_bazel_integration_test", + version = "0.25.0", + dev_dependency = True, +) + +bazel_binaries = use_extension( + "@rules_bazel_integration_test//:extensions.bzl", + "bazel_binaries", + dev_dependency = True, +) + +# NOTE: Keep in sync with WORKSPACE. +bazel_binaries.download(version_file = "//:.bazelversion") +bazel_binaries.download(version = "7.0.0") +use_repo( + bazel_binaries, + "bazel_binaries", + "bazel_binaries_bazelisk", + "build_bazel_bazel_.bazelversion", + "build_bazel_bazel_7_0_0", +) + +# TODO[AH] Should be an implicit transitive dependency through rules_bazel_integration_test. +# However, if we do not include it explicitly, then the runfiles resolution for +# cgrindel_bazel_starlib/shlib/lib/message.sh fails in +# rules_bazel_integration_test/tools/update_deleted_packages.sh when invoked +# through the rules_multirun target //util:update. +bazel_dep(name = "cgrindel_bazel_starlib", version = "0.21.0", dev_dependency = True) diff --git a/third_party/modules/rules_zig/20240904.0-010da15/source.json b/third_party/modules/rules_zig/20240904.0-010da15/source.json new file mode 100644 index 0000000..253af19 --- /dev/null +++ b/third_party/modules/rules_zig/20240904.0-010da15/source.json @@ -0,0 +1,5 @@ +{ + "type": "git_repository", + "remote": "https://github.com/zml/rules_zig.git", + "commit": "010da15abb4335479778d6b4fb2ca752a0ab80e3" +} diff --git a/third_party/modules/rules_zig/20240909.0-37f17ff/MODULE.bazel b/third_party/modules/rules_zig/20240909.0-37f17ff/MODULE.bazel new file mode 100644 index 0000000..4ded2bb --- /dev/null +++ b/third_party/modules/rules_zig/20240909.0-37f17ff/MODULE.bazel @@ -0,0 +1,68 @@ +module( + name = "rules_zig", + version = "20240909.0-37f17ff", + compatibility_level = 1, +) + +bazel_dep(name = "aspect_bazel_lib", version = "2.8.1") +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "platforms", version = "0.0.10") + +zig = use_extension("//zig:extensions.bzl", "zig") +zig.index(file = "//zig/private:versions.json") +use_repo(zig, "zig_toolchains") + +register_toolchains("@rules_zig//zig/target:all") + +register_toolchains("@zig_toolchains//:all") + +zig_dev = use_extension( + "//zig:extensions.bzl", + "zig", + dev_dependency = True, +) +zig_dev.toolchain(zig_version = "0.13.0") +zig_dev.toolchain(zig_version = "0.12.1") +zig_dev.toolchain(zig_version = "0.12.0") +zig_dev.toolchain(zig_version = "0.11.0") + +bazel_dep(name = "rules_cc", version = "0.0.9", dev_dependency = True) +bazel_dep(name = "stardoc", version = "0.7.0", dev_dependency = True, repo_name = "io_bazel_stardoc") +bazel_dep(name = "gazelle", version = "0.38.0", dev_dependency = True, repo_name = "bazel_gazelle") +bazel_dep(name = "bazel_skylib_gazelle_plugin", version = "1.7.1", dev_dependency = True) +bazel_dep( + name = "buildifier_prebuilt", + version = "7.3.1", + dev_dependency = True, +) +bazel_dep(name = "rules_multirun", version = "0.9.0", dev_dependency = True) +bazel_dep(name = "rules_python", version = "0.35.0", dev_dependency = True) +bazel_dep( + name = "rules_bazel_integration_test", + version = "0.25.0", + dev_dependency = True, +) + +bazel_binaries = use_extension( + "@rules_bazel_integration_test//:extensions.bzl", + "bazel_binaries", + dev_dependency = True, +) + +# NOTE: Keep in sync with WORKSPACE. +bazel_binaries.download(version_file = "//:.bazelversion") +bazel_binaries.download(version = "7.0.0") +use_repo( + bazel_binaries, + "bazel_binaries", + "bazel_binaries_bazelisk", + "build_bazel_bazel_.bazelversion", + "build_bazel_bazel_7_0_0", +) + +# TODO[AH] Should be an implicit transitive dependency through rules_bazel_integration_test. +# However, if we do not include it explicitly, then the runfiles resolution for +# cgrindel_bazel_starlib/shlib/lib/message.sh fails in +# rules_bazel_integration_test/tools/update_deleted_packages.sh when invoked +# through the rules_multirun target //util:update. +bazel_dep(name = "cgrindel_bazel_starlib", version = "0.21.0", dev_dependency = True) diff --git a/third_party/modules/rules_zig/20240909.0-37f17ff/source.json b/third_party/modules/rules_zig/20240909.0-37f17ff/source.json new file mode 100644 index 0000000..19d05ae --- /dev/null +++ b/third_party/modules/rules_zig/20240909.0-37f17ff/source.json @@ -0,0 +1,5 @@ +{ + "type": "git_repository", + "remote": "https://github.com/zml/rules_zig.git", + "commit": "37f17ffd2f6d04fc4bf9b583f9a1b117856a88d1" +} diff --git a/third_party/modules/rules_zig/20240912.0-41bfe84/MODULE.bazel b/third_party/modules/rules_zig/20240912.0-41bfe84/MODULE.bazel new file mode 100644 index 0000000..e288be5 --- /dev/null +++ b/third_party/modules/rules_zig/20240912.0-41bfe84/MODULE.bazel @@ -0,0 +1,68 @@ +module( + name = "rules_zig", + version = "20240912.0-41bfe84", + compatibility_level = 1, +) + +bazel_dep(name = "aspect_bazel_lib", version = "2.8.1") +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "platforms", version = "0.0.10") + +zig = use_extension("//zig:extensions.bzl", "zig") +zig.index(file = "//zig/private:versions.json") +use_repo(zig, "zig_toolchains") + +register_toolchains("@rules_zig//zig/target:all") + +register_toolchains("@zig_toolchains//:all") + +zig_dev = use_extension( + "//zig:extensions.bzl", + "zig", + dev_dependency = True, +) +zig_dev.toolchain(zig_version = "0.13.0") +zig_dev.toolchain(zig_version = "0.12.1") +zig_dev.toolchain(zig_version = "0.12.0") +zig_dev.toolchain(zig_version = "0.11.0") + +bazel_dep(name = "rules_cc", version = "0.0.9") +bazel_dep(name = "stardoc", version = "0.7.0", dev_dependency = True, repo_name = "io_bazel_stardoc") +bazel_dep(name = "gazelle", version = "0.38.0", dev_dependency = True, repo_name = "bazel_gazelle") +bazel_dep(name = "bazel_skylib_gazelle_plugin", version = "1.7.1", dev_dependency = True) +bazel_dep( + name = "buildifier_prebuilt", + version = "7.3.1", + dev_dependency = True, +) +bazel_dep(name = "rules_multirun", version = "0.9.0", dev_dependency = True) +bazel_dep(name = "rules_python", version = "0.35.0", dev_dependency = True) +bazel_dep( + name = "rules_bazel_integration_test", + version = "0.25.0", + dev_dependency = True, +) + +bazel_binaries = use_extension( + "@rules_bazel_integration_test//:extensions.bzl", + "bazel_binaries", + dev_dependency = True, +) + +# NOTE: Keep in sync with WORKSPACE. +bazel_binaries.download(version_file = "//:.bazelversion") +bazel_binaries.download(version = "7.0.0") +use_repo( + bazel_binaries, + "bazel_binaries", + "bazel_binaries_bazelisk", + "build_bazel_bazel_.bazelversion", + "build_bazel_bazel_7_0_0", +) + +# TODO[AH] Should be an implicit transitive dependency through rules_bazel_integration_test. +# However, if we do not include it explicitly, then the runfiles resolution for +# cgrindel_bazel_starlib/shlib/lib/message.sh fails in +# rules_bazel_integration_test/tools/update_deleted_packages.sh when invoked +# through the rules_multirun target //util:update. +bazel_dep(name = "cgrindel_bazel_starlib", version = "0.21.0", dev_dependency = True) diff --git a/third_party/modules/rules_zig/20240912.0-41bfe84/source.json b/third_party/modules/rules_zig/20240912.0-41bfe84/source.json new file mode 100644 index 0000000..3d576fb --- /dev/null +++ b/third_party/modules/rules_zig/20240912.0-41bfe84/source.json @@ -0,0 +1,5 @@ +{ + "type": "git_repository", + "remote": "https://github.com/zml/rules_zig.git", + "commit": "41bfe84e4d9a43cbe55281dddc80b683cc6fc6eb" +} diff --git a/third_party/modules/rules_zig/20240913.0-1957d05/MODULE.bazel b/third_party/modules/rules_zig/20240913.0-1957d05/MODULE.bazel new file mode 100644 index 0000000..f2ff768 --- /dev/null +++ b/third_party/modules/rules_zig/20240913.0-1957d05/MODULE.bazel @@ -0,0 +1,68 @@ +module( + name = "rules_zig", + version = "20240913.0-1957d05", + compatibility_level = 1, +) + +bazel_dep(name = "aspect_bazel_lib", version = "2.8.1") +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "platforms", version = "0.0.10") + +zig = use_extension("//zig:extensions.bzl", "zig") +zig.index(file = "//zig/private:versions.json") +use_repo(zig, "zig_toolchains") + +register_toolchains("@rules_zig//zig/target:all") + +register_toolchains("@zig_toolchains//:all") + +zig_dev = use_extension( + "//zig:extensions.bzl", + "zig", + dev_dependency = True, +) +zig_dev.toolchain(zig_version = "0.13.0") +zig_dev.toolchain(zig_version = "0.12.1") +zig_dev.toolchain(zig_version = "0.12.0") +zig_dev.toolchain(zig_version = "0.11.0") + +bazel_dep(name = "rules_cc", version = "0.0.9") +bazel_dep(name = "stardoc", version = "0.7.0", dev_dependency = True, repo_name = "io_bazel_stardoc") +bazel_dep(name = "gazelle", version = "0.38.0", dev_dependency = True, repo_name = "bazel_gazelle") +bazel_dep(name = "bazel_skylib_gazelle_plugin", version = "1.7.1", dev_dependency = True) +bazel_dep( + name = "buildifier_prebuilt", + version = "7.3.1", + dev_dependency = True, +) +bazel_dep(name = "rules_multirun", version = "0.9.0", dev_dependency = True) +bazel_dep(name = "rules_python", version = "0.35.0", dev_dependency = True) +bazel_dep( + name = "rules_bazel_integration_test", + version = "0.25.0", + dev_dependency = True, +) + +bazel_binaries = use_extension( + "@rules_bazel_integration_test//:extensions.bzl", + "bazel_binaries", + dev_dependency = True, +) + +# NOTE: Keep in sync with WORKSPACE. +bazel_binaries.download(version_file = "//:.bazelversion") +bazel_binaries.download(version = "7.0.0") +use_repo( + bazel_binaries, + "bazel_binaries", + "bazel_binaries_bazelisk", + "build_bazel_bazel_.bazelversion", + "build_bazel_bazel_7_0_0", +) + +# TODO[AH] Should be an implicit transitive dependency through rules_bazel_integration_test. +# However, if we do not include it explicitly, then the runfiles resolution for +# cgrindel_bazel_starlib/shlib/lib/message.sh fails in +# rules_bazel_integration_test/tools/update_deleted_packages.sh when invoked +# through the rules_multirun target //util:update. +bazel_dep(name = "cgrindel_bazel_starlib", version = "0.21.0", dev_dependency = True) diff --git a/third_party/modules/rules_zig/20240913.0-1957d05/source.json b/third_party/modules/rules_zig/20240913.0-1957d05/source.json new file mode 100644 index 0000000..9da3ae3 --- /dev/null +++ b/third_party/modules/rules_zig/20240913.0-1957d05/source.json @@ -0,0 +1,5 @@ +{ + "type": "git_repository", + "remote": "https://github.com/zml/rules_zig.git", + "commit": "1957d0572193fb859e721a0fab8bd8f0fb57f3ff" +} diff --git a/third_party/modules/rules_zig/metadata.json b/third_party/modules/rules_zig/metadata.json new file mode 100644 index 0000000..c6a894f --- /dev/null +++ b/third_party/modules/rules_zig/metadata.json @@ -0,0 +1,20 @@ +{ + "homepage": "https://github.com/zml/rules_zig", + "maintainers": [ + { + "email": "bzlmod@zml.ai", + "github": "zml", + "name": "ZML Engineering Team" + } + ], + "repository": [ + "github:zml/rules_zig" + ], + "versions": [ + "20240904.0-010da15", + "20240909.0-37f17ff", + "20240912.0-41bfe84", + "20240913.0-1957d05" + ], + "yanked_versions": {} +} diff --git a/third_party/modules/sentencepiece/20240618.0-d7ace0a/MODULE.bazel b/third_party/modules/sentencepiece/20240618.0-d7ace0a/MODULE.bazel new file mode 100644 index 0000000..af94d93 --- /dev/null +++ b/third_party/modules/sentencepiece/20240618.0-d7ace0a/MODULE.bazel @@ -0,0 +1,7 @@ +module( + name = "sentencepiece", + version = "20240618.0-d7ace0a", + compatibility_level = 1, +) + +bazel_dep(name = "rules_proto", version = "6.0.0-rc1") diff --git a/third_party/modules/sentencepiece/20240618.0-d7ace0a/overlay/BUILD.bazel b/third_party/modules/sentencepiece/20240618.0-d7ace0a/overlay/BUILD.bazel new file mode 100644 index 0000000..43639e8 --- /dev/null +++ b/third_party/modules/sentencepiece/20240618.0-d7ace0a/overlay/BUILD.bazel @@ -0,0 +1,7 @@ +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "sentencepiece_model_proto", + srcs = ["src/sentencepiece_model.proto"], + visibility = ["//visibility:public"], +) diff --git a/third_party/modules/sentencepiece/20240618.0-d7ace0a/overlay/MODULE.bazel b/third_party/modules/sentencepiece/20240618.0-d7ace0a/overlay/MODULE.bazel new file mode 100644 index 0000000..af94d93 --- /dev/null +++ b/third_party/modules/sentencepiece/20240618.0-d7ace0a/overlay/MODULE.bazel @@ -0,0 +1,7 @@ +module( + name = "sentencepiece", + version = "20240618.0-d7ace0a", + compatibility_level = 1, +) + +bazel_dep(name = "rules_proto", version = "6.0.0-rc1") diff --git a/third_party/modules/sentencepiece/20240618.0-d7ace0a/source.json b/third_party/modules/sentencepiece/20240618.0-d7ace0a/source.json new file mode 100644 index 0000000..588c9bc --- /dev/null +++ b/third_party/modules/sentencepiece/20240618.0-d7ace0a/source.json @@ -0,0 +1,9 @@ +{ + "strip_prefix": "sentencepiece-d7ace0a4df17af17d73dc8fe6ff92cfd8d08e2b8", + "url": "https://github.com/google/sentencepiece/archive/d7ace0a4df17af17d73dc8fe6ff92cfd8d08e2b8.tar.gz", + "integrity": "sha256-bt8QFNNIpqcJoCNMUrmWfUf0uNobtk8pW+XbHL+ZRLg=", + "overlay": { + "MODULE.bazel": "", + "BUILD.bazel": "" + } +} diff --git a/third_party/modules/sentencepiece/metadata.json b/third_party/modules/sentencepiece/metadata.json new file mode 100644 index 0000000..2c9758c --- /dev/null +++ b/third_party/modules/sentencepiece/metadata.json @@ -0,0 +1,17 @@ +{ + "homepage": "https://github.com/google/sentencepiece", + "maintainers": [ + { + "email": "bzlmod@zml.ai", + "github": "zml", + "name": "ZML Engineering Team" + } + ], + "repository": [ + "google/sentencepiece" + ], + "versions": [ + "20240618.0-d7ace0a" + ], + "yanked_versions": {} +} diff --git a/third_party/modules/stablehlo/20240829.0-54aa1a5/MODULE.bazel b/third_party/modules/stablehlo/20240829.0-54aa1a5/MODULE.bazel new file mode 100644 index 0000000..14386c0 --- /dev/null +++ b/third_party/modules/stablehlo/20240829.0-54aa1a5/MODULE.bazel @@ -0,0 +1,15 @@ +module( + name = "stablehlo", + version = "20240829.0-54aa1a5", + compatibility_level = 1, +) + +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "rules_cc", version = "0.0.9") +bazel_dep(name = "llvm-raw", version = "20240823.0-f142f8a") + +llvm = use_extension("@llvm-raw//utils/bazel:extension.bzl", "llvm") +llvm.configure( + targets = ["AArch64", "X86", "NVPTX"], +) +use_repo(llvm, "llvm-project") diff --git a/third_party/modules/stablehlo/20240829.0-54aa1a5/overlay/MODULE.bazel b/third_party/modules/stablehlo/20240829.0-54aa1a5/overlay/MODULE.bazel new file mode 100644 index 0000000..14386c0 --- /dev/null +++ b/third_party/modules/stablehlo/20240829.0-54aa1a5/overlay/MODULE.bazel @@ -0,0 +1,15 @@ +module( + name = "stablehlo", + version = "20240829.0-54aa1a5", + compatibility_level = 1, +) + +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "rules_cc", version = "0.0.9") +bazel_dep(name = "llvm-raw", version = "20240823.0-f142f8a") + +llvm = use_extension("@llvm-raw//utils/bazel:extension.bzl", "llvm") +llvm.configure( + targets = ["AArch64", "X86", "NVPTX"], +) +use_repo(llvm, "llvm-project") diff --git a/third_party/modules/stablehlo/20240829.0-54aa1a5/patches/0001-Remove-duplicated-symbols-in-StablehloApi.h.patch b/third_party/modules/stablehlo/20240829.0-54aa1a5/patches/0001-Remove-duplicated-symbols-in-StablehloApi.h.patch new file mode 100644 index 0000000..82ca0c4 --- /dev/null +++ b/third_party/modules/stablehlo/20240829.0-54aa1a5/patches/0001-Remove-duplicated-symbols-in-StablehloApi.h.patch @@ -0,0 +1,83 @@ +From f11d9bd7639f63cba681caa39cea27af114a4a71 Mon Sep 17 00:00:00 2001 +From: Steeve Morin +Date: Mon, 2 Sep 2024 23:02:28 +0200 +Subject: [PATCH 1/2] Remove duplicated symbols in StablehloApi.h + +This causes C compilers to choke. + +Refs #2494 +--- + stablehlo/integrations/c/StablehloApi.cpp | 2 +- + stablehlo/integrations/c/StablehloApi.h | 15 +-------------- + stablehlo/integrations/python/StablehloApi.cpp | 2 +- + 3 files changed, 3 insertions(+), 16 deletions(-) + +diff --git a/stablehlo/integrations/c/StablehloApi.cpp b/stablehlo/integrations/c/StablehloApi.cpp +index 8d922198..9b41ff21 100644 +--- a/stablehlo/integrations/c/StablehloApi.cpp ++++ b/stablehlo/integrations/c/StablehloApi.cpp +@@ -98,7 +98,7 @@ MlirLogicalResult stablehloSerializePortableArtifact( + return mlirLogicalResultSuccess(); + } + +-MlirLogicalResult stablehloDeserializePortableArtifact( ++MlirLogicalResult stablehloDeserializePortableArtifactToBytecode( + MlirStringRef artifactStr, MlirStringCallback callback, void *userData) { + mlir::detail::CallbackOstream stream(callback, userData); + if (failed(mlir::stablehlo::deserializePortableArtifact(unwrap(artifactStr), +diff --git a/stablehlo/integrations/c/StablehloApi.h b/stablehlo/integrations/c/StablehloApi.h +index 4c542508..f94dca8d 100644 +--- a/stablehlo/integrations/c/StablehloApi.h ++++ b/stablehlo/integrations/c/StablehloApi.h +@@ -76,16 +76,6 @@ MLIR_CAPI_EXPORTED MlirLogicalResult stablehloSerializePortableArtifact( + MlirStringRef moduleStr, MlirStringRef targetVersion, + MlirStringCallback callback, void* userData); + +-// Write a StableHLO program expressed as a string (either prettyprinted MLIR +-// module or MLIR bytecode) to a portable artifact. +-// Can fail if `moduleStr` cannot be parsed, or if it cannot be expressed in the +-// `targetVersion` version of StableHLO, e.g. if it's using new or removed +-// features, or if it involves unsupported dialects. +-// Returns false on failure. +-MLIR_CAPI_EXPORTED MlirLogicalResult stablehloSerializePortableArtifact( +- MlirModule moduleStr, MlirStringRef targetVersion, +- MlirStringCallback callback, void* userData); +- + // Read a StableHLO program from a portable artifact, returning the module as + // MLIR bytecode. Note, this bytecode returned is not a portable artifact, + // and has the stability of returning textual assembly format. Bytecode is +@@ -93,7 +83,7 @@ MLIR_CAPI_EXPORTED MlirLogicalResult stablehloSerializePortableArtifact( + // Can fail if `artifactStr` cannot be expressed in the current version of + // StableHLO, e.g. if it's using incompatible features. + // Returns false on failure. +-MLIR_CAPI_EXPORTED MlirLogicalResult stablehloDeserializePortableArtifact( ++MLIR_CAPI_EXPORTED MlirLogicalResult stablehloDeserializePortableArtifactAsBytecode( + MlirStringRef artifactStr, MlirStringCallback callback, void* userData); + + // Read a StableHLO program from a portable artifact, returning the module as +@@ -109,9 +99,6 @@ MLIR_CAPI_EXPORTED MlirModule stablehloDeserializePortableArtifact( + + // Call the Interpreter, returns MlirArrayAttr of dense element + // MlirAttribute results +-MLIR_CAPI_EXPORTED MlirModule stablehloDeserializePortableArtifact( +- MlirStringRef artifactStr, MlirContext ctx); +- + // Entrypoint for calling the StableHLO reference interpreter. + // Returns an array attribute of dense element attributes for results. + // Sets error code to non-zero on failure. +diff --git a/stablehlo/integrations/python/StablehloApi.cpp b/stablehlo/integrations/python/StablehloApi.cpp +index 46a640e1..4229ef76 100644 +--- a/stablehlo/integrations/python/StablehloApi.cpp ++++ b/stablehlo/integrations/python/StablehloApi.cpp +@@ -213,7 +213,7 @@ void AddPortableApi(py::module &m) { + "deserialize_portable_artifact_str", + [](std::string_view artifact) -> py::bytes { + StringWriterHelper accumulator; +- if (mlirLogicalResultIsFailure(stablehloDeserializePortableArtifact( ++ if (mlirLogicalResultIsFailure(stablehloDeserializePortableArtifactToBytecode( + toMlirStringRef(artifact), accumulator.getMlirStringCallback(), + accumulator.getUserData()))) { + PyErr_SetString(PyExc_ValueError, "failed to deserialize module"); +-- +2.39.3 (Apple Git-146) + diff --git a/third_party/modules/stablehlo/20240829.0-54aa1a5/patches/temporary.patch b/third_party/modules/stablehlo/20240829.0-54aa1a5/patches/temporary.patch new file mode 100644 index 0000000..5240a14 --- /dev/null +++ b/third_party/modules/stablehlo/20240829.0-54aa1a5/patches/temporary.patch @@ -0,0 +1,401 @@ +diff --ruN a/stablehlo/BUILD.bazel b/stablehlo/BUILD.bazel +--- stablehlo/BUILD.bazel ++++ stablehlo/BUILD.bazel +@@ -340,6 +340,21 @@ + ], + ) + ++gentbl_cc_library( ++ name = "stablehlo_create_compatibility_expander_inc_gen", ++ tbl_outs = [ ++ ( ++ ["--gen-rewriters"], ++ "stablehlo/transforms/StablehloCreateCompatibilityExpanderPatterns.h.inc", ++ ), ++ ], ++ tblgen = "@llvm-project//mlir:mlir-tblgen", ++ td_file = "stablehlo/transforms/StablehloCreateCompatibilityExpanderPatterns.td", ++ deps = [ ++ ":stablehlo_ops_td_files", ++ ], ++) ++ + cc_library( + name = "interpreter_ops", + srcs = [ +@@ -1086,6 +1101,7 @@ + "stablehlo/transforms/StablehloAggressiveSimplification.cpp", + "stablehlo/transforms/StablehloCanonicalizeDynamism.cpp", + "stablehlo/transforms/StablehloConvertToSignless.cpp", ++ "stablehlo/transforms/StablehloCreateCompatibilityExpander.cpp", + "stablehlo/transforms/StablehloLegalizeCompositeToCall.cpp", + "stablehlo/transforms/StablehloLegalizeDeprecatedOps.cpp", + "stablehlo/transforms/StablehloLegalizeQDQToQuantizedOp.cpp", +@@ -1109,6 +1125,7 @@ + ":chlo_ops", + ":chlo_rewriters_inc_gen", + ":linalg_passes", ++ ":stablehlo_create_compatibility_expander_inc_gen", + ":stablehlo_legalize_deprecated_ops_inc_gen", + ":stablehlo_ops", + ":stablehlo_ops_inc_gen", +diff --ruN a/stablehlo/stablehlo/dialect/Version.cpp b/stablehlo/stablehlo/dialect/Version.cpp +--- stablehlo/stablehlo/dialect/Version.cpp ++++ stablehlo/stablehlo/dialect/Version.cpp +@@ -82,7 +82,7 @@ + case CompatibilityRequirement::WEEK_4: + return Version(1, 3, 0); // v1.3.0 - Jul 15, 2024 + case CompatibilityRequirement::WEEK_12: +- return Version(1, 0, 0); // v1.0.0 - May 14, 2024 ++ return Version(1, 1, 0); // v1.1.0 - May 30, 2024 + case CompatibilityRequirement::MAX: + return Version::getMinimumVersion(); + } +diff --ruN a/stablehlo/stablehlo/tests/transforms/stablehlo_create_compatibility_expander.mlir b/stablehlo/stablehlo/tests/transforms/stablehlo_create_compatibility_expander.mlir +--- stablehlo/stablehlo/tests/transforms/stablehlo_create_compatibility_expander.mlir ++++ stablehlo/stablehlo/tests/transforms/stablehlo_create_compatibility_expander.mlir +@@ -0,0 +1,43 @@ ++// RUN: stablehlo-opt %s -verify-diagnostics -split-input-file -allow-unregistered-dialect --stablehlo-create-compatibility-expander='target=1.0.0' | FileCheck %s --check-prefixes=CHECK ++// RUN: stablehlo-opt %s -verify-diagnostics -split-input-file --stablehlo-create-compatibility-expander='target=1.6.0' | FileCheck %s --check-prefixes=CHECK-NO-DOWNGRADE ++ ++// ----- ++ ++// CHECK-LABEL @tan_op_non_complex ++// CHECK: %[[sine0:.*]] = stablehlo.sine %arg0 : tensor<4xf64> ++// CHECK-NEXT: %[[cosine1:.*]] = stablehlo.cosine %arg0 : tensor<4xf64> ++// CHECK-NEXT: %[[div2:.*]] = stablehlo.divide %[[sine0]], %[[cosine1]] : tensor<4xf64> ++// CHECK-NEXT: return %[[div2]] : tensor<4xf64> ++func.func @tan_op_non_complex(%arg0: tensor<4xf64>) -> tensor<4xf64> { ++ // CHECK-NO-DOWNGRADE: stablehlo.tan %arg0 : tensor<4xf64> ++ %1 = stablehlo.tan %arg0 : tensor<4xf64> ++ func.return %1 : tensor<4xf64> ++} ++ ++// ----- ++ ++// CHECK-LABEL: @tan_op_complex ++// CHECK: %[[cst:.*]] = stablehlo.constant dense<1.000000e+00> : tensor<4xf64> ++// CHECK: %[[complex:.*]] = stablehlo.complex %arg0, %arg1 : tensor<4xcomplex> ++// CHECK: %[[real:.*]] = stablehlo.real %[[complex]] : (tensor<4xcomplex>) -> tensor<4xf64> ++// CHECK: %[[sine:.*]] = stablehlo.sine %[[real]] : tensor<4xf64> ++// CHECK: %[[cosine:.*]] = stablehlo.cosine %[[real]] : tensor<4xf64> ++// CHECK: %[[divide1:.*]] = stablehlo.divide %[[sine]], %[[cosine]] : tensor<4xf64> ++// CHECK: %[[imag:.*]] = stablehlo.imag %[[complex]] : (tensor<4xcomplex>) -> tensor<4xf64> ++// CHECK: %[[tanh:.*]] = stablehlo.tanh %[[imag]] : tensor<4xf64> ++// CHECK: %[[complex2:.*]] = stablehlo.complex %[[divide1]], %[[tanh]] : tensor<4xcomplex> ++// CHECK: %[[multiply:.*]] = stablehlo.multiply %[[divide1]], %[[tanh]] : tensor<4xf64> ++// CHECK: %[[negate:.*]] = stablehlo.negate %[[multiply]] : tensor<4xf64> ++// CHECK: %[[complex3:.*]] = stablehlo.complex %[[cst]], %[[negate]] : tensor<4xcomplex> ++// CHECK: %[[divide2:.*]] = stablehlo.divide %[[complex2]], %[[complex3]] : tensor<4xcomplex> ++// CHECK: %[[real2:.*]] = stablehlo.real %[[divide2]] : (tensor<4xcomplex>) -> tensor<4xf64> ++// CHECK: %[[imag2:.*]] = stablehlo.imag %[[divide2]] : (tensor<4xcomplex>) -> tensor<4xf64> ++// CHECK: return %[[real2]], %[[imag2]] : tensor<4xf64>, tensor<4xf64> ++func.func @tan_op_complex(%arg0: tensor<4xf64>, %arg1: tensor<4xf64>) -> (tensor<4xf64>, tensor<4xf64>) { ++ %0 = stablehlo.complex %arg0, %arg1 : tensor<4xcomplex> ++ // CHECK-NO-DOWNGRADE: stablehlo.tan %0 : tensor<4xcomplex> ++ %1 = stablehlo.tan %0 : tensor<4xcomplex> ++ %2 = stablehlo.real %1 : (tensor<4xcomplex>) -> tensor<4xf64> ++ %3 = stablehlo.imag %1 : (tensor<4xcomplex>) -> tensor<4xf64> ++ func.return %2, %3 : tensor<4xf64>, tensor<4xf64> ++} +diff --ruN a/stablehlo/stablehlo/transforms/CMakeLists.txt b/stablehlo/stablehlo/transforms/CMakeLists.txt +--- stablehlo/stablehlo/transforms/CMakeLists.txt ++++ stablehlo/stablehlo/transforms/CMakeLists.txt +@@ -20,6 +20,10 @@ + mlir_tablegen(ChloDecompositionPatterns.h.inc --gen-rewriters) + add_public_tablegen_target(ChloDecompositionPatternsIncGen) + ++set(LLVM_TARGET_DEFINITIONS StablehloCreateCompatibilityExpanderPatterns.td) ++mlir_tablegen(StablehloCreateCompatibilityExpanderPatterns.h.inc --gen-rewriters) ++add_public_tablegen_target(StablehloCreateCompatibilityExpanderPatternsIncGen) ++ + set(LLVM_TARGET_DEFINITIONS StablehloLegalizeDeprecatedOpsPatterns.td) + mlir_tablegen(StablehloLegalizeDeprecatedOpsPatterns.h.inc --gen-rewriters) + add_public_tablegen_target(StablehloLegalizeDeprecatedOpsPatternsIncGen) +@@ -27,6 +31,7 @@ + set(LLVM_TARGET_DEFINITIONS VhloToVersionPatterns.td) + mlir_tablegen(VhloToVersionPatterns.h.inc --gen-rewriters) + add_public_tablegen_target(VhloToVersionPatterns) ++ + + add_mlir_dialect_library(StablehloPasses + PARTIAL_SOURCES_INTENDED +@@ -37,6 +42,7 @@ + StablehloAggressiveSimplification.cpp + StablehloCanonicalizeDynamism.cpp + StablehloConvertToSignless.cpp ++ StablehloCreateCompatibilityExpander.cpp + StablehloLegalizeCompositeToCall.cpp + StablehloLegalizeDeprecatedOps.cpp + StablehloLegalizeQuantToMath.cpp +@@ -53,6 +59,7 @@ + StablehloLegalizeDeprecatedOpsPatternsIncGen + PassesIncGen + VhloToVersionPatterns ++ StablehloCreateCompatibilityExpanderPatternsIncGen + + LINK_LIBS PUBLIC + ChloOps +diff --ruN a/stablehlo/stablehlo/transforms/Passes.h b/stablehlo/stablehlo/transforms/Passes.h +--- stablehlo/stablehlo/transforms/Passes.h ++++ stablehlo/stablehlo/transforms/Passes.h +@@ -25,6 +25,7 @@ + #include "mlir/Pass/Pass.h" + #include "mlir/Support/LogicalResult.h" + #include "mlir/Transforms/DialectConversion.h" ++#include "stablehlo/dialect/Version.h" + + namespace mlir { + namespace stablehlo { +@@ -96,6 +97,12 @@ + void populateShapeToStablehloPatterns(MLIRContext *context, + RewritePatternSet *patterns); + ++/// Collection of patterns to create compatibility expander for StableHLO ++/// operations. ++void populateStablehloCreateCompatibilityExpanderPatterns( ++ RewritePatternSet *patterns, MLIRContext *context, ++ vhlo::Version targetVersion); ++ + //// Additional pass constructors //// + + std::unique_ptr> createStablehloRefineArgumentsPass( +diff --ruN a/stablehlo/stablehlo/transforms/Passes.td b/stablehlo/stablehlo/transforms/Passes.td +--- stablehlo/stablehlo/transforms/Passes.td ++++ stablehlo/stablehlo/transforms/Passes.td +@@ -292,3 +292,51 @@ + "mlir::stablehlo::StablehloDialect", + ]; + } ++ ++def StablehloCreateCompatibilityExpanderPass : Pass<"stablehlo-create-compatibility-expander", "mlir::func::FuncOp"> { ++ let summary = "Create compatibility expander for StableHLO operations."; ++ ++ let description = [{ ++ StableHLO ops gets updates or new op is introduced in the latest versions. ++ This opt-in pass expands backward compatibility with older StableHLO ++ versions by decomposing newer StableHLO operations into equivalent ++ operations supported by those older versions. ++ ++ Why is this an opt-in pass? ++ ++ Occasionally, StableHLO op enhancements are used to greatly simplify the ++ handling of certain common patterns in the OpenXLA ecosystem. This ++ includes things like TanOp, which has high framework and compiler support, ++ as well as gather/scatter batching dimensions, which can be represented ++ using slices, but makes sharding much more difficult. For this category of ++ new features, we do not offer automatic downgrade, since it may throw away ++ important information used in subsequent optimizations. This pass can be ++ used to expand these ops based on a target version to maximize compatibility ++ at the expense of potentially less optimal compilation. ++ ++ ```mlir ++ func.func @tan_op_non_complex(%arg0: tensor<4xf64>) -> tensor<4xf64> { ++ %1 = stablehlo.tan %arg0 : tensor<4xf64> ++ func.return %1 : tensor<4xf64> ++ } ++ ``` ++ ++ will become: ++ ++ ```mlir ++ func.func @tan_op_non_complex(%arg0: tensor<4xf64>) -> tensor<4xf64> { ++ %0 = stablehlo.sine %arg0 : tensor<4xf64> ++ %1 = stablehlo.cosine %arg0 : tensor<4xf64> ++ %2 = stablehlo.divide %0, %1 : tensor<4xf64> ++ return %2 : tensor<4xf64> ++ } ++ ``` ++ }]; ++ let options = [ ++ Option<"targetVersionOption", "target", "std::string", "", ++ "The target version. Must be a version of the form #.#.#.">, ++ ]; ++ let dependentDialects = [ ++ "mlir::stablehlo::StablehloDialect", ++ ]; ++} +diff --ruN a/stablehlo/stablehlo/transforms/StablehloCreateCompatibilityExpander.cpp b/stablehlo/stablehlo/transforms/StablehloCreateCompatibilityExpander.cpp +--- stablehlo/stablehlo/transforms/StablehloCreateCompatibilityExpander.cpp ++++ stablehlo/stablehlo/transforms/StablehloCreateCompatibilityExpander.cpp +@@ -0,0 +1,128 @@ ++/* Copyright 2024 The StableHLO Authors. All Rights Reserved. ++Licensed under the Apache License, Version 2.0 (the "License"); ++you may not use this file except in compliance with the License. ++You may obtain a copy of the License at ++ http://www.apache.org/licenses/LICENSE-2.0 ++Unless required by applicable law or agreed to in writing, software ++distributed under the License is distributed on an "AS IS" BASIS, ++WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++See the License for the specific language governing permissions and ++limitations under the License. ++==============================================================================*/ ++ ++#include ++ ++#include ++ ++#include "llvm/ADT/APFloat.h" ++#include "llvm/Support/ErrorHandling.h" ++#include "mlir/Dialect/Func/IR/FuncOps.h" ++#include "mlir/IR/BuiltinAttributes.h" ++#include "mlir/IR/PatternMatch.h" ++#include "mlir/Support/LLVM.h" ++#include "mlir/Transforms/DialectConversion.h" ++#include "mlir/Transforms/GreedyPatternRewriteDriver.h" ++#include "stablehlo/dialect/StablehloOps.h" ++#include "stablehlo/dialect/Version.h" ++#include "stablehlo/transforms/Passes.h" ++ ++namespace mlir { ++namespace stablehlo { ++#define GEN_PASS_DEF_STABLEHLOCREATECOMPATIBILITYEXPANDERPASS ++#include "stablehlo/transforms/Passes.h.inc" ++ ++namespace { ++ ++//===----------------------------------------------------------------------===// ++// Helpers. ++//===----------------------------------------------------------------------===// ++ ++// Creates a constant with all ones. ++static Value createConstantWithAllOnes(OpBuilder &b, Location loc, Value val) { ++ auto shapedTy = dyn_cast(val.getType()); ++ if (!shapedTy) llvm_unreachable("Unsupported shaped type."); ++ ++ mlir::DenseElementsAttr elementsAttr = ++ mlir::DenseElementsAttr::get(shapedTy, 1.0); ++ ++ return b.create(loc, val.getType(), ++ elementsAttr); ++} ++ ++// Check user-specified target version. ++vhlo::Version validateTargetVersion(llvm::StringRef versionRef) { ++ auto failOrVersion = vhlo::Version::fromString(versionRef); ++ if (failed(failOrVersion)) { ++ assert(!versionRef.empty() && ++ "No target version specified. Target version must be of the form " ++ "`#.#.#`."); ++ assert(versionRef.empty() && ++ "Invalid target version argument. Target version must be of the " ++ "form `#.#.#`."); ++ } ++ vhlo::Version targetVersion = *failOrVersion; ++ assert((vhlo::Version::getMinimumVersion() <= targetVersion) && ++ "target version is less than minimum supported."); ++ assert((targetVersion <= vhlo::Version::getCurrentVersion()) && ++ "target version is greater than current version."); ++ return targetVersion; ++} ++ ++//===----------------------------------------------------------------------===// ++// Pass ++//===----------------------------------------------------------------------===// ++ ++struct StablehloCreateCompatibilityExpanderPass ++ : public impl::StablehloCreateCompatibilityExpanderPassBase< ++ StablehloCreateCompatibilityExpanderPass> { ++ StablehloCreateCompatibilityExpanderPass() ++ : StablehloCreateCompatibilityExpanderPassBase< ++ StablehloCreateCompatibilityExpanderPass>() {} ++ StablehloCreateCompatibilityExpanderPass( ++ const StablehloCreateCompatibilityExpanderPassOptions &opts) ++ : StablehloCreateCompatibilityExpanderPassBase< ++ StablehloCreateCompatibilityExpanderPass>(opts) {} ++ ++ public: ++ LogicalResult initialize(MLIRContext *context) override { ++ auto targetVersion = validateTargetVersion(targetVersionOption); ++ ++ config.useTopDownTraversal = true; ++ RewritePatternSet patterns_(context); ++ populateStablehloCreateCompatibilityExpanderPatterns(&patterns_, context, ++ targetVersion); ++ patterns = std::move(patterns_); ++ return success(); ++ } ++ ++ void runOnOperation() override { ++ auto func = getOperation(); ++ if (failed(applyPatternsAndFoldGreedily(func, patterns, config))) { ++ func.emitError( ++ "Failed to converge StableHLOCreateCompatibilityExpanderPass in ") ++ << config.maxIterations << " iterations"; ++ signalPassFailure(); ++ } ++ } ++ ++ private: ++ FrozenRewritePatternSet patterns; ++ GreedyRewriteConfig config; ++}; ++ ++#include "stablehlo/transforms/StablehloCreateCompatibilityExpanderPatterns.h.inc" ++ ++} // namespace ++ ++void populateStablehloCreateCompatibilityExpanderPatterns( ++ RewritePatternSet *patterns, MLIRContext *context, ++ vhlo::Version targetVersion) { ++ // StableHLO TanOp is introduced in v1.4.0. ++ if (targetVersion < vhlo::Version(1, 4, 0)) { ++ patterns->add(context); ++ patterns->add(context); ++ } ++} ++ ++} // namespace stablehlo ++} // namespace mlir +diff --ruN a/stablehlo/stablehlo/transforms/StablehloCreateCompatibilityExpanderPatterns.td b/stablehlo/stablehlo/transforms/StablehloCreateCompatibilityExpanderPatterns.td +--- stablehlo/stablehlo/transforms/StablehloCreateCompatibilityExpanderPatterns.td ++++ stablehlo/stablehlo/transforms/StablehloCreateCompatibilityExpanderPatterns.td +@@ -0,0 +1,47 @@ ++/* Copyright 2022 The StableHLO Authors. ++ ++Licensed under the Apache License, Version 2.0 (the "License"); ++you may not use this file except in compliance with the License. ++You may obtain a copy of the License at ++ ++ http://www.apache.org/licenses/LICENSE-2.0 ++ ++Unless required by applicable law or agreed to in writing, software ++distributed under the License is distributed on an "AS IS" BASIS, ++WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++See the License for the specific language governing permissions and ++limitations under the License. ++==============================================================================*/ ++ ++include "mlir/IR/OpBase.td" ++include "stablehlo/dialect/StablehloOps.td" ++ ++def ComplexElementType : Type< ++ CPred<"isa(cast($_self).getElementType())">, ++ "Complex element type">; ++ ++def NonComplexElementType : Type< ++ CPred<"!isa(cast($_self).getElementType())">, ++ "Non-complex element type">; ++ ++def createConstantWithAllOnes : NativeCodeCall<"createConstantWithAllOnes($_builder, $_loc, $0)">; ++ ++// Express `tan` as ++// sine(x) / cosine(x) ++def TanOp_CompatiblityExpander : Pat<(StableHLO_TanOp NonComplexElementType:$input), ++ (StableHLO_DivOp ++ (StableHLO_SineOp $input), ++ (StableHLO_CosineOp $input) ++ )>; ++ ++// Express `tan(a + bi)` as ++// (tan(a) + i tanh(b)) / (1 - i tan(a) * tanh(b)) ++def TanOp_ComplexElementType_CompatiblityExpander : Pat<(StableHLO_TanOp ComplexElementType:$input), ++ (StableHLO_DivOp ++ (StableHLO_ComplexOp ++ (StableHLO_TanOp:$tan (StableHLO_RealOp $input)), ++ (StableHLO_TanhOp:$tanh (StableHLO_ImagOp $input))), ++ (StableHLO_ComplexOp ++ (createConstantWithAllOnes $tan), ++ (StableHLO_NegOp (StableHLO_MulOp $tan, $tanh))) ++ )>; + diff --git a/third_party/modules/stablehlo/20240829.0-54aa1a5/source.json b/third_party/modules/stablehlo/20240829.0-54aa1a5/source.json new file mode 100644 index 0000000..6d271a5 --- /dev/null +++ b/third_party/modules/stablehlo/20240829.0-54aa1a5/source.json @@ -0,0 +1,12 @@ +{ + "strip_prefix": "stablehlo-54aa1a57178251981da616b877dda1a88d840d11", + "url": "https://github.com/openxla/stablehlo/archive/54aa1a57178251981da616b877dda1a88d840d11.tar.gz", + "integrity": "sha256-PFXXs3vQ+WlMiCC8twbGEFbsBEF/67Z4qtmq8CtUSUU=", + "overlay": { + "MODULE.bazel": "" + }, + "patch_strip": 1, + "patches": { + "0001-Remove-duplicated-symbols-in-StablehloApi.h.patch": "" + } +} diff --git a/third_party/modules/stablehlo/metadata.json b/third_party/modules/stablehlo/metadata.json new file mode 100644 index 0000000..7e0964b --- /dev/null +++ b/third_party/modules/stablehlo/metadata.json @@ -0,0 +1,17 @@ +{ + "homepage": "https://github.com/openxla/stablehlo", + "maintainers": [ + { + "email": "bzlmod@zml.ai", + "github": "zml", + "name": "ZML Engineering Team" + } + ], + "repository": [ + "github:openxla/stablehlo" + ], + "versions": [ + "20240829.0-54aa1a5" + ], + "yanked_versions": {} +} diff --git a/third_party/modules/xla/20240902.0-d18cd64/MODULE.bazel b/third_party/modules/xla/20240902.0-d18cd64/MODULE.bazel new file mode 100644 index 0000000..739fe83 --- /dev/null +++ b/third_party/modules/xla/20240902.0-d18cd64/MODULE.bazel @@ -0,0 +1,34 @@ +module( + name = "xla", + version = "20240902.0-d18cd64", + compatibility_level = 1, +) + +bazel_dep(name = "platforms", version = "0.0.8") +bazel_dep(name = "bazel_skylib", version = "1.5.0") +bazel_dep(name = "rules_cc", version = "0.0.9") +bazel_dep(name = "rules_apple", version = "3.2.1", repo_name = "build_bazel_rules_apple") +bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "com_google_absl") +bazel_dep(name = "rules_python", version = "0.29.0") +bazel_dep(name = "rules_proto", version = "6.0.0-rc1") +bazel_dep(name = "rules_java", version = "7.3.2") +bazel_dep(name = "rules_pkg", version = "0.9.1") +bazel_dep(name = "zlib", version = "1.2.13") +bazel_dep(name = "re2", version = "2024-02-01", repo_name = "com_googlesource_code_re2") +bazel_dep(name = "rules_license", version = "0.0.8") + +bazel_dep(name = "stablehlo", version = "20240829.0-54aa1a5") + +tsl = use_extension("//:tsl.bzl", "tsl") +use_repo(tsl, "tsl") + +xla_workspace = use_extension("//:workspace.bzl", "xla_workspace") +use_repo( + xla_workspace, + "com_github_grpc_grpc", + "com_google_protobuf", + "local_config_cuda", + "local_config_remote_execution", + "local_config_rocm", + "local_config_tensorrt", +) diff --git a/third_party/modules/xla/20240902.0-d18cd64/overlay/MODULE.bazel b/third_party/modules/xla/20240902.0-d18cd64/overlay/MODULE.bazel new file mode 100644 index 0000000..739fe83 --- /dev/null +++ b/third_party/modules/xla/20240902.0-d18cd64/overlay/MODULE.bazel @@ -0,0 +1,34 @@ +module( + name = "xla", + version = "20240902.0-d18cd64", + compatibility_level = 1, +) + +bazel_dep(name = "platforms", version = "0.0.8") +bazel_dep(name = "bazel_skylib", version = "1.5.0") +bazel_dep(name = "rules_cc", version = "0.0.9") +bazel_dep(name = "rules_apple", version = "3.2.1", repo_name = "build_bazel_rules_apple") +bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "com_google_absl") +bazel_dep(name = "rules_python", version = "0.29.0") +bazel_dep(name = "rules_proto", version = "6.0.0-rc1") +bazel_dep(name = "rules_java", version = "7.3.2") +bazel_dep(name = "rules_pkg", version = "0.9.1") +bazel_dep(name = "zlib", version = "1.2.13") +bazel_dep(name = "re2", version = "2024-02-01", repo_name = "com_googlesource_code_re2") +bazel_dep(name = "rules_license", version = "0.0.8") + +bazel_dep(name = "stablehlo", version = "20240829.0-54aa1a5") + +tsl = use_extension("//:tsl.bzl", "tsl") +use_repo(tsl, "tsl") + +xla_workspace = use_extension("//:workspace.bzl", "xla_workspace") +use_repo( + xla_workspace, + "com_github_grpc_grpc", + "com_google_protobuf", + "local_config_cuda", + "local_config_remote_execution", + "local_config_rocm", + "local_config_tensorrt", +) diff --git a/third_party/modules/xla/20240902.0-d18cd64/overlay/tsl.bzl b/third_party/modules/xla/20240902.0-d18cd64/overlay/tsl.bzl new file mode 100644 index 0000000..50c1df1 --- /dev/null +++ b/third_party/modules/xla/20240902.0-d18cd64/overlay/tsl.bzl @@ -0,0 +1,13 @@ +load("//third_party:repo.bzl", "tf_vendored") + +def _tsl_impl(mctx): + tf_vendored(name = "tsl", relpath = "third_party/tsl") + return mctx.extension_metadata( + reproducible = True, + root_module_direct_deps = "all", + root_module_direct_dev_deps = [], + ) + +tsl = module_extension( + implementation = _tsl_impl, +) diff --git a/third_party/modules/xla/20240902.0-d18cd64/overlay/workspace.bzl b/third_party/modules/xla/20240902.0-d18cd64/overlay/workspace.bzl new file mode 100644 index 0000000..87c035b --- /dev/null +++ b/third_party/modules/xla/20240902.0-d18cd64/overlay/workspace.bzl @@ -0,0 +1,52 @@ +load("@tsl//third_party:repo.bzl", "tf_http_archive", "tf_mirror_urls") +load("@tsl//third_party/gpus:cuda_configure.bzl", "cuda_configure") +load("@tsl//third_party/gpus:rocm_configure.bzl", "rocm_configure") +load("@tsl//third_party/tensorrt:tensorrt_configure.bzl", "tensorrt_configure") +load("@tsl//tools/toolchains/remote:configure.bzl", "remote_execution_configure") + +def _xla_workspace_impl(mctx): + cuda_configure(name = "local_config_cuda") + remote_execution_configure(name = "local_config_remote_execution") + rocm_configure(name = "local_config_rocm") + tensorrt_configure(name = "local_config_tensorrt") + tf_http_archive( + name = "com_github_grpc_grpc", + sha256 = "b956598d8cbe168b5ee717b5dafa56563eb5201a947856a6688bbeac9cac4e1f", + strip_prefix = "grpc-b54a5b338637f92bfcf4b0bc05e0f57a5fd8fadd", + system_build_file = "@tsl//third_party/systemlibs:grpc.BUILD", + patch_file = [ + "@tsl//third_party/grpc:generate_cc_env_fix.patch", + "@tsl//third_party/grpc:register_go_toolchain.patch", + ], + system_link_files = { + "@tsl//third_party/systemlibs:BUILD": "bazel/BUILD", + "@tsl//third_party/systemlibs:grpc.BUILD": "src/compiler/BUILD", + "@tsl//third_party/systemlibs:grpc.bazel.grpc_deps.bzl": "bazel/grpc_deps.bzl", + "@tsl//third_party/systemlibs:grpc.bazel.grpc_extra_deps.bzl": "bazel/grpc_extra_deps.bzl", + "@tsl//third_party/systemlibs:grpc.bazel.cc_grpc_library.bzl": "bazel/cc_grpc_library.bzl", + "@tsl//third_party/systemlibs:grpc.bazel.generate_cc.bzl": "bazel/generate_cc.bzl", + "@tsl//third_party/systemlibs:grpc.bazel.protobuf.bzl": "bazel/protobuf.bzl", + }, + urls = tf_mirror_urls("https://github.com/grpc/grpc/archive/b54a5b338637f92bfcf4b0bc05e0f57a5fd8fadd.tar.gz"), + ) + tf_http_archive( + name = "com_google_protobuf", + patch_file = ["@tsl//third_party/protobuf:protobuf.patch"], + sha256 = "f66073dee0bc159157b0bd7f502d7d1ee0bc76b3c1eac9836927511bdc4b3fc1", + strip_prefix = "protobuf-3.21.9", + system_build_file = "@tsl//third_party/systemlibs:protobuf.BUILD", + system_link_files = { + "@tsl//third_party/systemlibs:protobuf.bzl": "protobuf.bzl", + "@tsl//third_party/systemlibs:protobuf_deps.bzl": "protobuf_deps.bzl", + }, + urls = tf_mirror_urls("https://github.com/protocolbuffers/protobuf/archive/v3.21.9.zip"), + ) + return mctx.extension_metadata( + reproducible = True, + root_module_direct_deps = "all", + root_module_direct_dev_deps = [], + ) + +xla_workspace = module_extension( + implementation = _xla_workspace_impl, +) diff --git a/third_party/modules/xla/20240902.0-d18cd64/patches/0003-PJRT-C-API-Ensure-C-compliance-for-Profiler-Extensio.patch b/third_party/modules/xla/20240902.0-d18cd64/patches/0003-PJRT-C-API-Ensure-C-compliance-for-Profiler-Extensio.patch new file mode 100644 index 0000000..0f58f10 --- /dev/null +++ b/third_party/modules/xla/20240902.0-d18cd64/patches/0003-PJRT-C-API-Ensure-C-compliance-for-Profiler-Extensio.patch @@ -0,0 +1,27 @@ +From 4db5de34f70d991fedbe28915c8239b97ba7a064 Mon Sep 17 00:00:00 2001 +From: Steeve Morin +Date: Mon, 18 Mar 2024 17:17:34 +0100 +Subject: [PATCH 3/3] [PJRT C API] Ensure C compliance for Profiler Extension + +--- + xla/pjrt/c/pjrt_c_api_profiler_extension.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/xla/pjrt/c/pjrt_c_api_profiler_extension.h b/xla/pjrt/c/pjrt_c_api_profiler_extension.h +index c821916ad..89a596123 100644 +--- a/xla/pjrt/c/pjrt_c_api_profiler_extension.h ++++ b/xla/pjrt/c/pjrt_c_api_profiler_extension.h +@@ -16,8 +16,10 @@ limitations under the License. + #ifndef XLA_PJRT_C_PJRT_C_API_PROFILER_EXTENSION_H_ + #define XLA_PJRT_C_PJRT_C_API_PROFILER_EXTENSION_H_ + ++#ifdef __cplusplus + #include + #include ++#endif + + #include "xla/backends/profiler/plugin/profiler_c_api.h" + #include "xla/pjrt/c/pjrt_c_api.h" +-- +2.39.3 (Apple Git-146) + diff --git a/third_party/modules/xla/20240902.0-d18cd64/source.json b/third_party/modules/xla/20240902.0-d18cd64/source.json new file mode 100644 index 0000000..359f9b1 --- /dev/null +++ b/third_party/modules/xla/20240902.0-d18cd64/source.json @@ -0,0 +1,14 @@ +{ + "strip_prefix": "xla-d18cd64b7cd61a2ade10089665ac104f639101b1", + "url": "https://github.com/openxla/xla/archive/d18cd64b7cd61a2ade10089665ac104f639101b1.tar.gz", + "integrity": "sha256-EtKhjU91STBceUmg0TUE6cPeRkeSz3LI2S1i3EFMj/E=", + "overlay": { + "tsl.bzl": "", + "workspace.bzl": "", + "MODULE.bazel": "" + }, + "patch_strip": 1, + "patches": { + "0003-PJRT-C-API-Ensure-C-compliance-for-Profiler-Extensio.patch": "" + } +} diff --git a/third_party/modules/xla/metadata.json b/third_party/modules/xla/metadata.json new file mode 100644 index 0000000..568c92c --- /dev/null +++ b/third_party/modules/xla/metadata.json @@ -0,0 +1,17 @@ +{ + "homepage": "https://github.com/openxla/xla", + "maintainers": [ + { + "email": "bzlmod@zml.ai", + "github": "zml", + "name": "ZML Engineering Team" + } + ], + "repository": [ + "github:openxla/xla" + ], + "versions": [ + "20240902.0-d18cd64" + ], + "yanked_versions": {} +} diff --git a/third_party/modules/zig-protobuf/20240722.0-c644d11/MODULE.bazel b/third_party/modules/zig-protobuf/20240722.0-c644d11/MODULE.bazel new file mode 100644 index 0000000..4fb3992 --- /dev/null +++ b/third_party/modules/zig-protobuf/20240722.0-c644d11/MODULE.bazel @@ -0,0 +1,8 @@ +module( + name = "zig-protobuf", + version = "20240722.0-c644d11", + compatibility_level = 1, +) + +bazel_dep(name = "rules_zig", version = "20240904.0-010da15") +bazel_dep(name = "rules_proto", version = "6.0.0-rc1") diff --git a/third_party/modules/zig-protobuf/20240722.0-c644d11/overlay/BUILD.bazel b/third_party/modules/zig-protobuf/20240722.0-c644d11/overlay/BUILD.bazel new file mode 100644 index 0000000..832c759 --- /dev/null +++ b/third_party/modules/zig-protobuf/20240722.0-c644d11/overlay/BUILD.bazel @@ -0,0 +1,32 @@ +load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain") +load("@rules_zig//zig:defs.bzl", "BINARY_KIND", "zig_binary", "zig_library") + +zig_library( + name = "protobuf", + import_name = "protobuf", + main = "src/protobuf.zig", + visibility = ["//visibility:public"], +) + +zig_binary( + name = "generator", + srcs = [ + "bootstrapped-generator/FullName.zig", + "bootstrapped-generator/google/protobuf/compiler/plugin.pb.zig", + "bootstrapped-generator/google/protobuf/descriptor.pb.zig", + ], + kind = BINARY_KIND.exe, + main = "bootstrapped-generator/main.zig", + visibility = ["//visibility:public"], + deps = [":protobuf"], +) + +proto_lang_toolchain( + name = "zig_toolchain", + command_line = "--zig_out=$(OUT)", + output_files = "multiple", + plugin = ":generator", + plugin_format_flag = "--plugin=protoc-gen-zig=%s", + runtime = ":protobuf", + visibility = ["//visibility:public"], +) diff --git a/third_party/modules/zig-protobuf/20240722.0-c644d11/overlay/MODULE.bazel b/third_party/modules/zig-protobuf/20240722.0-c644d11/overlay/MODULE.bazel new file mode 100644 index 0000000..4fb3992 --- /dev/null +++ b/third_party/modules/zig-protobuf/20240722.0-c644d11/overlay/MODULE.bazel @@ -0,0 +1,8 @@ +module( + name = "zig-protobuf", + version = "20240722.0-c644d11", + compatibility_level = 1, +) + +bazel_dep(name = "rules_zig", version = "20240904.0-010da15") +bazel_dep(name = "rules_proto", version = "6.0.0-rc1") diff --git a/third_party/modules/zig-protobuf/20240722.0-c644d11/patches/0001-USE_MODULES-true.patch b/third_party/modules/zig-protobuf/20240722.0-c644d11/patches/0001-USE_MODULES-true.patch new file mode 100644 index 0000000..6735392 --- /dev/null +++ b/third_party/modules/zig-protobuf/20240722.0-c644d11/patches/0001-USE_MODULES-true.patch @@ -0,0 +1,11 @@ +--- a/bootstrapped-generator/main.zig ++++ b/bootstrapped-generator/main.zig +@@ -6,7 +6,7 @@ const descriptor = @import("google/protobuf/descriptor.pb.zig"); + const mem = std.mem; + const FullName = @import("./FullName.zig").FullName; + +-const USE_MODULES = false; ++const USE_MODULES = true; + + const allocator = std.heap.page_allocator; + diff --git a/third_party/modules/zig-protobuf/20240722.0-c644d11/source.json b/third_party/modules/zig-protobuf/20240722.0-c644d11/source.json new file mode 100644 index 0000000..f985b24 --- /dev/null +++ b/third_party/modules/zig-protobuf/20240722.0-c644d11/source.json @@ -0,0 +1,13 @@ +{ + "strip_prefix": "zig-protobuf-c644d1105caaca4d9a48d3536e253687052f74c8", + "url": "https://github.com/gwenzek/zig-protobuf/archive/c644d1105caaca4d9a48d3536e253687052f74c8.tar.gz", + "integrity": "sha256-KoZp8MLLEQQgS7Uip4sdjw7TYmhzKPdpilQYKp5iYV4=", + "overlay": { + "MODULE.bazel": "", + "BUILD.bazel": "" + }, + "patch_strip": 1, + "patches": { + "0001-USE_MODULES-true.patch": "" + } +} diff --git a/third_party/modules/zig-protobuf/metadata.json b/third_party/modules/zig-protobuf/metadata.json new file mode 100644 index 0000000..17e897b --- /dev/null +++ b/third_party/modules/zig-protobuf/metadata.json @@ -0,0 +1,17 @@ +{ + "homepage": "https://github.com/gwenzek/zig-protobuf", + "maintainers": [ + { + "email": "bzlmod@zml.ai", + "github": "zml", + "name": "ZML Engineering Team" + } + ], + "repository": [ + "gwenzek/zig-protobuf" + ], + "versions": [ + "20240722.0-c644d11" + ], + "yanked_versions": {} +} diff --git a/third_party/modules/zig-yaml/20240903.0-83d5fdf/MODULE.bazel b/third_party/modules/zig-yaml/20240903.0-83d5fdf/MODULE.bazel new file mode 100644 index 0000000..151f333 --- /dev/null +++ b/third_party/modules/zig-yaml/20240903.0-83d5fdf/MODULE.bazel @@ -0,0 +1,7 @@ +module( + name = "zig-yaml", + version = "20240903.0-83d5fdf", + compatibility_level = 1, +) + +bazel_dep(name = "rules_zig", version = "20240904.0-010da15") diff --git a/third_party/modules/zig-yaml/20240903.0-83d5fdf/overlay/BUILD.bazel b/third_party/modules/zig-yaml/20240903.0-83d5fdf/overlay/BUILD.bazel new file mode 100644 index 0000000..94897f7 --- /dev/null +++ b/third_party/modules/zig-yaml/20240903.0-83d5fdf/overlay/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_zig//zig:defs.bzl", "zig_library") + +zig_library( + name = "zig-yaml", + srcs = glob([ + "src/*.zig", + "src/parse/*.zig", + "src/yaml/*.zig", + ]), + main = "src/yaml.zig", + visibility = ["//visibility:public"], +) diff --git a/third_party/modules/zig-yaml/20240903.0-83d5fdf/overlay/MODULE.bazel b/third_party/modules/zig-yaml/20240903.0-83d5fdf/overlay/MODULE.bazel new file mode 100644 index 0000000..151f333 --- /dev/null +++ b/third_party/modules/zig-yaml/20240903.0-83d5fdf/overlay/MODULE.bazel @@ -0,0 +1,7 @@ +module( + name = "zig-yaml", + version = "20240903.0-83d5fdf", + compatibility_level = 1, +) + +bazel_dep(name = "rules_zig", version = "20240904.0-010da15") diff --git a/third_party/modules/zig-yaml/20240903.0-83d5fdf/source.json b/third_party/modules/zig-yaml/20240903.0-83d5fdf/source.json new file mode 100644 index 0000000..643aa23 --- /dev/null +++ b/third_party/modules/zig-yaml/20240903.0-83d5fdf/source.json @@ -0,0 +1,9 @@ +{ + "strip_prefix": "zig-yaml-83d5fdfdd6c847b4bd2a8cad73b05a5c6447984b", + "url": "https://github.com/gwenzek/zig-yaml/archive/83d5fdfdd6c847b4bd2a8cad73b05a5c6447984b.tar.gz", + "integrity": "sha256-uusblAIZQgyKlg0qVmuHWD2JG+dMM+N6oKNGZsBdpEk=", + "overlay": { + "MODULE.bazel": "", + "BUILD.bazel": "" + } +} diff --git a/third_party/modules/zig-yaml/metadata.json b/third_party/modules/zig-yaml/metadata.json new file mode 100644 index 0000000..3aa2c43 --- /dev/null +++ b/third_party/modules/zig-yaml/metadata.json @@ -0,0 +1,17 @@ +{ + "homepage": "https://github.com/gwenzek/zig-yaml", + "maintainers": [ + { + "email": "bzlmod@zml.ai", + "github": "zml", + "name": "ZML Engineering Team" + } + ], + "repository": [ + "github:gwenzek/zig-yaml" + ], + "versions": [ + "20240903.0-83d5fdf" + ], + "yanked_versions": {} +} diff --git a/third_party/modules/zigcoro/20240829.0-fc1db29/MODULE.bazel b/third_party/modules/zigcoro/20240829.0-fc1db29/MODULE.bazel new file mode 100644 index 0000000..a59b2d8 --- /dev/null +++ b/third_party/modules/zigcoro/20240829.0-fc1db29/MODULE.bazel @@ -0,0 +1,8 @@ +module( + name = "zigcoro", + version = "20240829.0-fc1db29", + compatibility_level = 1, +) + +bazel_dep(name = "rules_zig", version = "20240904.0-010da15") +bazel_dep(name = "libxev", version = "20240825.0-dbe2291") diff --git a/third_party/modules/zigcoro/20240829.0-fc1db29/overlay/BUILD.bazel b/third_party/modules/zigcoro/20240829.0-fc1db29/overlay/BUILD.bazel new file mode 100644 index 0000000..29227e9 --- /dev/null +++ b/third_party/modules/zigcoro/20240829.0-fc1db29/overlay/BUILD.bazel @@ -0,0 +1,29 @@ +load("@rules_zig//zig:defs.bzl", "zig_library") + +genrule( + name = "libcoro_options_gen", + outs = ["options.zig"], + cmd = """\ +cat < $@ +pub const default_stack_size: usize = 4096; +pub const debug_log_level: usize = 0; +EOF +""", +) + +zig_library( + name = "libcoro_options", + main = ":libcoro_options_gen", +) + +zig_library( + name = "libcoro", + srcs = glob(["src/*.zig"]), + extra_srcs = glob(["src/asm/*.s"]), + main = "src/main.zig", + visibility = ["//visibility:public"], + deps = [ + ":libcoro_options", + "@libxev//:xev", + ], +) diff --git a/third_party/modules/zigcoro/20240829.0-fc1db29/overlay/MODULE.bazel b/third_party/modules/zigcoro/20240829.0-fc1db29/overlay/MODULE.bazel new file mode 100644 index 0000000..a59b2d8 --- /dev/null +++ b/third_party/modules/zigcoro/20240829.0-fc1db29/overlay/MODULE.bazel @@ -0,0 +1,8 @@ +module( + name = "zigcoro", + version = "20240829.0-fc1db29", + compatibility_level = 1, +) + +bazel_dep(name = "rules_zig", version = "20240904.0-010da15") +bazel_dep(name = "libxev", version = "20240825.0-dbe2291") diff --git a/third_party/modules/zigcoro/20240829.0-fc1db29/patches/0001-Handle-generic-function-in-Signature.patch b/third_party/modules/zigcoro/20240829.0-fc1db29/patches/0001-Handle-generic-function-in-Signature.patch new file mode 100644 index 0000000..6072de0 --- /dev/null +++ b/third_party/modules/zigcoro/20240829.0-fc1db29/patches/0001-Handle-generic-function-in-Signature.patch @@ -0,0 +1,48 @@ +From e2416ff5ec9cad5572e6a5edac3f949b75024c00 Mon Sep 17 00:00:00 2001 +From: Steeve Morin +Date: Tue, 6 Aug 2024 11:34:35 +0200 +Subject: [PATCH 1/2] Handle generic function in Signature + +--- + src/coro.zig | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/coro.zig b/src/coro.zig +index 9285489..8a34717 100644 +--- a/src/coro.zig ++++ b/src/coro.zig +@@ -266,6 +266,7 @@ const CoroT = struct { + YieldT: type = void, + InjectT: type = void, + ArgsT: type, ++ _ReturnT: type, + + // If the function this signature represents is compile-time known, + // it can be held here. +@@ -273,19 +274,21 @@ const CoroT = struct { + + fn init(comptime Func: anytype, comptime options: CoroT.Options) @This() { + const FuncT = if (@TypeOf(Func) == type) Func else @TypeOf(Func); ++ const ArgsT = options.ArgsT orelse ArgsTuple(FuncT); + return .{ + .Func = FuncT, + .YieldT = options.YieldT, + .InjectT = options.InjectT, +- .ArgsT = options.ArgsT orelse ArgsTuple(FuncT), ++ .ArgsT = ArgsT, + .func_ptr = if (@TypeOf(Func) == type) null else struct { + const val = Func; + }, ++ ._ReturnT = @TypeOf(@call(.auto, Func, @as(ArgsT, undefined))), + }; + } + + pub fn ReturnT(comptime self: @This()) type { +- return @typeInfo(self.Func).Fn.return_type.?; ++ return self._ReturnT; + } + }; + +-- +2.39.3 (Apple Git-146) + diff --git a/third_party/modules/zigcoro/20240829.0-fc1db29/patches/0002-asyncio-return-error-super-set-in-pread-pwrite.patch b/third_party/modules/zigcoro/20240829.0-fc1db29/patches/0002-asyncio-return-error-super-set-in-pread-pwrite.patch new file mode 100644 index 0000000..f1e6862 --- /dev/null +++ b/third_party/modules/zigcoro/20240829.0-fc1db29/patches/0002-asyncio-return-error-super-set-in-pread-pwrite.patch @@ -0,0 +1,34 @@ +From d8a4773ee9fa0ae5c5fd91e84c322e75a634a077 Mon Sep 17 00:00:00 2001 +From: Steeve Morin +Date: Tue, 6 Aug 2024 13:14:59 +0200 +Subject: [PATCH 2/2] asyncio: return error super set in pread/pwrite + +--- + src/asyncio.zig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/asyncio.zig b/src/asyncio.zig +index 68cc7d3..8487754 100644 +--- a/src/asyncio.zig ++++ b/src/asyncio.zig +@@ -354,7 +354,7 @@ pub const File = struct { + } + + const PReadResult = xev.ReadError!usize; +- pub fn pread(self: Self, buf: xev.ReadBuffer, offset: u64) PReadResult { ++ pub fn pread(self: Self, buf: xev.ReadBuffer, offset: u64) !usize { + const ResultT = PReadResult; + const Data = struct { + result: ResultT = undefined, +@@ -391,7 +391,7 @@ pub const File = struct { + } + + const PWriteResult = xev.WriteError!usize; +- pub fn pwrite(self: Self, buf: xev.WriteBuffer, offset: u64) PWriteResult { ++ pub fn pwrite(self: Self, buf: xev.WriteBuffer, offset: u64) !usize { + const ResultT = PWriteResult; + const Data = struct { + result: ResultT = undefined, +-- +2.39.3 (Apple Git-146) + diff --git a/third_party/modules/zigcoro/20240829.0-fc1db29/source.json b/third_party/modules/zigcoro/20240829.0-fc1db29/source.json new file mode 100644 index 0000000..17e66d4 --- /dev/null +++ b/third_party/modules/zigcoro/20240829.0-fc1db29/source.json @@ -0,0 +1,14 @@ +{ + "strip_prefix": "zigcoro-fc1db29dee049ce572a516f1586cce0eca4fcb2a", + "url": "https://github.com/rsepassi/zigcoro/archive/fc1db29dee049ce572a516f1586cce0eca4fcb2a.tar.gz", + "integrity": "sha256-2ynCPLSRFPto3HIOhDTBDyUS770PNMI9ioMkj8Z7Y+s=", + "overlay": { + "MODULE.bazel": "", + "BUILD.bazel": "" + }, + "patch_strip": 1, + "patches": { + "0001-Handle-generic-function-in-Signature.patch": "", + "0002-asyncio-return-error-super-set-in-pread-pwrite.patch": "" + } +} diff --git a/third_party/modules/zigcoro/metadata.json b/third_party/modules/zigcoro/metadata.json new file mode 100644 index 0000000..533957c --- /dev/null +++ b/third_party/modules/zigcoro/metadata.json @@ -0,0 +1,17 @@ +{ + "homepage": "https://github.com/rsepassi/zigcoro", + "maintainers": [ + { + "email": "bzlmod@zml.ai", + "github": "zml", + "name": "ZML Engineering Team" + } + ], + "repository": [ + "github:rsepassi/zigcoro" + ], + "versions": [ + "20240829.0-fc1db29" + ], + "yanked_versions": {} +} diff --git a/third_party/zls/BUILD.bazel b/third_party/zls/BUILD.bazel new file mode 100644 index 0000000..223284e --- /dev/null +++ b/third_party/zls/BUILD.bazel @@ -0,0 +1,14 @@ +load(":zls.bzl", "targets", "zig_runner", "zls_runner") + +toolchain_type(name = "toolchain_type") + +targets() + +zig_runner( + name = "zig", +) + +zls_runner( + name = "zls", + zig = ":zig", +) diff --git a/third_party/zls/zls.bzl b/third_party/zls/zls.bzl new file mode 100644 index 0000000..816c1d0 --- /dev/null +++ b/third_party/zls/zls.bzl @@ -0,0 +1,238 @@ +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +_VERSION = "0.13.0" + +_ARCH = { + "x86_64-linux": struct( + sha256 = "ec4c1b45caf88e2bcb9ebb16c670603cc596e4f621b96184dfbe837b39cd8410", + exec_compatible_with = [ + "@platforms//os:linux", + "@platforms//cpu:x86_64", + ], + ), + "aarch64-macos": struct( + sha256 = "9848514524f5e5d33997ac280b7d92388407209d4b8d4be3866dc3cf30ca6ca8", + exec_compatible_with = [ + "@platforms//os:macos", + "@platforms//cpu:aarch64", + ], + ), +} + +ZlsInfo = provider( + fields = { + "bin": "ZLS binary", + }, +) + +def _zls_toolchain_impl(ctx): + default = DefaultInfo( + files = depset(direct = [ctx.file.zls]), + ) + zlsinfo = ZlsInfo( + bin = ctx.file.zls, + ) + toolchain_info = platform_common.ToolchainInfo( + default = default, + zlsinfo = zlsinfo, + ) + + return [ + default, + zlsinfo, + toolchain_info, + ] + +zls_toolchain = rule( + implementation = _zls_toolchain_impl, + attrs = { + "zls": attr.label( + executable = True, + allow_single_file = True, + cfg = "exec", + ), + }, +) + +def _repo_impl(mctx): + for arch, config in _ARCH.items(): + http_archive( + name = "zls_{}".format(arch), + url = "https://github.com/zigtools/zls/releases/download/{version}/zls-{arch}.tar.xz".format( + version = _VERSION, + arch = arch, + ), + sha256 = config.sha256, + build_file_content = """\ +load("@zml//third_party/zls:zls.bzl", "zls_toolchain") +zls_toolchain(name = "toolchain", zls = "zls") +""", + ) + return mctx.extension_metadata( + reproducible = True, + root_module_direct_deps = "all", + root_module_direct_dev_deps = [], + ) + +repo = module_extension( + implementation = _repo_impl, +) + +def targets(): + for arch, config in _ARCH.items(): + native.toolchain( + name = "toolchain_{}".format(arch), + exec_compatible_with = config.exec_compatible_with, + target_compatible_with = config.exec_compatible_with, + toolchain = "@zls_{}//:toolchain".format(arch), + toolchain_type = "@zml//third_party/zls:toolchain_type", + ) + +_ZIG_RUNNER_TPL = """\ +#!/bin/bash + +if [[ "${{1}}" == "build" ]]; then + for arg in "${{@:2}}"; do + if [[ "${{arg}}" == "-Dcmd="* ]]; then + cd ${{BUILD_WORKSPACE_DIRECTORY}} + exec ${{arg/-Dcmd=/}} + fi + done +fi + +export ZIG_GLOBAL_CACHE_DIR="$(realpath {zig_cache})" +export ZIG_LOCAL_CACHE_DIR="$(realpath {zig_cache})" +export ZIG_LIB_DIR="$(realpath {zig_lib_path})" +exec {zig_exe_path} "${{@}}" +""" + +_RUNNER_TPL = """\ +#!/bin/bash +set -eo pipefail + +zig() {{ + if [[ "${{1}}" == "build" ]]; then + for arg in "${{@:2}}"; do + if [[ "${{arg}}" == "-Dcmd="* ]]; then + cd ${{BUILD_WORKSPACE_DIRECTORY}} + exec ${{arg/-Dcmd=/}} + fi + done + fi + + export ZIG_GLOBAL_CACHE_DIR="$(realpath {zig_cache})" + export ZIG_LOCAL_CACHE_DIR="$(realpath {zig_cache})" + export ZIG_LIB_DIR="$(realpath {zig_lib_path})" + exec {zig_exe_path} "${{@}}" +}} + +zls() {{ + json_config="$(mktemp)" + ZLS_ARGS=("--config-path" "${{json_config}}") + + cat < ${{json_config}} +{{ + "zig_lib_path": "$(realpath {zig_lib_path})", + "zig_exe_path": "$(realpath {zig_exe_path})", + "global_cache_path": "$(realpath {zig_cache})" +}} +EOF + + while ((${{#}})); do + case "${{1}}" in + --config-path) + cat "${{2}}" >> "${{json_config}}" + {jq} -s add "${{json_config}}" > "${{json_config}}.tmp" + mv "${{json_config}}.tmp" "${{json_config}}" + shift 2 + ;; + *) + ZLS_ARGS+=("${{1}}") + shift + ;; + esac + done + + exec {zls} "${{ZLS_ARGS[@]}}" +}} + +case $1 in + zig) + shift + zig "${{@}}" + ;; + zls) + shift + zls "${{@}}" + ;; +esac +""" + +def _zls_runner_impl(ctx): + jqinfo = ctx.toolchains["@aspect_bazel_lib//lib:jq_toolchain_type"].jqinfo + zigtoolchaininfo = ctx.toolchains["@rules_zig//zig:toolchain_type"].zigtoolchaininfo + zlsinfo = ctx.toolchains["@zml//third_party/zls:toolchain_type"].zlsinfo + + zls_runner = ctx.actions.declare_file(ctx.label.name + ".zls_runner.sh") + ctx.actions.write(zls_runner, _RUNNER_TPL.format( + jq = jqinfo.bin.short_path, + zig_cache = zigtoolchaininfo.zig_cache, + zig_exe_path = zigtoolchaininfo.zig_exe.short_path, + zig_lib_path = zigtoolchaininfo.zig_lib.short_path, + zls = zlsinfo.bin.short_path, + )) + + return [ + DefaultInfo( + files = depset([zls_runner]), + executable = zls_runner, + runfiles = ctx.runfiles( + files = [ + ctx.executable.zig, + jqinfo.bin, + zlsinfo.bin, + ], + transitive_files = zigtoolchaininfo.zig_files, + ), + ), + ] + +zls_runner = rule( + implementation = _zls_runner_impl, + attrs = { + "zig": attr.label(mandatory = True, executable = True, cfg = "exec"), + }, + executable = True, + toolchains = [ + "@rules_zig//zig:toolchain_type", + "@aspect_bazel_lib//lib:jq_toolchain_type", + "@zml//third_party/zls:toolchain_type", + ], +) + +def _zig_runner_impl(ctx): + zigtoolchaininfo = ctx.toolchains["@rules_zig//zig:toolchain_type"].zigtoolchaininfo + + zig_runner = ctx.actions.declare_file(ctx.label.name + ".zig_runner.sh") + ctx.actions.write(zig_runner, _ZIG_RUNNER_TPL.format( + zig_cache = zigtoolchaininfo.zig_cache, + zig_exe_path = zigtoolchaininfo.zig_exe.short_path, + zig_lib_path = zigtoolchaininfo.zig_lib.short_path, + )) + + return [ + DefaultInfo( + files = depset([zig_runner]), + executable = zig_runner, + runfiles = ctx.runfiles( + files = [zig_runner], + transitive_files = zigtoolchaininfo.zig_files, + ), + ), + ] + +zig_runner = rule( + implementation = _zig_runner_impl, + executable = True, + toolchains = ["@rules_zig//zig:toolchain_type"], +) diff --git a/tools/buildifier.sh b/tools/buildifier.sh new file mode 100755 index 0000000..3e1b093 --- /dev/null +++ b/tools/buildifier.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cd "$(dirname "${BASH_SOURCE[0]}")" +exec bazel run -- @buildifier_prebuilt//:buildifier "$@" diff --git a/tools/zig.sh b/tools/zig.sh new file mode 100755 index 0000000..a9b746c --- /dev/null +++ b/tools/zig.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cd "$(dirname "${BASH_SOURCE[0]}")" +exec bazel run --config=silent @zml//third_party/zls:zls -- zig "${@}" diff --git a/tools/zls.sh b/tools/zls.sh new file mode 100755 index 0000000..9fd4514 --- /dev/null +++ b/tools/zls.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cd "$(dirname "${BASH_SOURCE[0]}")" +exec bazel run --config=silent @zml//third_party/zls:zls -- zls "${@}" diff --git a/tools/zml_utils.py b/tools/zml_utils.py new file mode 100644 index 0000000..10e3216 --- /dev/null +++ b/tools/zml_utils.py @@ -0,0 +1,275 @@ +# Copyright 2024 ZML +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import builtins +import enum +import functools +import inspect +import logging +import re + +import torch +from torch import Tensor + +log = logging.getLogger(__name__) + +builtin_open = builtins.open + + +def log_and_open(file, *args, **kwargs): + print("open:", file, args, kwargs) + return builtin_open(file, *args, **kwargs) + + +builtins.open = log_and_open + + +class CollectionOver(Exception): + pass + +class ActivationCollector: + """Wrap a given torch.nn.Module and collect all its intermediary activations. + + Usage: + + collector = zml_utils.ActivationCollector(model, **collection_config) + model_output, activations = collector(model_input) + zml_utils.save_with_confirmation("activations.pt", activations) + + Args: + * max_layers: stop collecting activations after this many collected + * stop_after_first_step: if a layer is called twice (typically for generative model), stop immediately + * blacklist_regexes: skeep layers matching any of the regexes + """ + + def __init__( + self, + model, + *, + max_layers: int = -1, + stop_after_first_step: bool = False, + blacklist_regexes: list[str] = [r".*\.(\d\d+)\.", r".*\.[1-9]\."], + ): + self.model = model + self.max_layers = max_layers + self.stop_after_first_step = stop_after_first_step + self.blacklist_regexes = blacklist_regexes + self.count = 0 + mods = named_modules(model) + self.outs = {id(module): (name, None, None) for name, module in mods} + + def __call__(self, *args, **kwargs): + """Call the wrapped model with the given arguments. + + Return the model output and the activations. + """ + self.count = 0 + hook = torch.nn.modules.module.register_module_forward_hook( + self.log_activation_hook + ) + # modeling_llama.apply_rotary_pos_emb = my_rot + try: + res = self.model(*args, **kwargs) + except ActivationCollector.CollectionOver: + res = None + finally: + # modeling_llama.apply_rotary_pos_emb = rot + hook.remove() + + tensors = {} + # print(module_outs) + for name, outputs, inputs in self.outs.values(): + # Only save first layer for a smaller file. + for blacklist in self.blacklist_regexes: + if re.match(blacklist, name): + # print("skipping:", name) + continue + + if name == "": + # Skip the softmax output + continue + if (outputs, inputs) == (None, None): + # print(f"no inputs/outputs for {name}") + continue + for idx, inp in enumerate(inputs): + tensors[f"{name}.in.{idx}"] = inp + + for idx, out in enumerate(outputs): + tensors[f"{name}.out.{idx}"] = out + + for k, v in tensors.items(): + if k.endswith(".out.1"): + print(k, "->", v.shape) + + return res, tensors + + def log_activation_hook(self, module, input, out) -> None: + name, prev_out, prev_in = self.outs.get(id(module), (None, None, None)) + + if self.stop_after_first_step and prev_out is not None: + print(f"stopping collection cause {name} was already recorded") + raise ActivationCollector.CollectionOver() + return + + if prev_out is None: + self.count += 1 + + if name is None: + print("err: unknown module", module.__class__) + breakpoint() + return + + assert out is not None + outs = [o.detach().cpu() for o in _flatten(out)] + inputs = [i.detach().cpu() for i in _flatten(input)] + + kwargs = inspect.stack()[1].frame.f_locals["kwargs"] + extra_inputs = [i.detach().cpu() for i in _flatten(kwargs)] + + self.outs[id(module)] = (name, outs, inputs + extra_inputs) + if 0 < self.max_layers < self.count: + print(f"stopping collection cause we got {self.count} activations already") + raise ActivationCollector.CollectionOver() + + +def save_with_confirmation(filename: str, tensors: dict): + """Regular torch.save with a CLI confirmation.""" + sizes = [(v.numel() * v.dtype.itemsize, k) for k, v in tensors.items()] + sizes.sort() + disk_size = sum(s for s, k in sizes) + + GB = 1024**3 + print(f"About to write {disk_size/ GB:.3f}GB at {filename}. Biggest tensors:") + print(sizes[-20:]) + print("Enter `c` to continue, `q` to quit.") + + breakpoint() + torch.save(tensors, filename) + + +def _flatten(out): + if out is None: + return [] + elif isinstance(out, torch.Tensor): + outs = [out] + elif isinstance(out, tuple): + outs = [] + for x in out: + outs.extend(_flatten(x)) + elif isinstance(out, dict): + outs = [] + for x in out.values(): + outs.extend(_flatten(x)) + else: + outs = [] + return outs + + +def named_modules(model): + if hasattr(model, "named_modules"): + return model.named_modules() + + else: + root_modules = [ + (k, v) for k, v in model.__dict__.items() if isinstance(v, torch.nn.Module) + ] + for root, mod in root_modules: + for k, v in mod.named_modules(): + if k: + yield f"{root}.{k}", v + else: + yield root, v + + +def read_layer_config(model: torch.nn.Module) -> dict: + layer_config = {} + + def _append_node_config(node, prefix: str) -> None: + for k, v in node.__dict__.items(): + # Skip special members. In particular all children module and tensors + # will be hidden in special dicts `_parameters` and `_modules` + if k.startswith("_"): + continue + # All modules have a "training" flag + if k in ("training", "init_fn"): + continue + if v is None: + continue + + if not is_basic_type(v): + log.warning(f"Skipping layer config {k}={v!r}") + continue + layer_config[prefix + k] = v + + _append_node_config(model, "") + for name, node in find_children(model, torch.nn.Module): + _append_node_config(node, name + ".") + + return layer_config + + +def find_children(model: torch.nn.Module, t: type, layer_filter: str = "") -> list: + queue = list(model._modules.items()) + modules = [] + while queue: + name, node = queue.pop() + if node is None: + continue + if layer_filter and not re.match(layer_filter, name): + continue + if isinstance(node, t): + modules.append((name, node)) + for child_name, child_node in node._modules.items(): + queue.append((".".join((name, child_name)), child_node)) + + return modules + + +def is_basic_type(value) -> bool: + if isinstance(value, int): + return True + if isinstance(value, float): + return True + if isinstance(value, bool): + return True + if isinstance(value, enum.Enum): + return True + if isinstance(value, tuple) and len(value) == 1: + return True + if isinstance(value, str) and len(value) < 8: + return True + return False + + +def pdb_persistent(name, fn, *args, **kwargs): + """Cache that can survive through a PDB restart. + + Useful when debugging to avoid reloading models all the time. + """ + import sys + + pdb = sys.modules.get("pdb", None) + if pdb is None: + return fn(*args, **kwargs) + + if not hasattr(pdb, "__cache__"): + setattr(pdb, "__cache__", {}) + + cache = getattr(pdb, "__cache__") + entry = cache.get(name) + if entry is not None: + return entry + + res = fn(*args, **kwargs) + cache[name] = res + return res diff --git a/zls.build.json b/zls.build.json new file mode 100644 index 0000000..a426832 --- /dev/null +++ b/zls.build.json @@ -0,0 +1,8 @@ +{ + "build_options": [ + { + "name": "cmd", + "value": "bazel run @zml//zml:completion" + } + ] +} diff --git a/zml/BUILD.bazel b/zml/BUILD.bazel new file mode 100644 index 0000000..3a8bfc2 --- /dev/null +++ b/zml/BUILD.bazel @@ -0,0 +1,84 @@ +load("@aspect_bazel_lib//lib:tar.bzl", "mtree_spec", "tar") +load("@rules_zig//zig:defs.bzl", "zig_library", "zls_completion") +load("//bazel:zig.bzl", "zig_cc_test") +load("//bazel:zig_proto_library.bzl", "zig_proto_library") + +cc_library( + name = "posix", + hdrs = ["posix.h"], +) + +zig_library( + name = "zml", + srcs = glob([ + "*.zig", + "aio/**/*.zig", + "nn/**/*.zig", + "ops/**/*.zig", + ]), + copts = ["-lc"], + main = "zml.zig", + visibility = ["//visibility:public"], + deps = [ + ":posix", + ":sentencepiece_model_proto", + ":xla_proto", + "//async", + "//mlir", + "//mlir/dialects", + "//pjrt", + "//runtimes", + "//zml/tools", + "@rules_zig//zig/lib:libc", + "@rules_zig//zig/runfiles", + "@zig-yaml//:zig-yaml", + ], +) + +zls_completion( + name = "completion", + deps = [":zml"], +) + +zig_proto_library( + name = "xla_proto", + import_name = "//xla:xla_proto", + deps = ["@xla//xla/pjrt:compile_options_proto"], +) + +zig_proto_library( + name = "sentencepiece_model_proto", + import_name = "//sentencepiece:model_proto", + deps = ["@sentencepiece//:sentencepiece_model_proto"], +) + +# All ZML Tests + +zig_cc_test( + name = "test", + data = [ + "aio/torch/simple.pt", + "aio/torch/simple_test.pickle", + ], + test_runner = "test_runner.zig", + deps = [":zml"], +) + +filegroup( + name = "srcs", + srcs = [":test_test_lib"], + output_group = "srcs", +) + +mtree_spec( + name = "mtree", + srcs = [":srcs"], +) + +tar( + name = "sources", + srcs = [":srcs"], + args = [ + ], + mtree = ":mtree", +) diff --git a/zml/aio.zig b/zml/aio.zig new file mode 100644 index 0000000..46c6efd --- /dev/null +++ b/zml/aio.zig @@ -0,0 +1,591 @@ +const builtin = @import("builtin"); +const asynk = @import("async"); +const std = @import("std"); +const zml = @import("zml.zig"); +const pjrt = @import("pjrtx.zig"); +const c = @import("c"); +const posix = @import("posix.zig"); + +pub const gguf = @import("aio/gguf.zig"); +pub const nemo = @import("aio/nemo.zig"); +pub const safetensors = @import("aio/safetensors.zig"); +pub const sentencepiece = @import("aio/sentencepiece.zig"); +pub const tinyllama = @import("aio/tinyllama.zig"); +pub const torch = @import("aio/torch.zig"); +pub const yaml = @import("aio/yaml.zig"); + +pub const log = std.log.scoped(.zml_aio); +pub const Value = @import("aio/value.zig").Value; +const HostBuffer = @import("hostbuffer.zig").HostBuffer; + +/// Detects the format of the model file (base on filename) and open it. +pub fn detectFormatAndOpen(allocator: std.mem.Allocator, model_path: []const u8) !BufferStore { + return if (std.mem.endsWith(u8, model_path, ".safetensors")) + try safetensors.open(allocator, model_path) + else if (std.mem.endsWith(u8, model_path, ".safetensors.index.json")) + try safetensors.open(allocator, model_path) + else if (std.mem.endsWith(u8, model_path, ".gguf")) + try gguf.open(allocator, model_path) + else if (std.mem.endsWith(u8, model_path, ".pt")) + try torch.open(allocator, model_path) + else if (std.mem.endsWith(u8, model_path, ".tinyllama")) + try tinyllama.open(allocator, model_path) + else { + std.debug.panic("File extension not recognized: {s}", .{model_path}); + }; +} + +pub fn detectFormatAndLoadTokenizer(allocator: std.mem.Allocator, tokenizer_path: []const u8) !zml.tokenizer.Tokenizer { + return if (std.mem.endsWith(u8, tokenizer_path, ".json")) + try zml.tokenizer.fromHfJson(allocator, tokenizer_path) + else if (std.mem.endsWith(u8, tokenizer_path, ".gguf")) { + const store = try gguf.open(allocator, tokenizer_path); + return gguf.getGgufTokenizer(store, allocator); + } else if (std.mem.endsWith(u8, tokenizer_path, ".pb") or std.mem.endsWith(u8, tokenizer_path, ".model")) + try sentencepiece.loadTokenizerFromPath(allocator, tokenizer_path) + else if (std.mem.endsWith(u8, tokenizer_path, ".tinyllama")) + try zml.aio.tinyllama.loadTokenizer(allocator, tokenizer_path, 32000) + else { + zml.log.err("Failed to recognized tokenizer format of: {s}", .{tokenizer_path}); + return error.FormatNotRecognized; + }; +} + +/// Creates a Model struct with tensor shapes read from the given BufferStore. +/// The result can be used to pass to `compileModel`. +/// +/// * The `Tensor` field `Model.a.b` will be populated with a `Tensor` +/// whose shape is read from the "a.b" tensor. +/// * If `Model` contains a list of layers, then the field: +/// `Model.layers[2].a.b` will be populated from the "layers.2.a.b" tensor. +pub fn populateModel(comptime Model: type, allocator: std.mem.Allocator, buffer_store: BufferStore) !Model { + return populateModelWithPrefix(Model, allocator, buffer_store, ""); +} + +/// Creates a Model struct with tensor shapes read from the given TensorStore, +/// using a given prefix. +/// The result can be used to pass to `compileWithModel`. +/// +/// * The `Tensor` field `Model.a.b` will be populated with a `Tensor` +/// whose shape is read from the "prefix.a.b" tensor. +/// * If `Model` contains a list of layers, then the field: +/// `Model.layers[2].a.b` will be populated from the "prefix.layers.2.a.b" tensor. +pub fn populateModelWithPrefix(comptime Model: type, allocator: std.mem.Allocator, store: BufferStore, prefix: []const u8) !Model { + var model: Model = undefined; + + var prefix_builder: PrefixBuilder = .{}; + try prefix_builder.push(allocator, prefix); + defer prefix_builder.deinit(allocator); + + var unique_id = zml.Tensor.reserveIdRange(@intCast(store.buffers.count())); + const ok = _populateStruct(allocator, &prefix_builder, &unique_id, store, &model, true) catch |err| { + std.debug.panic("Can't populate model of type {s}: {s}", .{ @typeName(type), @errorName(err) }); + }; + if (!ok) return error.TensorNotFound; + return model; +} + +/// A struct containing all the buffers and metadata found in a model file. +pub const BufferStore = struct { + pub const Buffers = std.StringArrayHashMapUnmanaged(HostBuffer); + pub const Metadata = std.StringArrayHashMapUnmanaged(Value); + + arena: std.heap.ArenaAllocator, + files: []MemoryMappedFile = &.{}, + buffers: Buffers = .{}, + _metadata: Metadata = .{}, + + pub fn deinit(self: BufferStore) void { + for (self.files) |*file| file.deinit(); + self.arena.deinit(); + } + + pub fn get(self: BufferStore, key: []const u8) ?HostBuffer { + return self.buffers.get(key); + } + + /// Count layers starting with the given prefix. + pub fn countLayers(self: BufferStore, prefix: []const u8) usize { + // Note: This is kinda inefficient + const digit_start_index = prefix.len + 1; + var it = self.buffers.iterator(); + var maybe_max_index: ?usize = null; + while (it.next()) |entry| { + if (!std.mem.startsWith(u8, entry.key_ptr.*, prefix)) continue; + + const next_dot_index = std.mem.indexOfScalarPos(u8, entry.key_ptr.*, digit_start_index, '.') orelse entry.key_ptr.len; + const index = std.fmt.parseInt(usize, entry.key_ptr.*[digit_start_index..next_dot_index], 10) catch continue; + if (maybe_max_index) |*max_index| { + max_index.* = @max(max_index.*, index); + } else { + maybe_max_index = index; + } + } + + return if (maybe_max_index) |index| index + 1 else 0; + } + + pub fn metadata(self: BufferStore, key: []const u8, comptime tag: std.meta.FieldEnum(Value)) ?std.meta.FieldType(Value, tag) { + const wrapped_value = self._metadata.get(key) orelse return null; + + if (wrapped_value != tag) { + zml.log.err("Tried to interpret metadata '{s}' as {}, but was of type {}", .{ key, tag, wrapped_value }); + @panic("invalid metadata type"); + } + return @field(wrapped_value, @tagName(tag)); + } + + pub fn metadataSlice(self: BufferStore, key: []const u8, comptime tag: Value.Slice.ItemType) ?[]const Value.Slice.toZigType(tag) { + const wrapped_value = self._metadata.get(key) orelse return null; + + if (wrapped_value != .array or wrapped_value.array.item_type != tag) { + return null; + } + const T = Value.Slice.toZigType(tag); + return @alignCast(std.mem.bytesAsSlice(T, wrapped_value.array.data)); + } +}; + +/// A file containing contiguous/non-contiguous buffers, that can be read with mmap +/// (assumes contiguous if `strides` is `null`). +/// This struct is meant to be wrapped into a format specific struct, like io.gguf.File. +pub const MemoryMappedFile = struct { + /// underlying file handle + file: asynk.File, + data: []align(std.mem.page_size) const u8, + data_offset: u64 = 0, + + pub fn init(file: asynk.File) !MemoryMappedFile { + const data_len: usize = (try file.stat()).size; + const data_ = try asynk.call(std.posix.mmap, .{ + null, + data_len, + std.posix.PROT.READ, + .{ .TYPE = .PRIVATE }, + file.inner.file.fd, + 0, + }); + + try asynk.call(posix.madvise, .{ data_.ptr, @intCast(data_.len), @intCast(c.MADV_SEQUENTIAL) }); + + return .{ + .file = file, + .data = data_, + }; + } + + pub fn mappedSlice(self: *MemoryMappedFile, start: usize, len: usize) []const u8 { + return self.data[self.data_offset + start ..][0..len]; + } + + pub fn deinit(self: *MemoryMappedFile) void { + std.posix.munmap(self.data); + self.file.close() catch @panic("failed to close file"); + self.* = undefined; + } +}; + +/// Helper handling prefix building. +/// +/// This allows to easily push/pop prefixes and handles the generation of the string with the correct format. +const PrefixBuilder = struct { + /// Stores the computed prefix. + data: std.ArrayListUnmanaged(u8) = .{}, + /// Stack storing the size of the intermediary prefix. + subprefixes: std.ArrayListUnmanaged(u32) = .{}, + + pub fn deinit(self: *PrefixBuilder, allocator: std.mem.Allocator) void { + self.data.deinit(allocator); + self.subprefixes.deinit(allocator); + } + + pub fn push(self: *PrefixBuilder, allocator: std.mem.Allocator, prefix: []const u8) !void { + const old_len: u32 = @intCast(self.data.items.len); + try self.subprefixes.append(allocator, old_len); + errdefer _ = self.subprefixes.pop(); + + if (old_len == 0) { + try self.data.appendSlice(allocator, prefix); + } else { + try self.data.ensureUnusedCapacity(allocator, prefix.len + 1); + self.data.appendAssumeCapacity('.'); + self.data.appendSliceAssumeCapacity(prefix); + } + } + + pub fn pushDigit(self: *PrefixBuilder, allocator: std.mem.Allocator, idx: usize) !void { + const old_len: u32 = @intCast(self.data.items.len); + try self.subprefixes.append(allocator, old_len); + errdefer _ = self.subprefixes.pop(); + + try self.data.ensureUnusedCapacity(allocator, 16); + if (old_len > 0) { + self.data.appendAssumeCapacity('.'); + } + try self.data.writer(allocator).print("{d}", .{idx}); + } + + pub fn pop(self: *PrefixBuilder) void { + const last_prefix_len = self.subprefixes.popOrNull() orelse unreachable; + self.data.shrinkRetainingCapacity(last_prefix_len); + } +}; + +fn _populateStruct( + allocator: std.mem.Allocator, + prefix_builder: *PrefixBuilder, + unique_id: *u64, + buffer_store: BufferStore, + obj: anytype, + required: bool, +) !bool { + const err_msg = "_populateStruct must be called with a pointer to type. Received "; + const type_info, const T = switch (@typeInfo(@TypeOf(obj))) { + .Pointer => |ptr_info| switch (ptr_info.size) { + .One => .{ @typeInfo(ptr_info.child), ptr_info.child }, + else => @compileError(err_msg ++ @typeName(@TypeOf(obj))), + }, + else => @compileError(err_msg ++ @typeName(@TypeOf(obj))), + }; + + const prefix = prefix_builder.data.items; + if (T == zml.Tensor) { + return if (buffer_store.get(prefix)) |buffer| { + obj.* = zml.Tensor{ + ._shape = buffer.shape(), + ._id = .{ .buffer_id = unique_id.* }, + ._donation = .input_buffer, + }; + unique_id.* += 1; + return true; + } else { + if (required) { + std.log.err("Tensor not found: {s} ({d})", .{ prefix, buffer_store.buffers.count() }); + } + return false; + }; + } + + switch (type_info) { + .Pointer => |ptr_info| { + if (ptr_info.size == .Slice) { + obj.* = &.{}; + + const len = buffer_store.countLayers(prefix); + if (len > 0) { + obj.* = try allocator.alloc(ptr_info.child, len); + + for (obj.*, 0..) |*value, i| { + try prefix_builder.pushDigit(allocator, i); + defer prefix_builder.pop(); + + const found = try _populateStruct(allocator, prefix_builder, unique_id, buffer_store, value, required); + if (!found) { + std.log.err("Not able to load {s} as {s}", .{ prefix, @typeName(ptr_info.child) }); + return false; + } + } + } else if (required) { + log.warn("No layer found at {s}", .{prefix}); + } + return true; + } else if (ptr_info.size == .One) { + //if (ptr_info.child != zml.Tensor and ptr_info.child != ?zml.Tensor) { + // // Note: should we recurse on all pointers ? + // log.warn("Not looking into: {any}", .{prefix}); + // return false; + //} + //obj.* = try allocator.create(ptr_info.child); + //return try _populateStruct(allocator, buffer_store, unique_id, prefix, obj.*, required); + } else { + std.log.err("{s} - {s}: {s} type not supported", .{ @src().fn_name, prefix, @typeName(T) }); + return false; + } + }, + .Struct => |struct_info| { + // TODO(Corentin): See if we keep that + //if (@hasDecl(T, "_zml_reader_skip_me_")) return false; + + var partial_struct = false; + inline for (struct_info.fields) |field| { + try prefix_builder.push(allocator, field.name); + defer prefix_builder.pop(); + + var has_default = false; + if (field.default_value) |_| has_default = true; + + const field_found = try _populateStruct(allocator, prefix_builder, unique_id, buffer_store, &@field(obj, field.name), required and !has_default); + partial_struct = partial_struct or field_found; + if (!field_found) { + if (field.default_value) |v| { + @field(obj, field.name) = @as(*const field.type, @alignCast(@ptrCast(v))).*; + } else { + if (partial_struct) { + log.warn("Incomplete metadata '{0s}': {1s}. Missing field: '{2s}'. '{0s}' will be ignored.", .{ prefix, @typeName(T), field.name }); + obj.* = undefined; + return false; + } + + return false; + } + } + } + return true; + }, + //.Array => |array_info| { + // var new_prefix = prefix; + // if (prefix.items.len > 0) + // new_prefix.appendAssumeCapacity('.'); + // const len = new_prefix.items.len; + // for (obj, 0..) |*value, i| { + // new_prefix.items.len += std.fmt.formatIntBuf(new_prefix.unusedCapacitySlice(), i, 10, .lower, .{}); + // const found = try _populateStruct(allocator, buffer_store, unique_id, new_prefix, value, required); + // if (!found) return false; + // new_prefix.shrinkRetainingCapacity(len); + // } + // const num_layers = buffer_store.numLayers(prefix.items); + // if (num_layers != array_info.len) { + // log.warn("Found {d} layers with prefix {s}, but only loaded {d}", .{ num_layers, prefix.items, array_info.len }); + // } + // return true; + //}, + .Optional => |opt_info| { + obj.* = @as(opt_info.child, undefined); + const found = try _populateStruct(allocator, prefix_builder, unique_id, buffer_store, &(obj.*.?), false); + if (!found) obj.* = null; + return true; + }, + //.Union => |union_info| { + // // Note: the main issue here is that several fields could match but we only return the first one. + // inline for (union_info.fields) |field| { + // // interpret obj as a "field", and try to populate that. + // obj.* = @unionInit(T, field.name, undefined); + // const found = try _populateStruct(allocator, buffer_store, unique_id, prefix, &@field(obj.*, field.name), false); + // if (found) { + // std.log.info("Interpreted {s} as {s}", .{ prefix.items, @typeName(field.type) }); + // return true; + // } + // } + // obj.* = undefined; + // if (required) { + // std.log.err("Not able to intepret {s} as any member of the union: {s}", .{ prefix.items, @typeName(T) }); + // } + // return false; + //}, + .Int => { + obj.* = undefined; + return true; + }, + .Float => { + obj.* = undefined; + return true; + }, + else => if (required) { + std.log.err("{s}: {s} type not supported", .{ prefix, @typeName(T) }); + return error.UnsupportedMetadataType; + } else return false, + } +} + +/// Creates a bufferized version of a Model from the given BufferStore. For details about +/// bufferization, see the documentation of Bufferized(T). +/// +/// This will represent the weights of the model, loaded on a specific platform. +/// It can be used with a `module.Exe` (a compiled version of the same Model), to make a +/// `module.ExeWithWeights` ready to be called. +/// +/// The `init_args` are used to initialize the non Buffer fields, using `Model.init` function. +pub fn loadBuffers( + comptime Model: type, + init_args: anytype, + buffer_store: BufferStore, + allocator: std.mem.Allocator, + platform: zml.Platform, +) !zml.Bufferized(Model) { + var arena_state = std.heap.ArenaAllocator.init(allocator); + defer arena_state.deinit(); + const arena = arena_state.allocator(); + var model: Model = try zml.aio.populateModel(Model, arena, buffer_store); + + // If the Model has a "init" function, call it with the given parameters. + if (@hasDecl(Model, "init")) { + @call(.auto, Model.init, .{&model} ++ init_args); + } else { + zml.meta.assertComptime(@TypeOf(init_args) == void or @TypeOf(init_args) == @TypeOf(.{}), "Model of type {} has no init function, so `loadBuffers` should be call with init_args set to {{}} (void)", .{Model}); + } + + return loadModelBuffers(Model, model, buffer_store, allocator, platform); +} + +/// Creates a bufferized version of a Model from the given BufferStore. For details about +/// bufferization, see the documentation of Bufferized(T). +/// +/// This will represent the weights of the model, loaded on a specific platform. +/// It can be used with a `module.Exe` (a compiled version of the same Model), to make a +/// `module.ExeWithWeights` ready to be called. +pub fn loadModelBuffers( + comptime Model: type, + model: Model, + buffer_store: BufferStore, + allocator: std.mem.Allocator, + platform: zml.Platform, +) !zml.Bufferized(Model) { + return try loadModelBuffersWithPrefix(Model, model, buffer_store, allocator, platform, ""); +} + +pub fn loadModelBuffersWithPrefix( + comptime Model: type, + model: Model, + buffer_store: BufferStore, + allocator: std.mem.Allocator, + platform: zml.Platform, + prefix: []const u8, +) !zml.Bufferized(Model) { + // Allocate the bufferized version. + // We set fields to undefined, cause visitStructAndLoadBuffer is responsible + // to write them just afterward. + var res: zml.Bufferized(Model) = undefined; + try zml.meta.mapAlloc(struct { + pub fn initBuffer(_: void, _: zml.Tensor) zml.Buffer { + return undefined; + } + }.initBuffer, allocator, {}, model, &res); + + var prefix_builder: PrefixBuilder = .{}; + try prefix_builder.push(allocator, prefix); + defer prefix_builder.deinit(allocator); + + try visitStructAndLoadBuffer(allocator, &prefix_builder, buffer_store, &res, platform); + return res; +} + +/// Creates a bufferized version of a Model from the given BufferStore and the given prefix. +/// For details about bufferization, see the documentation of Bufferized(T). +/// +/// This will represent the weights of the model, loaded on a specific platform. +/// It can be used with a `module.Exe` (a compiled version of the same Model), to make a +/// `module.ExeWithWeights` ready to be called. +pub fn loadBuffersFromModelWithPrefix(comptime Model: type, model: Model, buffer_store: BufferStore, allocator: std.mem.Allocator, prefix: []const u8, platform: zml.Platform) !zml.Bufferized(Model) { + + // Allocate the bufferized version. + // We set fields to undefined, cause visitStructAndLoadBuffer is responsible + // to write them just afterward. + var res: zml.Bufferized(Model) = undefined; + try zml.meta.mapAlloc(struct { + pub fn initBuffer(_: void, _: zml.Tensor) zml.Buffer { + return undefined; + } + }.initBuffer, allocator, {}, model, &res); + + var prefix_builder: PrefixBuilder = .{}; + defer prefix_builder.deinit(allocator); + try prefix_builder.push(allocator, prefix); + + try visitStructAndLoadBuffer(allocator, &prefix_builder, buffer_store, &res, platform); + return res; +} + +/// Takes a bufferized version of a `model`, ie a mirror struct of the `model`, and deinit all the +/// Buffer found. +pub fn unloadBuffers(model: anytype) void { + zml.meta.visit((struct { + fn cb(_: void, buffer: *zml.Buffer) void { + buffer.deinit(); + } + }).cb, {}, model); +} + +fn visitStructAndLoadBuffer(allocator: std.mem.Allocator, prefix_builder: *PrefixBuilder, buffer_store: BufferStore, obj: anytype, platform: zml.Platform) !void { + const err_msg = "visitStructAndLoadBuffer must be called with a pointer to type. Received "; + const type_info, const T = switch (@typeInfo(@TypeOf(obj))) { + .Pointer => |ptr_info| switch (ptr_info.size) { + .One => .{ @typeInfo(ptr_info.child), ptr_info.child }, + else => @compileError(err_msg ++ @typeName(@TypeOf(obj))), + }, + else => @compileError(err_msg ++ @typeName(@TypeOf(obj))), + }; + + const prefix = prefix_builder.data.items; + if (T == zml.Buffer) { + return if (buffer_store.get(prefix)) |host_buffer| { + obj.* = try zml.Buffer.from(platform, host_buffer); + } else { + return error.BufferNotFound; + }; + } + + switch (type_info) { + .Pointer => |ptr_info| { + if (ptr_info.size == .Slice) { + for (obj.*, 0..) |*value, i| { + var buffer: [100]u8 = undefined; + const new_prefix = std.fmt.bufPrint(&buffer, "{d}", .{i}) catch unreachable; + + try prefix_builder.push(allocator, new_prefix); + defer prefix_builder.pop(); + + try visitStructAndLoadBuffer(allocator, prefix_builder, buffer_store, value, platform); + } + } else return error.TypeNotSupported; + }, + .Struct => |struct_info| { + // TODO(Corentin): See if we keep that + //if (@hasDecl(T, "_zml_reader_skip_me_")) return false; + + inline for (struct_info.fields) |field| { + try prefix_builder.push(allocator, field.name); + defer prefix_builder.pop(); + + try visitStructAndLoadBuffer(allocator, prefix_builder, buffer_store, &@field(obj, field.name), platform); + } + }, + //.Array => |array_info| { + // var new_prefix = prefix; + // if (prefix.items.len > 0) + // new_prefix.appendAssumeCapacity('.'); + // const len = new_prefix.items.len; + // for (obj, 0..) |*value, i| { + // new_prefix.items.len += std.fmt.formatIntBuf(new_prefix.unusedCapacitySlice(), i, 10, .lower, .{}); + // const found = try _populateStruct(allocator, buffer_store, unique_id, new_prefix, value, required); + // if (!found) return false; + // new_prefix.shrinkRetainingCapacity(len); + // } + // const num_layers = buffer_store.numLayers(prefix.items); + // if (num_layers != array_info.len) { + // log.warn("Found {d} layers with prefix {s}, but only loaded {d}", .{ num_layers, prefix.items, array_info.len }); + // } + // return true; + //}, + .Optional => |opt_info| { + var child = @as(opt_info.child, undefined); + if (visitStructAndLoadBuffer(allocator, prefix_builder, buffer_store, &child, platform)) { + obj.* = child; + } else |err| switch (err) { + error.BufferNotFound => {}, + else => return err, + } + }, + //.Union => |union_info| { + // // Note: the main issue here is that several fields could match but we only return the first one. + // inline for (union_info.fields) |field| { + // // interpret obj as a "field", and try to populate that. + // obj.* = @unionInit(T, field.name, undefined); + // const found = try _populateStruct(allocator, buffer_store, unique_id, prefix, &@field(obj.*, field.name), false); + // if (found) { + // std.log.info("Interpreted {s} as {s}", .{ prefix.items, @typeName(field.type) }); + // return true; + // } + // } + // obj.* = undefined; + // if (required) { + // std.log.err("Not able to intepret {s} as any member of the union: {s}", .{ prefix.items, @typeName(T) }); + // } + // return false; + //}, + else => {}, + } +} + +test { + std.testing.refAllDecls(@This()); +} diff --git a/zml/aio/gguf.zig b/zml/aio/gguf.zig new file mode 100644 index 0000000..efe5b37 --- /dev/null +++ b/zml/aio/gguf.zig @@ -0,0 +1,148 @@ +const asynk = @import("async"); +const core = @import("gguf/core.zig"); +const std = @import("std"); +const zml = @import("../zml.zig"); + +const HostBuffer = @import("../hostbuffer.zig").HostBuffer; + +const Allocator = std.mem.Allocator; +const assert = std.debug.assert; + +const log = std.log.scoped(.zml_io); + +pub fn open(allocator: Allocator, path: []const u8) !zml.aio.BufferStore { + var file = try core.GgufFile.open(path); + errdefer file.close(); + + var res: zml.aio.BufferStore = .{ + .arena = std.heap.ArenaAllocator.init(allocator), + }; + errdefer res.arena.deinit(); + const arena = res.arena.allocator(); + + res.files = try arena.dupe(zml.aio.MemoryMappedFile, &.{file.file}); + + // metadata must be read in order to read tensors + try loadMetadata(arena, &res, &file); + try loadBuffers(arena, &res, &file); + if (res.buffers.count() != file.header.tensor_count) { + log.warn("Expected to find {d} tensors in {s}, only found {d}", .{ file.header.tensor_count, path, res.buffers.count() }); + } + return res; +} + +pub fn getGgufTokenizer(self: zml.aio.BufferStore, allocator: std.mem.Allocator) !zml.tokenizer.Tokenizer { + const tokens = self.metadataSlice("tokenizer.ggml.tokens", .string) orelse { + log.err("GGUF File: Tokens not found", .{}); + return error.TokensNotFound; + }; + const scores = self.metadataSlice("tokenizer.ggml.scores", .float32) orelse { + log.err("GGUF File: Scores not found", .{}); + return error.ScoresNotFound; + }; + assert(tokens.len == scores.len); + const tokenizer_type = self.metadata("tokenizer.ggml.model", .string) orelse "llama"; + const tokenizer_impl: zml.tokenizer.KnownImplementation = if (std.mem.eql(u8, tokenizer_type, "gpt2")) .gpt2 else .sentencepiece; + const bos = self.metadata("tokenizer.ggml.bos_token_id", .uint32); + const eos = self.metadata("tokenizer.ggml.eos_token_id", .uint32); + const unk = self.metadata("tokenizer.ggml.unknown_token_id", .uint32); + const pad = self.metadata("tokenizer.ggml.padding_token_id", .uint32); + + const NOT_FOUND = std.math.maxInt(u32); + const special_tokens: zml.tokenizer.Tokenizer.SpecialTokens = .{ + .bos = bos.?, + .eos = eos.?, + .unk = unk orelse NOT_FOUND, + .pad = pad orelse NOT_FOUND, + }; + + // default options + const gguf_normalizer: zml.tokenizer.Normalizer = .{ .flags = .{ + .escape_whitespaces = true, + .remove_extra_whitespaces = true, + .add_dummy_prefix = true, + .add_dummy_suffix = false, + .lower_case_ascii = false, + .split_on_punct_ascii = false, + } }; + + const extra_tokens: u8 = if (tokenizer_impl == .gpt2) 1 else 0; + const n_tokens: u32 = @intCast(tokens.len + extra_tokens); + + var tokenizer = try zml.tokenizer.Tokenizer.init( + allocator, + n_tokens, + 32, + gguf_normalizer, + special_tokens, + true, + ); + + var gpt2_unicode = if (tokenizer_impl == .gpt2) + try zml.tokenizer.Gpt2TextDecoder.init(allocator) + else + null; + defer if (gpt2_unicode) |*gpt2| gpt2.deinit(); + var decoded = std.ArrayList(u8).init(allocator); + defer decoded.deinit(); + + // copy the tokens to the tokenizer arena. + for (tokens, 0..tokens.len) |t, i| { + if (tokenizer_impl == .gpt2) { + decoded.clearRetainingCapacity(); + try tokenizer.addToken(scores[i], try gpt2_unicode.?.decode(&decoded, t)); + // log.debug("token: {s} -> {s}", .{t, decoded.items}); + } else { + try tokenizer.addToken(scores[i], t); + } + } + + // Gpt2 tokenizer always splits on spaces. + if (tokenizer_impl == .gpt2) { + tokenizer.normalizer.?.flags.add_dummy_prefix = true; + tokenizer.normalizer.?.flags.escape_whitespaces = false; + tokenizer.special_tokens.hard_space = tokenizer.next_token_id; + tokenizer.addOwnedToken(0, " "); + } + + return tokenizer; +} + +fn loadMetadata(allocator: Allocator, store: *zml.aio.BufferStore, file: *core.GgufFile) !void { + try store._metadata.ensureTotalCapacity(allocator, @intCast(file.header.metadata_kv_count)); + + while (file.readMetadata(allocator)) |entry| { + log.info("Loading MetaData: {s}", .{entry.name}); + const res = store._metadata.getOrPutAssumeCapacity(entry.name); + if (res.found_existing) { + // This file seems invalid. Since most metadatas aren't required, continue ahead. + log.warn("Found duplicated metadata key: {s}", .{entry.name}); + continue; + } + res.value_ptr.* = entry.val.asLoaderValue(); + } else |err| switch (err) { + error.EndOfMetadata => {}, + else => return err, + } +} + +fn loadBuffers(allocator: Allocator, store: *zml.aio.BufferStore, file: *core.GgufFile) !void { + try store.buffers.ensureTotalCapacity(allocator, @intCast(file.header.tensor_count)); + while (file.readTensorInfo(allocator)) |info| { + const res = store.buffers.getOrPutAssumeCapacity(info.name); + if (res.found_existing) { + // This file seems invalid. Try to continue anyway. + log.warn("Found duplicated tensor: {s}", .{info.name}); + continue; + } + + // TODO: handle quantized types + const dtype: zml.DataType = info.t.toDtype() orelse return error.UnsupportedGgufType; + const buffer = HostBuffer.fromBytes(zml.Shape.init(info.shape(), dtype), file.file.mappedSlice(info.start, info.byte_len)); + res.value_ptr.* = buffer; + // store the info index. + } else |err| switch (err) { + error.EndOfMetadata => {}, + else => return err, + } +} diff --git a/zml/aio/gguf/core.zig b/zml/aio/gguf/core.zig new file mode 100644 index 0000000..61b5137 --- /dev/null +++ b/zml/aio/gguf/core.zig @@ -0,0 +1,530 @@ +const asynk = @import("async"); +const std = @import("std"); +const utils = @import("../utils.zig"); +const zml = @import("../../zml.zig"); + +const assert = std.debug.assert; +const log = std.log.scoped(.zml_io); + +pub const GgufErrors = error{ + ValueTypeMismatch, + InvalidGguf, + UnsupportedGgufType, + EndOfMetadata, + OutOfMemory, +}; + +// Enums and structures +pub const TensorType = enum(u32) { + f32 = 0, + f16 = 1, + q4_0 = 2, + q4_1 = 3, + deprecated_q4_2 = 4, + deprecated_q4_3 = 5, + q5_0 = 6, + q5_1 = 7, + q8_0 = 8, + q8_1 = 9, + // k-quantizations + q2_k = 10, + q3_k = 11, + q4_k = 12, + q5_k = 13, + q6_k = 14, + q8_k = 15, + i8 = 16, + i16 = 17, + i32 = 18, + + const MAX_KNOWN_ENUM = 18; + + pub fn canConvertQuant(self: TensorType) bool { + return switch (self) { + .q8_0, .q4_k, .q6_k, .q2_k, .q4_0, .q4_1 => true, + else => false, + }; + } + + pub fn toDtype(self: TensorType) ?zml.DataType { + return switch (self) { + .f32 => .f32, + .f16 => .f16, + .i8 => .i8, + .i16 => .i16, + .i32 => .i32, + else => null, + }; + } + + pub fn sizeOf(self: TensorType) usize { + return self.toDtype().?.sizeOf(); + } + + /// Return the tensor type features + pub fn getFeatures(t: TensorType) TensorTypeFeatures { + return switch (t) { + inline else => |val| @field(TENSOR_TYPE_FEATURES, @tagName(val)), + }; + } +}; + +/// GGUF tensor type to features lookup table. +pub const TensorTypeFeatures = struct { + items_per_block: u29, + bytes_per_block: u29, + + pub fn alignment(features: TensorTypeFeatures) u8 { + return std.math.log2_int(u29, features.bytes_per_block); + } +}; + +pub const TENSOR_TYPE_FEATURES: std.enums.EnumFieldStruct(TensorType, TensorTypeFeatures, null) = .{ + .f32 = .{ .items_per_block = 1, .bytes_per_block = @sizeOf(f32) }, + .f16 = .{ .items_per_block = 1, .bytes_per_block = @sizeOf(f16) }, + .q4_0 = .{ .items_per_block = 32, .bytes_per_block = 18 }, + .q4_1 = .{ .items_per_block = 32, .bytes_per_block = 20 }, + .deprecated_q4_2 = .{ .items_per_block = 0, .bytes_per_block = 0 }, + .deprecated_q4_3 = .{ .items_per_block = 0, .bytes_per_block = 0 }, + .q5_0 = .{ .items_per_block = 32, .bytes_per_block = 22 }, + .q5_1 = .{ .items_per_block = 32, .bytes_per_block = 24 }, + .q8_0 = .{ .items_per_block = 32, .bytes_per_block = 34 }, + .q8_1 = .{ .items_per_block = 32, .bytes_per_block = 40 }, + .q2_k = .{ .items_per_block = 256, .bytes_per_block = 82 }, + .q3_k = .{ .items_per_block = 256, .bytes_per_block = 110 }, + .q4_k = .{ .items_per_block = 256, .bytes_per_block = 144 }, + .q5_k = .{ .items_per_block = 256, .bytes_per_block = 176 }, + .q6_k = .{ .items_per_block = 256, .bytes_per_block = 210 }, + .q8_k = .{ .items_per_block = 256, .bytes_per_block = 292 }, + .i8 = .{ .items_per_block = 1, .bytes_per_block = @sizeOf(i8) }, + .i16 = .{ .items_per_block = 1, .bytes_per_block = @sizeOf(i16) }, + .i32 = .{ .items_per_block = 1, .bytes_per_block = @sizeOf(i32) }, +}; + +pub const GgufValueType = enum(u32) { + // The value is a 8-bit unsigned integer. + uint8 = 0, + // The value is a 8-bit signed integer. + int8 = 1, + // The value is a 16-bit unsigned little-endian integer. + uint16 = 2, + // The value is a 16-bit signed little-endian integer. + int16 = 3, + // The value is a 32-bit unsigned little-endian integer. + uint32 = 4, + // The value is a 32-bit signed little-endian integer. + int32 = 5, + // The value is a 32-bit IEEE754 floating point number. + float32 = 6, + // The value is a boolean. + // 1-byte value where 0 is false and 1 is true. + // Anything else is invalid, and should be treated as either the model + // being invalid or the reader being buggy. + bool = 7, + // The value is a UTF-8 non-null-terminated string, with length prepended. + string = 8, + // The value is an array of other values, with the length and type + // prepended. Arrays can be nested, and the length of the array is the + // number of elements in the array, not the number of bytes. + array = 9, + // The value is a 64-bit unsigned little-endian integer. + uint64 = 10, + // The value is a 64-bit signed little-endian integer. + int64 = 11, + // The value is a 64-bit IEEE754 floating point number. + float64 = 12, + // Special values used by the callbacks of gguf_do_with_value(). + array_start = 100, + array_end = 101, + + // Allow other values in case GGUF add more types without us noticing + _, + + pub fn sizeOf(self: GgufValueType) usize { + return switch (self) { + .uint8 => @sizeOf(u8), + .int8 => @sizeOf(i8), + .uint16 => @sizeOf(u16), + .int16 => @sizeOf(i16), + .uint32 => @sizeOf(u32), + .int32 => @sizeOf(i32), + .float32 => @sizeOf(f32), + .bool => @sizeOf(bool), + .uint64 => @sizeOf(u64), + .int64 => @sizeOf(i64), + .float64 => @sizeOf(f64), + .string => @sizeOf([]u8), + else => unreachable, + }; + } + + pub fn arrayTypeCheck(self: GgufValueType, comptime T: type) !void { + switch (self) { + .string => if (T != []u8 and T != []const u8) return error.ValueTypeMismatch, + .uint8 => if (T != u8) return error.ValueTypeMismatch, + .int8 => if (T != i8) return error.ValueTypeMismatch, + .uint16 => if (T != u16) return error.ValueTypeMismatch, + .int16 => if (T != i16) return error.ValueTypeMismatch, + .uint32 => if (T != u32) return error.ValueTypeMismatch, + .int32 => if (T != i32) return error.ValueTypeMismatch, + .float32 => if (T != f32) return error.ValueTypeMismatch, + .bool => if (T != bool) return error.ValueTypeMismatch, + .uint64 => if (T != u64) return error.ValueTypeMismatch, + .int64 => if (T != i64) return error.ValueTypeMismatch, + .float64 => if (T != f64) return error.ValueTypeMismatch, + else => {}, + } + } +}; + +pub const ValueType = enum { + uint8, + int8, + uint16, + int16, + uint32, + int32, + float32, + uint64, + int64, + float64, + boolval, + string, + array, +}; + +// Union of possible values. +pub const GgufValue = union(ValueType) { + uint8: u8, + int8: i8, + uint16: u16, + int16: i16, + uint32: u32, + int32: i32, + float32: f32, + uint64: u64, + int64: i64, + float64: f64, + boolval: bool, + string: []const u8, + array: Array, + + pub const Array = struct { + // Any value type is valid, including arrays. + child: GgufValueType, + // Number of elements, not bytes + len: usize, + data: []u8, + }; + + pub fn asLoaderValue(self: GgufValue) zml.aio.Value { + return switch (self) { + .array => |v| .{ + .array = .{ + .item_type = switch (v.child) { + .bool => .boolval, + .uint8 => .uint8, + .int8 => .int8, + .uint16 => .uint16, + .int16 => .int16, + .uint32 => .uint32, + .int32 => .int32, + .float32 => .float32, + .uint64 => .uint64, + .int64 => .int64, + .float64 => .float64, + .string => .string, + // TODO: .array => .array, + else => unreachable, + }, + .data = v.data, + }, + }, + inline else => |v, tag| @unionInit(zml.aio.Value, @tagName(tag), v), + }; + } +}; + +// Header +const GgufHeader = extern struct { + // Magic number to announce that this is a GGUF file. Must be `GUFF`. + magic: [4]u8, + // The version of the format implemented. + // Must be `3` for version described in this spec. + version: u32, + // The number of tensors in the file. + // This is explicit, instead of being included in the metadata, to ensure + // it is always present for loading the tensors. + tensor_count: usize, + // The number of metadata key-value pairs. + metadata_kv_count: usize, + + pub fn validate(self: GgufHeader) !void { + if (!std.mem.eql(u8, &self.magic, "GGUF")) { + log.err("Invalid GGUF file: wrong header {s}", .{self.magic}); + return error.InvalidGguf; + } + } +}; + +// Key representation in this library API. +pub const GgufMetadataKv = struct { + name: []const u8, + type_: GgufValueType, + val: GgufValue, +}; + +// Tensor representation in this library API. +const GGUF_TENSOR_MAX_DIM: usize = 8; // Future-proof: actual limit is 4. +pub const GgufTensorInfo = struct { + name: []const u8, + t: TensorType, // Tensor type (enum TensorType). + rank: usize, // Number of dimensions of the tensor. + dims: [GGUF_TENSOR_MAX_DIM]i64, // Dimensions (Eg. [512, 1024, 1, 1]). + start: usize, // Offset from start of data section. + byte_len: usize, // Total size in bytes. + num_weights: usize, // Total number of parameters. + + pub inline fn shape(info: GgufTensorInfo) []const i64 { + return info.dims[0..info.rank]; + } +}; + +// Return the value type name given the type ID. +fn getValueTypeName(t: u32) []const u8 { + if (@as(usize, @intCast(t)) >= GGUF_VALUE_NAME.len) return "unknown"; + return GGUF_VALUE_NAME[@intCast(t)]; +} + +const GGUF_VALUE_NAME = [_][]const u8{ + "uint8", "int8", "uint16", "int16", "uint32", "int32", + "float32", "bool", "string", "array", "uint64", "int64", + "float64", +}; + +/// GGUF file API +/// A memory-mapped view of a .gguf file. +/// Format used by GGML models: https://github.com/ggerganov/ggml/ +pub const GgufFile = struct { + header: GgufHeader, // GUFF file header info. + size: usize, // Total file size. + file: zml.aio.MemoryMappedFile, + left_kv: usize, // Number of key-value pairs yet to read. + left_tensors: usize, // Number of tensors yet to read. + off: usize, // Offset of the next item to parse. + alignment: usize = 32, // File data alignment. Default: 32 bytes. + + /// Open and memmap the given file. + pub fn open(path: []const u8) !GgufFile { + const file = try asynk.File.open(path, .{}); + const header = try file.reader().readStruct(GgufHeader); + try header.validate(); + return .{ + .header = header, + .size = (try file.stat()).size, + .file = try zml.aio.MemoryMappedFile.init(file), + .off = @sizeOf(GgufHeader), + .left_kv = header.metadata_kv_count, + .left_tensors = header.tensor_count, + }; + } + + /// Unmap the file memory and close the file handle. + pub fn close(self: *GgufFile) void { + self.file.deinit(); + } + + /// Set the context to read the first key-value entry in the GGUF + /// file and then all the rest. Is used when creating a new context + /// and also when you want to restart scanning the key-value + /// items in the file. + fn rewind(ctx: *GgufFile) void { + ctx.off = @sizeOf(GgufHeader); + ctx.left_kv = ctx.header.metadata_kv_count; + ctx.left_tensors = ctx.header.tensor_count; + } + + pub fn seek(self: *GgufFile, pos: usize) void { + assert(pos < self.size); + self.off = pos; + } + + fn readInt(self: *GgufFile, comptime T: type) !T { + if (self.off + @sizeOf(T) >= self.size) return error.InvalidGguf; + const res = self.file.file.reader().readInt(T, .little); + self.off += @sizeOf(T); + return res; + } + + fn readTensorType(self: *GgufFile) !TensorType { + const raw = try self.readInt(u32); + if (raw > TensorType.MAX_KNOWN_ENUM) { + log.err("Unsupported GGUF tensor type: {d}", .{raw}); + return error.UnsupportedGgufType; + } + return @enumFromInt(raw); + } + + fn readValueType(self: *GgufFile) !GgufValueType { + const raw = try self.readInt(u32); + const t: GgufValueType = @enumFromInt(raw); + switch (t) { + .uint8, .int8, .uint16, .int16, .uint32, .int32, .float32, .bool, .string, .array, .uint64, .int64, .float64, .array_start, .array_end => {}, + else => { + log.err("Unsupported GGUF value type: {s}", .{@tagName(t)}); + return error.UnsupportedGgufType; + }, + } + return t; + } + + pub fn readAlloc(self: *GgufFile, allocator: std.mem.Allocator, len: usize) ![]u8 { + const data = try allocator.alloc(u8, len); + const read = try self.file.file.reader().readAll(data); + if (read != data.len) return error.InvalidGguf; + self.off += len; + return data; + } + + pub fn skipBytes(self: *GgufFile, len: usize) !void { + try self.file.file.seekBy(@intCast(len)); + self.off += len; + } + + /// Read the len then the actual bytes. + pub fn readString(self: *GgufFile, allocator: std.mem.Allocator) ![]u8 { + const len: usize = try self.readInt(u64); + return self.readAlloc(allocator, len); + } + + pub fn skipString(self: *GgufFile) !void { + const len: usize = try self.readInt(u64); + return self.skipBytes(len); + } + + fn readArrayHeader(self: *GgufFile, allocator: std.mem.Allocator) !GgufValue.Array { + const child = try self.readValueType(); + const len: usize = try self.readInt(u64); + const data = switch (child) { + // Since strings have variable lenghts, we need to read them one by one + .string => str: { + var data = try allocator.alloc([]u8, len); + for (0..len) |i| data[i] = try self.readString(allocator); + break :str std.mem.sliceAsBytes(data); + }, + else => try self.readAlloc(allocator, len * child.sizeOf()), + }; + return .{ + .child = child, + .len = len, + .data = data, + }; + } + + fn readTypedValue(self: *GgufFile, allocator: std.mem.Allocator, t: GgufValueType) !GgufValue { + return switch (t) { + .uint8 => .{ .uint8 = try self.readInt(u8) }, + .int8 => .{ .int8 = try self.readInt(i8) }, + .uint16 => .{ .uint16 = try self.readInt(u16) }, + .int16 => .{ .int16 = try self.readInt(i16) }, + .uint32 => .{ .uint32 = try self.readInt(u32) }, + .int32 => .{ .int32 = try self.readInt(i32) }, + .float32 => .{ .float32 = @bitCast(try self.readInt(u32)) }, + .bool => .{ .boolval = try self.readInt(u8) != 0 }, + .string => .{ .string = try self.readString(allocator) }, + .array => .{ .array = try self.readArrayHeader(allocator) }, + .uint64 => .{ .uint64 = try self.readInt(u64) }, + .int64 => .{ .int64 = try self.readInt(i64) }, + .float64 => .{ .float64 = @bitCast(try self.readInt(u64)) }, + else => error.UnsupportedGgufType, + }; + } + + /// Parses the next metadata entry. + /// Returns error.EndOfMetadata if there are no longer metadata to process in this GGUF file. + pub fn readMetadata(self: *GgufFile, allocator: std.mem.Allocator) !GgufMetadataKv { + if (self.left_kv == 0) return error.EndOfMetadata; + self.left_kv -= 1; + const name = try self.readString(allocator); + const type_ = try self.readValueType(); + const val: GgufValue = try self.readTypedValue(allocator, type_); + return .{ .name = name, .type_ = type_, .val = val }; + } + + // Set the data section offset. This function must be called exactly when + // all the key-values are consumed, in the context of the first call of + // ctx.getTensor(): this way we will be able to return tensor offsets + // as absolute positions and pointers to the mmapped file. + fn setDataOffset(self: *GgufFile) !void { + const base_off = self.off; + + assert(self.left_kv == 0 and self.left_tensors == self.header.tensor_count); + + for (0..self.left_tensors) |_| try self.skipTensor(); + const padding: usize = getAlignmentPadding(self.alignment, self.off); + self.file.data_offset = self.off + padding; + + try self.file.file.seekTo(base_off); + self.off = base_off; + } + + pub fn skipTensor(self: *GgufFile) !void { + try self.skipString(); // Skip name + const num_dim: u32 = try self.readInt(u32); + // dimensions, type, and offset. + try self.skipBytes(8 * num_dim + 4 + 8); + } + + /// Parses the next tensor entry. + /// Returns error.EndOfMetadata if there are no longer tensor metadata to process in this GGUF file. + pub fn readTensorInfo(self: *GgufFile, allocator: std.mem.Allocator) !GgufTensorInfo { + if (self.left_tensors == 0 or self.left_kv != 0) { + return error.EndOfMetadata; + } + + // We want to return tensor data with offsets relative to the start + // of the file, so that the user of the API is able to access tensors + // as it iterates over them. To do so, we need to perform a full + // scan if this is the first tensor info we are reading. + // TODO: explicitly set the data offset in + if (self.file.data_offset == 0) try self.setDataOffset(); + self.left_tensors -= 1; + const name = try self.readString(allocator); + const num_dim = try self.readInt(u32); + assert(@as(usize, @intCast(num_dim)) <= GGUF_TENSOR_MAX_DIM); + // Read the dimentions; unused dimensions are left `undefined`. + // Note: we reverse the order of the dimensions to match zml convention. + var dims: [GGUF_TENSOR_MAX_DIM]i64 = undefined; + var num_weights: usize = 1; + for (0..num_dim) |j| { + const d = try self.readInt(u64); + dims[num_dim - 1 - j] = @intCast(d); + num_weights *= d; + } + const t: TensorType = try self.readTensorType(); + const start = try self.readInt(u64); + // To accurately calculate the bytes used by this tensor on the GGUF + // file, we need to take into account that quantization methods store + // tensors as block of N weights. So first of all we need to understand + // the number of padding weights (since the last block may have just + // fewer weights stored inside, but still requires to be stored to its full + // length). Then we can do the math to see how many blocks we need, and + // multiply by the block size to obtain the final total size. + const tf = t.getFeatures(); + const byte_len: usize = (std.math.divCeil(usize, num_weights, tf.items_per_block) catch unreachable) * tf.bytes_per_block; + return .{ + .name = name, + .t = t, + .rank = num_dim, + .dims = dims, + .start = start, + .byte_len = byte_len, + .num_weights = num_weights, + }; + } +}; + +/// Given an offset or a length, returns the padding needed to align it to alignment. +fn getAlignmentPadding(alignment: usize, offset: usize) usize { + return @rem((alignment - @rem(offset, alignment)), alignment); +} diff --git a/zml/aio/json.zig b/zml/aio/json.zig new file mode 100644 index 0000000..b08cb17 --- /dev/null +++ b/zml/aio/json.zig @@ -0,0 +1,103 @@ +const asynk = @import("async"); +const std = @import("std"); +const utils = @import("utils.zig"); +const zml = @import("../zml.zig"); + +const StringBuilder = std.ArrayListUnmanaged(u8); +const Allocator = std.mem.Allocator; + +pub fn open(allocator: std.mem.Allocator, path: []const u8) !zml.aio.BufferStore { + const file = try std.fs.cwd().openFile(path, .{}); + defer file.close(); + var res: zml.aio.BufferStore = .{ + .arena = std.heap.ArenaAllocator.init(allocator), + }; + errdefer res.arena.deinit(); + const arena = res.arena.allocator(); + + const json_data = try file.reader().readAllAlloc(arena, (try file.metadata()).size()); + const metadata = try std.json.parseFromSliceLeaky(std.json.Value, allocator, json_data, .{ .allocate = .alloc_if_needed }); + + var it = metadata.object.iterator(); + while (it.next()) |entry| { + var prefix_buf: [1024]u8 = undefined; + try parseMetadata(allocator, &res, StringBuilder.initBuffer(&prefix_buf), entry.value_ptr.*); + } + + return res; +} + +pub fn parseMetadata(allocator: Allocator, store: *zml.aio.BufferStore, key: StringBuilder, val: std.json.Value) !void { + const metadata = &store._metadata; + switch (val) { + .null => try metadata.put(allocator, try allocator.dupe(u8, key.items), .{ .null = {} }), + .bool => |v| try metadata.put(allocator, try allocator.dupe(u8, key.items), .{ .boolval = v }), + .integer => |v| try metadata.put(allocator, try allocator.dupe(u8, key.items), .{ .int64 = v }), + .float => |v| try metadata.put(allocator, try allocator.dupe(u8, key.items), .{ .float64 = v }), + .number_string, .string => |v| try metadata.put(allocator, try allocator.dupe(u8, key.items), .{ .string = try allocator.dupe(u8, v) }), + .array => |v| switch (validSlice(v)) { + true => { + if (v.items.len == 0) return; + switch (v.items[0]) { + .bool => { + const values = try allocator.alloc(bool, v.items.len); + errdefer allocator.free(values); + for (v.items, 0..) |item, i| values[i] = item.bool; + try metadata.put(allocator, try allocator.dupe(u8, key.items), .{ .array = .{ .item_type = .boolval, .data = std.mem.sliceAsBytes(values) } }); + }, + .integer => { + const values = try allocator.alloc(i64, v.items.len); + errdefer allocator.free(values); + for (v.items, 0..) |item, i| values[i] = item.integer; + try metadata.put(allocator, try allocator.dupe(u8, key.items), .{ .array = .{ .item_type = .int64, .data = std.mem.sliceAsBytes(values) } }); + }, + .float => { + const values = try allocator.alloc(f64, v.items.len); + errdefer allocator.free(values); + for (v.items, 0..) |item, i| values[i] = item.float; + try metadata.put(allocator, try allocator.dupe(u8, key.items), .{ .array = .{ .item_type = .float64, .data = std.mem.sliceAsBytes(values) } }); + }, + inline .string, .number_string => |_, tag| { + const values = try allocator.alloc([]const u8, v.items.len); + errdefer allocator.free(values); + for (v.items, 0..) |item, i| { + values[i] = @field(item, @tagName(tag)); + } + try metadata.put(allocator, try allocator.dupe(u8, key.items), .{ .array = .{ .item_type = .string, .data = std.mem.sliceAsBytes(values) } }); + }, + else => unreachable, + } + }, + false => for (v.items, 0..) |item, i| { + var new_key = key; + if (key.items.len > 0) + new_key.appendAssumeCapacity('.'); + new_key.items.len += std.fmt.formatIntBuf(new_key.unusedCapacitySlice(), i, 10, .lower, .{}); + try parseMetadata(allocator, store, new_key, item); + }, + }, + .object => |v| { + var obj_iter = v.iterator(); + while (obj_iter.next()) |entry| { + var new_key = key; + if (key.items.len > 0) + new_key.appendAssumeCapacity('.'); + new_key.appendSliceAssumeCapacity(entry.key_ptr.*); + try parseMetadata(allocator, store, new_key, entry.value_ptr.*); + } + }, + } +} + +fn validSlice(v: std.json.Array) bool { + const item_type = std.meta.activeTag(v.items[0]); + switch (item_type) { + .null, .array, .object => return false, + else => {}, + } + + for (v.items[1..]) |item| + if (item_type != std.meta.activeTag(item)) return false; + + return true; +} diff --git a/zml/aio/nemo.zig b/zml/aio/nemo.zig new file mode 100644 index 0000000..7fb5f30 --- /dev/null +++ b/zml/aio/nemo.zig @@ -0,0 +1,56 @@ +const asynk = @import("async"); +const eval = @import("torch/eval.zig"); +const std = @import("std"); +const yaml = @import("zig-yaml"); +const zml = @import("../zml.zig"); + +const Decoder = @import("torch/parser.zig").Decoder; + +const StringBuilder = std.ArrayListUnmanaged(u8); + +pub fn open(allocator: std.mem.Allocator, path: []const u8) !zml.aio.BufferStore { + var res: zml.aio.BufferStore = .{ + .arena = std.heap.ArenaAllocator.init(allocator), + }; + errdefer res.arena.deinit(); + + const arena = res.arena.allocator(); + + var mapped_file = try zml.aio.MemoryMappedFile.init(try asynk.File.open(path, .{})); + errdefer mapped_file.deinit(); + + var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined; + var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined; + var tar_iter = std.tar.iterator( + mapped_file.file.reader(), + .{ + .file_name_buffer = &file_name_buffer, + .link_name_buffer = &link_name_buffer, + }, + ); + while (try tar_iter.next()) |file| { + if (std.mem.endsWith(u8, file.name, ".yaml")) { + const yaml_data = try file.reader().readAllAlloc(arena, file.size); + const parsed = try yaml.Yaml.load(arena, yaml_data); + + var prefix_buf: [1024]u8 = undefined; + try zml.aio.yaml.parseMetadata(arena, &res, StringBuilder.initBuffer(&prefix_buf), parsed.docs.items[0].map); + } else if (std.mem.endsWith(u8, file.name, ".ckpt") or std.mem.endsWith(u8, file.name, ".pt")) { + const start = try mapped_file.file.getPos(); + var tmp: zml.aio.torch.PickleData = .{ + .data = try Decoder.fromTarFile(arena, mapped_file, file), + .memo = undefined, + .stack = undefined, + }; + tmp.stack, tmp.memo = try eval.evaluate(arena, tmp.data.ops, true); + try tmp.parseModel(arena, &res); + // Since we directly manipulate the file handle pointer, + // reset to the end of file so iterator does not error + // and avoid `skipBytes`. + try mapped_file.file.seekTo(start + file.size); + file.unread_bytes.* = 0; + } else if (std.mem.eql(u8, file.name, "./model_weights/")) @panic(".NeMo sharded weights are not yet supported") else continue; + } + + return res; +} diff --git a/zml/aio/safetensors.zig b/zml/aio/safetensors.zig new file mode 100644 index 0000000..c56e4b0 --- /dev/null +++ b/zml/aio/safetensors.zig @@ -0,0 +1,140 @@ +const asynk = @import("async"); +const std = @import("std"); +const zml = @import("../zml.zig"); +const helpers = @import("../helpers.zig"); +const utils = @import("utils.zig"); +const json = @import("json.zig"); +const HostBuffer = @import("../hostbuffer.zig").HostBuffer; +const MemoryMappedFile = @import("../aio.zig").MemoryMappedFile; + +const StringBuilder = std.ArrayListUnmanaged(u8); +const Allocator = std.mem.Allocator; +const log = std.log.scoped(.zml_io); + +fn stringToDtype(v: []const u8) !zml.DataType { + const Case = enum { F64, F32, F16, BF16, F8_E4M3, I64, I32, I16, I8, U64, U32, U16, U8, BOOL }; + if (std.meta.stringToEnum(Case, v)) |case| { + return switch (case) { + .F64 => .f64, + .F32 => .f32, + .F16 => .f16, + .BF16 => .bf16, + .F8_E4M3 => .f8e4m3fn, + .I64 => .i64, + .I32 => .i32, + .I16 => .i16, + .I8 => .i8, + .U64 => .u64, + .U32 => .u32, + .U16 => .u16, + .U8 => .u8, + .BOOL => .bool, + }; + } + std.log.err("Unsupported type-string: {s}\n", .{v}); + return error.UnsupportedDataType; +} + +pub fn open(allocator: std.mem.Allocator, path: []const u8) !zml.aio.BufferStore { + var res: zml.aio.BufferStore = .{ + .arena = std.heap.ArenaAllocator.init(allocator), + }; + errdefer res.arena.deinit(); + const arena = res.arena.allocator(); + + var files = std.ArrayList(MemoryMappedFile).init(arena); + errdefer files.deinit(); + + if (std.mem.endsWith(u8, path, ".safetensors.index.json")) { + try loadFromIndex(arena, &res, &files, path); + } else { + try loadFile(arena, &res, &files, path); + } + res.files = try files.toOwnedSlice(); + return res; +} + +fn loadFromIndex(allocator: Allocator, store: *zml.aio.BufferStore, files: *std.ArrayList(MemoryMappedFile), path: []const u8) !void { + const file = asynk.File.open(path, .{}) catch |err| { + log.err("Failed to open {s}: {}", .{ path, err }); + return err; + }; + errdefer file.close() catch unreachable; + var r = file.reader(); + + const json_data = try allocator.alloc(u8, (try file.stat()).size); + _ = try r.readAtLeast(json_data, json_data.len); + const metadata = try std.json.parseFromSliceLeaky(std.json.Value, allocator, json_data, .{ .allocate = .alloc_if_needed }); + var loaded_files = std.StringHashMap(void).init(allocator); + + const weight_map = metadata.object.get("weight_map").?.object; + var it = weight_map.iterator(); + while (it.next()) |entry| { + const filename = entry.value_ptr.string; + if (loaded_files.contains(filename)) { + continue; + } + + log.debug("Loading shard: {s}", .{filename}); + try loaded_files.put(filename, {}); + + const full_filename = try std.fs.path.join(allocator, &.{ std.fs.path.dirname(path).?, filename }); + try loadFile(allocator, store, files, full_filename); + } +} + +fn loadFile(allocator: Allocator, store: *zml.aio.BufferStore, files: *std.ArrayList(MemoryMappedFile), path: []const u8) !void { + const file = asynk.File.open(path, .{}) catch |err| { + log.err("Failed to open {s}: {}", .{ path, err }); + return err; + }; + errdefer file.close() catch unreachable; + var r = file.reader(); + + const json_header_length: usize = @intCast(try r.readInt(u64, std.builtin.Endian.little)); + const json_data = try allocator.alloc(u8, json_header_length); + _ = try r.readAtLeast(json_data, json_header_length); + const metadata = try std.json.parseFromSliceLeaky(std.json.Value, allocator, json_data, .{ .allocate = .alloc_if_needed }); + + var buffer_file = try MemoryMappedFile.init(file); + errdefer buffer_file.deinit(); + buffer_file.data_offset = 8 + json_header_length; + + try files.append(buffer_file); + errdefer _ = files.popOrNull(); + + var it = metadata.object.iterator(); + while (it.next()) |entry| { + const key = entry.key_ptr.*; + if (std.mem.eql(u8, key, "__metadata__")) { + var prefix_buf: [1024]u8 = undefined; + try json.parseMetadata(allocator, store, StringBuilder.initBuffer(&prefix_buf), entry.value_ptr.*); + continue; + } + const val = entry.value_ptr.*; + const shape_field = val.object.get("shape").?.array; + if (shape_field.items.len > zml.Shape.MAX_RANK) { + // Not an error until someone tries to read the tensor itself. + log.warn("Can't load tensor {s}, too many dims: {}", .{ key, shape_field.items.len }); + continue; + } + const offset_field = val.object.get("data_offsets").?; + const start: usize = @intCast(offset_field.array.items[0].integer); + const end: usize = @intCast(offset_field.array.items[1].integer); + const dtype = try stringToDtype(val.object.get("dtype").?.string); + var dims: std.BoundedArray(i64, zml.Shape.MAX_RANK) = .{}; + for (shape_field.items) |d| { + dims.appendAssumeCapacity(d.integer); + } + + const out_shape = zml.Shape.init(dims.constSlice(), dtype); + // We aren't storing 'end', so check we can infer it from the tensor shape. + // This is fine cause safetensor only allow storing contiguous tensors. + // https://github.com/huggingface/safetensors/blob/main/README.md#format + // > The byte buffer needs to be entirely indexed, and cannot contain holes. This prevents the creation of polyglot files. + std.debug.assert(end - start == out_shape.byteSize()); + + const buf = HostBuffer.fromBytes(out_shape, buffer_file.mappedSlice(start, out_shape.byteSize())); + try store.buffers.put(allocator, try allocator.dupe(u8, key), buf); + } +} diff --git a/zml/aio/sentencepiece.zig b/zml/aio/sentencepiece.zig new file mode 100644 index 0000000..8b4b04a --- /dev/null +++ b/zml/aio/sentencepiece.zig @@ -0,0 +1,79 @@ +const std = @import("std"); +const asynk = @import("async"); +const zml = @import("../zml.zig"); + +const sentencepiece_proto = @import("//sentencepiece:model_proto"); +const Normalizer = zml.tokenizer.Normalizer; +const Tokenizer = zml.tokenizer.Tokenizer; + +pub fn loadTokenizerFromPath(allocator: std.mem.Allocator, path: []const u8) !Tokenizer { + const file = try asynk.File.open(path, .{}); + defer file.close() catch unreachable; + + return loadTokenizerFromFile(allocator, file); +} + +pub fn loadTokenizerFromFile(allocator: std.mem.Allocator, file: asynk.File) !Tokenizer { + const reader = file.reader(); + const input = try reader.readAllAlloc(allocator, 16 * 1024 * 1024); + defer allocator.free(input); + + var proto_arena = std.heap.ArenaAllocator.init(allocator); + defer proto_arena.deinit(); + + const model = try sentencepiece_proto.ModelProto.decode(input, proto_arena.allocator()); + // no deinit, memory will be freed by the proto_arena + + return loadTokenizerFromModelProto(allocator, model); +} + +pub fn loadTokenizerFromModelProto(allocator: std.mem.Allocator, model: sentencepiece_proto.ModelProto) !Tokenizer { + std.debug.assert(model.trainer_spec.?.model_type.? == .BPE); + const special_tokens: Tokenizer.SpecialTokens = .{ + .unk = @intCast(model.trainer_spec.?.unk_id.?), + .bos = @intCast(model.trainer_spec.?.bos_id.?), + .eos = @intCast(model.trainer_spec.?.eos_id.?), + .pad = parseTokenId(model.trainer_spec.?.pad_id), + }; + + var tokenizer = try Tokenizer.init( + allocator, + @intCast(model.pieces.items.len), + @intCast(model.trainer_spec.?.max_sentencepiece_length.?), + normalizerFromSpec(model.normalizer_spec.?), + special_tokens, + true, + ); + errdefer tokenizer.deinit(); + + for (model.pieces.items) |*piece| { + try tokenizer.addToken(piece.score.?, piece.piece.?.getSlice()); + } + + return tokenizer; +} + +fn parseTokenId(id: ?i32) u32 { + if (id) |idx| { + if (idx > 0) return @intCast(idx); + } + + return std.math.maxInt(u32); +} + +pub fn normalizerFromSpec(spec: sentencepiece_proto.NormalizerSpec) Normalizer { + std.log.info("NormalizerSpec: {}", .{spec}); + if (spec.normalization_rule_tsv) |rule_tsv| { + if (!rule_tsv.isEmpty()) { + std.debug.panic("SentencePiece model with normalization rules not supported: model.normalizer_spec.normalization_rule_tsv: {s}", .{spec.normalization_rule_tsv.?.getSlice()}); + } + } + if (!std.mem.eql(u8, spec.name.?.getSlice(), "identity")) std.debug.panic("Normalizer only supports NormalizerSpec with name \"identity\", got \"{s}\"", .{spec.name.?.getSlice()}); + if (!spec.escape_whitespaces.?) std.debug.panic("Normalizer only supports NormalizerSpec with \"escape_whitespaces\" flag set", .{}); + if (spec.remove_extra_whitespaces) |_| {} else std.debug.panic("Normalizer only supports NormalizerSpec with \"remove_extra_whitespaces\" flag set", .{}); + if (spec.add_dummy_prefix) |_| {} else std.debug.panic("Normalizer only supports NormalizerSpec with \"add_dummy_prefix\" flag set", .{}); + return .{ .flags = .{ + .remove_extra_whitespaces = spec.remove_extra_whitespaces orelse false, + .add_dummy_prefix = spec.add_dummy_prefix orelse true, + } }; +} diff --git a/zml/aio/tinyllama.zig b/zml/aio/tinyllama.zig new file mode 100644 index 0000000..3f65149 --- /dev/null +++ b/zml/aio/tinyllama.zig @@ -0,0 +1,162 @@ +/// Tools to load models from https://huggingface.co/karpathy/tinyllamas/ +/// Originally made to be run with https://github.com/karpathy/llama2.c +const std = @import("std"); + +const asynk = @import("async"); + +const zml = @import("../zml.zig"); + +const TinyLlamaConfig = extern struct { + dim: u32, + hidden_dim: u32, + n_layers: u32, + n_heads: u32, + n_kv_heads: u32, + // llama2.c uses the sign bit of the vocab size to store if we need + // a second embedding layer. + vocab: packed struct(u32) { + size: u31, + has_lm_head: bool, + }, + seq_len: u32, +}; + +/// Open a tinyllama file. +/// For convenience we use the same layer names +/// than the one used by the Llama-3.1 models. +pub fn open(allocator: std.mem.Allocator, model_path: []const u8) !zml.aio.BufferStore { + var res: zml.aio.BufferStore = .{ + .arena = std.heap.ArenaAllocator.init(allocator), + }; + errdefer res.arena.deinit(); + const arena = res.arena.allocator(); + + const file = try asynk.File.open(model_path, .{}); + res.files = try arena.alloc(zml.aio.MemoryMappedFile, 1); + res.files[0] = try zml.aio.MemoryMappedFile.init(file); + + const c = try file.reader().readStructEndian(TinyLlamaConfig, .little); + zml.log.info("Read TinyLlamaConfig: {}", .{c}); + + const dim = c.dim; + const hidden_dim = c.hidden_dim; + const n_layers = c.n_layers; + const n_heads = c.n_heads; + const n_kv_heads = c.n_kv_heads; + const seq_len = c.seq_len; + const head_size = c.dim / c.n_heads; + + var off: usize = @sizeOf(TinyLlamaConfig); + try res.buffers.ensureUnusedCapacity(arena, 8 + 9 * n_layers); + + // Map tinyllama naming to Meta llama3 naming. + // token_embedding_table + off = newBuff(&res, "model.embed_tokens.weight", .{ .voc = c.vocab.size, .d = dim }, off); + // rms_att_weight + off = try splitBuff(&res, "model.layers.{d}.input_layernorm.weight", .{dim}, n_layers, off); + // wq + off = try splitBuff(&res, "model.layers.{d}.self_attn.q_proj.weight", .{ dim, n_heads * head_size }, n_layers, off); + // wk + off = try splitBuff(&res, "model.layers.{d}.self_attn.k_proj.weight", .{ dim, n_kv_heads * head_size }, n_layers, off); + // wv + off = try splitBuff(&res, "model.layers.{d}.self_attn.v_proj.weight", .{ dim, n_kv_heads * head_size }, n_layers, off); + // wo + off = try splitBuff(&res, "model.layers.{d}.self_attn.o_proj.weight", .{ n_heads * head_size, dim }, n_layers, off); + // rms_ffn_weight + off = try splitBuff(&res, "model.layers.{d}.post_attention_layernorm.weight", .{dim}, n_layers, off); + // w1 + off = try splitBuff(&res, "model.layers.{d}.mlp.gate_proj.weight", .{ hidden_dim, dim }, n_layers, off); + // w2 + off = try splitBuff(&res, "model.layers.{d}.mlp.down_proj.weight", .{ dim, hidden_dim }, n_layers, off); + // w3 + off = try splitBuff(&res, "model.layers.{d}.mlp.up_proj.weight", .{ hidden_dim, dim }, n_layers, off); + // rms_final_weight + off = newBuff(&res, "model.norm.weight", .{dim}, off); + // freq_cis_real (not used) + off = newBuff(&res, "freq_cis_real", .{ seq_len, head_size / 2 }, off); + off = newBuff(&res, "freq_cis_imag", .{ seq_len, head_size / 2 }, off); + + // wcls + if (c.vocab.has_lm_head) { + off = newBuff(&res, "lm_head.weight", .{ c.vocab.size, c.dim }, off); + } else { + res.buffers.putAssumeCapacityNoClobber("lm_head.weight", res.buffers.get("model.embed_tokens.weight").?); + } + + const weights_size = off; + std.log.info("Loaded a tinyllama file of {} bytes.\nThis is the parsed configuration of this llama model: {}", .{ weights_size, c }); + if (file.stat() catch null) |stat| { + zml.meta.assert(weights_size == stat.size, "Expected to have a tinyllama file of {} bytes but file only got {} !\nThis is the parsed configuration of this llama model: {}", .{ weights_size, stat.size, c }); + } + + { + try res._metadata.ensureUnusedCapacity(arena, 11); + res._metadata.putAssumeCapacityNoClobber("dim", .{ .int64 = c.dim }); + res._metadata.putAssumeCapacityNoClobber("hidden_dim", .{ .int64 = c.hidden_dim }); + res._metadata.putAssumeCapacityNoClobber("n_layers", .{ .int64 = c.n_layers }); + res._metadata.putAssumeCapacityNoClobber("num_heads", .{ .int64 = c.n_heads }); + res._metadata.putAssumeCapacityNoClobber("num_kv_heads", .{ .int64 = c.n_kv_heads }); + res._metadata.putAssumeCapacityNoClobber("vocab_size", .{ .int64 = c.vocab.size }); + res._metadata.putAssumeCapacityNoClobber("has_lm_head", .{ .boolval = c.vocab.has_lm_head }); + res._metadata.putAssumeCapacityNoClobber("max_seq_len", .{ .int64 = c.seq_len }); + res._metadata.putAssumeCapacityNoClobber("rope_impl", .{ .string = "interleaved" }); + res._metadata.putAssumeCapacityNoClobber("rope_freq_base", .{ .float64 = 10_000 }); + res._metadata.putAssumeCapacityNoClobber("rms_norm_eps", .{ .float64 = 1e-6 }); + } + + return res; +} + +fn newBuff(store: *zml.aio.BufferStore, name: []const u8, sh: anytype, offset: usize) usize { + var shape = zml.Shape.init(sh, .f32); + const n = shape.byteSize(); + const buff = zml.HostBuffer.fromBytes(shape, store.files[0].data[offset..][0..n]); + store.buffers.putAssumeCapacityNoClobber(name, buff); + zml.log.info("Found {s}: {}", .{ name, shape }); + return offset + n; +} + +fn splitBuff(store: *zml.aio.BufferStore, comptime fmt: []const u8, sh: anytype, layers: usize, offset: usize) !usize { + var shape = zml.Shape.init(sh, .f32); + const n = shape.byteSize(); + var off = offset; + for (0..layers) |i| { + const name = try std.fmt.allocPrint(store.arena.allocator(), fmt, .{i}); + const buff = zml.HostBuffer.fromBytes(shape, store.files[0].data[off..][0..n]); + store.buffers.putAssumeCapacityNoClobber(name, buff); + off += n; + if (i == 0) zml.log.info("Found {s}: {}", .{ name, shape }); + } + return off; +} + +pub fn loadTokenizer(allocator: std.mem.Allocator, tokenizer_path: []const u8, vocab_size: u32) !zml.tokenizer.Tokenizer { + const tokenizer_file = try std.fs.cwd().openFile(tokenizer_path, .{}); + defer tokenizer_file.close(); + var tok_reader = std.io.bufferedReader(tokenizer_file.reader()); + const r = tok_reader.reader(); + + const max_token_len = try r.readInt(u32, .little); + const special_tokens: zml.tokenizer.Tokenizer.SpecialTokens = .{ + .unk = 0, + .bos = 1, + .eos = 2, + }; + var tokenizer = try zml.tokenizer.Tokenizer.init(allocator, vocab_size, max_token_len, null, special_tokens, true); + var i: u32 = 0; + while (readToken(&tokenizer, &r)) : (i += 1) { + // Pass + } else |_| { + if (i < vocab_size) { + zml.log.info("Read {d} words out of {?d}", .{ i, vocab_size }); + } + tokenizer.vocab_size = i; + } + return tokenizer; +} + +fn readToken(tokenizer: *zml.tokenizer.Tokenizer, tok_reader: anytype) !void { + const score: f32 = @bitCast(try tok_reader.readInt(u32, .little)); + const len: usize = @intCast(try tok_reader.readInt(u32, .little)); + try tokenizer.readTokenInto(score, len, tok_reader); +} diff --git a/zml/aio/torch.zig b/zml/aio/torch.zig new file mode 100644 index 0000000..2de206e --- /dev/null +++ b/zml/aio/torch.zig @@ -0,0 +1,440 @@ +const asynk = @import("async"); +const std = @import("std"); +const zml = @import("../zml.zig"); + +const HostBuffer = @import("../hostbuffer.zig").HostBuffer; + +const toVoidSlice = @import("utils.zig").toVoidSlice; +const eval = @import("torch/eval.zig"); +const utils = @import("torch/utils.zig"); +const value = @import("torch/value.zig"); +const Decoder = @import("torch/parser.zig").Decoder; +const PersId = value.PersId; +const PickleMemo = eval.PickleMemo; +const PickleStack = eval.PickleStack; +const Sequence = value.Sequence; +const Value = value.Value; +const ValueType = value.ValueType; + +const StringBuilder = std.ArrayListUnmanaged(u8); +const Allocator = std.mem.Allocator; +const log = std.log.scoped(.zml_io); + +const TorchType = enum { + float64, + double, + float32, + float, + float16, + half, + bfloat16, + int64, + long, + int32, + int, + int16, + short, + int8, + char, + uint8, + byte, +}; + +fn dtypeFromStr(str: []const u8) !zml.DataType { + const case = std.meta.stringToEnum(TorchType, str) orelse return error.UnknownTensorType; + return switch (case) { + .float64, .double => .f64, + .float32, .float => .f32, + .float16, .half => .f16, + .bfloat16 => .bf16, + .int64, .long => .i64, + .int32, .int => .i32, + .int16, .short => .i16, + .int8, .char => .i8, + .uint8, .byte => .u8, + }; +} + +/// Opens and loads a BufferStore from the torch file at the given path. +pub fn open(allocator: Allocator, path: []const u8) !zml.aio.BufferStore { + const file = asynk.File.open(path, .{}) catch |err| { + log.err("Failed to open {s}: {}", .{ path, err }); + return err; + }; + errdefer file.close() catch unreachable; + + var res: zml.aio.BufferStore = .{ + .arena = std.heap.ArenaAllocator.init(allocator), + }; + + const arena = res.arena.allocator(); + + var tmp: PickleData = .{ + .data = try Decoder.init(arena, file), + .memo = undefined, + .stack = undefined, + }; + tmp.stack, tmp.memo = try eval.evaluate(arena, tmp.data.ops, true); + res.files = try arena.dupe(zml.aio.MemoryMappedFile, &.{tmp.data.buffer_file}); + try tmp.parseModel(arena, &res); + return res; +} + +pub const PickleData = struct { + stack: PickleStack, + memo: PickleMemo, + data: Decoder, + + fn basicTypeCheck(v: Value, ns: []const u8, name: []const u8) bool { + return switch (v) { + .global => |object| switch (object.member) { + .raw => |raw| { + if (std.mem.eql(u8, ns, raw.global[0]) and std.mem.eql(u8, name, raw.global[1]) and object.args[0] == .seq) { + return true; + } else return false; + }, + else => false, + }, + else => false, + }; + } + + fn isTensor(v: Value) bool { + if (basicTypeCheck(v, "torch._utils", "_rebuild_tensor_v2")) { + const args = v.global.args[0].seq[1]; + if (args.len >= 5 and + args[0] == .pers_id and + args[1] == .int and + args[2] == .seq and args[2].seq[0] == .tuple and + args[3] == .seq and args[3].seq[0] == .tuple) + { + return true; + } else @panic("Unexpected value in call to torch._utils._rebuild_tensor_v2"); + } + return false; + } + + fn dimsFromValues(values: []Value) [zml.Tensor.MAX_RANK]i64 { + std.debug.assert(values.len <= zml.Tensor.MAX_RANK); + var result: [zml.Tensor.MAX_RANK]i64 = undefined; + for (values, result[0..values.len]) |val, *elem| { + switch (val) { + .int => |int| elem.* = int, + else => @panic("Bad value for shape item"), + } + } + return result; + } + + pub fn parseModel(self: *PickleData, allocator: Allocator, store: *zml.aio.BufferStore) !void { + for (self.stack.stack) |item| { + var prefix_buf: [1024]u8 = undefined; + try self.parseValue(allocator, store, StringBuilder.initBuffer(&prefix_buf), item); + } + } + + fn tensorOffset(self: *PickleData, seekable_stream: anytype, sfile: []const u8) !u64 { + if (self.data.file_map.get(sfile)) |entry| { + const local_header = blk: { + try seekable_stream.seekTo(entry.file_offset); + break :blk try seekable_stream.context.reader().readStructEndian(std.zip.LocalFileHeader, .little); + }; + if (!std.mem.eql(u8, &local_header.signature, &std.zip.local_file_header_sig)) + return error.ZipBadFileOffset; + if (local_header.version_needed_to_extract != entry.version_needed_to_extract) + return error.ZipMismatchVersionNeeded; + if (local_header.last_modification_time != entry.last_modification_time) + return error.ZipMismatchModTime; + if (local_header.last_modification_date != entry.last_modification_date) + return error.ZipMismatchModDate; + + if (@as(u16, @bitCast(local_header.flags)) != @as(u16, @bitCast(entry.flags))) + return error.ZipMismatchFlags; + if (local_header.crc32 != 0 and local_header.crc32 != entry.crc32) + return error.ZipMismatchCrc32; + if (local_header.compressed_size != 0 and + local_header.compressed_size != entry.compressed_size) + return error.ZipMismatchCompLen; + if (local_header.uncompressed_size != 0 and + local_header.uncompressed_size != entry.uncompressed_size) + return error.ZipMismatchUncompLen; + if (local_header.filename_len != entry.filename_len) + return error.ZipMismatchFilenameLen; + + return (try seekable_stream.context.getPos()) + + @as(u64, local_header.filename_len) + + @as(u64, local_header.extra_len); + } + + std.log.err("Could not find file ending in `{s}` in archive", .{sfile}); + return error.TensorNotFound; + } + + fn parseTorchGlobal(self: *PickleData, allocator: Allocator, store: *zml.aio.BufferStore, prefix: StringBuilder, v: Value) !bool { + return switch (v) { + .global => |object| { + if (isTensor(v)) { + const args = object.args[0].seq[1]; + const pidval: *PersId, var offs: u64, const raw_shape: Sequence, const raw_strides: Sequence = .{ args[0].pers_id, @intCast(args[1].int), args[2].seq, args[3].seq }; + const rank = raw_shape[1].len; + const shape = dimsFromValues(raw_shape[1]); + var strides = dimsFromValues(raw_strides[1]); + const stype: []const u8, const sfile: []const u8, const sdev: []const u8 = switch (pidval.ref) { + .seq => |seq| blk: { + const sargs = seq[1]; + if (seq[0] == .tuple and + sargs.len >= 5 and + sargs[0] == .string and std.mem.eql(u8, sargs[0].string, "storage") and + sargs[1] == .raw and sargs[1].raw == .global and + sargs[2] == .string and + sargs[3] == .string) + { + const op = sargs[1].raw.global; + const sfile = sargs[2].string; + const sdev = sargs[3].string; + const styp = op[1]; + if (std.mem.eql(u8, "torch", op[0]) and std.mem.endsWith(u8, styp, "Storage")) { + break :blk .{ std.ascii.lowerString(styp[0 .. styp.len - 7], styp[0 .. styp.len - 7]), sfile, sdev }; + } else @panic("Unexpected storage type part of persistant ID"); + } else @panic("Unexpected value for persistant ID"); + }, + else => @panic("Unexpected value for persistant ID"), + }; + _ = sdev; + const data_type = try dtypeFromStr(stype); + for (strides[0..rank]) |*s| s.* *= data_type.sizeOf(); + + var sfile_buf = std.ArrayList(u8).init(allocator); + defer sfile_buf.deinit(); + try sfile_buf.writer().print("{s}data/{s}", .{ self.data.zip_prefix, sfile }); + + // find offsets for tensor zip file + const absolute_offset = blk: { + if (self.data.tar_file) |t| { + break :blk try self.tensorOffset(t.seekableStream(), sfile_buf.items); + } else { + break :blk try self.tensorOffset(self.data.buffer_file.file.seekableStream(), sfile_buf.items); + } + }; + offs = offs * data_type.sizeOf(); + const key = try allocator.dupe(u8, prefix.items); + const entry = try store.buffers.getOrPut(allocator, key); + if (entry.found_existing) { + log.warn("Duplicate key: {s}", .{prefix.items}); + allocator.free(key); + } + const out_shape = zml.Shape.init(shape[0..rank], data_type); + entry.value_ptr.* = HostBuffer.fromStridedSlice( + out_shape, + self.data.buffer_file.mappedSlice((if (self.data.tar_file) |t| t.start else 0) + absolute_offset + offs, out_shape.byteSize()), + strides[0..rank], + ); + return true; + } else if (basicTypeCheck(v, "torch", "Size")) { + const size = object.args[0].seq[1][0].seq[1]; + const key = try allocator.dupe(u8, prefix.items); + const entry = try store._metadata.getOrPut(allocator, key); + if (entry.found_existing) { + log.warn("Duplicate key: {s}", .{prefix.items}); + allocator.free(key); + } + const d = try allocator.alloc(i64, size.len); + for (d, 0..) |*di, i| di.* = size[i].int; + entry.value_ptr.* = .{ .array = .{ .item_type = .int64, .data = std.mem.sliceAsBytes(d) } }; + return true; + } else if (basicTypeCheck(v, "fractions", "Fraction")) { + const fraction_str = object.args[0].seq[1][0].string; + if (std.mem.indexOfScalar(u8, fraction_str, '/')) |split_idx| { + { + var new_prefix = prefix; + new_prefix.appendSliceAssumeCapacity(".numerator"); + try store._metadata.put(allocator, try allocator.dupe(u8, new_prefix.items), .{ .int64 = try std.fmt.parseInt(i64, fraction_str[0..split_idx], 10) }); + } + { + var new_prefix = prefix; + new_prefix.appendSliceAssumeCapacity(".denominator"); + try store._metadata.put(allocator, try allocator.dupe(u8, new_prefix.items), .{ .int64 = try std.fmt.parseInt(i64, fraction_str[split_idx + 1 ..], 10) }); + } + return true; + } + } + return false; + }, + else => false, + }; + } + + pub fn parseValue(self: *PickleData, allocator: Allocator, store: *zml.aio.BufferStore, prefix: StringBuilder, v: Value) !void { + switch (v) { + .app, .object, .global => |object| { + if (!(try self.parseTorchGlobal(allocator, store, prefix, v))) { + try self.parseValue(allocator, store, prefix, object.member); + for (object.args) |item| { + // if possible, coerce to `kv_tuple` (only if key val doesn't match root of prefix) + if (item == .seq and item.seq[0] == .tuple and item.seq[1].len == 2 and item.seq[1][0] == .string) { + try self.parseValue(allocator, store, prefix, .{ .seq = .{ .kv_tuple, item.seq[1] } }); + } else try self.parseValue(allocator, store, prefix, item); + } + } + }, + .build => |build| { + // `build` contains info about python struct being constructed + switch (build.member) { + .object => |obj| switch (obj.member) { + .raw => |raw| switch (raw) { + .global => |global| { + // in this case, we can capture the name of the python type + // which can be used for codegen (e.g. `torch.nn.modules.conv.Conv2d`) + var new_prefix = prefix; + if (prefix.items.len > 0) { + new_prefix.appendAssumeCapacity('.'); + } + new_prefix.appendSliceAssumeCapacity("_gen_type_helper"); + const key = try allocator.dupe(u8, new_prefix.items); + const d = try store._metadata.getOrPut(allocator, key); + if (d.found_existing) { + log.err("Duplicate key: {s}", .{new_prefix.items}); + allocator.free(key); + } else { + const val = try allocator.alloc(u8, global[0].len + 1 + global[1].len); + @memcpy(val[0..global[0].len], global[0]); + val[global[0].len] = '.'; + @memcpy(val[global[0].len + 1 ..], global[1]); + d.value_ptr.* = .{ .string = val }; + } + }, + else => try self.parseValue(allocator, store, prefix, build.member), // parse normally + }, + else => try self.parseValue(allocator, store, prefix, build.member), // parse normally + }, + else => try self.parseValue(allocator, store, prefix, build.member), // parse normally + } + try self.parseValue(allocator, store, prefix, build.args); + }, + .pers_id => |pers_id| try self.parseValue(allocator, store, prefix, pers_id.ref), + .seq => |*seq| switch (seq[0]) { + .list, .tuple, .set, .frozen_set => { + const elemCheck = struct { + fn call(comptime T: ValueType) fn (v: Value) bool { + return struct { + fn call(val: Value) bool { + return val == T; + } + }.call; + } + }.call; + + if (seq[1].len > 0 and switch (seq[1][0]) { + inline .int, .bool, .float => |_, tag| utils.allTrue(seq[1][1..], elemCheck(tag)), + else => false, + }) { + const out: []u8 = switch (seq[1][0]) { + .int => blk: { + const d = try allocator.alloc(i64, seq[1].len); + for (seq[1], 0..) |item, i| { + d[i] = item.int; + } + break :blk std.mem.sliceAsBytes(d); + }, + .float => blk: { + const d = try allocator.alloc(f64, seq[1].len); + for (seq[1], 0..) |item, i| { + d[i] = item.float; + } + break :blk std.mem.sliceAsBytes(d); + }, + else => blk: { + const d = try allocator.alloc(bool, seq[1].len); + for (seq[1], 0..) |item, i| { + d[i] = item.bool; + } + break :blk std.mem.sliceAsBytes(d); + }, + }; + const key = try allocator.dupe(u8, prefix.items); + const d = try store._metadata.getOrPut(allocator, key); + if (d.found_existing) { + log.warn("Duplicate key: {s}", .{prefix.items}); + allocator.free(key); + allocator.free(out); + } else d.value_ptr.* = @unionInit(zml.aio.Value, "array", .{ .item_type = switch (seq[1][0]) { + .int => .int64, + .float => .float64, + .string => .string, + else => .boolval, + }, .data = out }); + } else { + for (seq[1], 0..) |item, i| { + var new_prefix = prefix; + if (v.isPrimitive()) { + if (prefix.items.len > 0) { + new_prefix.appendAssumeCapacity('.'); + } + new_prefix.items.len += std.fmt.formatIntBuf(new_prefix.unusedCapacitySlice(), i, 10, .lower, .{}); + } + try self.parseValue(allocator, store, new_prefix, item); + } + } + }, + .dict => { + for (seq[1]) |item| { + try self.parseValue(allocator, store, prefix, item); + } + }, + .kv_tuple => { + const key = seq[1][0]; + const val = seq[1][1]; + switch (key) { + .string => |s| { + if (std.mem.eql(u8, s, "_modules") or std.mem.eql(u8, s, "_parameters") or std.mem.eql(u8, s, "_buffers")) { + try self.parseValue(allocator, store, prefix, val); + } else { + var new_prefix = prefix; + if (prefix.items.len > 0) { + new_prefix.appendAssumeCapacity('.'); + } + new_prefix.appendSliceAssumeCapacity(s); + try self.parseValue(allocator, store, new_prefix, val); + } + }, + .int => |int| { + var new_prefix = prefix; + if (prefix.items.len > 0) { + new_prefix.appendAssumeCapacity('.'); + } + new_prefix.items.len += std.fmt.formatIntBuf(new_prefix.unusedCapacitySlice(), int, 10, .lower, .{}); + try self.parseValue(allocator, store, new_prefix, val); + }, + inline else => |_, tag| std.debug.panic("Unexpected key type: {s}", .{@tagName(tag)}), + } + }, + }, + .bytes => |val| { + const key = try allocator.dupe(u8, prefix.items); + const d = try store._metadata.getOrPut(allocator, key); + if (d.found_existing) { + log.warn("Duplicate key: {s}", .{prefix.items}); + allocator.free(key); + } else d.value_ptr.* = .{ .array = .{ .item_type = .uint8, .data = @constCast(val) } }; + }, + inline .float, .int, .bool, .bigint, .string => |val, tag| { + const key = try allocator.dupe(u8, prefix.items); + const d = try store._metadata.getOrPut(allocator, key); + if (d.found_existing) { + log.warn("Duplicate key: {s}", .{prefix.items}); + allocator.free(key); + } else d.value_ptr.* = @unionInit(zml.aio.Value, switch (tag) { + .int => "int64", + .float => "float64", + .bool => "boolval", + else => @tagName(tag), + }, val); + }, + else => {}, + } + } +}; + +test { + std.testing.refAllDecls(@This()); +} diff --git a/zml/aio/torch/b_tree_map.zig b/zml/aio/torch/b_tree_map.zig new file mode 100644 index 0000000..19cc8bf --- /dev/null +++ b/zml/aio/torch/b_tree_map.zig @@ -0,0 +1,652 @@ +const std = @import("std"); + +/// BTreeMap Node implementation. +pub fn NodeType(comptime K: type, comptime V: type, comptime B: u32) type { + return struct { + const Self = @This(); + keys: [2 * B - 1]K = [_]K{undefined} ** (2 * B - 1), + values: [2 * B - 1]V = [_]V{undefined} ** (2 * B - 1), + len: usize = 0, + edges: [2 * B]?*Self = [_]?*Self{null} ** (2 * B), + + pub const KV = struct { key: K, value: V }; + const KVE = struct { key: K, value: V, edge: ?*Self }; + const Entry = struct { key_ptr: *K, value_ptr: *V }; + + /// Initializes an empty Node. + pub fn initEmpty(allocator: std.mem.Allocator) !*Self { + const res: *Self = try allocator.create(Self); + res.* = .{}; + return res; + } + + /// Initializes a Node with a single Entry. + pub fn initKeyValue(allocator: std.mem.Allocator, entry: struct { K, V }) !*Self { + const key, const value = entry; + var res = try Self.initEmpty(allocator); + res.keys[0] = key; + res.values[0] = value; + res.len = 1; + return res; + } + + fn initFromSplit(allocator: std.mem.Allocator, keys: []K, values: []V, edges: []?*Self) !*Self { + var out = try Self.initEmpty(allocator); + std.mem.copyBackwards(K, out.keys[0..], keys); + std.mem.copyBackwards(V, out.values[0..], values); + std.mem.copyBackwards(?*Self, out.edges[0..], edges); + out.len = keys.len; + return out; + } + + pub fn count(self: Self) usize { + var len: usize = self.len; + for (0..self.len + 1) |i| { + if (!self.isLeaf()) { + len += self.edges[i].?.count(); + } + } + return len; + } + + // Searches the Node for a key. + pub fn search(self: Self, key: K) std.meta.Tuple(&.{ bool, usize }) { + var i: usize = 0; + while (i < self.len) : (i += 1) { + if (eql(key, self.keys[i])) { + return .{ true, i }; + } else if (lt(key, self.keys[i])) { + return .{ false, i }; + } + } + return .{ false, self.len }; + } + + pub fn insertOrSplit( + self: *Self, + allocator: std.mem.Allocator, + index: usize, + key: K, + value: V, + edge: ?*Self, + ) !?KVE { + if (self.isFull()) { + var split_result = try self.split(allocator); + switch (index < B) { + true => self.insert(index, key, value, edge), + false => split_result.edge.?.insert(index - B, key, value, edge), + } + return split_result; + } + self.insert(index, key, value, edge); + return null; + } + + pub fn swapValue(self: *Self, index: usize, value: V) V { + const out = self.values[index]; + self.values[index] = value; + return out; + } + + pub fn swapKeyValue(self: *Self, index: usize, key: K, value: V) KV { + const out = .{ .key = self.keys[index], .value = self.values[index] }; + self.values[index] = value; + self.keys[index] = key; + return out; + } + + pub fn orderedRemove(self: *Self, index: usize) KVE { + const out: KVE = .{ + .key = self.keys[index], + .value = self.values[index], + .edge = self.edges[index + 1], + }; + std.mem.copyForwards(K, self.keys[index..], self.keys[index + 1 .. self.len]); + std.mem.copyForwards(V, self.values[index..], self.values[index + 1 .. self.len]); + self.keys[self.len - 1] = undefined; + self.values[self.len - 1] = undefined; + if (!self.isLeaf()) { + std.mem.copyForwards(?*Self, self.edges[index + 1 ..], self.edges[index + 2 .. self.len + 1]); + self.edges[self.len] = null; + } + self.len -= 1; + return out; + } + + fn pop(self: *Self) KVE { + return self.orderedRemove(self.len - 1); + } + + fn shift(self: *Self) KVE { + const out: KVE = .{ + .key = self.keys[0], + .value = self.values[0], + .edge = self.edges[0], + }; + std.mem.copyForwards(K, self.keys[0..], self.keys[1..self.len]); + std.mem.copyForwards(V, self.values[0..], self.values[1..self.len]); + self.keys[self.len - 1] = undefined; + self.values[self.len - 1] = undefined; + if (!self.isLeaf()) { + std.mem.copyForwards( + ?*Self, + self.edges[0..], + self.edges[1 .. self.len + 1], + ); + self.edges[self.len] = null; + } + self.len -= 1; + return out; + } + + fn insert(self: *Self, index: usize, key: K, value: V, edge: ?*Self) void { + std.mem.copyBackwards( + K, + self.keys[index + 1 .. self.len + 1], + self.keys[index..self.len], + ); + self.keys[index] = key; + std.mem.copyBackwards(V, self.values[index + 1 .. self.len + 1], self.values[index..self.len]); + self.values[index] = value; + if (!self.isLeaf()) { + std.mem.copyBackwards(?*Self, self.edges[index + 2 .. self.len + 2], self.edges[index + 1 .. self.len + 1]); + self.edges[index + 1] = edge; + } + self.len += 1; + } + + fn append(self: *Self, key: K, value: V, edge: ?*Self) void { + self.keys[self.len] = key; + self.values[self.len] = value; + self.edges[self.len + 1] = edge; + self.len += 1; + } + + fn unshift(self: *Self, key: K, value: V, edge: ?*Self) void { + std.mem.copyBackwards(K, self.keys[1 .. self.len + 1], self.keys[0..self.len]); + self.keys[0] = key; + std.mem.copyBackwards(V, self.values[1 .. self.len + 1], self.values[0..self.len]); + self.values[0] = value; + if (!self.isLeaf()) { + std.mem.copyBackwards(?*Self, self.edges[1 .. self.len + 2], self.edges[0 .. self.len + 1]); + self.edges[0] = edge; + } + self.len += 1; + } + + pub fn borrowRight(self: *Self, index: usize) bool { + if (index == self.len) return false; + var from = self.edges[index + 1].?; + if (from.len > B - 1) { + var to = self.edges[index].?; + const borrowed = from.shift(); + to.append(self.keys[index], self.values[index], borrowed.edge); + _ = self.swapKeyValue(index, borrowed.key, borrowed.value); + return true; + } + return false; + } + + pub fn borrowLeft(self: *Self, index: usize) bool { + if (index == 0) return false; + var from = self.edges[index - 1].?; + if (from.len > B - 1) { + var to = self.edges[index].?; + const borrowed = from.pop(); + to.unshift(self.keys[index - 1], self.values[index - 1], borrowed.edge); + _ = self.swapKeyValue(index - 1, borrowed.key, borrowed.value); + return true; + } + return false; + } + + pub fn mergeEdges(self: *Self, allocator: std.mem.Allocator, left_edge_index: usize) void { + var left = self.edges[left_edge_index].?; + const removed = self.orderedRemove(left_edge_index); + left.append(removed.key, removed.value, null); + std.mem.copyBackwards(K, left.keys[left.len..], removed.edge.?.keys[0..removed.edge.?.len]); + std.mem.copyBackwards(V, left.values[left.len..], removed.edge.?.values[0..removed.edge.?.len]); + std.mem.copyBackwards(?*Self, left.edges[left.len..], removed.edge.?.edges[0 .. removed.edge.?.len + 1]); + left.len += removed.edge.?.len; + allocator.destroy(removed.edge.?); + } + + fn split(self: *Self, allocator: std.mem.Allocator) !KVE { + const median = B - 1; + const new_key = self.keys[median]; + const new_value = self.values[median]; + const new_node = try Self.initFromSplit( + allocator, + self.keys[median + 1 .. self.len], + self.values[median + 1 .. self.len], + self.edges[median + 1 .. self.len + 1], + ); + @memset(self.keys[median..], undefined); + @memset(self.values[median..], undefined); + @memset(self.edges[median + 1 ..], null); + self.len = median; + return .{ .key = new_key, .value = new_value, .edge = new_node }; + } + + pub fn isLeaf(self: Self) bool { + return self.edges[0] == null; + } + + pub fn isFull(self: Self) bool { + return self.len == 2 * B - 1; + } + + pub fn isLacking(self: Self) bool { + return self.len < B - 1; + } + }; +} + +pub fn BTreeMap(comptime K: type, comptime V: type) type { + return struct { + const Self = @This(); + + const B = 6; + const Node = NodeType(K, V, B); + const KV = Node.KV; + const SearchResult = std.meta.Tuple(&.{ bool, usize }); + const StackEntry = struct { node: *Node, index: usize }; + + allocator: std.mem.Allocator, + root: ?*Node = null, + + pub fn init(allocator: std.mem.Allocator) Self { + return .{ .allocator = allocator }; + } + + pub fn deinit(self: Self) !void { + if (self.root == null) return; + var stack = std.ArrayList(*Node).init(self.allocator); + defer stack.deinit(); + if (self.root) |root| { + try stack.append(root); + } + while (stack.popOrNull()) |node| { + if (!node.isLeaf()) { + for (0..node.len + 1) |i| { + try stack.append(node.edges[i].?); + } + } + self.allocator.destroy(node); + } + } + + pub fn count(self: Self) usize { + if (self.root == null) return 0; + var len: usize = 0; + if (self.root) |node| { + len += node.count(); + } + return len; + } + + pub fn isEmpty(self: *const Self) bool { + if (self.root == null) return true; + return self.root.?.len == 0; + } + + pub fn get(self: Self, key: K) ?V { + var current = self.root; + while (current) |node| { + const found, const index = node.search(key); + switch (found) { + true => return node.values[index], + false => current = node.edges[index], + } + } + return null; + } + + pub fn getPtr(self: Self, key: K) ?*V { + var current = self.root; + while (current) |node| { + const found, const index = node.search(key); + switch (found) { + true => return &node.values[index], + false => current = node.edges[index], + } + } + return null; + } + + pub fn fetchPut(self: *Self, key: K, value: V) !?KV { + if (self.root == null) { + self.root = try Node.initKeyValue(self.allocator, .{ key, value }); + return null; + } + var stack = std.ArrayList(StackEntry).init(self.allocator); + defer stack.deinit(); + var current = self.root; + var search_result: SearchResult = undefined; + while (current) |node| { + search_result = node.search(key); + if (search_result[0]) { + return .{ .key = key, .value = node.swapValue(search_result[1], value) }; + } + current = node.edges[search_result[1]]; + try stack.append(.{ .node = node, .index = search_result[1] }); + } + var stack_next: ?StackEntry = stack.pop(); + var split_result = try stack_next.?.node.insertOrSplit( + self.allocator, + stack_next.?.index, + key, + value, + null, + ); + if (split_result == null) { + return null; + } + stack_next = stack.popOrNull(); + while (split_result) |split_result_unwrapped| { + if (stack_next) |stack_next_unwrapped| { + split_result = try stack_next_unwrapped.node.insertOrSplit( + self.allocator, + stack_next_unwrapped.index, + split_result_unwrapped.key, + split_result_unwrapped.value, + split_result_unwrapped.edge, + ); + stack_next = stack.popOrNull(); + } else { + var new_root = try Node.initKeyValue( + self.allocator, + .{ split_result_unwrapped.key, split_result_unwrapped.value }, + ); + new_root.edges[0] = self.root; + new_root.edges[1] = split_result_unwrapped.edge; + self.root = new_root; + return null; + } + } else return null; + } + + pub fn fetchRemove(self: *Self, key: K) !?KV { + var stack = std.ArrayList(StackEntry).init(self.allocator); + defer stack.deinit(); + var current = self.root; + var search_result: SearchResult = undefined; + var found_key_ptr: ?*K = null; + var found_value_ptr: ?*V = null; + while (current) |node| { + search_result = node.search(key); + if (search_result[0]) { + found_key_ptr = &node.keys[search_result[1]]; + found_value_ptr = &node.values[search_result[1]]; + if (!node.isLeaf()) search_result[1] += 1; + } + try stack.append(.{ + .node = node, + .index = search_result[1], + }); + current = node.edges[search_result[1]]; + if (search_result[0]) break; + } else return null; + while (current) |node| { + try stack.append(.{ .node = node, .index = 0 }); + current = node.edges[0]; + } + var current_stack = stack.pop(); + const out: KV = .{ .key = found_key_ptr.?.*, .value = found_value_ptr.?.* }; + found_key_ptr.?.* = current_stack.node.keys[current_stack.index]; + found_value_ptr.?.* = current_stack.node.values[current_stack.index]; + _ = current_stack.node.orderedRemove(current_stack.index); + if (current_stack.node == self.root) return out; + while (current_stack.node.isLacking()) { + current_stack = stack.pop(); + if (current_stack.node.borrowRight(current_stack.index)) return out; + if (current_stack.node.borrowLeft(current_stack.index)) return out; + if (current_stack.index == current_stack.node.len) { + current_stack.node.mergeEdges(self.allocator, current_stack.index - 1); + } else { + current_stack.node.mergeEdges(self.allocator, current_stack.index); + } + if (current_stack.node == self.root) { + if (self.root.?.len == 0) { + const new_root = current_stack.node.edges[0].?; + self.allocator.destroy(self.root.?); + self.root.? = new_root; + } + break; + } + } + return out; + } + + const Iterator = struct { + stack: std.ArrayList(StackEntry), + backwards: bool, + + pub fn deinit(it: Iterator) void { + it.stack.deinit(); + } + + pub fn next(it: *Iterator) ?Node.Entry { + while (it.topStackItem()) |item| { + if (!item.node.isLeaf() and !it.backwards) { + const child = item.node.edges[item.index].?; + it.stack.append(StackEntry{ .node = child, .index = 0 }) catch unreachable; + } else { + if (item.index < item.node.len) { + const out: Node.Entry = .{ .key_ptr = &item.node.keys[item.index], .value_ptr = &item.node.values[item.index] }; + item.index += 1; + it.backwards = false; + return out; + } else { + _ = it.stack.popOrNull(); + it.backwards = true; + } + } + } else return null; + } + + fn topStackItem(it: *Iterator) ?*StackEntry { + return switch (it.stack.items.len) { + 0 => null, + else => &it.stack.items[it.stack.items.len - 1], + }; + } + }; + + pub fn iterator(self: *const Self) Iterator { + var new_stack = std.ArrayList(StackEntry).init(self.allocator); + if (self.root) |root| { + new_stack.append(.{ .node = root, .index = 0 }) catch unreachable; + } + return Iterator{ + .stack = new_stack, + .backwards = false, + }; + } + }; +} + +/// Compares two of any type for equality. Containers are compared on a field-by-field basis, +/// where possible. Pointers are followed if the addresses are not equal. +fn eql(a: anytype, b: @TypeOf(a)) bool { + const T = @TypeOf(a); + switch (@typeInfo(T)) { + .Struct => |info| { + inline for (info.fields) |field_info| { + if (!eql(@field(a, field_info.name), @field(b, field_info.name))) return false; + } + return true; + }, + .ErrorUnion => { + if (a) |a_p| { + if (b) |b_p| return eql(a_p, b_p) else |_| return false; + } else |a_e| { + if (b) |_| return false else |b_e| return a_e == b_e; + } + }, + .Union => |info| { + if (info.tag_type) |UnionTag| { + const tag_a = std.meta.activeTag(a); + const tag_b = std.meta.activeTag(b); + if (tag_a != tag_b) return false; + + inline for (info.fields) |field_info| { + if (@field(UnionTag, field_info.name) == tag_a) { + return eql(@field(a, field_info.name), @field(b, field_info.name)); + } + } + return false; + } + + @compileError("Cannot compare untagged union type " ++ @typeName(T)); + }, + .Array => { + if (a.len != b.len) return false; + for (a, 0..) |e, i| + if (!eql(e, b[i])) return false; + return true; + }, + .Vector => |info| { + var i: usize = 0; + while (i < info.len) : (i += 1) { + if (!eql(a[i], b[i])) return false; + } + return true; + }, + .Pointer => |info| { + return switch (info.size) { + .One => if (a == b) true else eql(a.*, b.*), + .Many => if (a == b) true else { + if (info.sentinel) { + if (std.mem.len(a) != std.mem.len(b)) return false; + var i: usize = 0; + while (i < std.mem.len(a)) : (i += 1) + if (!eql(a[i], b[i])) return false; + return true; + } + @compileError("Cannot compare many-item Pointers without sentinel value"); + }, + .C => if (a == b) true else @compileError("Cannot compare C pointers"), + .Slice => if (a.ptr == b.ptr and a.len == b.len) true else { + if (a.len != b.len) return false; + for (a, 0..) |_, i| + if (!eql(a[i], b[i])) return false; + return true; + }, + }; + }, + .Optional => { + if (a == null and b == null) return true; + if (a == null or b == null) return false; + return eql(a.?, b.?); + }, + else => return a == b, + } +} + +fn lt(a: anytype, b: @TypeOf(a)) bool { + const T = @TypeOf(a); + + switch (@typeInfo(T)) { + .Int, .ComptimeInt, .Float, .ComptimeFloat => { + return a < b; + }, + .Struct => { + if (!@hasDecl(T, "lt")) { + @compileError("Type `" ++ @typeName(T) ++ "` must implement a `lt` comparison method."); + } + return T.lt(a, b); + }, + .Union => |info| { + if (info.tag_type) |UnionTag| { + const tag_a = std.meta.activeTag(a); + const tag_b = std.meta.activeTag(b); + // if tags are not equal, perform comparison based on tag + if (tag_a != tag_b) { + return std.ascii.lessThanIgnoreCase(@tagName(tag_a), @tagName(tag_b)); + } + // if tags are equal, compare based on the active field + inline for (info.fields) |field_info| { + if (@field(UnionTag, field_info.name) == tag_a) { + return lt(@field(a, field_info.name), @field(b, field_info.name)); + } + } + return false; + } + + @compileError("Cannot perform `lt` check on untagged union type " ++ @typeName(T)); + }, + .Array => { + for (a, 0..) |_, i| { + if (lt(a[i], b[i])) { + return true; + } else if (eql(a[i], b[i])) { + continue; + } else { + return false; + } + } + return false; + }, + .Vector => |info| { + var i: usize = 0; + while (i < info.len) : (i += 1) { + if (lt(a[i], b[i])) { + return true; + } else if (eql(a[i], b[i])) { + continue; + } else { + return false; + } + } + return false; + }, + .Pointer => |info| { + switch (info.size) { + .One => return lt(a.*, b.*), + .Slice => { + const n = @min(a.len, b.len); + for (a[0..n], 0..) |_, i| { + if (lt(a[i], b[i])) { + return true; + } else if (eql(a[i], b[i])) { + continue; + } else { + return false; + } + } + return lt(a.len, b.len); + }, + .Many => { + if (info.sentinel) { + const n = @min(std.mem.len(a), std.mem.len(b)); + var i: usize = 0; + while (i < n) : (i += 1) { + if (lt(a[i], b[i])) { + return true; + } else if (eql(a[i], b[i])) { + continue; + } else { + return false; + } + } + return lt(std.mem.len(a), std.mem.len(b)); + } + @compileError("Cannot compare many-item pointer to unknown number of items without sentinel value"); + }, + .C => @compileError("Cannot compare C pointers"), + } + }, + .Optional => { + if (a == null or b == null) return false; + return lt(a.?, b.?); + }, + else => { + @compileError("Cannot compare type '" ++ @typeName(T) ++ "'"); + }, + } +} + +pub fn gt(a: anytype, b: @TypeOf(a)) bool { + return !lt(a, b) and !eql(a, b); +} diff --git a/zml/aio/torch/eval.zig b/zml/aio/torch/eval.zig new file mode 100644 index 0000000..246a714 --- /dev/null +++ b/zml/aio/torch/eval.zig @@ -0,0 +1,485 @@ +const std = @import("std"); +const zml = @import("../../zml.zig"); +const meta = zml.meta; + +const value = @import("value.zig"); +const BTreeMap = @import("b_tree_map.zig").BTreeMap; +const PickleOp = @import("ops.zig").PickleOp; + +const Build = value.Build; +const Object = value.Object; +const PersId = value.PersId; +const Sequence = value.Sequence; +const SequenceType = value.SequenceType; +const Value = value.Value; + +const MAX_DEPTH: usize = 250; +const MAX_PROTOCOL: u8 = 5; + +pub const PickleMemo = struct { + allocator: std.mem.Allocator, + map: BTreeMap(u32, Value), + + pub fn init(allocator: std.mem.Allocator) PickleMemo { + return .{ + .allocator = allocator, + .map = BTreeMap(u32, Value).init(allocator), + }; + } + + pub fn deinit(self: *PickleMemo) void { + var iterator = self.map.iterator(); + defer iterator.deinit(); + while (iterator.next()) |entry| { + entry.value_ptr.deinit(self.allocator); + } + self.map.deinit() catch unreachable; + self.* = undefined; + } + + pub fn resolve(self: *PickleMemo, allocator: std.mem.Allocator, op: Value, recursive: bool) !Value { + var used_op = op; + while (used_op == .ref) { + var count: usize = 0; + const val = self.map.get(op.ref) orelse { + return error.BadMemoRef; + }; + if (!recursive) { + return val.clone(allocator); + } + + count += 1; + if (count >= MAX_DEPTH or val != .ref) { + used_op = try val.clone(allocator); + break; + } + used_op = val; + } + if (used_op.containsRef()) { + switch (used_op) { + .app, .object, .global => |v| { + if (v.member.containsRef()) { + v.member = try self.resolve(allocator, v.member, recursive); + } + for (v.args) |*item| { + if (item.containsRef()) { + item.* = try self.resolve(allocator, item.*, recursive); + } + } + }, + .build => |v| { + if (v.member.containsRef()) { + v.member = try self.resolve(allocator, v.member, recursive); + } + if (v.args.containsRef()) { + v.args = try self.resolve(allocator, v.args, recursive); + } + }, + .pers_id => |v| { + if (v.ref.containsRef()) { + v.ref = try self.resolve(allocator, v.ref, recursive); + } + }, + .seq => |*v| { + for (v[1]) |*item| { + if (item.containsRef()) { + item.* = try self.resolve(allocator, item.*, recursive); + } + } + }, + else => {}, + } + } + return used_op; + } + + pub fn insert(self: *PickleMemo, mid: u32, val: Value) !void { + _ = try self.map.fetchPut(mid, val); + } + + pub fn resolveMut(self: *PickleMemo, op: *Value, recursive: bool) !*Value { + if (op.* != .ref) return op; + var lastmid = op.ref; + var count: usize = 0; + var val = self.map.get(lastmid) orelse { + return error.BadMemoRef; + }; + while (val == .ref) { + lastmid = val.ref; + if (!recursive) { + break; + } + count += 1; + if (count >= MAX_DEPTH) { + break; + } + val = self.map.get(lastmid) orelse { + return error.BadMemoRef; + }; + } + return (self.map.getPtr(lastmid) orelse { + return error.BadMemoRef; + }); + } + + const MemoError = std.math.big.int.Managed.ConvertError || std.mem.Allocator.Error || error{BadMemoRef}; + + pub fn resolveAllRefsIter(self: *PickleMemo, allocator: std.mem.Allocator, depth: usize, vals: []Value, fix_values: bool) MemoError![]Value { + if (depth >= MAX_DEPTH) { + return vals; + } + const res = try allocator.alloc(Value, vals.len); + for (vals, 0..) |v, i| { + res[i] = try self.resolveAllRefs(allocator, depth + 1, v, fix_values); + } + return res; + } + + pub fn resolveAllRefs(self: *PickleMemo, allocator: std.mem.Allocator, depth: usize, val: Value, fix_values: bool) !Value { + var output: Value = switch (val) { + .ref => try self.resolve(allocator, val, true), + inline .app, .object, .global => |v, tag| @unionInit(Value, @tagName(tag), try Object.init( + allocator, + try self.resolveAllRefs(allocator, depth + 1, v.member, fix_values), + try self.resolveAllRefsIter(allocator, depth + 1, v.args, fix_values), + )), + .build => |v| .{ .build = try Build.init( + allocator, + try self.resolveAllRefs(allocator, depth + 1, v.member, fix_values), + try self.resolveAllRefs(allocator, depth + 1, v.args, fix_values), + ) }, + .seq => |v| .{ .seq = .{ v[0], try self.resolveAllRefsIter(allocator, depth + 1, v[1], fix_values) } }, + .pers_id => |v| .{ .pers_id = try PersId.init(allocator, try self.resolveAllRefs(allocator, depth + 1, v.ref, fix_values)) }, + else => try val.clone(allocator), + }; + if (fix_values) { + output = try output.coerceFromRaw(allocator); + } + return output; + } +}; + +pub const InternalStack = struct { + allocator: std.mem.Allocator, + values: std.ArrayList(Value), + + pub fn init(allocator: std.mem.Allocator) InternalStack { + return .{ + .allocator = allocator, + .values = std.ArrayList(Value).init(allocator), + }; + } + + pub fn deinit(self: *InternalStack) void { + for (0..self.values.items.len) |i| self.values.items[i].deinit(self.allocator); + self.values.deinit(); + self.* = undefined; + } + + pub fn pop(self: *InternalStack) !Value { + if (self.values.items.len == 0) { + return error.StackUnderrun; + } + return self.values.pop(); + } + + pub fn popMark(self: *InternalStack, allocator: ?std.mem.Allocator) ![]Value { + const markidx = try self.findMark(); + var postmark: []Value = &[_]Value{}; + if (allocator) |a| { + postmark = try a.alloc(Value, self.values.items.len - (markidx + 1)); + @memcpy(postmark, self.values.items[markidx + 1 ..]); + } + self.values.shrinkAndFree(markidx); + return postmark; + } + + pub fn lastMut(self: *InternalStack) !*Value { + if (self.values.items.len == 0) { + return error.UnexpectedEmptyStack; + } + return &self.values.items[self.values.items.len - 1]; + } + + pub fn findMark(self: *InternalStack) !usize { + const len = self.values.items.len; + for (0..len) |i| { + const idx = (len - 1) - i; + const val = self.values.items[idx]; + if (val == .raw and val.raw == .mark) { + return idx; + } + } + zml.log.warn("pytorch loader: missing mark", .{}); + return 0; + } + + pub fn toPickleStack(self: *InternalStack) !PickleStack { + return .{ .stack = try self.values.toOwnedSlice(), .allocator = self.allocator }; + } +}; + +pub const PickleStack = struct { + stack: []Value, + allocator: std.mem.Allocator, + + pub fn init(allocator: std.mem.Allocator, values: []Value) PickleStack { + return .{ .allocator = allocator, .stack = values }; + } + + pub fn deinit(self: *PickleStack) void { + for (self.stack) |*v| v.deinit(self.allocator); + self.allocator.free(self.stack); + } +}; + +pub fn evaluate(allocator: std.mem.Allocator, x: []const PickleOp, resolve_refs: bool) !struct { PickleStack, PickleMemo } { + var stack = InternalStack.init(allocator); + defer stack.deinit(); + var memo = PickleMemo.init(allocator); + errdefer memo.deinit(); + + const makeKVList = (struct { + pub fn call(alloc: std.mem.Allocator, items: []const Value) ![]Value { + meta.assert(items.len & 1 == 0, "Bad value for setitems", .{}); + var kv_items = try std.ArrayList(Value).initCapacity(alloc, items.len); + errdefer kv_items.deinit(); + var idx: usize = 0; + while (idx < items.len) : (idx += 2) { + if (idx + 1 >= items.len) { + return error.MissingValueItem; + } + const kv = try alloc.alloc(Value, 2); + kv[0] = items[idx]; + kv[1] = items[idx + 1]; + kv_items.appendAssumeCapacity(.{ .seq = .{ .kv_tuple, kv } }); + } + return kv_items.toOwnedSlice(); + } + }).call; + + outer: for (x) |op| { + switch (op) { + .mark => try stack.values.append(.{ .raw = op }), + .stop => break :outer, + .pop => _ = try stack.pop(), + .pop_mark => _ = try stack.popMark(allocator), + .dup => { + if (stack.values.getLastOrNull()) |item| { + try stack.values.append(try item.clone(allocator)); + } else { + return error.CannotDupEmptyStack; + } + }, + .persid => |v| try stack.values.append(.{ .pers_id = try PersId.init(allocator, .{ .string = try allocator.dupe(u8, v) }) }), + .binpersid => try stack.values.append(.{ .pers_id = try PersId.init(allocator, try stack.pop()) }), + .reduce => try stack.values.append(.{ .global = blk: { + const values = try allocator.alloc(Value, 1); + values[0] = try memo.resolve(allocator, try stack.pop(), true); + break :blk try Object.init(allocator, try memo.resolve(allocator, try stack.pop(), true), values); + } }), + .build => try stack.values.append(blk: { + const args = try memo.resolve(allocator, try stack.pop(), true); + const member = try memo.resolve(allocator, try stack.pop(), true); + break :blk .{ .build = try Build.init(allocator, member, args) }; + }), + .empty_dict => try stack.values.append(.{ .seq = .{ .dict, &[_]Value{} } }), + .get => |v| try stack.values.append(.{ .ref = try std.fmt.parseInt(u32, v, 10) }), + inline .binget, .long_binget => |v| try stack.values.append(.{ .ref = v }), + .empty_list => try stack.values.append(.{ .seq = .{ .list, &[_]Value{} } }), + .binput, .long_binput => |v| { + try memo.insert(v, try stack.pop()); + try stack.values.append(.{ .ref = v }); + }, + .tuple => try stack.values.append(blk: { + const popped = try stack.popMark(allocator); + break :blk .{ .seq = .{ .tuple, popped } }; + }), + .empty_tuple => try stack.values.append(.{ .seq = .{ .tuple, &[_]Value{} } }), + .setitem => { + const v, const k = .{ try stack.pop(), try stack.pop() }; + const top = try stack.lastMut(); + const rtop = try memo.resolveMut(top, true); + switch (rtop.*) { + .global => |obj| { + obj.args = try assuredResize(Value, allocator, obj.args, obj.args.len + 1); + obj.args[obj.args.len - 1] = .{ .seq = .{ .tuple, try allocator.dupe(Value, &.{ k, v }) } }; + }, + .seq => |*tup| { + tup[1] = try assuredResize(Value, allocator, tup[1], tup[1].len + 1); + tup[1][tup[1].len - 1] = .{ .seq = .{ .tuple, try allocator.dupe(Value, &.{ k, v }) } }; + }, + else => { + return error.BadStackTopForSetItem; + }, + } + }, + .setitems => { + const popped = try stack.popMark(allocator); + defer allocator.free(popped); + const kv_items = try makeKVList(allocator, popped); + const top = try stack.lastMut(); + const rtop = try memo.resolveMut(top, true); + switch (rtop.*) { + .global => |obj| { + obj.args = try assuredResize(Value, allocator, obj.args, obj.args.len + 1); + obj.args[obj.args.len - 1] = .{ .seq = .{ .tuple, kv_items } }; + }, + .seq => |*tup| { + tup[1] = try assuredResize(Value, allocator, tup[1], tup[1].len + 1); + tup[1][tup[1].len - 1] = .{ .seq = .{ .tuple, kv_items } }; + }, + else => { + defer allocator.free(kv_items); + return error.BadStackTopForSetItems; + }, + } + }, + .proto => |proto| meta.assert(proto <= MAX_PROTOCOL, "Unsupported protocol {d}", .{proto}), + .tuple1 => try stack.values.append(blk: { + const tup_values = try allocator.alloc(Value, 1); + tup_values[0] = try stack.pop(); + break :blk .{ .seq = .{ .tuple, tup_values } }; + }), + .tuple2 => try stack.values.append(blk: { + const tup_values = try allocator.alloc(Value, 2); + inline for (0..2) |i| tup_values[(tup_values.len - 1) - i] = try stack.pop(); + break :blk .{ .seq = .{ .tuple, tup_values } }; + }), + .tuple3 => try stack.values.append(blk: { + const tup_values = try allocator.alloc(Value, 3); + inline for (0..3) |i| tup_values[(tup_values.len - 1) - i] = try stack.pop(); + break :blk .{ .seq = .{ .tuple, tup_values } }; + }), + .append => { + const v = try stack.pop(); + const top = try stack.lastMut(); + const rtop = try memo.resolveMut(top, true); + switch (rtop.*) { + .global => |obj| { + obj.args = try assuredResize(Value, allocator, obj.args, obj.args.len + 1); + obj.args[obj.args.len - 1] = v; + }, + .seq => |*tup| { + tup[1] = try assuredResize(Value, allocator, tup[1], tup[1].len + 1); + tup[1][tup[1].len - 1] = v; + }, + else => { + return error.BadStackTopForAppend; + }, + } + }, + .appends => { + const postmark = try stack.popMark(allocator); + defer allocator.free(postmark); + const top = try stack.lastMut(); + const rtop = try memo.resolveMut(top, true); + switch (rtop.*) { + .global => |obj| { + const obj_len = obj.args.len; + obj.args = try assuredResize(Value, allocator, obj.args, obj_len + postmark.len); + @memcpy(obj.args[obj_len..], postmark); + }, + .seq => |*tup| { + const tup_len = tup[1].len; + tup[1] = try assuredResize(Value, allocator, tup[1], tup_len + postmark.len); + @memcpy(tup[1][tup_len..], postmark); + }, + else => { + return error.BadStackTopForAppends; + }, + } + }, + .dict => try stack.values.append(blk: { + const popped = try stack.popMark(allocator); + defer allocator.free(popped); + const kv_items = try makeKVList(allocator, popped); + break :blk .{ .seq = .{ .dict, kv_items } }; + }), + .list => try stack.values.append(.{ .seq = .{ .list, try stack.popMark(allocator) } }), + .inst => |v| try stack.values.append(blk: { + const tup_items = try allocator.dupe(Value, &.{ .{ .string = v[0] }, .{ .string = v[1] } }); + break :blk .{ .object = try Object.init(allocator, .{ .seq = .{ .tuple, tup_items } }, try stack.popMark(allocator)) }; + }), + .obj => try stack.values.append(blk: { + const markidx = try stack.findMark(); + const args = try allocator.alloc(Value, stack.values.items.len - (markidx + 2)); + @memcpy(args, stack.values.items[markidx + 2 ..]); + const member = stack.values.items[markidx + 1]; + break :blk .{ .object = try Object.init(allocator, member, args) }; + }), + .put => |v| { + const mid = try std.fmt.parseInt(u32, v, 10); + try memo.insert(mid, try stack.pop()); + try stack.values.append(.{ .ref = mid }); + }, + .newobj => try stack.values.append(blk: { + const args = try allocator.alloc(Value, 1); + args[0] = try stack.pop(); + break :blk .{ .object = try Object.init(allocator, try stack.pop(), args) }; + }), + .empty_set => try stack.values.append(.{ .seq = .{ .set, &[_]Value{} } }), + .additems => { + const postmark = try stack.popMark(allocator); + defer allocator.free(postmark); + const top = try stack.lastMut(); + const rtop = try memo.resolveMut(top, true); + switch (rtop.*) { + .global => |obj| { + const obj_len = obj.args.len; + obj.args = try assuredResize(Value, allocator, obj.args, obj_len + postmark.len); + @memcpy(obj.args[obj_len..], postmark); + }, + .seq => |*tup| { + const tup_len = tup[1].len; + tup[1] = try assuredResize(Value, allocator, tup[1], tup_len + postmark.len); + @memcpy(tup[1][tup_len..], postmark); + }, + else => { + return error.BadStackTopForSetItem; + }, + } + }, + .frozenset => try stack.values.append(.{ .seq = .{ .frozen_set, try stack.popMark(allocator) } }), + .newobj_ex => try stack.values.append(blk: { + const kwargs, const args, const cls = .{ try stack.pop(), try stack.pop(), try stack.pop() }; + const new_seq: Sequence = .{ .tuple, try allocator.dupe(Value, &.{ args, kwargs }) }; + break :blk .{ .object = try Object.init(allocator, cls, try allocator.dupe(Value, &.{.{ .seq = new_seq }})) }; + }), + .stack_global => try stack.values.append(blk: { + const gn, const mn = .{ + try memo.resolve(allocator, try stack.pop(), true), + try memo.resolve(allocator, try stack.pop(), true), + }; + const new_seq: Sequence = .{ .tuple, try allocator.dupe(Value, &.{ gn, mn }) }; + break :blk .{ .object = try Object.init(allocator, .{ .seq = new_seq }, &[_]Value{}) }; + }), + .memoize => { + const item = stack.values.getLastOrNull() orelse { + return error.StackUnderrun; + }; + try memo.insert(@intCast(memo.map.count()), try item.clone(allocator)); + }, + else => try stack.values.append(.{ .raw = try op.clone(allocator) }), + } + } + if (!resolve_refs) { + return .{ try stack.toPickleStack(), memo }; + } + return .{ + PickleStack.init(allocator, try memo.resolveAllRefsIter(allocator, 0, stack.values.items, true)), + memo, + }; +} + +// TODO: this is a unmanaged array list, minus the optimisation. We should use that instead +fn assuredResize(comptime T: type, allocator: std.mem.Allocator, old: []T, new_length: usize) ![]T { + if (allocator.resize(old, new_length)) { + return old; + } else { + defer allocator.free(old); + const new = try allocator.alloc(T, new_length); + @memcpy(new[0..old.len], old); + return new; + } +} diff --git a/zml/aio/torch/ops.zig b/zml/aio/torch/ops.zig new file mode 100644 index 0000000..a12a556 --- /dev/null +++ b/zml/aio/torch/ops.zig @@ -0,0 +1,226 @@ +const std = @import("std"); + +/// A decoded Pickle operation in its natural state. +pub const PickleOp = union(RawPickleOp) { + mark, + stop, + pop, + pop_mark, + dup, + float: []u8, + int: []u8, + binint: i32, + binint1: u8, + long: []u8, + binint2: u16, + none, + persid: []u8, + binpersid, + reduce, + string: []u8, + binstring: []u8, + short_binstring: []u8, + unicode: []u8, + binunicode: []u8, + append, + build, + global: [2][]u8, + dict, + empty_dict, + appends, + get: []u8, + binget: u8, + inst: [2][]u8, + long_binget: u32, + list, + empty_list, + obj, + put: []u8, + binput: u8, + long_binput: u32, + setitem, + tuple, + empty_tuple, + setitems, + binfloat: f64, + proto: u8, + newobj, + ext1: u8, + ext2: i16, + ext4: i32, + tuple1, + tuple2, + tuple3, + newtrue, + newfalse, + long1: []u8, + long4: []u8, + binbytes: []u8, + short_binbytes: []u8, + short_binunicode: []u8, + binunicode8: []u8, + binbytes8: []u8, + empty_set, + additems, + frozenset, + newobj_ex, + stack_global, + memoize, + frame: u64, + bytearray8: []u8, + next_buffer, + readonly_buffer, + + pub fn deinit(self: PickleOp, allocator: std.mem.Allocator) void { + switch (self) { + .float, + .int, + .long, + .persid, + .string, + .binstring, + .short_binstring, + .unicode, + .binunicode, + .get, + .put, + .long1, + .long4, + .binbytes, + .short_binbytes, + .short_binunicode, + .binunicode8, + .binbytes8, + .bytearray8, + => |v| allocator.free(v), + .global, .inst => |fields| { + inline for (fields) |field| { + allocator.free(field); + } + }, + else => {}, + } + } + + pub fn clone(self: PickleOp, allocator: std.mem.Allocator) !PickleOp { + var res = self; + return switch (self) { + inline .float, + .int, + .long, + .persid, + .string, + .binstring, + .short_binstring, + .unicode, + .binunicode, + .get, + .put, + .long1, + .long4, + .binbytes, + .short_binbytes, + .short_binunicode, + .binunicode8, + .binbytes8, + .bytearray8, + => |v, tag| { + const cloned = try allocator.alloc(u8, v.len); + @memcpy(cloned, v); + @field(res, @tagName(tag)) = cloned; + return res; + }, + inline .global, .inst => |v, tag| { + var out: std.meta.Tuple(&.{ []u8, []u8 }) = undefined; + inline for (0..2) |i| { + out[i] = try allocator.alloc(u8, v[i].len); + @memcpy(out[i], v[i]); + } + @field(res, @tagName(tag)) = out; + return res; + }, + else => self, + }; + } +}; + +/// The values for the possible opcodes are in this enum. +pub const RawPickleOp = enum(u8) { + mark = '(', // push special markobject on stack + stop = '.', // every pickle ends with stop + pop = '0', // discard topmost stack item + pop_mark = '1', // discard stack top through topmost markobject + dup = '2', // duplicate top stack item + float = 'F', // push float object; decimal string argument + int = 'I', // push integer or bool; decimal string argument + binint = 'J', // push four-byte signed int + binint1 = 'K', // push 1-byte unsigned int + long = 'L', // push long; decimal string argument + binint2 = 'M', // push 2-byte unsigned int + none = 'N', // push None + persid = 'P', // push persistent object; id is taken from string arg + binpersid = 'Q', // " " " ; " " " " stack + reduce = 'R', // apply callable to argtuple, both on stack + string = 'S', // push string; NL-terminated string argument + binstring = 'T', // push string; counted binary string argument + short_binstring = 'U', // " " ; " " " " < 256 bytes + unicode = 'V', // push Unicode string; raw-unicode-escaped'd argument + binunicode = 'X', // " " " ; counted UTF-8 string argument + append = 'a', // append stack top to list below it + build = 'b', // call __setstate__ or __dict__.update() + global = 'c', // push self.find_class(modname, name); 2 string args + dict = 'd', // build a dict from stack items + empty_dict = '}', // push empty dict + appends = 'e', // extend list on stack by topmost stack slice + get = 'g', // push item from memo on stack; index is string arg + binget = 'h', // " " " " " " ; " " 1-byte arg + inst = 'i', // build & push class instance + long_binget = 'j', // push item from memo on stack; index is 4-byte arg + list = 'l', // build list from topmost stack items + empty_list = ']', // push empty list + obj = 'o', // build & push class instance + put = 'p', // store stack top in memo; index is string arg + binput = 'q', // " " " " " ; " " 1-byte arg + long_binput = 'r', // " " " " " ; " " 4-byte arg + setitem = 's', // add key+value pair to dict + tuple = 't', // build tuple from topmost stack items + empty_tuple = ')', // push empty tuple + setitems = 'u', // modify dict by adding topmost key+value pairs + binfloat = 'G', // push float; arg is 8-byte float encoding + + // Protocol 2 + proto = '\x80', // identify pickle protocol + newobj = '\x81', // build object by applying cls.__new__ to argtuple + ext1 = '\x82', // push object from extension registry; 1-byte index + ext2 = '\x83', // ditto, but 2-byte index + ext4 = '\x84', // ditto, but 4-byte index + tuple1 = '\x85', // build 1-tuple from stack top + tuple2 = '\x86', // build 2-tuple from two topmost stack items + tuple3 = '\x87', // build 3-tuple from three topmost stack items + newtrue = '\x88', // push True + newfalse = '\x89', // push False + long1 = '\x8a', // push long from < 256 bytes + long4 = '\x8b', // push really big long + + // Protocol 3 + binbytes = 'B', // push bytes; counted binary string argument + short_binbytes = 'C', // " " ; " " " " < 256 bytes + + // Protocol 4 + short_binunicode = '\x8c', // push short string; UTF-8 length < 256 bytes + binunicode8 = '\x8d', // push very long string + binbytes8 = '\x8e', // push very long bytes string + empty_set = '\x8f', // push empty set on the stack + additems = '\x90', // modify set by adding topmost stack items + frozenset = '\x91', // build frozenset from topmost stack items + newobj_ex = '\x92', // like newobj but work with keyword only arguments + stack_global = '\x93', // same as GLOBAL but using names on the stacks + memoize = '\x94', // store top of the stack in memo + frame = '\x95', // indicate the beginning of a new frame + + // Protocol 5 + bytearray8 = '\x96', // push bytearray + next_buffer = '\x97', // push next out-of-band buffer + readonly_buffer = '\x98', // make top of stack readonly + _, +}; diff --git a/zml/aio/torch/parser.zig b/zml/aio/torch/parser.zig new file mode 100644 index 0000000..93bafcb --- /dev/null +++ b/zml/aio/torch/parser.zig @@ -0,0 +1,481 @@ +const asynk = @import("async"); +const std = @import("std"); +const zml = @import("../../zml.zig"); + +const utils = @import("utils.zig"); +const PickleOp = @import("ops.zig").PickleOp; +const RawPickleOp = @import("ops.zig").RawPickleOp; + +const Allocator = std.mem.Allocator; +const testing = std.testing; + +pub const Decoder = struct { + buffer_file: zml.aio.MemoryMappedFile, + file_map: std.StringArrayHashMapUnmanaged(std.zip.Iterator(asynk.File.SeekableStream).Entry) = .{}, + tar_file: ?TarStream = null, + ops: []PickleOp, + is_zip_file: bool, + zip_prefix: []const u8 = &[_]u8{}, + + const magic = "PK\x03\x04"; + + pub fn fromTarFile(allocator: Allocator, mapped: zml.aio.MemoryMappedFile, file: std.tar.Iterator(asynk.File.Reader).File) !Decoder { + const tar_stream = try TarStream.init(file); + const file_magic = try tar_stream.reader().readBytesNoEof(magic.len); + try tar_stream.seekTo(0); + var self: Decoder = .{ + .buffer_file = mapped, + .tar_file = tar_stream, + .ops = undefined, + .is_zip_file = std.mem.eql(u8, &file_magic, magic), + }; + if (!self.is_zip_file) { + const reader = tar_stream.reader(); + self.ops = try parse(allocator, reader, try tar_stream.getEndPos()); + } else { + self.ops = try self.parseOps(allocator, self.tar_file.?.seekableStream()); + } + return self; + } + + pub fn init(allocator: Allocator, file: asynk.File) !Decoder { + const file_magic = try file.reader().readBytesNoEof(magic.len); + try file.seekTo(0); + var self: Decoder = .{ + .buffer_file = try zml.aio.MemoryMappedFile.init(file), + .is_zip_file = std.mem.eql(u8, &file_magic, magic), + .ops = undefined, + }; + if (!self.is_zip_file) { + const reader = self.buffer_file.file.reader(); + self.ops = try parse(allocator, reader, try reader.context.getEndPos()); + } else { + self.ops = try self.parseOps(allocator, self.buffer_file.file.seekableStream()); + } + return self; + } + + pub fn deinit(self: *Decoder) void { + self.buffer_file.deinit(); + self.* = undefined; + } + + fn parseOps(self: *Decoder, allocator: Allocator, seekable_stream: asynk.File.SeekableStream) ![]PickleOp { + // TODO(SuperAuguste): deflate using `std.compress.flate`'s `decompressor` + // TODO(SuperAuguste): explore swapping in non-generic reader here instead of using switch(?) + // not sure if that'd actually be beneficial in any way + + var iter = try std.zip.Iterator(asynk.File.SeekableStream).init(seekable_stream); + var filename_buf: [std.fs.max_path_bytes]u8 = undefined; + while (try iter.next()) |entry| { + const filename = filename_buf[0..entry.filename_len]; + try seekable_stream.seekTo(entry.header_zip_offset + @sizeOf(std.zip.CentralDirectoryFileHeader)); + const len = try seekable_stream.context.reader().readAll(filename); + if (len != filename.len) return error.ZipBadFileOffset; + if (isBadFilename(filename)) return error.ZipBadFilename; + std.mem.replaceScalar(u8, filename, '\\', '/'); // normalize path separators + try self.file_map.put(allocator, try allocator.dupe(u8, filename), entry); + } + + var file_iter = self.file_map.iterator(); + while (file_iter.next()) |e| { + const entry = e.value_ptr.*; + const filename = e.key_ptr.*; + if (std.mem.indexOf(u8, filename, "data.pkl")) |idx| { + self.zip_prefix = filename[0..idx]; + const local_data_header_offset: u64 = local_data_header_offset: { + const local_header = blk: { + try seekable_stream.seekTo(entry.file_offset); + break :blk try seekable_stream.context.reader().readStructEndian(std.zip.LocalFileHeader, .little); + }; + if (!std.mem.eql(u8, &local_header.signature, &std.zip.local_file_header_sig)) + return error.ZipBadFileOffset; + if (local_header.version_needed_to_extract != entry.version_needed_to_extract) + return error.ZipMismatchVersionNeeded; + if (local_header.last_modification_time != entry.last_modification_time) + return error.ZipMismatchModTime; + if (local_header.last_modification_date != entry.last_modification_date) + return error.ZipMismatchModDate; + + if (@as(u16, @bitCast(local_header.flags)) != @as(u16, @bitCast(entry.flags))) + return error.ZipMismatchFlags; + if (local_header.crc32 != 0 and local_header.crc32 != entry.crc32) + return error.ZipMismatchCrc32; + if (local_header.compressed_size != 0 and + local_header.compressed_size != entry.compressed_size) + return error.ZipMismatchCompLen; + if (local_header.uncompressed_size != 0 and + local_header.uncompressed_size != entry.uncompressed_size) + return error.ZipMismatchUncompLen; + if (local_header.filename_len != entry.filename_len) + return error.ZipMismatchFilenameLen; + + break :local_data_header_offset @as(u64, local_header.filename_len) + + @as(u64, local_header.extra_len); + }; + + const local_data_file_offset: u64 = + @as(u64, entry.file_offset) + + @as(u64, @sizeOf(std.zip.LocalFileHeader)) + + local_data_header_offset; + try seekable_stream.seekTo(local_data_file_offset); + + switch (entry.compression_method) { + .store => { + return parse(allocator, seekable_stream.context.reader(), entry.uncompressed_size); + }, + .deflate => { + // TODO(cryptodeal): handle decompress + @panic("TODO support use of `deflate`"); + }, + else => @panic("TODO support other modes of compression"), + } + } + } + + std.log.err("Could not find file ending in `data.pkl` in archive", .{}); + return error.PickleNotFound; + } + + fn parse(allocator: Allocator, reader: anytype, len: usize) ![]PickleOp { + var results = std.ArrayList(PickleOp).init(allocator); + errdefer results.deinit(); + outer: while (true) { + const b = try reader.readByte(); + switch (@as(RawPickleOp, @enumFromInt(b))) { + .mark => try results.append(.{ .mark = {} }), + .stop => { + try results.append(.{ .stop = {} }); + break :outer; + }, + .pop => try results.append(.{ .pop = {} }), + .pop_mark => try results.append(.{ .pop_mark = {} }), + .dup => try results.append(.{ .dup = {} }), + .float => { + const buf = try reader.readUntilDelimiterAlloc(allocator, '\n', len); + errdefer allocator.free(buf); + try results.append(.{ .float = buf }); + }, + .int => { + const buf = try reader.readUntilDelimiterAlloc(allocator, '\n', len); + errdefer allocator.free(buf); + try results.append(.{ .int = buf }); + }, + .binint => try results.append(.{ .binint = try reader.readInt(i32, .little) }), + .binint1 => try results.append(.{ .binint1 = try reader.readByte() }), + .long => { + const buf = try reader.readUntilDelimiterAlloc(allocator, '\n', len); + errdefer allocator.free(buf); + try results.append(.{ .long = buf }); + }, + .binint2 => try results.append(.{ .binint2 = try reader.readInt(u16, .little) }), + .none => try results.append(.{ .none = {} }), + .persid => { + const buf = try reader.readUntilDelimiterAlloc(allocator, '\n', len); + errdefer allocator.free(buf); + try results.append(.{ .persid = buf }); + }, + .binpersid => try results.append(.{ .binpersid = {} }), + .reduce => try results.append(.{ .reduce = {} }), + .string => { + const buf = try reader.readUntilDelimiterAlloc(allocator, '\n', len); + errdefer allocator.free(buf); + try results.append(.{ .string = buf }); + }, + .binstring => { + const str_len = try reader.readInt(u32, .little); + const buf = try allocator.alloc(u8, str_len); + errdefer allocator.free(buf); + _ = try reader.read(buf); + try results.append(.{ .binstring = buf }); + }, + .short_binstring => { + const str_len = try reader.readByte(); + const buf = try allocator.alloc(u8, str_len); + errdefer allocator.free(buf); + _ = try reader.read(buf); + try results.append(.{ .short_binstring = buf }); + }, + .unicode => { + const buf = try reader.readUntilDelimiterAlloc(allocator, '\n', len); + errdefer allocator.free(buf); + try results.append(.{ .unicode = buf }); + }, + .binunicode => { + const str_len = try reader.readInt(u32, .little); + const buf = try allocator.alloc(u8, str_len); + errdefer allocator.free(buf); + _ = try reader.read(buf); + try results.append(.{ .binunicode = buf }); + }, + .append => try results.append(.{ .append = {} }), + .build => try results.append(.{ .build = {} }), + .global => { + const buf0 = try reader.readUntilDelimiterAlloc(allocator, '\n', len); + errdefer allocator.free(buf0); + const buf1 = try reader.readUntilDelimiterAlloc(allocator, '\n', len); + errdefer allocator.free(buf1); + _ = (buf1.len + 1); + try results.append(.{ .global = .{ buf0, buf1 } }); + }, + .dict => try results.append(.{ .dict = {} }), + .empty_dict => try results.append(.{ .empty_dict = {} }), + .appends => try results.append(.{ .appends = {} }), + .get => { + const buf = try reader.readUntilDelimiterAlloc(allocator, '\n', len); + errdefer allocator.free(buf); + try results.append(.{ .get = buf }); + }, + .binget => try results.append(.{ .binget = try reader.readByte() }), + .inst => { + const buf0 = try reader.readUntilDelimiterAlloc(allocator, '\n', len); + errdefer allocator.free(buf0); + const buf1 = try reader.readUntilDelimiterAlloc(allocator, '\n', len); + errdefer allocator.free(buf1); + _ = (buf1.len + 1); + try results.append(.{ .inst = .{ buf0, buf1 } }); + }, + .long_binget => try results.append(.{ .long_binget = try reader.readInt(u32, .little) }), + .list => try results.append(.{ .list = {} }), + .empty_list => try results.append(.{ .empty_list = {} }), + .obj => try results.append(.{ .obj = {} }), + .put => { + const buf = try reader.readUntilDelimiterAlloc(allocator, '\n', len); + errdefer allocator.free(buf); + try results.append(.{ .put = buf }); + }, + .binput => { + try results.append(.{ .binput = try reader.readByte() }); + }, + .long_binput => { + try results.append(.{ .long_binput = try reader.readInt(u32, .little) }); + }, + .setitem => try results.append(.{ .setitem = {} }), + .tuple => try results.append(.{ .tuple = {} }), + .empty_tuple => try results.append(.{ .empty_tuple = {} }), + .setitems => try results.append(.{ .setitems = {} }), + .binfloat => try results.append(.{ .binfloat = @bitCast(try reader.readInt(u64, .big)) }), + .proto => try results.append(.{ .proto = try reader.readByte() }), + .newobj => try results.append(.{ .newobj = {} }), + .ext1 => try results.append(.{ .ext1 = try reader.readByte() }), + .ext2 => try results.append(.{ .ext2 = try reader.readInt(i16, .little) }), + .ext4 => try results.append(.{ .ext4 = try reader.readInt(i32, .little) }), + .tuple1 => try results.append(.{ .tuple1 = {} }), + .tuple2 => try results.append(.{ .tuple2 = {} }), + .tuple3 => try results.append(.{ .tuple3 = {} }), + .newtrue => try results.append(.{ .newtrue = {} }), + .newfalse => try results.append(.{ .newfalse = {} }), + .long1 => { + const str_len = try reader.readByte(); + const buf = try allocator.alloc(u8, str_len); + errdefer allocator.free(buf); + _ = try reader.read(buf); + try results.append(.{ .long1 = buf }); + }, + .long4 => { + const str_len = try reader.readInt(u32, .little); + const buf = try allocator.alloc(u8, str_len); + errdefer allocator.free(buf); + _ = try reader.read(buf); + try results.append(.{ .long4 = buf }); + }, + .binbytes => { + const str_len = try reader.readInt(u32, .little); + const buf = try allocator.alloc(u8, str_len); + errdefer allocator.free(buf); + _ = try reader.read(buf); + try results.append(.{ .binbytes = buf }); + }, + .binbytes8 => { + const str_len = try reader.readInt(u64, .little); + const buf = try allocator.alloc(u8, str_len); + errdefer allocator.free(buf); + _ = try reader.read(buf); + try results.append(.{ .binbytes8 = buf }); + }, + .short_binbytes => { + const str_len = try reader.readByte(); + const buf = try allocator.alloc(u8, str_len); + errdefer allocator.free(buf); + _ = try reader.read(buf); + try results.append(.{ .short_binbytes = buf }); + }, + .binunicode8 => { + const str_len = try reader.readInt(u64, .little); + const buf = try allocator.alloc(u8, str_len); + errdefer allocator.free(buf); + _ = try reader.read(buf); + try results.append(.{ .binunicode8 = buf }); + }, + .short_binunicode => { + const str_len = try reader.readByte(); + const buf = try allocator.alloc(u8, str_len); + errdefer allocator.free(buf); + _ = try reader.read(buf); + try results.append(.{ .binunicode8 = buf }); + }, + .empty_set => try results.append(.{ .empty_set = {} }), + .additems => try results.append(.{ .additems = {} }), + .frozenset => try results.append(.{ .frozenset = {} }), + .newobj_ex => try results.append(.{ .newobj_ex = {} }), + .stack_global => try results.append(.{ .stack_global = {} }), + .memoize => try results.append(.{ .memoize = {} }), + .frame => try results.append(.{ .frame = try reader.readInt(u64, .little) }), + .bytearray8 => { + const str_len = try reader.readInt(u64, .little); + const buf = try allocator.alloc(u8, str_len); + errdefer allocator.free(buf); + _ = try reader.read(buf); + try results.append(.{ .bytearray8 = buf }); + }, + .next_buffer => try results.append(.{ .next_buffer = {} }), + .readonly_buffer => try results.append(.{ .readonly_buffer = {} }), + else => {}, + } + } + return results.toOwnedSlice(); + } +}; + +const TarStream = struct { + pub const SeekableStream = std.io.SeekableStream( + TarStream, + asynk.File.SeekError, + asynk.File.GetSeekPosError, + TarStream.seekTo, + TarStream.seekBy, + TarStream.getPos, + TarStream.getEndPos, + ); + + file: std.tar.Iterator(asynk.File.Reader).File, + start: usize, + + pub fn init(file: std.tar.Iterator(asynk.File.Reader).File) !TarStream { + return .{ + .file = file, + .start = try file.parent_reader.context.getPos(), + }; + } + + pub fn reader(file: TarStream) std.tar.Iterator(asynk.File.Reader).File.Reader { + return file.file.reader(); + } + + pub fn seekTo(self: TarStream, offset: u64) !void { + return self.file.parent_reader.context.seekTo(self.start + offset); + } + + pub fn seekBy(self: TarStream, offset: i64) !void { + return self.file.parent_reader.context.seekBy(offset); + } + + pub fn getPos(self: TarStream) !u64 { + return try self.file.parent_reader.context.getPos() - self.start; + } + + pub fn getEndPos(self: TarStream) !u64 { + return self.file.size; + } + + pub fn seekableStream(self: TarStream) TarStream.SeekableStream { + return .{ .context = self }; + } +}; + +test "Read pickle (simple)" { + var arena = std.heap.ArenaAllocator.init(testing.allocator); + defer arena.deinit(); + const allocator = arena.allocator(); + const eval = @import("eval.zig"); + const file = try asynk.File.open("zml/aio/torch/simple_test.pickle", .{ .mode = .read_only }); + var data = try Decoder.init(allocator, file); + defer data.deinit(); + var vals, var memo = try eval.evaluate(allocator, data.ops, true); + defer vals.deinit(); + defer memo.deinit(); + + try testing.expect(vals.stack.len == 2); + // skip first value (frame) + try testing.expect(vals.stack[1] == .seq); + try testing.expect(vals.stack[1].seq[0] == .dict); + const entries = vals.stack[1].seq[1][0].seq[1]; + try testing.expect(entries.len == 5); + for (entries, 0..) |kv, i| { + try testing.expect(kv == .seq); + try testing.expect(kv.seq[0] == .kv_tuple); + switch (i) { + 0 => { + const key = kv.seq[1][0]; + try testing.expect(key == .string); + try testing.expectEqualStrings("hello", key.string); + const value = kv.seq[1][1]; + try testing.expect(value == .string); + try testing.expectEqualStrings("world", value.string); + }, + 1 => { + const key = kv.seq[1][0]; + try testing.expect(key == .string); + try testing.expectEqualStrings("int", key.string); + const value = kv.seq[1][1]; + try testing.expect(value == .int); + try testing.expect(value.int == 1); + }, + 2 => { + const key = kv.seq[1][0]; + try testing.expect(key == .string); + try testing.expectEqualStrings("float", key.string); + const value = kv.seq[1][1]; + try testing.expect(value == .float); + try testing.expectEqual(@as(f64, 3.141592), value.float); + }, + 3 => { + const key = kv.seq[1][0]; + try testing.expect(key == .string); + try testing.expectEqualStrings("list", key.string); + const value = kv.seq[1][1]; + try testing.expect(value == .seq); + try testing.expect(value.seq[0] == .list); + for (value.seq[1], 0..) |item, j| { + try testing.expect(item == .int); + try testing.expect(item.int == @as(i64, @intCast(j))); + } + }, + 4 => { + const key = kv.seq[1][0]; + try testing.expect(key == .string); + try testing.expectEqualStrings("tuple", key.string); + const value = kv.seq[1][1]; + try testing.expect(value == .seq); + try testing.expect(value.seq[0] == .tuple); + try testing.expect(value.seq[1][0] == .string); + try testing.expectEqualStrings("a", value.seq[1][0].string); + try testing.expect(value.seq[1][1] == .int); + try testing.expect(value.seq[1][1].int == 10); + }, + else => unreachable, + } + } +} + +test "Read pickle (zipped)" { + var arena = std.heap.ArenaAllocator.init(testing.allocator); + defer arena.deinit(); + const allocator = arena.allocator(); + const file = try asynk.File.open("zml/aio/torch/simple.pt", .{ .mode = .read_only }); + var data = try Decoder.init(allocator, file); + defer data.deinit(); +} + +pub fn isBadFilename(filename: []const u8) bool { + if (filename.len == 0 or filename[0] == '/') + return true; + + var it = std.mem.splitScalar(u8, filename, '/'); + while (it.next()) |part| { + if (std.mem.eql(u8, part, "..")) + return true; + } + + return false; +} diff --git a/zml/aio/torch/simple.pt b/zml/aio/torch/simple.pt new file mode 100644 index 0000000..beeb39d Binary files /dev/null and b/zml/aio/torch/simple.pt differ diff --git a/zml/aio/torch/simple_test.pickle b/zml/aio/torch/simple_test.pickle new file mode 100644 index 0000000..19d7260 Binary files /dev/null and b/zml/aio/torch/simple_test.pickle differ diff --git a/zml/aio/torch/utils.zig b/zml/aio/torch/utils.zig new file mode 100644 index 0000000..2b573dd --- /dev/null +++ b/zml/aio/torch/utils.zig @@ -0,0 +1,23 @@ +const std = @import("std"); + +const Value = @import("value.zig").Value; + +pub fn allTrue(values: []const Value, func: fn (v: Value) bool) bool { + for (values) |v| { + if (!func(v)) return false; + } + return true; +} + +pub fn isBadFilename(filename: []const u8) bool { + if (filename.len == 0 or filename[0] == '/') + return true; + + var it = std.mem.splitScalar(u8, filename, '/'); + while (it.next()) |part| { + if (std.mem.eql(u8, part, "..")) + return true; + } + + return false; +} diff --git a/zml/aio/torch/value.zig b/zml/aio/torch/value.zig new file mode 100644 index 0000000..302f85e --- /dev/null +++ b/zml/aio/torch/value.zig @@ -0,0 +1,401 @@ +const std = @import("std"); +const utils = @import("utils.zig"); + +const PickleOp = @import("ops.zig").PickleOp; + +const big_int = std.math.big.int; + +/// The types of sequences that exist. +pub const SequenceType = enum { + list, + dict, + kv_tuple, + tuple, + set, + frozen_set, +}; + +pub const Object = struct { + allocator: std.mem.Allocator, + member: Value, + args: []Value, + + pub fn init(allocator: std.mem.Allocator, member: Value, args: []Value) !*Object { + const self = try allocator.create(Object); + self.* = .{ .allocator = allocator, .member = member, .args = args }; + return self; + } + + pub fn clone(self: *Object, allocator: std.mem.Allocator) std.mem.Allocator.Error!*Object { + const res = try allocator.create(Object); + res.* = .{ .allocator = allocator, .member = try self.member.clone(allocator), .args = try allocator.alloc(Value, self.args.len) }; + for (self.args, 0..) |v, i| res.args[i] = try v.clone(allocator); + return res; + } + + pub fn deinit(self: *Object) void { + self.member.deinit(self.allocator); + for (self.args) |*v| v.deinit(self.allocator); + self.allocator.free(self.args); + self.allocator.destroy(self); + } +}; + +pub const Build = struct { + allocator: std.mem.Allocator, + member: Value, + args: Value, + + pub fn init(allocator: std.mem.Allocator, member: Value, args: Value) !*Build { + const self = try allocator.create(Build); + self.* = .{ .allocator = allocator, .member = member, .args = args }; + return self; + } + + pub fn clone(self: *Build, allocator: std.mem.Allocator) std.mem.Allocator.Error!*Build { + const res = try allocator.create(Build); + res.* = .{ .allocator = allocator, .member = try self.member.clone(allocator), .args = try self.args.clone(allocator) }; + return res; + } + + pub fn deinit(self: *Build) void { + self.member.deinit(self.allocator); + self.args.deinit(self.allocator); + self.allocator.destroy(self); + } +}; + +pub const Sequence = struct { SequenceType, []Value }; + +pub const PersId = struct { + allocator: std.mem.Allocator, + ref: Value, + + pub fn init(allocator: std.mem.Allocator, ref: Value) !*PersId { + const self = try allocator.create(PersId); + self.* = .{ .allocator = allocator, .ref = ref }; + return self; + } + + pub fn clone(self: *PersId, allocator: std.mem.Allocator) std.mem.Allocator.Error!*PersId { + const res = try allocator.create(PersId); + res.* = .{ .allocator = allocator, .ref = try self.ref.clone(allocator) }; + return res; + } + + pub fn deinit(self: *PersId) void { + self.ref.deinit(self.allocator); + self.allocator.destroy(self); + } +}; + +pub const ValueType = enum { + raw, + ref, + app, + object, + build, + pers_id, + global, + seq, + string, + bytes, + int, + bigint, + float, + raw_num, + bool, + none, +}; + +/// A processed value. +pub const Value = union(ValueType) { + /// Types that we can't handle or just had to give up on processing. + raw: PickleOp, + + /// A reference. You might be able to look it up in the memo map + /// unless there's something weird going on like recursive references. + /// You generally shouldn't see this in the result unless bad things + /// are going on... + ref: u32, + + /// The result of applying a thing to another thing. We're not + /// Python so we don't really know what a "thing" is. + app: *Object, + + /// An object or something. The first tuple member is the + /// thing, the second one is the arguments it got applied to. + object: *Object, + + /// Something we tried to build. The first tuple member is the + /// thing, the second one is the arguments it got applied to. + build: *Build, + + /// References to persistant storage. They basically could be anything. + /// You kind of have to know what the thing you're trying to + /// interface wants to use as keys for persistant storage. + /// Good luck. + pers_id: *PersId, + + /// A global value of some kind. The first tuple member is + /// the thing, the second one is the arguments it got applied to. + global: *Object, + + /// A sequence. We don't really distinguish between them + /// much. The one exception is when the SequenceType is + /// Dict we try to split the flat list of `[k, v, k, v, k, v]` + /// into a list of tuples with the key and value. + seq: Sequence, + + /// A string, but not the crazy strings that have to be + /// unescaped as if they were Python strings. If you + /// need one of those, look for it inside a `Value.raw`. + string: []const u8, + + /// Some bytes. It might be a byte array or a binary + /// string that couldn't get UTF8 decoded. We do the best + /// we can. + bytes: []const u8, + + /// An integer, but not the crazy kind that comes as a string + /// that has to be parsed. You can look in `Value.raw_num` for + /// those. + int: i64, + + /// An integer that can't fit in i64. + bigint: big_int.Managed, + + /// An float, but not the crazy kind that comes as a string + /// that has to be parsed. You can look in `Value.raw_num` for + /// those. + float: f64, + + /// Some kind of weird number we can't handle. + raw_num: PickleOp, + + /// A boolean value. + bool: bool, + + /// Python `None`. + none: void, + + pub fn deinit(self: *Value, allocator: std.mem.Allocator) void { + switch (self.*) { + .raw, .raw_num => |v| v.deinit(allocator), + inline .app, .object, .global, .build, .pers_id => |v| v.deinit(), + .seq => |v| { + for (v[1]) |*val| val.deinit(allocator); + allocator.free(v[1]); + }, + .string, .bytes => |v| allocator.free(v), + .bigint => self.bigint.deinit(), + else => {}, + } + self.* = undefined; + } + + inline fn writeIndents(indents: usize, writer: anytype) !void { + try writer.writeBytesNTimes(" ", indents); // resolve tab = 2 spaces + // try writer.writeByteNTimes('\t'); + } + + fn internalFormat(value: Value, indents: usize, writer: anytype) !void { + try writeIndents(indents, writer); + try writer.writeAll(".{\n"); + try writeIndents(indents + 1, writer); + try writer.print(".{s} = ", .{@tagName(std.meta.activeTag(value))}); + switch (value) { + inline .ref, .int, .float => |v| try writer.print("{d} ", .{v}), + .app, .object, .global => |v| { + try writer.writeAll(".{\n"); + try internalFormat(v.member, indents + 2, writer); + try writer.writeAll(",\n"); + try writeIndents(indents + 2, writer); + if (v.args.len > 0) { + try writer.writeAll(".{\n"); + for (v.args, 0..) |arg, i| { + try internalFormat(arg, indents + 3, writer); + if (i < v.args.len - 1) try writer.writeAll(","); + try writer.writeByte('\n'); + } + try writeIndents(indents + 2, writer); + try writer.writeAll("}\n"); + } else { + try writer.writeAll(".{}\n"); + } + try writeIndents(indents + 1, writer); + try writer.writeAll("}"); + }, + .build => |v| { + try writer.writeAll(".{\n"); + try internalFormat(v.member, indents + 2, writer); + try writer.writeAll(",\n"); + try internalFormat(v.args, indents + 2, writer); + try writer.writeAll(",\n"); + try writeIndents(indents + 1, writer); + try writer.writeAll("}"); + }, + inline .pers_id => |v| { + try writer.writeByte('\n'); + try internalFormat(v.ref, indents + 2, writer); + }, + .seq => |v| { + try writer.writeAll(".{\n"); + try writeIndents(indents + 2, writer); + try writer.print(".{s},\n", .{@tagName(v[0])}); + try writeIndents(indents + 2, writer); + if (v[1].len > 0) { + try writer.writeAll(".{\n"); + for (v[1], 0..) |arg, i| { + try internalFormat(arg, indents + 3, writer); + if (i < v[1].len - 1) try writer.writeAll(","); + try writer.writeByte('\n'); + } + try writeIndents(indents + 2, writer); + try writer.writeAll("}\n"); + } else { + try writer.writeAll(".{}\n"); + } + + try writeIndents(indents + 1, writer); + try writer.writeAll("}"); + }, + .string => |v| try writer.print("\"{s}\"", .{v}), + .raw => |v| switch (v) { + .global => |raw_global| try writer.print("\"{s}\", \"{s}\"", .{ raw_global[0], raw_global[1] }), + else => try writer.print("{any}", .{v}), + }, + inline else => |v| { + try writer.print("{any}", .{v}); + }, + } + try writer.writeByte('\n'); + try writeIndents(indents, writer); + try writer.writeByte('}'); + } + + pub fn format(self: Value, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + return internalFormat(self, 0, writer); + } + + pub fn clone(self: Value, allocator: std.mem.Allocator) !Value { + return switch (self) { + inline .raw, .raw_num => |v, tag| @unionInit(Value, @tagName(tag), try v.clone(allocator)), + inline .app, .object, .global, .build, .pers_id => |v, tag| @unionInit(Value, @tagName(tag), try v.clone(allocator)), + .seq => |seq| blk: { + const new_val: Sequence = .{ seq[0], try allocator.alloc(Value, seq[1].len) }; + for (seq[1], 0..) |v, i| new_val[1][i] = try v.clone(allocator); + break :blk .{ .seq = new_val }; + }, + inline .string, .bytes => |v, tag| @unionInit(Value, @tagName(tag), try allocator.dupe(u8, v)), + .bigint => |v| .{ .bigint = try v.clone() }, + else => self, + }; + } + + pub fn isPrimitive(self: Value) bool { + return switch (self) { + .int, .bigint, .float, .string, .bytes, .bool, .none => true, + .seq => |seq| utils.allTrue(seq[1], Value.isPrimitive), + else => false, + }; + } + + pub fn containsRef(self: Value) bool { + switch (self) { + .ref => return true, + .app, .object, .global => |v| { + if (v.member.containsRef()) return true; + for (v.args) |arg| if (arg.containsRef()) return true; + return false; + }, + .build => |v| { + if (v.member.containsRef()) return true; + if (v.args.containsRef()) return true; + return false; + }, + .pers_id => |v| return v.ref.containsRef(), + .seq => |v| { + for (v[1]) |val| if (val.containsRef()) return true; + return false; + }, + else => return false, + } + } + + const BI64MIN = big_int.Const{ + .limbs = &.{@intCast(@abs(std.math.minInt(i64)))}, + .positive = false, + }; + + const BI64MAX = big_int.Const{ + .limbs = &.{@intCast(std.math.maxInt(i64))}, + .positive = true, + }; + + pub fn coerceFromRaw(self: Value, allocator: std.mem.Allocator) !Value { + return switch (self) { + .raw => |raw_val| switch (raw_val) { + .binint, .binint1, .binint2 => |val| .{ .int = val }, + .long1, .long4 => |b| if (b.len != 0) { + var bint = try big_int.Managed.initCapacity(allocator, std.math.big.int.calcTwosCompLimbCount(b.len)); + var mutable = bint.toMutable(); + mutable.readTwosComplement(b, b.len, .little, .signed); + const min_comp = bint.toConst().order(BI64MIN); + const max_comp = bint.toConst().order(BI64MAX); + if ((min_comp == .gt or min_comp == .eq) and (max_comp == .lt or max_comp == .eq)) { + defer bint.deinit(); + return .{ .int = try bint.to(i64) }; + } else return .{ .bigint = bint }; + } else .{ .raw_num = raw_val }, + .binfloat => |val| .{ .float = val }, + .binunicode, .binunicode8, .short_binunicode => |s| .{ .string = s }, + .binbytes, .binbytes8, .short_binbytes, .bytearray8 => |b| .{ .bytes = b }, + // This isn't how Pickle actually works but we just try to UTF8 decode the + // string and if it fails, we make it a bytes value instead. If anyone + // actually cares they can just fix values themselves or recover the raw bytes + // from the UTF8 string (it's guaranteed to be reversible, as far as I know). + .binstring, .short_binstring => |b| if (std.unicode.utf8ValidateSlice(b)) .{ .string = b } else .{ .bytes = b }, + .newtrue => .{ .bool = true }, + .newfalse => .{ .bool = false }, + .none => .{ .none = {} }, + inline .int, + .float, + .long, + => |v, tag| { + if (tag == .int and std.mem.eql(u8, v, "01")) { + return .{ .bool = true }; + } else if (tag == .int and std.mem.eql(u8, v, "00")) { + return .{ .bool = false }; + } else { + return .{ .raw_num = raw_val }; + } + }, + else => self, + }, + .app, .object, .global => |v| blk: { + v.member = try v.member.coerceFromRaw(allocator); + for (v.args) |*arg| { + arg.* = try arg.coerceFromRaw(allocator); + } + break :blk self; + }, + .build => |v| blk: { + v.member = try v.member.coerceFromRaw(allocator); + v.args = try v.args.coerceFromRaw(allocator); + break :blk self; + }, + .pers_id => |v| blk: { + v.ref = try v.ref.coerceFromRaw(allocator); + break :blk self; + }, + .seq => |*v| blk: { + for (v[1]) |*val| { + val.* = try val.coerceFromRaw(allocator); + } + break :blk self; + }, + else => self, + }; + } +}; diff --git a/zml/aio/utils.zig b/zml/aio/utils.zig new file mode 100644 index 0000000..0bf1043 --- /dev/null +++ b/zml/aio/utils.zig @@ -0,0 +1,7 @@ +pub fn toVoidSlice(data: anytype) []void { + const info = @typeInfo(@TypeOf(data)); + if (info != .Pointer or info.Pointer.size != .Slice) { + @compileError("toVoidSlice expects a slice"); + } + return @as([*]void, @ptrCast(@alignCast(data.ptr)))[0..data.len]; +} diff --git a/zml/aio/value.zig b/zml/aio/value.zig new file mode 100644 index 0000000..7cc4d2f --- /dev/null +++ b/zml/aio/value.zig @@ -0,0 +1,262 @@ +const std = @import("std"); + +pub const Value = union(enum) { + pub const Slice = struct { + pub const ItemType = enum { + uint8, + int8, + uint16, + int16, + uint32, + int32, + uint64, + int64, + float16, + float32, + float64, + boolval, + string, + // TODO (cryptodeal): gguf/torch/json (safetensors) in theory support nested arrays; + // we should support for the sake of completeness, but we have not yet encountered + // a model containing these types. + // TODO (cryptodeal): array, + }; + + item_type: ItemType, + data: []u8, + + fn isNestedSlice(comptime T: type) bool { + const info = @typeInfo(T); + if (info != .Pointer or info.Pointer.size != .Slice) { + return false; + } + + var child_info = @typeInfo(info.Pointer.child); + while (child_info == .Pointer and child_info.Pointer.size == .Slice) : (child_info = @typeInfo(child_info.Pointer.child)) {} + return switch (@TypeOf(child_info)) {}; + } + + fn fromZigType(comptime T: type) ItemType { + return switch (T) { + u8 => .uint8, + i8 => .int8, + u16 => .uint16, + i16 => .int16, + u32 => .uint32, + i32 => .int32, + u64 => .uint64, + i64 => .int64, + f16 => .float16, + f32 => .float32, + f64 => .float64, + bool => .boolval, + []const u8 => .string, + else => @panic("Unsupported type for LoaderValue.Slice: " ++ @typeName(T)), + }; + } + + pub fn toZigType(comptime kind: ItemType) type { + return switch (kind) { + .uint8 => u8, + .int8 => i8, + .uint16 => u16, + .int16 => i16, + .uint32 => u32, + .int32 => i32, + .uint64 => u64, + .int64 => i64, + .float16 => f16, + .float32 => f32, + .float64 => f64, + .boolval => bool, + .string => []const u8, + }; + } + + pub fn cast(self: *Slice, comptime T: type) []T { + if (fromZigType(T) != self.item_type) { + @panic("Type mismatch in LoaderValue.Slice cast"); + } + return @as([*]T, @ptrCast(@alignCast(self.data.ptr)))[0..self.data.len]; + } + }; + + // TODO: this is overkill we don't need that many different types + // to represent metadata. bool, i64, f64, string are enough (like Json). + null, + uint8: u8, + int8: i8, + uint16: u16, + int16: i16, + uint32: u32, + int32: i32, + uint64: u64, + int64: i64, + float16: f16, + float32: f32, + float64: f64, + bigint: std.math.big.int.Managed, + boolval: bool, + array: Slice, + string: []const u8, + + pub fn wrap(x: anytype) Value { + const tag = switch (@TypeOf(x)) { + u8 => .uint8, + i8 => .int8, + u16 => .uint16, + i16 => .int16, + u32 => .uint32, + i32 => .int32, + u64 => .uint64, + i64 => .int64, + f16 => .float16, + f32 => .float32, + f64 => .float64, + bool => .boolval, + []const u8 => .string, + else => @panic("Unsupported type for zml.aio.Value: " ++ @typeName(@TypeOf(x))), + }; + return @unionInit(Value, @tagName(tag), x); + } + + pub fn @"null"(self: Value) error{IncorrectType}!void { + switch (self) { + .null => {}, + inline else => |v| { + std.log.err("Expected `null`, actual value is {s}\n", .{@typeName(@TypeOf(v))}); + return error.IncorrectType; + }, + } + } + + pub fn @"u8"(self: Value) error{IncorrectType}!u8 { + switch (self) { + .uint8 => |v| return v, + inline else => |v| { + std.log.err("Expected `u8`, actual value is {s}\n", .{@typeName(@TypeOf(v))}); + return error.IncorrectType; + }, + } + } + + pub fn @"i8"(self: Value) error{IncorrectType}!i8 { + switch (self) { + .int8 => |v| return v, + inline else => |v| { + std.log.err("Expected `i8`, actual value is {s}\n", .{@typeName(@TypeOf(v))}); + return error.IncorrectType; + }, + } + } + + pub fn @"u16"(self: Value) error{IncorrectType}!u16 { + switch (self) { + .uint16 => |v| return v, + inline else => |v| { + std.log.err("Expected `u16`, actual value is {s}\n", .{@typeName(@TypeOf(v))}); + return error.IncorrectType; + }, + } + } + + pub fn @"i16"(self: Value) error{IncorrectType}!i16 { + switch (self) { + .int16 => |v| return v, + inline else => |v| { + std.log.err("Expected `i16`, actual value is {s}\n", .{@typeName(@TypeOf(v))}); + return error.IncorrectType; + }, + } + } + + pub fn @"u32"(self: Value) error{IncorrectType}!u32 { + switch (self) { + .uint32 => |v| return v, + inline else => |v| { + std.log.err("Expected `u32`, actual value is {s}\n", .{@typeName(@TypeOf(v))}); + return error.IncorrectType; + }, + } + } + + pub fn @"i32"(self: Value) error{IncorrectType}!i32 { + switch (self) { + .int32 => |v| return v, + inline else => |v| { + std.log.err("Expected `i32`, actual value is {s}\n", .{@typeName(@TypeOf(v))}); + return error.IncorrectType; + }, + } + } + + pub fn @"u64"(self: Value) error{IncorrectType}!u64 { + switch (self) { + .uint64 => |v| return v, + inline else => |v| { + std.log.err("Expected `u64`, actual value is {s}\n", .{@typeName(@TypeOf(v))}); + return error.IncorrectType; + }, + } + } + + pub fn @"i64"(self: Value) error{IncorrectType}!i64 { + switch (self) { + .int64 => |v| return v, + inline else => |v| { + std.log.err("Expected `i64`, actual value is {s}\n", .{@typeName(@TypeOf(v))}); + return error.IncorrectType; + }, + } + } + + pub fn @"f16"(self: Value) error{IncorrectType}!f16 { + switch (self) { + .float16 => |v| return v, + inline else => |v| { + std.log.err("Expected `f16`, actual value is {s}\n", .{@typeName(@TypeOf(v))}); + return error.IncorrectType; + }, + } + } + + pub fn @"f32"(self: Value) error{IncorrectType}!f32 { + switch (self) { + .float32 => |v| return v, + inline else => |v| { + std.log.err("Expected `f32`, actual value is {s}\n", .{@typeName(@TypeOf(v))}); + return error.IncorrectType; + }, + } + } + + pub fn @"f64"(self: Value) error{IncorrectType}!f64 { + switch (self) { + .float64 => |v| return v, + inline else => |v| { + std.log.err("Expected `f64`, actual value is {s}\n", .{@typeName(@TypeOf(v))}); + return error.IncorrectType; + }, + } + } + + pub fn @"bool"(self: Value) error{IncorrectType}!bool { + switch (self) { + .boolval => |v| return v, + inline else => |v| { + std.log.err("Expected `bool`, actual value is {s}\n", .{@typeName(@TypeOf(v))}); + return error.IncorrectType; + }, + } + } + + pub fn string(self: Value) error{IncorrectType}![]const u8 { + switch (self) { + .string => |v| return v, + inline else => |v| { + std.log.err("Expected string (`[]const u8`), actual value is {s}\n", .{@typeName(@TypeOf(v))}); + return error.IncorrectType; + }, + } + } +}; diff --git a/zml/aio/yaml.zig b/zml/aio/yaml.zig new file mode 100644 index 0000000..741a402 --- /dev/null +++ b/zml/aio/yaml.zig @@ -0,0 +1,98 @@ +const std = @import("std"); +const utils = @import("utils.zig"); +const yaml = @import("zig-yaml"); +const zml = @import("../zml.zig"); + +const Allocator = std.mem.Allocator; + +const StringBuilder = std.ArrayListUnmanaged(u8); + +pub fn open(allocator: Allocator, path: []const u8) !zml.aio.BufferStore { + const file = try std.fs.cwd().openFile(path, .{}); + defer file.close(); + var res: zml.aio.BufferStore = .{ + .arena = std.heap.ArenaAllocator.init(allocator), + }; + errdefer res.arena.deinit(); + const arena = res.arena.allocator(); + + const yaml_data = try file.reader().readAllAlloc(arena, (try file.metadata()).size()); + const parsed = try yaml.Yaml.load(arena, yaml_data); + + const map = parsed.docs.items[0].map; + var map_iter = map.iterator(); + while (map_iter.next()) |entry| { + var prefix_buf: [1024]u8 = undefined; + try parseMetadata(arena, &res, StringBuilder.initBuffer(&prefix_buf), entry.key, entry.value); + } + return res; +} + +pub fn parseMetadata(allocator: Allocator, store: *zml.aio.BufferStore, key: StringBuilder, val: yaml.Value) !void { + switch (val) { + .int => |v| try store.metadata.put(allocator, try allocator.dupe(u8, key.items), .{ .int64 = v }), + .float => |v| try store.metadata.put(allocator, try allocator.dupe(u8, key.items), .{ .float64 = v }), + .string => |v| try store.metadata.put(allocator, try allocator.dupe(u8, key.items), .{ .string = v }), + .list => |v| switch (validSlice(v)) { + true => { + if (v.len == 0) return; + switch (v[0]) { + .int => { + const values = try allocator.alloc(i64, v.len); + errdefer allocator.free(values); + for (v, 0..) |item, i| values[i] = item.int; + try store.metadata.put(allocator, try allocator.dupe(u8, key.items), .{ .array = .{ .item_type = .int64, .data = utils.toVoidSlice(values) } }); + }, + .float => { + const values = try allocator.alloc(f64, v.len); + errdefer allocator.free(values); + for (v, 0..) |item, i| values[i] = item.float; + try store.metadata.put(allocator, try allocator.dupe(u8, key.items), .{ .array = .{ .item_type = .float64, .data = utils.toVoidSlice(values) } }); + }, + .string => { + const values = try allocator.alloc([]const u8, v.len); + errdefer allocator.free(values); + for (v, 0..) |item, i| { + values[i] = try allocator.dupe(u8, item.string); + } + try store.metadata.put(allocator, try allocator.dupe(u8, key.items), .{ .array = .{ .item_type = .string, .data = utils.toVoidSlice(values) } }); + }, + .list => unreachable, + else => {}, + } + }, + false => for (v, 0..) |item, i| { + var new_key = key; + if (key.items.len > 0) + new_key.appendAssumeCapacity('.'); + new_key.items.len += std.fmt.formatIntBuf(new_key.unusedCapacitySlice(), i, 10, .lower, .{}); + try parseMetadata(allocator, store, new_key, item); + }, + }, + .map => { + var map_iter = val.map.iterator(); + while (map_iter.next()) |entry| { + var new_prefix = key; + if (key.items.len > 0) + new_prefix.appendAssumeCapacity('.'); + new_prefix.appendSliceAssumeCapacity(entry.key_ptr.*); + try parseMetadata(allocator, store, new_prefix, entry.value_ptr.*); + } + }, + else => {}, + } +} + +fn validSlice(v: []yaml.Value) bool { + if (v.len == 0) return false; + const item_type = std.meta.activeTag(v[0]); + switch (item_type) { + .empty, .list, .map => return false, + else => {}, + } + + for (v[1..]) |item| + if (item_type != std.meta.activeTag(item)) return false; + + return true; +} diff --git a/zml/buffer.zig b/zml/buffer.zig new file mode 100644 index 0000000..e38a602 --- /dev/null +++ b/zml/buffer.zig @@ -0,0 +1,221 @@ +const std = @import("std"); +const testing = std.testing; + +const meta = @import("meta.zig"); +const pjrt = @import("pjrt"); +const pjrtx = @import("pjrtx.zig"); +const platform = @import("platform.zig"); + +const Context = @import("context.zig").Context; +const HostBuffer = @import("hostbuffer.zig").HostBuffer; +const Shape = @import("shape.zig").Shape; +const Tensor = @import("tensor.zig").Tensor; +const Data = @import("dtype.zig").Data; +const DataType = @import("dtype.zig").DataType; +const Target = @import("platform.zig").Target; + +/// Buffer is a multi-dimension array, whose memory is allocated on an accelerator. +/// +/// * contains a handle that the ZML runtime can use to convert into a physical address, but there is no guarantee this address is visible from the CPU. +/// * loading weights from disk directly to the `device zml.aio.loadBuffers` +/// * can be created by calling `HostBuffer.toDevice(platform)`. +pub const Buffer = struct { + _shape: Shape, + _shards: Shape = undefined, + _platform: platform.Platform, + _data: *pjrtx.Buffer, + + /// Copies the content of the given buffer from host memory to the accelerator memory. + pub fn from(platform_: platform.Platform, buf: HostBuffer) !Buffer { + const pjrt_buffer = try platform_.pjrt_client.bufferFromHostBuffer(platform_.pjrt_api, .{ + .data = buf.data, + .buffer_type = pjrtx.Buffer.BufferTypeFromDType(buf.shape().dtype()), + .dims = buf.shape().dims(), + .byte_strides = null, + .device = platform_.getDevices()[0], + .host_buffer_semantics = .ImmutableUntilTransferCompletes, + }); + return .{ + ._platform = platform_, + ._shape = buf.shape(), + ._data = pjrt_buffer, + }; + } + + /// Wraps a pre-exisiting `pjrt.Buffer` into a `zml.Buffer`. + pub fn fromPjrtBuffer(platform_: platform.Platform, pjrt_buffer: *pjrtx.Buffer) Buffer { + return .{ + ._platform = platform_, + ._shape = _shapeFromPjrtBuffer(platform_, pjrt_buffer), + ._data = pjrt_buffer, + }; + } + + /// Copies the given Zig slice to the accelerator memory and + /// return a Buffer with the given dimensions. + pub fn fromSlice(platform_: platform.Platform, dimz: anytype, s: anytype) !Buffer { + const sh = Shape.init(dimz, DataType.fromSliceElementType(s)); + return from(platform_, HostBuffer.fromBytes(sh, std.mem.sliceAsBytes(s))); + } + + /// Copies the given Zig array to the accelerator memory and + /// return a Buffer using the array shape. + pub fn fromArray(platform_: platform.Platform, arr: anytype) !Buffer { + const host_buffer = HostBuffer.fromArray(&arr); + return try host_buffer.toDevice(platform_); + } + + /// Creates a Buffer with a single element. + pub fn scalar(platform_: platform.Platform, val: anytype, dtype_: DataType) !Buffer { + const x = dtype_.constant(val); + const host_buffer = HostBuffer.fromBytes(Shape.init(.{}, dtype_), x.constSlice()); + return try host_buffer.toDevice(platform_); + } + + /// Creates a Buffer as a view of memory visible from the device, + /// thus avoiding a copy. + /// + /// On CUDA, it also allows you to specify a host allocated slice as they seem to be accessible. + /// Be careful though, as it requires a specific alignment. + /// Also note that it might not work on all platforms, + /// could lead to crashes and is considerably slower. + pub fn asViewOf(platform_: platform.Platform, buf: HostBuffer) !Buffer { + const minor_to_major: [Shape.MAX_RANK]i64 = comptime blk: { + var res: [Shape.MAX_RANK]i64 = undefined; + for (0..Shape.MAX_RANK) |i| { + res[i] = @intCast(Shape.MAX_RANK - i - 1); + } + break :blk res; + }; + + const pjrt_buffer = try platform_.pjrt_client.createViewOfDeviceBuffer(platform_.pjrt_api, .{ + .data = buf.data, + .element_type = pjrtx.Buffer.BufferTypeFromDType(buf.shape().dtype()), + .dims = buf.shape().dims(), + .device = platform_.getDevices()[0], + .layout = .{ + .Tiled = .{ + .minor_to_major = minor_to_major[Shape.MAX_RANK - buf.shape().rank() ..], + .tile_dims = &.{}, + .tile_dims_sizes = &.{}, + }, + }, + }); + + return .{ + ._platform = platform_, + ._shape = buf.shape(), + ._data = pjrt_buffer, + }; + } + + /// Fetches the content of the given buffer into a stack variable of the given type. + pub fn getValue(self: Buffer, T: type) !T { + meta.assert(self._shape.byteSize() == @sizeOf(T), "Buffer {} has {d} bytes of data, can't load it to a {s} with {d} bytes", .{ self, self._shape.byteSize(), @typeName(T), @sizeOf(T) }); + var res: T = undefined; + try self._data.toHostBuffer(self._platform.pjrt_api, std.mem.asBytes(&res)); + return res; + } + + /// Copies the content of the Buffer back to host, in the given buffer, + /// and return a new `HostBuffer` object with the same shape. + /// The returned `HostBuffer` doesn't own the memory. + pub fn toHost(self: Buffer, output: []u8) !HostBuffer { + try self._data.toHostBuffer(self._platform.pjrt_api, output); + return HostBuffer.fromBytes(self.shape(), output); + } + + /// Copies the content of the Buffer to the host. + /// The returned `HostBuffer` does own the memory. + pub fn toHostAlloc(self: Buffer, allocator: std.mem.Allocator) !HostBuffer { + const output = try HostBuffer.empty(allocator, self.shape()); + try self._data.toHostBuffer(self._platform.pjrt_api, @constCast(output.data)); + return output; + } + + /// Frees the accelerator memory. + /// Depending on the platform, the memory is typically not released to the OS + /// but just marked as available in the memory pool. + pub fn deinit(self: *const Buffer) void { + self._data.deinit(self._platform.pjrt_api); + } + + /// This Buffer shape. + pub fn shape(self: Buffer) Shape { + return self._shape; + } + + /// This Buffer shape as a slice of dims. + pub fn dims(self: *const Buffer) []const i64 { + return self._shape.dims(); + } + + /// This Buffer element type. + pub fn dtype(self: Buffer) DataType { + return self._shape.dtype(); + } + + /// This Buffer rank. + pub fn rank(self: Buffer) u4 { + return self._shape.rank(); + } + + /// Test helper: returns a new Buffer with the given tags. + /// Allows to call `zml.testing.compileAndCall` when the tested + /// functions requires tagged tensors. + pub fn withTags(self: Buffer, tags_: anytype) Buffer { + var res = self; + res._shape = self._shape.withTags(tags_); + return res; + } + + pub fn format( + self: Buffer, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, + ) !void { + _ = fmt; + _ = options; + try writer.print("Tensor({_})", .{self._shape}); + } + + fn _shapeFromPjrtBuffer(platform_: platform.Platform, buf: *pjrtx.Buffer) Shape { + const dt: DataType = switch (buf.getElementType(platform_.pjrt_api)) { + // Please keep the list exhaustive and in the same order than in DataType. + .PRED => .bool, + .F8E4M3B11FNUZ => .f8e4m3b11fnuz, + .F8E4M3FN => .f8e4m3fn, + .F8E4M3FNUZ => .f8e4m3fnuz, + .F8E5M2 => .f8e5m2, + .F8E5M2FNUZ => .f8e5m2fnuz, + .BF16 => .bf16, + .F16 => .f16, + .F32 => .f32, + .F64 => .f64, + .S4 => .i4, + .S8 => .i8, + .S16 => .i16, + .S32 => .i32, + .S64 => .i64, + .U4 => .u4, + .U8 => .u8, + .U16 => .u16, + .U32 => .u32, + .U64 => .u64, + .C64 => .c64, + .C128 => .c128, + .INVALID => @panic("Can't handle INVALID Pjrt buffers."), + }; + + return Shape.init(buf.getDimensions(platform_.pjrt_api), dt); + } + + pub const From = meta.MapType(Tensor, Buffer).map; +}; + +/// Returns a mirrored version of T where each Tensor has been replaced by a Buffer. +pub fn Bufferized(comptime T: type) type { + const M = meta.MapType(Tensor, Buffer); + return M.map(T); +} diff --git a/zml/context.zig b/zml/context.zig new file mode 100644 index 0000000..a7f26ae --- /dev/null +++ b/zml/context.zig @@ -0,0 +1,133 @@ +const builtin = @import("builtin"); +const std = @import("std"); +const mlir = @import("mlir"); +const asynk = @import("async"); + +const platform = @import("platform.zig"); +const pjrtx = @import("pjrtx.zig"); + +const available_targets = @import("platform.zig").available_targets; +const Target = @import("platform.zig").Target; +const Platform = @import("platform.zig").Platform; + +const log = std.log.scoped(.zml); + +const PjrtApiMap = std.EnumArray(Target, ?*const pjrtx.Api); +const PlatformsMap = std.EnumArray(Target, ?Platform); + +/// Every program using ZML must start with a `zml.Context.init(.{});` +/// The ZML context contains global state to interact with the different +/// devices available on your system. +/// Note that the runtimes available depends on how the program was compiled. +/// For example you need to compile your program with `--//runtimes:cuda=true` +/// to have the CUDA runtime available. +pub const Context = struct { + var apis = PjrtApiMap.initFill(null); + var apis_once = std.once(struct { + fn call() void { + inline for (platform.available_targets) |t| { + if (canLoad(t)) { + if (pjrtx.Api.loadFrom(platformToLibrary(t))) |api| { + Context.apis.set(t, api); + } else |_| {} + } + } + } + }.call); + + var mlir_once = std.once(struct { + fn call() void { + mlir.registerPasses("Transforms"); + } + }.call); + + platforms: PlatformsMap, + + /// Creates a ZML Context and returns it. + pub fn init() !Context { + Context.apis_once.call(); + Context.mlir_once.call(); + + var platforms = PlatformsMap.initFill(null); + var it = Context.apis.iterator(); + while (it.next()) |entry| { + if (entry.value.*) |api| { + const target = entry.key; + const p = Platform.init(target, api) catch continue; + if (p.getDevices().len == 0) { + log.err("No device found for platform {} !", .{target}); + continue; + } + platforms.set(target, p); + } + } + return .{ + .platforms = platforms, + }; + } + + fn platformToLibrary(comptime target: Target) []const u8 { + const ext = switch (builtin.os.tag) { + .windows => ".dll", + .macos, .ios, .watchos => ".dylib", + else => ".so", + }; + return switch (target) { + inline else => "libpjrt_" ++ @tagName(target) ++ ext, + }; + } + + fn canLoad(t: Target) bool { + return switch (t) { + .tpu => isRunningOnGCP() catch false, + else => true, + }; + } + + /// Check if running on Google Compute Engine, because TPUs will poll the + /// metadata server, hanging the process. So only do it on GCP. + /// Do it using the official method at: + /// https://cloud.google.com/compute/docs/instances/detect-compute-engine?hl=en#use_operating_system_tools_to_detect_if_a_vm_is_running_in + fn isRunningOnGCP() !bool { + // TODO: abstract that in the client and fail init + const GoogleComputeEngine = "Google Compute Engine"; + + var f = try asynk.File.open("/sys/devices/virtual/dmi/id/product_name", .{ .mode = .read_only }); + defer f.close() catch {}; + + var buf = [_]u8{0} ** GoogleComputeEngine.len; + _ = try f.reader().readAll(&buf); + + return std.mem.eql(u8, &buf, GoogleComputeEngine); + } + + pub fn pjrtApi(target: Target) *const pjrtx.Api { + return Context.apis.get(target).?; + } + + pub fn deinit(self: *Context) void { + var iterator = self.platforms.iterator(); + while (iterator.next()) |entry| { + if (entry.value.*) |*p| { + p.deinit(); + } + } + self.* = undefined; + } + + /// Automatically selects the best Platform loaded in the current Context. + /// + /// For example, if supported, this will select a platform corresponding to an accelerator (GPU, TPU, ...). + pub fn autoPlatform(self: *Context) Platform { + // the last platform is the one that with the high enum number, so considered + // to be the "best" one + var platform_: Platform = undefined; + var iterator = self.platforms.iterator(); + while (iterator.next()) |entry| { + if (entry.value.*) |p| { + platform_ = p; + } + } + return platform_; + } +}; diff --git a/zml/dtype.zig b/zml/dtype.zig new file mode 100644 index 0000000..fc1883c --- /dev/null +++ b/zml/dtype.zig @@ -0,0 +1,340 @@ +const std = @import("std"); +const floats = @import("floats.zig"); + +const C64 = std.math.Complex(f32); +const C128 = std.math.Complex(f64); + +pub const DataType = enum(u8) { + bool, + f8e4m3b11fnuz, + f8e4m3fn, + f8e4m3fnuz, + f8e5m2, + f8e5m2fnuz, + bf16, + f16, + f32, + f64, + i4, + i8, + i16, + i32, + i64, + u4, + u8, + u16, + u32, + u64, + c64, + c128, + + pub fn str(self: DataType) [:0]const u8 { + return switch (self) { + inline else => |tag| @tagName(tag), + }; + } + + pub const Class = enum(u8) { + bool, + float, + integer, + complex, + }; + + pub fn class(self: DataType) Class { + return switch (self) { + .bool => .bool, + .f8e4m3b11fnuz, .f8e4m3fn, .f8e4m3fnuz, .f8e5m2, .f8e5m2fnuz, .bf16, .f16, .f32, .f64 => .float, + .i4, .i8, .i16, .i32, .i64, .u4, .u8, .u16, .u32, .u64 => .integer, + .c64, .c128 => .complex, + }; + } + + pub fn isInteger(self: DataType) bool { + return self.class() == .integer; + } + + pub fn isFloat(self: DataType) bool { + return self.class() == .float; + } + + pub fn isComplex(self: DataType) bool { + return self.class() == .complex; + } + + pub fn fromZigType(comptime T: type) DataType { + return switch (T) { + floats.Float8E4M3B11FNUZ => .f8e4m3b11fnuz, + floats.Float8E4M3FN => .f8e4m3fn, + floats.Float8E4M3FNUZ => .f8e4m3fnuz, + floats.Float8E5M2 => .f8e5m2, + floats.Float8E5M2FNUZ => .f8e5m2fnuz, + floats.BFloat16 => .bf16, + f16 => .f16, + f32 => .f32, + f64 => .f64, + bool => .bool, + i4 => .i4, + i8 => .i8, + i16 => .i16, + i32 => .i32, + i64 => .i64, + u4 => .u4, + u8 => .u8, + u16 => .u16, + u32 => .u32, + u64 => .u64, + C64 => .c64, + C128 => .c128, + else => @compileError("Unsupported Zig type: " ++ @typeName(T)), + }; + } + + pub fn fromSliceElementType(slice: anytype) DataType { + const type_info = @typeInfo(@TypeOf(slice)); + if (type_info != .Pointer) { + @compileError("`initFromSlice` expects a slice, got " ++ @tagName(type_info)); + } + + return switch (type_info.Pointer.size) { + .Slice, .C, .Many => DataType.fromZigType(type_info.Pointer.child), + .One => b: { + const child_type_info = @typeInfo(type_info.Pointer.child); + break :b DataType.fromZigType(child_type_info.Array.child); + }, + }; + } + + pub fn toZigType(comptime dtype: DataType) type { + return switch (dtype) { + inline else => |tag| std.meta.TagPayload(Data, tag), + }; + } + + pub fn isSignedInt(dtype: DataType) bool { + return switch (dtype) { + .i4, .i8, .i16, .i32, .i64 => true, + else => false, + }; + } + + pub fn sizeOf(self: DataType) u16 { + return switch (self) { + inline else => |tag| @sizeOf(std.meta.TagPayload(Data, tag)), + }; + } + + pub fn bitSizeOf(self: DataType) u16 { + return switch (self) { + inline else => |tag| @bitSizeOf(std.meta.TagPayload(Data, tag)), + }; + } + + pub fn alignOf(self: DataType) u29 { + return switch (self) { + inline else => |tag| @alignOf(std.meta.TagPayload(Data, tag)), + }; + } + + /// Try to find a type compatible with both dtype. + pub fn resolvePeerType(a: DataType, b: DataType) ?DataType { + if (a == b) { + return a; + } + + // only resolve types in the same class + if (a.class() != b.class()) { + return null; + } + + return if (a.sizeOf() >= b.sizeOf()) a else b; + } + + test resolvePeerType { + try std.testing.expectEqual(DataType.f16.resolvePeerType(.f16), .f16); + try std.testing.expectEqual(DataType.f32.resolvePeerType(.f32), .f32); + + try std.testing.expectEqual(DataType.f16.resolvePeerType(.f32), .f32); + try std.testing.expectEqual(DataType.f32.resolvePeerType(.f16), .f32); + + try std.testing.expectEqual(DataType.f32.resolvePeerType(.f64), .f64); + try std.testing.expectEqual(DataType.f64.resolvePeerType(.f32), .f64); + try std.testing.expectEqual(DataType.f32.resolvePeerType(.i32), null); + + try std.testing.expectEqual(DataType.c64.resolvePeerType(.c128), .c128); + try std.testing.expectEqual(DataType.c128.resolvePeerType(.i32), null); + try std.testing.expectEqual(DataType.c64.resolvePeerType(.f32), null); + } + + pub fn zero(dtype: DataType) Data { + return Data.init(dtype, 0); + } + + pub fn one(dtype: DataType) Data { + return Data.init(dtype, 1); + } + + pub fn minValue(dtype: DataType) Data { + return switch (dtype) { + .bool => .{ .bool = false }, + inline .f8e4m3b11fnuz, .f8e4m3fn, .f8e4m3fnuz, .f8e5m2fnuz => |tag| @unionInit(Data, @tagName(tag), std.meta.FieldType(Data, tag).zero()), + inline .f8e5m2, .bf16 => |tag| @unionInit(Data, @tagName(tag), std.meta.FieldType(Data, tag).minusInf()), + inline .f16, .f32, .f64 => |tag| @unionInit(Data, @tagName(tag), -std.math.inf(std.meta.FieldType(Data, tag))), + inline .i4, .i8, .i16, .i32, .i64, .u4, .u8, .u16, .u32, .u64 => |tag| @unionInit(Data, @tagName(tag), std.math.minInt(std.meta.FieldType(Data, tag))), + inline else => |tag| @panic("Unsupported type: " ++ @tagName(tag)), + }; + } + + pub fn maxValue(dtype: DataType) Data { + return switch (dtype) { + .bool => .{ .bool = true }, + inline .f8e4m3b11fnuz, .f8e4m3fn, .f8e4m3fnuz, .f8e5m2fnuz => |tag| @panic("DataType doesn't have a max value: " ++ @tagName(tag)), + inline .f8e5m2, .bf16 => |tag| @unionInit(Data, @tagName(tag), std.meta.FieldType(Data, tag).inf()), + inline .f16, .f32, .f64 => |tag| @unionInit(Data, @tagName(tag), std.math.inf(std.meta.FieldType(Data, tag))), + inline .i4, .i8, .i16, .i32, .i64, .u4, .u8, .u16, .u32, .u64 => |tag| @unionInit(Data, @tagName(tag), std.math.maxInt(std.meta.FieldType(Data, tag))), + inline .c64, .c128 => |tag| @panic("DataType doesn't have a max value: " ++ @tagName(tag)), + }; + } + + pub fn constant(dtype: DataType, value: anytype) Data { + return Data.init(dtype, value); + } +}; + +pub const Data = union(DataType) { + bool: bool, + f8e4m3b11fnuz: floats.Float8E4M3B11FNUZ, + f8e4m3fn: floats.Float8E4M3FN, + f8e4m3fnuz: floats.Float8E4M3FNUZ, + f8e5m2: floats.Float8E5M2, + f8e5m2fnuz: floats.Float8E5M2FNUZ, + bf16: floats.BFloat16, + f16: f16, + f32: f32, + f64: f64, + i4: i4, + i8: i8, + i16: i16, + i32: i32, + i64: i64, + u4: u4, + u8: u8, + u16: u16, + u32: u32, + u64: u64, + c64: C64, + c128: C128, + + /// Creates `Data` from a `value`. + /// + /// If the `dtype` and `@TypeOf(value)` are incompatible + /// or a cast from `value` to `FieldType(dtype)` would + /// be lossy, a panic occurs. + pub fn init(dtype: DataType, value: anytype) Data { + const T = @TypeOf(value); + const Ti = @typeInfo(T); + + return switch (dtype) { + .bool => switch (Ti) { + .Bool => .{ .bool = value }, + .ComptimeInt, .Int, .ComptimeFloat, .Float => .{ .bool = value != 0 }, + else => @panic("Could not create Data of type bool from value of type " ++ @typeName(T)), + }, + inline .f8e4m3b11fnuz, .f8e4m3fn, .f8e4m3fnuz, .f8e5m2, .f8e5m2fnuz, .bf16 => |tag| switch (Ti) { + .ComptimeInt, .Int => @unionInit(Data, @tagName(tag), std.meta.FieldType(Data, tag).fromF32(@floatFromInt(value))), + .ComptimeFloat, .Float => @unionInit(Data, @tagName(tag), std.meta.FieldType(Data, tag).fromF32(@floatCast(value))), + else => @panic("Could not create Data of type bf16 from value of type " ++ @typeName(T)), + }, + inline .f16, .f32, .f64 => |tag| switch (Ti) { + .ComptimeInt, .Int => @unionInit(Data, @tagName(tag), @floatFromInt(value)), + .ComptimeFloat, .Float => @unionInit(Data, @tagName(tag), @floatCast(value)), + else => @panic("Could not create Data of type " ++ @tagName(tag) ++ " from value of type " ++ @typeName(T)), + }, + inline .i4, .i8, .i16, .i32, .i64, .u4, .u8, .u16, .u32, .u64 => |tag| switch (Ti) { + .ComptimeInt => blk: { + const OutT = std.meta.FieldType(Data, tag); + if (value >= std.math.minInt(OutT) and value <= std.math.maxInt(OutT)) { + break :blk @unionInit(Data, @tagName(tag), @intCast(value)); + } else { + @panic("Could not create Data of type " ++ @tagName(tag) ++ " from value of type " ++ @typeName(T)); + } + }, + .Int => @unionInit(Data, @tagName(tag), @intCast(value)), + else => @panic("Could not create Data of type " ++ @tagName(tag) ++ " from value of type " ++ @typeName(T)), + }, + .c64 => switch (T) { + C64 => .{ .c64 = value }, + C128 => .{ .c64 = .{ .re = @floatCast(value.re), .im = @floatCast(value.im) } }, + else => @panic("Could not create Data of type c64 from value of type " ++ @typeName(T)), + }, + .c128 => switch (T) { + C64 => .{ .c128 = .{ .re = @floatCast(value.re), .im = @floatCast(value.im) } }, + C128 => .{ .c128 = value }, + else => @panic("Could not create Data of type c128 from value of type " ++ @typeName(T)), + }, + }; + } + + test init { + try std.testing.expectEqual(20.0, Data.init(.f16, 20).f16); + try std.testing.expectEqual(20.5, Data.init(.f16, 20.5).f16); + try std.testing.expectEqual(20, Data.init(.f16, @as(u8, 20)).f16); + try std.testing.expectEqual(-20, Data.init(.f16, @as(i8, -20)).f16); + try std.testing.expectEqual(2000.5, Data.init(.f16, @as(f32, 2000.5)).f16); + + try std.testing.expectEqual(true, Data.init(.bool, true).bool); + + try std.testing.expectEqual(10, Data.init(.u8, 10).u8); + try std.testing.expectEqual(10, Data.init(.u8, @as(u16, 10)).u8); + + try std.testing.expectEqual(10, Data.init(.i8, 10).i8); + try std.testing.expectEqual(10, Data.init(.i8, @as(u16, 10)).i8); + try std.testing.expectEqual(-10, Data.init(.i8, -10).i8); + try std.testing.expectEqual(-10, Data.init(.i8, @as(i16, -10)).i8); + + try std.testing.expectEqual(C64.init(1, 2), Data.init(.c64, C64.init(1, 2)).c64); + try std.testing.expectEqual(C64.init(1, 2), Data.init(.c64, C128.init(1, 2)).c64); + try std.testing.expectEqual(C128.init(1, 2), Data.init(.c128, C128.init(1, 2)).c128); + try std.testing.expectEqual(C128.init(1, 2), Data.init(.c128, C64.init(1, 2)).c128); + } + + pub fn dataType(self: Data) DataType { + return std.meta.activeTag(self); + } + + pub fn constSlice(data: *const Data) []const u8 { + return switch (data.*) { + inline else => |*value| std.mem.asBytes(value), + }; + } + + pub fn as(self: Data, comptime T: type) T { + // TODO allow more lossless conversions + switch (@typeInfo(T)) { + .Bool => return self.bool, + .Float => switch (self) { + inline .f16, .f32, .f64 => |v| return @floatCast(v), + inline .f8e4m3b11fnuz, .f8e4m3fn, .f8e4m3fnuz, .f8e5m2, .f8e5m2fnuz, .bf16 => |v| return @floatCast(v.toF32()), + else => {}, + }, + .Int => switch (self) { + inline .i4, .i8, .i16, .i32, .i64, .u4, .u8, .u16, .u32, .u64 => |v| return @intCast(v), + else => {}, + }, + else => {}, + } + std.debug.panic("Unsupported conversion {} -> {s}", .{ self.dataType(), @typeName(T) }); + } +}; + +pub fn mantissaSize(dtype: DataType) usize { + return switch (dtype) { + .f8e4m3b11fnuz, .f8e4m3fn, .f8e4m3fnuz => 3, + .f8e5m2, .f8e5m2fnuz => 2, + .f16 => 10, + .bf16 => 7, + .f32 => 23, + .f64 => 52, + else => @panic("Can't get mantissa size for a non-float dtype"), + }; +} diff --git a/zml/floats.zig b/zml/floats.zig new file mode 100644 index 0000000..2694688 --- /dev/null +++ b/zml/floats.zig @@ -0,0 +1,232 @@ +const std = @import("std"); + +fn allBitsOne(v: anytype) bool { + return v == std.math.maxInt(@TypeOf(v)); +} + +fn FloatType(sign_bits: u1, exponent_bits: u8, mantissa_bits: u8, innerT: type) type { + return packed struct(std.meta.Int(.unsigned, @intCast(sign_bits + exponent_bits + mantissa_bits))) { + const Self = @This(); + + mantissa: std.meta.Int(.unsigned, @intCast(mantissa_bits)), + exponent: std.meta.Int(.unsigned, @intCast(exponent_bits)), + sign: std.meta.Int(.unsigned, @intCast(sign_bits)), + + pub fn zero() Self { + return .{ + .sign = 0, + .exponent = 0, + .mantissa = 0, + }; + } + + pub fn neg(self: Self) Self { + return .{ + .sign = self.sign ^ 1, + .exponent = self.exponent, + .mantissa = self.mantissa, + }; + } + + /// Lossy conversion from f32, similar to @floatCast + pub fn fromF32(f: f32) Self { + const vf32: Float32 = @bitCast(f); + const precision_loss = @bitSizeOf(@TypeOf(vf32.mantissa)) - mantissa_bits; + return .{ + .sign = vf32.sign, + .exponent = @intCast(vf32.exponent), + .mantissa = shr(vf32.mantissa, precision_loss), + }; + } + + /// Lossless conversion to f32. + pub fn toF32(self: Self) f32 { + var vf32: Float32 = undefined; + const precision_loss = @bitSizeOf(@TypeOf(vf32.mantissa)) - mantissa_bits; + vf32 = .{ + .sign = self.sign, + .exponent = self.exponent, + .mantissa = @shlExact(@as(@TypeOf(vf32.mantissa), self.mantissa), precision_loss), + }; + return @bitCast(vf32); + } + + fn truncMantissa(T: type, x: anytype) T { + const off = @bitSizeOf(@TypeOf(x)) - @bitSizeOf(T); + return @intCast(x >> off); + } + + fn shr(x: anytype, comptime off: u8) std.meta.Int(.unsigned, @bitSizeOf(@TypeOf(x)) - off) { + // @setRuntimeSafety(false); + return @intCast(x >> off); + } + + pub fn format( + self: @This(), + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, + ) !void { + _ = options; + try writer.print("{" ++ fmt ++ "}", .{self.toF32()}); + } + + pub usingnamespace innerT; + }; +} + +const Float32 = FloatType(1, 8, 23, struct {}); +const Float64 = FloatType(1, 11, 52, struct {}); + +pub const Float8E4M3B11FNUZ = FloatType(1, 4, 3, struct { + pub fn nan() Float8E4M3B11FNUZ { + return .{ + .sign = 1, + .exponent = 0, + .mantissa = 0, + }; + } + + pub fn isNan(self: Float8E4M3B11FNUZ) bool { + return self.sign == 1 and self.exponent == 0 and self.mantissa == 0; + } +}); + +pub const Float8E4M3FN = FloatType(1, 4, 3, struct { + pub fn nan() Float8E4M3FN { + return .{ + .sign = 0, + .exponent = std.math.maxInt(u4), + .mantissa = std.math.maxInt(u3), + }; + } + + pub fn isNan(self: Float8E4M3FN) bool { + return allBitsOne(self.exponent) and allBitsOne(self.mantissa); + } +}); + +pub const Float8E4M3FNUZ = FloatType(1, 4, 3, struct { + pub fn nan() Float8E4M3FNUZ { + return .{ + .sign = 1, + .exponent = 0, + .mantissa = 0, + }; + } + + pub fn isNan(self: Float8E4M3FNUZ) bool { + return self.sign == 1 and self.exponent == 0 and self.mantissa == 0; + } +}); + +pub const Float8E5M2 = FloatType(1, 5, 2, struct { + pub fn nan() Float8E5M2 { + return .{ + .sign = 0, + .exponent = std.math.maxInt(u5), + .mantissa = 1, + }; + } + + pub fn isNan(self: Float8E5M2) bool { + return allBitsOne(self.exponent) and self.mantissa != 0; + } + + pub fn minusInf() Float8E5M2 { + return .{ + .sign = 1, + .exponent = std.math.maxInt(u5), + .mantissa = 0, + }; + } + + pub fn inf() Float8E5M2 { + return .{ + .sign = 0, + .exponent = std.math.maxInt(u5), + .mantissa = 0, + }; + } + + pub fn isInf(self: Float8E5M2) bool { + return allBitsOne(self.exponent) and self.mantissa == 0; + } +}); + +pub const Float8E5M2FNUZ = FloatType(1, 5, 2, struct { + pub fn nan() Float8E5M2FNUZ { + return .{ + .sign = 1, + .exponent = 0, + .mantissa = 0, + }; + } + + pub fn isNan(self: Float8E5M2FNUZ) bool { + return self.sign == 1 and self.exponent == 0 and self.mantissa == 0; + } +}); + +pub const BFloat16 = FloatType(1, 8, 7, struct { + pub fn nan() BFloat16 { + return .{ + .sign = 0, + .exponent = std.math.maxInt(u8), + .mantissa = 1, + }; + } + + pub fn isNan(self: BFloat16) bool { + return allBitsOne(self.exponent) and self.mantissa != 0; + } + + pub fn minusInf() BFloat16 { + return .{ + .sign = 1, + .exponent = std.math.maxInt(u8), + .mantissa = 0, + }; + } + + pub fn inf() BFloat16 { + return .{ + .sign = 0, + .exponent = std.math.maxInt(u8), + .mantissa = 0, + }; + } + + pub fn isInf(self: BFloat16) bool { + return allBitsOne(self.exponent) and self.mantissa == 0; + } +}); + +test BFloat16 { + // From https://en.wikipedia.org/wiki/Bfloat16_floating-point_format#Examples + try std.testing.expectEqual(BFloat16.fromF32(0), BFloat16{ .sign = 0, .exponent = 0, .mantissa = 0 }); + try std.testing.expectEqual(BFloat16.fromF32(-2), BFloat16{ .sign = 1, .exponent = 127 + 1, .mantissa = 0 }); + try std.testing.expectEqual(BFloat16.fromF32(3.02344107628), BFloat16{ .sign = 0, .exponent = 127 + 1, .mantissa = 65 }); + try std.testing.expectEqual(BFloat16.fromF32(1.0 / 128.0), BFloat16{ .sign = 0, .exponent = 127 - 7, .mantissa = 0 }); + try std.testing.expectEqual(std.mem.toBytes(BFloat16.inf().neg()), [_]u8{ 0x80, 0xff }); + + const lossless = [_]f32{ 0, -2, 1.0 / 128.0, -1e64, std.math.inf(f32) }; + for (&lossless) |v| { + try std.testing.expectEqual(v, BFloat16.fromF32(v).toF32()); + } + const lossy = [_]f32{3.02344107628}; + for (&lossy) |x| { + const y = BFloat16.fromF32(x).toF32(); + if (!std.math.approxEqRel(f32, x, y, 1e-2)) { + std.log.err("expected ~{d}, got {d}", .{ x, y }); + return error.TestUnexpectedResult; + } + } +} + +pub fn floatCast(T: type, x: anytype) T { + return switch (@TypeOf(x)) { + f64, f32, f16 => @floatCast(x), + else => @floatCast(x.toF32()), + }; +} diff --git a/zml/helpers.zig b/zml/helpers.zig new file mode 100644 index 0000000..f336316 --- /dev/null +++ b/zml/helpers.zig @@ -0,0 +1,172 @@ +//! Public helpers to manipulate tensors or shapes. +const std = @import("std"); + +const meta = @import("meta.zig"); +const Shape = @import("shape.zig").Shape; +const Tensor = @import("tensor.zig").Tensor; + +const EnumLiteral = @TypeOf(.enum_literal); +const log = std.log.scoped(.zml_tensor); + +const ShapeError = error{ DimMismatch, NotFound }; +const NOT_SET: i64 = 0; +const DIM_MISMATCH: i64 = -1; + +/// Collect the given dimensions inside a struct containing tagged tensors. +pub fn collectDims( + comptime dims: anytype, + v: anytype, + comptime mode: enum { strict, allow_extra_dims, ignore_errors }, +) ShapeError!ShapeStruct(dims) { + const LocalContext = struct { + res: ShapeStruct(dims), + mode: @TypeOf(mode), + }; + var context = LocalContext{ + .res = std.mem.zeroes(ShapeStruct(dims)), + .mode = mode, + }; + + meta.visit((struct { + fn cb(ctx: *LocalContext, shape: *const Shape) void { + inline for (dims) |a| { + if (shape.hasTag(a)) |axis| { + const dim = shape.dim(axis); + + const expected_dim = &@field(ctx.res, @tagName(a)); + if (expected_dim.* == NOT_SET) { + expected_dim.* = dim; + } else if (expected_dim.* == DIM_MISMATCH) { + // this axis has already been reported as invalid. + } else if (dim != expected_dim.*) { + if (mode != .ignore_errors) { + log.warn("Dim mismatch ! Axis {0s}={1d} but received a new tensor where {0s}={2d}", .{ @tagName(a), expected_dim.*, dim }); + } + expected_dim.* = DIM_MISMATCH; + } + } + // TODO: strict mode: + // else if (mode == .strict) { + // @compileError("Found unexpected axis " ++ @tagName(a) ++ " when collecting " ++ @typeName(ShapeStruct(dims))); + // } + } + } + }).cb, &context, v); + + if (context.mode != .ignore_errors) { + inline for (shapeToDims(context.res), dims) |dim, dim_tag| { + if (dim == NOT_SET) { + log.warn("Axis not found: {s}", .{@tagName(dim_tag)}); + return error.NotFound; + } + if (dim == DIM_MISMATCH) return error.DimMismatch; + } + } + return context.res; +} + +fn shapeToDims(shape: anytype) [@divExact(@sizeOf(@TypeOf(shape)), @sizeOf(i64))]i64 { + return @bitCast(shape); +} + +test collectDims { + const zml = @import("zml.zig"); + + const Model = struct { + x: Shape, + y: Shape, + bias: Shape, + }; + + { + var model: Model = .{ + .x = Shape.init(.{ 2, 5 }, .f32).withTags(.{ .b, .d }), + .y = Shape.init(.{ 2, 5 }, .f32).withTags(.{ .b, .d }), + .bias = Shape.init(.{5}, .f32).withTags(.{.d}), + }; + try zml.testing.expectEqual(collectDims(.{ .b, .d }, &model, .strict), .{ .b = 2, .d = 5 }); + } + { + var model: Model = .{ + .x = Shape.init(.{ 2, 5 }, .f32).withTags(.{ .b, .d }), + .y = Shape.init(.{ 3, 5 }, .f32).withTags(.{ .b, .d }), + .bias = Shape.init(.{5}, .f32).withTags(.{.d}), + }; + try std.testing.expectEqual( + collectDims(.{ .b, .d }, &model, .strict), + error.DimMismatch, + ); + try zml.testing.expectEqual(collectDims(.{ .b, .d }, &model, .ignore_errors), .{ .b = -1, .d = 5 }); + } + { + var model: Model = .{ + .x = Shape.init(.{ 2, 5 }, .f32).withTags(.{ .b, .d }), + .y = Shape.init(.{ 2, 5 }, .f32).withTags(.{ .b, .d }), + .bias = Shape.init(.{5}, .f32).withTags(.{.d}), + }; + try std.testing.expectEqual(collectDims(.{ .b, .d, .c }, &model, .strict), error.NotFound); + try zml.testing.expectEqual(collectDims(.{ .b, .d, .c }, &model, .ignore_errors), .{ .b = 2, .d = 5, .c = 0 }); + } + { + var model: Model = .{ + .x = Shape.init(.{ 2, 5 }, .f32).withTags(.{ .b, .d }), + .y = Shape.init(.{ 2, 5 }, .f32).withTags(.{ .b, .d }), + .bias = Shape.init(.{7}, .f32).withTags(.{.d}), + }; + try std.testing.expectEqual(collectDims(.{ .b, .d }, &model, .strict), error.DimMismatch); + try zml.testing.expectEqual(collectDims(.{ .b, .d }, &model, .ignore_errors), .{ .b = 2, .d = -1 }); + } +} + +fn ShapeStruct(comptime dims: anytype) type { + const rank = dims.len; + @setEvalBranchQuota(rank + 5); + var struct_fields: [rank]std.builtin.Type.StructField = undefined; + const default: i64 = NOT_SET; + for (&struct_fields, dims) |*struct_field, axis| { + struct_field.* = .{ + .name = @tagName(axis), + .type = i64, + .default_value = &default, + .is_comptime = false, + .alignment = @alignOf(i64), + }; + } + return @Type(.{ .Struct = .{ + .layout = .@"extern", + .fields = &struct_fields, + .decls = &.{}, + .is_tuple = false, + } }); +} + +/// Return a new struct with all tensors replaced by the output of the given function. +pub fn mapTensors(func: anytype, v: anytype, args: anytype) @TypeOf(v) { + const T = @TypeOf(v); + const type_info = @typeInfo(T); + if (T == Tensor) return @call(.auto, func, .{v} ++ args); + + return switch (type_info) { + .Pointer => @compileError("mapTensors only accept by value arguments. Received: " ++ @typeName(T)), + .Struct => |struct_info| { + var copy: T = v; + inline for (struct_info.fields) |feeld| { + if (feeld.is_comptime) continue; + if (@typeInfo(feeld.type) == .Pointer) { + @compileError("mapTensors doesn't follow pointers and don't accept struct containing them. Received: " ++ @typeName(T)); + } + @field(copy, feeld.name) = mapTensors(func, @field(v, feeld.name), args); + } + return copy; + }, + .Array => { + var res: T = undefined; + for (v, &res) |item, *r| { + r.* = mapTensors(func, item, args); + } + return res; + }, + .Union, .Optional => @compileError("mapTensors doesn't yet support " ++ @typeName(T)), + else => v, + }; +} diff --git a/zml/hostbuffer.zig b/zml/hostbuffer.zig new file mode 100644 index 0000000..5f34733 --- /dev/null +++ b/zml/hostbuffer.zig @@ -0,0 +1,319 @@ +const std = @import("std"); + +const Buffer = @import("buffer.zig").Buffer; +const Shape = @import("shape.zig").Shape; +const Tensor = @import("tensor.zig").Tensor; +const Data = @import("dtype.zig").Data; +const DataType = @import("dtype.zig").DataType; +const Platform = @import("platform.zig").Platform; +const meta = @import("meta.zig"); + +/// Represents a tensor with associated data allocated by user code. +/// If the memory is `.managed` it needs to be freed with `x.deinit(allocator)` +/// If the memory is `.unmanaged` it doesn't need to be freed (eg memory mapped, or tracked elsewhere). +pub const HostBuffer = struct { + _shape: Shape, + _strides: ?[Shape.MAX_RANK]i64 = null, + data: []const u8, + _memory: union(enum) { + managed: u5, + unmanaged, + } = .unmanaged, + + /// Allocates a HostBuffer with the given shape. + /// The memory is left undefined. + /// The caller owns the memory, and need to call `deinit()`. + pub fn empty(allocator: std.mem.Allocator, sh: Shape) !HostBuffer { + return .{ + ._shape = sh, + .data = try allocator.alignedAlloc(u8, std.atomic.cache_line, sh.byteSize()), + ._memory = .{ .managed = std.math.log2_int(u16, std.atomic.cache_line) }, + }; + } + + /// Wraps an exisiting slice of bytes into a HostBuffer. + /// The returned HostBuffer doesn't take ownership of the slice + /// that will still need to be deallocated. + pub fn fromBytes(shape_: Shape, data_: []const u8) HostBuffer { + std.debug.assert(shape_.byteSize() == data_.len); + return .{ + ._shape = shape_, + .data = data_, + ._memory = .unmanaged, + }; + } + + /// Frees the underlying memory if we owned it, ie if we've been created with `HostBuffer.empty`. + pub fn deinit(self: *const HostBuffer, allocator: std.mem.Allocator) void { + // This means we don't own the data. + if (self._memory == .unmanaged) return; + const log2_align = self._memory.managed; + allocator.rawFree(@constCast(self.data), log2_align, @returnAddress()); + } + + /// Wraps an exisiting slice into a HostBuffer. + /// The element type is inferred from the slice type. + /// The returned HostBuffer doesn't take ownership of the slice + /// that will still need to be deallocated. + pub fn fromSlice(sh: anytype, s: anytype) HostBuffer { + const shape_ = Shape.init(sh, DataType.fromSliceElementType(s)); + std.debug.assert(shape_.count() == s.len); + return .{ + ._shape = shape_, + .data = @alignCast(std.mem.sliceAsBytes(s)), + ._memory = .unmanaged, + }; + } + + /// Wraps an exisiting slice into a HostBuffer. + /// The element type is inferred from the slice type. + /// The values in the slice doesn't need to be contiguous, + /// strides can be specified. + /// The returned HostBuffer doesn't take ownership of the slice. + pub fn fromStridedSlice(sh: Shape, s: anytype, strides_: []const i64) HostBuffer { + // std.debug.assert(sh.count() == s.len); + var tmp: [Shape.MAX_RANK]i64 = undefined; + @memcpy(tmp[0..strides_.len], strides_); + return .{ + ._shape = sh, + .data = @alignCast(std.mem.sliceAsBytes(s)), + ._strides = tmp, + ._memory = .unmanaged, + }; + } + + /// Creates a tensor from a **pointer** to a "multi dimension" array. + /// Note this doesn't copy, the pointee array need to survive the `HostBuffer` object. + pub fn fromArray(arr_ptr: anytype) HostBuffer { + const T = @TypeOf(arr_ptr.*); + const sh = parseArrayInfo(T); + return .{ + ._shape = sh, + .data = @alignCast(std.mem.sliceAsBytes(arr_ptr)), + // Array are typically stack allocated and don't need to be freed. + ._memory = .unmanaged, + }; + } + + /// Allocates a HostBuffer with the given shape. + /// The memory is initialized with increasing numbers. + /// The caller owns the memory, and need to call `deinit()`. + pub fn arange(allocator: std.mem.Allocator, args: Tensor.ArangeArgs, dt: DataType) !HostBuffer { + meta.assert(args.start < args.end, "arange expects 'args.start' to be less than 'args.end', got {} and {}", .{ args.start, args.end }); + meta.assert(args.step > 0, "arange expects 'args.step' to be positive, got {}", .{args.step}); + + const n_steps = std.math.divCeil(i64, args.end - args.start, args.step) catch unreachable; + const b = dt.sizeOf(); + const res = try empty(allocator, Shape.init(.{n_steps}, dt)); + meta.assert(dt.class() == .integer, "arange expects type to be integer, got {} instead.", .{dt}); + var data_ = @constCast(res.data); + switch (dt) { + inline else => { + var j: i64 = args.start; + for (0..@intCast(n_steps)) |i| { + var v = Data.init(dt, j); + @memcpy(data_[i * b .. (i + 1) * b], v.constSlice()); + j +%= args.step; + } + }, + } + return res; + } + + test arange { + { + var x = try arange(std.testing.allocator, .{ .end = 8 }, .i32); + defer x.deinit(std.testing.allocator); + try std.testing.expectEqualSlices(i32, &.{ 0, 1, 2, 3, 4, 5, 6, 7 }, x.items(i32)); + } + { + var x = try arange(std.testing.allocator, .{ .start = -3, .end = 12, .step = 2 }, .i32); + defer x.deinit(std.testing.allocator); + try std.testing.expectEqualSlices(i32, &.{ -3, -1, 1, 3, 5, 7, 9, 11 }, x.items(i32)); + } + } + + /// Embeds a tensor with concrete values into an Mlir program. + /// The content is copied, so the HostBuffer can be safely `deinit`. + pub fn toStaticTensor(self: HostBuffer) Tensor { + return Tensor.staticTensor(self.shape(), self.data); + } + + /// Copies this HostBuffer to the given accelerator. + pub fn toDevice(self: HostBuffer, platform_: Platform) !Buffer { + return try Buffer.from(platform_, self); + } + + pub fn items(self: HostBuffer, comptime T: type) []const T { + if (DataType.fromZigType(T) != self.dtype()) { + std.debug.panic("Can't reinterpret HostBuffer({_}) as {s}", .{ self.shape(), @typeName(T) }); + } + const ptr: [*]const T = @alignCast(@ptrCast(self.data.ptr)); + return ptr[0..self._shape.count()]; + } + + pub fn shape(self: HostBuffer) Shape { + return self._shape; + } + + pub fn dtype(self: HostBuffer) DataType { + return self._shape.dtype(); + } + + pub fn strides(self: HostBuffer) ?[]const i64 { + return self._strides; + } + + pub fn data(self: HostBuffer) []const u8 { + return self.data; + } + + pub inline fn rank(self: HostBuffer) u4 { + return self._shape.rank(); + } + + pub inline fn count(self: HostBuffer) usize { + return self._shape.count(); + } + + pub fn dim(self: HostBuffer, axis: anytype) i64 { + return self._shape.dim(axis); + } + + pub fn reshape(self: HostBuffer, shape_: anytype) HostBuffer { + meta.assert(self._strides == null, "reshape expects a contiguous tensor, got: {}", .{self}); + var res = self; + res._shape = self._shape.reshape(shape_); + return res; + } + + pub const Slice = struct { + single: ?i64 = null, + start: i64 = 0, + end: ?i64 = null, + step: i64 = 1, + }; + + pub inline fn copySlice1d(self: HostBuffer, allocator: std.mem.Allocator, axis: i8, _args: Slice) !HostBuffer { + var slices = [_]Slice{.{}} ** 5; + slices[self._shape.axis(axis)] = _args; + return copySlice(self, allocator, slices[0..self._shape.rank()]); + } + + pub fn copySlice(self: HostBuffer, allocator: std.mem.Allocator, slices: []const Slice) !HostBuffer { + const byte_size = self.dtype().sizeOf(); + var start_indices = [_]usize{0} ** 5; + var strides_ = [_]usize{1} ** 5; + const dims = self._shape.dims(); + var sh = self._shape; + + for (slices, 0..) |_args, a| { + const args: Slice = .{ + .start = if (_args.start >= 0) _args.start else _args.start + dims[a], + .end = _args.end orelse dims[a], + .step = _args.step, + }; + start_indices[a] = @intCast(args.start); + strides_[a] = @intCast(args.step); + sh._dims.set(a, b: { + const range = args.end.? - args.start; + const counts = @divFloor(range - 1, args.step) + 1; + break :b counts; + }); + } + + const rk = self.rank(); + meta.assert(rk <= 5, "copySlice only supports less than 5-D tensors. Received: {}", .{self}); + const raw_strides: [Shape.MAX_RANK]usize = blk: { + var res: [Shape.MAX_RANK]usize = undefined; + const _strides = self._shape.computeStrides(self.dtype().sizeOf()); + for (_strides.constSlice(), 0..rk) |stride, i| res[i] = @intCast(stride); + break :blk res; + }; + + const result_tensor = try HostBuffer.empty(allocator, sh); + + const res_strides: [Shape.MAX_RANK]usize = blk: { + var res: [Shape.MAX_RANK]usize = undefined; + const _strides = self._shape.computeStrides(self.dtype().sizeOf()); + for (_strides.constSlice(), 0..rk) |stride, i| res[i] = @intCast(stride); + break :blk res; + }; + + const src_data = self.data; + const data_ = @constCast(result_tensor.data); + for (0..@intCast(sh.dim(0))) |j0| { + const off0 = (j0 * strides_[0] + start_indices[0]) * raw_strides[0]; + const res_off0 = j0 * res_strides[0]; + if (rk == 1) { + @memcpy(data_[res_off0..][0..byte_size], src_data[off0..][0..byte_size]); + continue; + } + for (0..@intCast(sh.dim(1))) |j1| { + const off1 = off0 + (j1 * strides_[1] + start_indices[1]) * raw_strides[1]; + const res_off1 = res_off0 + j1 * res_strides[1]; + if (rk == 2) { + @memcpy(data_[res_off1..][0..byte_size], src_data[off1..][0..byte_size]); + continue; + } + for (0..@intCast(sh.dim(2))) |j2| { + const off2 = off1 + (j2 * strides_[2] + start_indices[2]) * raw_strides[2]; + const res_off2 = res_off1 + j2 * res_strides[2]; + if (rk == 3) { + @memcpy(data_[res_off2..][0..byte_size], src_data[off2..][0..byte_size]); + continue; + } + for (0..@intCast(sh.dim(3))) |j3| { + const off3 = off2 + (j3 * strides_[3] + start_indices[3]) * raw_strides[3]; + const res_off3 = res_off2 + j3 * res_strides[3]; + if (rk == 4) { + @memcpy(data_[res_off3..][0..byte_size], src_data[off3..][0..byte_size]); + continue; + } + for (0..@intCast(sh.dim(4))) |j4| { + const off4 = off3 + (j4 * strides_[4] + start_indices[4]) * raw_strides[4]; + const res_off4 = res_off3 + j4 * res_strides[4]; + @memcpy(data_[res_off4..][0..byte_size], src_data[off4..][0..byte_size]); + } + } + } + } + } + + return result_tensor; + } + + test copySlice { + var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena_state.deinit(); + const allocator = arena_state.allocator(); + + const x = HostBuffer.fromSlice(.{ 2, 5 }, &[_]f32{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + { + const res = try copySlice1d(x, allocator, 0, .{ .end = 1 }); + try std.testing.expectEqualSlices(f32, &.{ 0, 1, 2, 3, 4 }, res.items(f32)); + } + // { // failing + // const res = try copySlice1d(x, allocator, -1, .{ .start = -2 }); + // try testing.expectEqualSlices(f32, &.{ 3, 4, 8, 9 }, res.items(f32)); + // } + // {// failing + // const res = try copySlice1d(x, allocator, 1, .{ .start = 1, .step = 2 }); + // try testing.expectEqualSlices(f32, &.{ 1, 3, 6, 8 }, res.items(f32)); + // } + { + const res = try copySlice(x, allocator, &.{ .{ .start = 1 }, .{ .start = 1, .step = 2 } }); + try std.testing.expectEqualSlices(f32, &.{ 6, 8 }, res.items(f32)); + } + } +}; + +fn parseArrayInfo(T: type) Shape { + return switch (@typeInfo(T)) { + .Array => |arr| { + const s = parseArrayInfo(arr.child); + return s.insert(0, .{arr.len}); + }, + else => .{ ._dtype = DataType.fromZigType(T) }, + }; +} diff --git a/zml/meta.zig b/zml/meta.zig new file mode 100644 index 0000000..e9883f9 --- /dev/null +++ b/zml/meta.zig @@ -0,0 +1,657 @@ +const std = @import("std"); + +const testing = std.testing; + +/// Computes floating point value division between two integers. +pub fn divFloat(T: type, numerator: anytype, denominator: anytype) T { + return toFloat(T, numerator) / toFloat(T, denominator); +} + +fn toFloat(T: type, x: anytype) T { + return switch (@typeInfo(@TypeOf(x))) { + .Float => @floatCast(x), + else => @floatFromInt(x), + }; +} + +pub fn guard(check: bool, src: std.builtin.SourceLocation) void { + assert(check, "Invalid inputs {s}@{s}:{d}", .{ src.file, src.fn_name, src.line }); +} + +pub inline fn internalAssert(check: bool, comptime msg: []const u8, args: anytype) void { + assert(check, "ZML internal error: " ++ msg, args); +} + +pub fn assert(check: bool, comptime msg: []const u8, args: anytype) void { + if (!check) panic(msg, args); +} + +pub fn panic(comptime msg: []const u8, args: anytype) noreturn { + std.log.err(msg, args); + @panic(msg); +} + +pub fn compileLog(comptime msg: []const u8, comptime args: anytype) void { + @compileLog(std.fmt.comptimePrint(msg, args)); +} + +pub fn compileError(comptime msg: []const u8, comptime args: anytype) noreturn { + @compileError(std.fmt.comptimePrint(msg, args)); +} + +pub fn assertComptime(comptime check: bool, comptime msg: []const u8, comptime args: anytype) void { + if (check == false) { + compileError(msg, args); + } +} + +pub fn isStruct(comptime T: type) bool { + return switch (@typeInfo(T)) { + .Struct => true, + else => false, + }; +} + +pub fn isTuple(comptime T: type) bool { + return switch (@typeInfo(T)) { + .Struct => |info| info.is_tuple, + else => false, + }; +} + +pub fn isStructOf(comptime T: type, comptime Elem: type) bool { + return switch (@typeInfo(T)) { + .Struct => |info| blk: { + inline for (info.fields) |field| { + if (field.type != Elem) { + break :blk false; + } + } + break :blk true; + }, + else => false, + }; +} + +pub fn isStructOfAny(comptime T: type, comptime f: fn (comptime type) bool) bool { + return switch (@typeInfo(T)) { + .Struct => |info| blk: { + inline for (info.fields) |field| { + if (f(field.type) == false) { + break :blk false; + } + } + break :blk true; + }, + else => false, + }; +} + +pub fn isTupleOf(comptime T: type, comptime Elem: type) bool { + return isTuple(T) and isStructOf(T, Elem); +} + +pub fn isTupleOfAny(comptime T: type, comptime f: fn (comptime type) bool) bool { + return isTuple(T) and isStructOfAny(T, f); +} + +pub fn isSliceOf(comptime T: type, comptime Elem: type) bool { + return switch (@typeInfo(T)) { + .Pointer => |info| switch (info.size) { + .Slice => info.child == Elem, + .One => switch (@typeInfo(info.child)) { + // As Zig, convert pointer to Array as a slice. + .Array => |arr_info| arr_info.child == Elem, + else => false, + }, + else => false, + }, + else => false, + }; +} + +pub fn asSlice(comptime T: type) type { + const err_msg = "Type " ++ @typeName(T) ++ " can't be interpreted as a slice"; + return switch (@typeInfo(T)) { + .Pointer => |info| switch (info.size) { + .Slice => info.child, + .One => switch (@typeInfo(info.child)) { + // As Zig, convert pointer to Array as a slice. + .Array => |arr_info| arr_info.child, + else => @compileError(err_msg), + }, + else => @compileError(err_msg), + }, + else => @compileError(err_msg), + }; +} + +pub fn isInteger(comptime T: type) bool { + return switch (@typeInfo(T)) { + .Int, .ComptimeInt => true, + else => false, + }; +} + +pub fn isSliceOfAny(comptime T: type, comptime f: fn (comptime type) bool) bool { + return switch (@typeInfo(T)) { + .Pointer => |info| info.size == .Slice and f(info.child), + else => false, + }; +} + +pub fn DeclEnum(comptime T: type) type { + return std.meta.DeclEnum(UnwrapPtr(T)); +} + +pub fn UnwrapPtr(comptime T: type) type { + return switch (@typeInfo(T)) { + .Pointer => |info| switch (info.size) { + .One => info.child, + else => T, + }, + else => T, + }; +} + +pub fn FnParam(func: anytype, n: comptime_int) type { + return @typeInfo(@TypeOf(func)).Fn.params[n].type orelse @compileError("anytype not supported in callbacks"); +} + +pub fn FnParams(func: anytype) type { + return std.meta.ArgsTuple(@TypeOf(func)); +} + +pub fn FnResult(func: anytype) type { + return @typeInfo(@TypeOf(func)).Fn.return_type.?; +} + +pub fn FnResultPayload(func: anytype) type { + const return_type = @typeInfo(@TypeOf(func)).Fn.return_type.?; + const payload_type = switch (@typeInfo(return_type)) { + .ErrorUnion => |u| u.payload, + else => return_type, + }; + return payload_type; +} + +pub fn FnResultErrorSet(func: anytype) ?type { + const return_type = @typeInfo(@TypeOf(func)).Fn.return_type.?; + const error_set = switch (@typeInfo(return_type)) { + .ErrorUnion => |u| u.error_set, + else => null, + }; + return error_set; +} + +pub fn Signature(comptime func: anytype, comptime argsT: ?type) type { + return struct { + pub const FuncT = if (@TypeOf(func) == type) func else @TypeOf(func); + pub const ArgsT = blk: { + if (@typeInfo(FuncT).Fn.params.len == 0) { + break :blk @TypeOf(.{}); + } + break :blk argsT orelse std.meta.ArgsTuple(FuncT); + }; + pub const ReturnT = @TypeOf(@call(.auto, func, @as(ArgsT, undefined))); + pub const ReturnPayloadT = blk: { + break :blk switch (@typeInfo(ReturnT)) { + .ErrorUnion => |u| u.payload, + else => ReturnT, + }; + }; + pub const ReturnErrorSet: ?type = blk: { + break :blk switch (@typeInfo(ReturnT)) { + .ErrorUnion => |u| u.error_set, + else => null, + }; + }; + }; +} + +pub fn MapType(From: type, To: type) type { + return struct { + pub fn map(T: type) type { + switch (T) { + To => return To, + ?To => return ?To, + From => return To, + *From => return *To, + ?From => return ?To, + else => {}, + } + + return switch (@typeInfo(T)) { + .Struct => |struct_infos| { + const fields = struct_infos.fields; + var same: bool = true; + var struct_fields: [fields.len]std.builtin.Type.StructField = undefined; + for (struct_fields[0..], fields) |*struct_field, field| { + if (!field.is_comptime) { + const R = map(field.type); + if (R == field.type) { + struct_field.* = field; + } else { + struct_field.* = .{ + .name = field.name, + .type = R, + .default_value = null, + .is_comptime = field.is_comptime, + .alignment = @alignOf(R), + }; + same = false; + // Handle the case `field: ?Tensor = null` + // Generic handling of default value is complicated, + // it would require to call the callback at comptime. + if (R == ?To) { + struct_field.default_value = &@as(R, null); + } + } + } else { + struct_field.* = field; + } + } + if (same) return T; + return @Type(.{ .Struct = .{ + .layout = .auto, + .fields = struct_fields[0..], + .decls = &.{}, + .is_tuple = struct_infos.is_tuple, + } }); + }, + .Array => |arr_info| [arr_info.len]map(arr_info.child), + .Pointer => |ptr_info| switch (ptr_info.size) { + .Slice => if (ptr_info.is_const) + []const map(ptr_info.child) + else + []map(ptr_info.child), + .One => *map(ptr_info.child), + else => T, + }, + .Optional => |opt_info| ?map(opt_info.child), + else => T, + }; + } + }; +} + +/// Given a callback: `fn(Ctx, From) To`, recursively visits the given `from` struct +/// and calls the callback when it finds a `From` element, and writes it to the `to` struct. +/// The `to` parameter must be passed with mutable pointer, and tensor data need to be mutable if callback needs it. +/// `mapAlloc` tries as much as possible to respect the conversions made by Zig itself. +/// For example it can convert from a comptime array to a runtime slice. +/// `mapAlloc` can allocate new slices to write the result if the result struct requires it. +/// The caller is owning said allocations, using an `ArenaAllocator` might help tracking them. +// TODO: handle tuple to slice conversion +pub fn mapAlloc(comptime cb: anytype, allocator: std.mem.Allocator, ctx: FnParam(cb, 0), from: anytype, to: anytype) !void { + // const Ctx = FnParam(cb, 0); + const From = FnParam(cb, 1); + const FromStruct = @TypeOf(from); + + const type_info_to_ptr = @typeInfo(@TypeOf(to)); + if (type_info_to_ptr != .Pointer) { + @compileError("convertType is expecting a mutable `to` argument but received: " ++ @typeName(@TypeOf(to))); + } + const ToStruct = type_info_to_ptr.Pointer.child; + const type_info_to = @typeInfo(ToStruct); + + if (FromStruct == From) { + // Special case for converting from shape to tensor: + // If the target type is Shape, skip tensor conversion. + // A general `to.* = from` assignment causes a Zig error in this scenario. + // (see below) + if (ToStruct == @import("shape.zig").Shape and FromStruct == ToStruct) { // FromStruct) { + to.* = from; + } else { + to.* = @call(.auto, cb, .{ ctx, from }); + } + return; + } + + // This is generally due to a user error, but let this fn compile, + // and the user will have a Zig error. + if (FromStruct == ToStruct) { + to.* = from; + return; + } + + // Don't go into Shape objects because of the weird tag. + // TODO: we could not error on pointers to basic types like u8 + if (FromStruct == @import("shape.zig").Shape) { + to.* = from; + return; + } + switch (type_info_to) { + .Struct => |info| inline for (info.fields) |field| { + // if (field.is_comptime) continue; + const field_type_info = @typeInfo(field.type); + // If the field is already a pointer, we recurse with it directly, otherwise, we recurse with a pointer to the field. + switch (field_type_info) { + // .Pointer => try convertType(From, To, allocator, @field(from, field.name), @field(to, field.name), Ctx, ctx, cb), + .Array, .Optional, .Union, .Struct, .Pointer => if (@hasField(FromStruct, field.name)) { + try mapAlloc( + cb, + allocator, + ctx, + @field(from, field.name), + &@field(to, field.name), + ); + } else if (field.default_value) |_| { + @field(to, field.name) = null; + } else { + compileError("Mapping {} to {} failed. Missing field {s}", .{ FromStruct, ToStruct, field.name }); + }, + else => @field(to, field.name) = @field(from, field.name), + } + }, + .Array => for (from, to) |f, *t| { + try mapAlloc(cb, allocator, ctx, f, t); + }, + .Pointer => |ptr_info| switch (ptr_info.size) { + .One => switch (type_info_to_ptr.Pointer.size) { + // pointer to array -> slice promotion + .Slice => { + to.* = try allocator.alloc(type_info_to_ptr.Pointer.child, from.len); + for (from, to.*) |f, *t| { + try mapAlloc(cb, allocator, ctx, f, t); + } + }, + else => try mapAlloc(cb, allocator, ctx, from.*, to.*), + }, + .Slice => { + const items = try allocator.alloc(@typeInfo(ToStruct).Pointer.child, from.len); + for (from, items) |f, *t| { + try mapAlloc(cb, allocator, ctx, f, t); + } + to.* = items; + }, + else => @compileError("zml.meta.mapAlloc doesn't support: " ++ @typeName(FromStruct)), + }, + .Optional => if (from) |f| { + to.* = @as(@typeInfo(type_info_to_ptr.Pointer.child).Optional.child, undefined); + try mapAlloc(cb, allocator, ctx, f, &(to.*.?)); + } else { + to.* = null; + }, + .Int, .Float => to.* = from, + else => @compileError("zml.meta.mapAlloc doesn't support: " ++ @typeName(FromStruct)), + } +} + +test mapAlloc { + const B = struct { b: u8 }; + const A = struct { + a: u8, + pub fn convert(_: void, a: @This()) B { + return .{ .b = a.a }; + } + }; + + const AA = struct { + field: A, + array: [2]A, + slice: []const A, + other: u8, + // We want to allow conversion from comptime to runtime, because Zig type inference works like this. + comptime static_val: u8 = 8, + comptime static_slice: [2]A = .{ .{ .a = 11 }, .{ .a = 12 } }, + }; + const BB = struct { + field: B, + array: [2]B, + slice: []const B, + other: u8, + static_val: u8, + static_slice: []B, + }; + + const aa: AA = .{ + .field = .{ .a = 4 }, + .array = .{ .{ .a = 5 }, .{ .a = 6 } }, + .other = 7, + .slice = &.{ .{ .a = 9 }, .{ .a = 10 } }, + }; + var bb: BB = undefined; + + try mapAlloc(A.convert, testing.allocator, {}, aa, &bb); + defer testing.allocator.free(bb.slice); + defer testing.allocator.free(bb.static_slice); + + try testing.expectEqual(4, bb.field.b); + try testing.expectEqual(5, bb.array[0].b); + try testing.expectEqual(6, bb.array[1].b); + try testing.expectEqual(7, bb.other); + try testing.expectEqual(8, bb.static_val); + try testing.expectEqual(9, bb.slice[0].b); + try testing.expectEqual(10, bb.slice[1].b); + try testing.expectEqual(11, bb.static_slice[0].b); + try testing.expectEqual(12, bb.static_slice[1].b); +} + +/// Recursively visit the given struct and calls the callback for each K found. +/// The `v` parameter must me a pointer, and tensor data need to be mutable if callbacks needs it. +pub fn visit(comptime cb: anytype, ctx: FnParam(cb, 0), v: anytype) void { + const T = @TypeOf(v); + const type_info_v = @typeInfo(T); + const K = switch (@typeInfo(FnParam(cb, 1))) { + .Pointer => |info| info.child, + else => @compileError("zml.meta.visit is expecting a pointer value as second parameter in callback to use but found " ++ @typeName(FnParam(cb, 1))), + }; + + if (type_info_v != .Pointer) { + const Callback = @TypeOf(cb); + @compileError("zml.meta.visit is expecting a pointer input to go with following callback signature: " ++ @typeName(Callback) ++ " but received: " ++ @typeName(T)); + } + + const ptr_info = type_info_v.Pointer; + // This is important, because with trivial types like void, + // Zig sometimes decide to call `visit` at comptime, but can't do + // the pointer wrangling logic at comptime. + // So we detect early this case and return. + if (@sizeOf(ptr_info.child) == 0) return; + + switch (ptr_info.size) { + // If we have a single pointer, two cases: + // * It's a pointer to K, in which case we call the callback. + // * It's a pointer to something else, in which case, we explore and recurse if needed. + .One => if (ptr_info.child == K) { + cb(ctx, v); + } else if (ptr_info.child == ?K) { + if (v.*) |*val| cb(ctx, val); + } else switch (@typeInfo(ptr_info.child)) { + .Struct => |s| inline for (s.fields) |field_info| { + if (field_info.is_comptime) continue; + const field_type_info = @typeInfo(field_info.type); + // If the field is already a pointer, we recurse with it directly, otherwise, we recurse with a pointer to the field. + switch (field_type_info) { + .Pointer => visit(cb, ctx, @field(v, field_info.name)), + .Array, .Optional, .Union, .Struct => visit(cb, ctx, &@field(v, field_info.name)), + else => {}, + } + }, + .Array => |_| for (v) |*elem| visit(cb, ctx, elem), + .Optional => if (v.* != null) visit(cb, ctx, &v.*.?), + .Union => switch (v.*) { + inline else => |*v_field| visit(cb, ctx, v_field), + }, + else => {}, + }, + // If we have a slice, two cases also: + // * It's a slice of K, in which case we call the callback for each element of the slice. + // * It's a slice to something else, in which case, for each element we explore and recurse if needed. + .Slice => { + for (v) |*v_elem| { + if (ptr_info.child == K) { + cb(ctx, v_elem); + } else switch (@typeInfo(ptr_info.child)) { + .Struct => |s| inline for (s.fields) |field_info| { + const field_type_info = @typeInfo(field_info.type); + // If the field is already a pointer, we recurse with it directly, otherwise, we recurse with a pointer to the field. + if (field_type_info == .Pointer) { + visit(cb, ctx, @field(v_elem, field_info.name)); + } else { + visit(cb, ctx, &@field(v_elem, field_info.name)); + } + }, + .Array => |_| for (v) |*elem| visit(cb, ctx, elem), + .Optional => if (v.* != null) visit(cb, ctx, &v.*.?), + .Union => switch (v_elem.*) { + inline else => |*v_field| visit(cb, ctx, v_field), + }, + else => {}, + } + } + }, + else => @compileError("Only single pointer and slice are supported. Received " ++ @typeName(T)), + } +} + +test visit { + const Attr = struct { data: usize }; + const OtherAttr = struct { other: []const u8 }; + const NestedAttr = struct { nested: Attr }; + const NestedAttrOptional = struct { nested: ?Attr }; + const SimpleStruct = struct { prop: Attr }; + const MultipleTypesStruct = struct { prop1: Attr, prop2: OtherAttr, prop3: ?Attr }; + const NestedTypesStruct = struct { prop1: Attr, prop2: OtherAttr, prop3: NestedAttr, prop4: NestedAttrOptional }; + + const LocalContext = struct { + result: usize, + }; + + { + var context: LocalContext = .{ .result = 0 }; + const container: SimpleStruct = .{ .prop = .{ .data = 1 } }; + + visit((struct { + fn cb(ctx: *LocalContext, attr: *const Attr) void { + ctx.result += attr.data; + } + }).cb, &context, &container); + + try std.testing.expectEqual(1, context.result); + } + { + var context: LocalContext = .{ .result = 0 }; + var container: SimpleStruct = .{ .prop = .{ .data = 1 } }; + + visit((struct { + fn cb(ctx: *LocalContext, attr: *Attr) void { + ctx.result += attr.data; + } + }).cb, &context, &container); + + try std.testing.expectEqual(1, context.result); + } + { + var context: LocalContext = .{ .result = 0 }; + var container: MultipleTypesStruct = .{ .prop1 = .{ .data = 1 }, .prop2 = .{ .other = "hello" }, .prop3 = null }; + + visit((struct { + fn cb(ctx: *LocalContext, attr: *Attr) void { + ctx.result += attr.data; + } + }).cb, &context, &container); + + try std.testing.expectEqual(1, context.result); + } + { + var context: LocalContext = .{ .result = 0 }; + const container: MultipleTypesStruct = .{ .prop1 = .{ .data = 1 }, .prop2 = .{ .other = "hello" }, .prop3 = .{ .data = 2 } }; + + visit((struct { + fn cb(ctx: *LocalContext, attr: *const Attr) void { + ctx.result += attr.data; + } + }).cb, &context, &container); + + try std.testing.expectEqual(3, context.result); + } + { + var context: LocalContext = .{ .result = 0 }; + const container: NestedTypesStruct = .{ + .prop1 = .{ .data = 1 }, + .prop2 = .{ .other = "hello" }, + .prop3 = .{ .nested = .{ .data = 2 } }, + .prop4 = .{ .nested = .{ .data = 3 } }, + }; + + visit((struct { + fn cb(ctx: *LocalContext, attr: *const Attr) void { + ctx.result += attr.data; + } + }).cb, &context, &container); + + try std.testing.expectEqual(6, context.result); + } +} + +/// Given a `fn([]const T, Args) T` and a slice of values, +/// will combine all values in one value. +/// Only T elements of values will be looked at. +/// This only works for simple types, in particular `zip` doesn't follow pointers. +/// Which means that zip only allocate temp memory, and nothing need to be freed after the call. +pub fn zip(func: anytype, allocator: std.mem.Allocator, values: anytype, args: anytype) error{OutOfMemory}!asSlice(@TypeOf(values)) { + const sliceT = @typeInfo(FnParam(func, 0)); + assertComptime(sliceT == .Pointer and sliceT.Pointer.size == .Slice and sliceT.Pointer.child == FnResult(func), "zip requires a `fn([]const T, Args) T`, received: {}", .{@TypeOf(func)}); + + const T = sliceT.Pointer.child; + const V = asSlice(@TypeOf(values)); + if (V == T) { + return @call(.auto, func, .{values} ++ args); + } + // const fn_args + + return switch (@typeInfo(V)) { + .Pointer => @compileError("zip only accept by value arguments. Received: " ++ @typeName(V)), + .Struct => |struct_info| { + var out: V = values[0]; + inline for (struct_info.fields) |f| { + if (f.is_comptime) continue; + if (@typeInfo(f.type) == .Pointer) { + @compileError("zip doesn't follow pointers and don't accept struct containing them. Received: " ++ @typeName(V)); + } + var fields = try allocator.alloc(f.type, values.len); + defer allocator.free(fields); + for (values, 0..) |val, i| { + fields[i] = @field(val, f.name); + } + @field(out, f.name) = try zip(func, allocator, fields, args); + } + return out; + }, + .Array => |arr_info| { + if (@typeInfo(arr_info.child) == .Pointer) { + @compileError("zip doesn't follow pointers and don't accept struct containing them. Received: " ++ @typeName(V)); + } + var out: V = undefined; + var slice = try allocator.alloc(arr_info.child, values.len); + defer allocator.free(slice); + for (&out, 0..) |*o, j| { + for (values, 0..) |val, i| { + slice[i] = val[j]; + } + o.* = try zip(func, allocator, slice, args); + } + return out; + }, + .Union, .Optional => @compileError("zip doesn't yet support " ++ @typeName(V)), + else => values[0], + }; +} + +test zip { + const A = struct { a: u8, b: [2]u8 }; + const a0: A = .{ .a = 1, .b = .{ 2, 3 } }; + const a1: A = .{ .a = 4, .b = .{ 5, 6 } }; + + const Sum = struct { + pub fn call(x: []const u8) u8 { + var res: u8 = 0; + for (x) |xx| res += xx; + return res; + } + }; + const a_sum: A = try zip(Sum.call, testing.allocator, &[_]A{ a0, a1 }, .{}); + try testing.expectEqual(A{ .a = 5, .b = .{ 7, 9 } }, a_sum); +} diff --git a/zml/mlir.zig b/zml/mlir.zig new file mode 100644 index 0000000..538deeb --- /dev/null +++ b/zml/mlir.zig @@ -0,0 +1,176 @@ +const mlir = @This(); + +const builtin = @import("builtin"); +const std = @import("std"); + +const dtype = @import("dtype.zig"); +const meta = @import("meta.zig"); + +const Shape = @import("shape.zig").Shape; +const Tensor = @import("tensor.zig").Tensor; + +const log = std.log.scoped(.zml_mlir); + +pub usingnamespace @import("mlir"); + +pub const ext = struct { + pub fn mlirType(ctx: mlir.Context, sh: Shape) mlir.Type { + return mlir.RankedTensorType.init(sh.dims(), mlir.ext.Type.fromDType(ctx, sh.dtype())).as(mlir.Type).?; + } + + pub fn denseElementAttrType(dt: dtype.DataType) mlir.DenseElementsAttributeTypes { + return switch (dt) { + .bool => .bool, + .i8 => .i8, + .i16 => .i16, + .i32 => .i32, + .i64 => .i64, + .u8 => .u8, + .u16 => .u16, + .u32 => .u32, + .u64 => .u64, + .bf16 => .bf16, + .f16 => .f16, + .f32 => .f32, + .f64 => .f64, + inline else => |tag| @panic("Unsupported data type: " ++ @tagName(tag)), + }; + } + + pub fn denseElementsAttr(dt: dtype.DataType, _: usize, bytes: []const u8, ranked_type: mlir.RankedTensorType) mlir.Attribute { + const ranked_type_ = ranked_type.as(mlir.Type).?; + return switch (dt) { + .bool => mlir.DenseIntOrFPElementsAttribute(.bool).init(ranked_type_, bytes).as(mlir.Attribute).?, + .i8 => mlir.DenseIntOrFPElementsAttribute(.i8).init(ranked_type_, bytes).as(mlir.Attribute).?, + .i16 => mlir.DenseIntOrFPElementsAttribute(.i16).init(ranked_type_, bytes).as(mlir.Attribute).?, + .i32 => mlir.DenseIntOrFPElementsAttribute(.i32).init(ranked_type_, bytes).as(mlir.Attribute).?, + .i64 => mlir.DenseIntOrFPElementsAttribute(.i64).init(ranked_type_, bytes).as(mlir.Attribute).?, + .u8 => mlir.DenseIntOrFPElementsAttribute(.u8).init(ranked_type_, bytes).as(mlir.Attribute).?, + .u16 => mlir.DenseIntOrFPElementsAttribute(.u16).init(ranked_type_, bytes).as(mlir.Attribute).?, + .u32 => mlir.DenseIntOrFPElementsAttribute(.u32).init(ranked_type_, bytes).as(mlir.Attribute).?, + .u64 => mlir.DenseIntOrFPElementsAttribute(.u64).init(ranked_type_, bytes).as(mlir.Attribute).?, + .bf16 => mlir.DenseIntOrFPElementsAttribute(.bf16).init(ranked_type_, bytes).as(mlir.Attribute).?, + .f16 => mlir.DenseIntOrFPElementsAttribute(.f16).init(ranked_type_, bytes).as(mlir.Attribute).?, + .f32 => mlir.DenseIntOrFPElementsAttribute(.f32).init(ranked_type_, bytes).as(mlir.Attribute).?, + .f64 => mlir.DenseIntOrFPElementsAttribute(.f64).init(ranked_type_, bytes).as(mlir.Attribute).?, + inline else => |tag| @panic("Unsupported data type: " ++ @tagName(tag)), + }; + } + + pub const RankedTensorType = struct { + pub fn fromShape(ctx: mlir.Context, sh: Shape) mlir.RankedTensorType { + return mlir.RankedTensorType.init(sh.dims(), mlir.ext.Type.fromDType(ctx, sh.dtype())); + } + }; + + pub const Type = struct { + pub fn fromDType(ctx: mlir.Context, dt: dtype.DataType) mlir.Type { + return switch (dt) { + .bool => mlir.IntegerType(.i1).init(ctx).as(mlir.Type).?, + .f8e4m3b11fnuz => mlir.FloatType(.f8e4m3b11fnuz).init(ctx).as(mlir.Type).?, + .f8e4m3fn => mlir.FloatType(.f8e4m3fn).init(ctx).as(mlir.Type).?, + .f8e4m3fnuz => mlir.FloatType(.f8e4m3fnuz).init(ctx).as(mlir.Type).?, + .f8e5m2 => mlir.FloatType(.f8e5m2).init(ctx).as(mlir.Type).?, + .f8e5m2fnuz => mlir.FloatType(.f8e5m2fnuz).init(ctx).as(mlir.Type).?, + .bf16 => mlir.FloatType(.bf16).init(ctx).as(mlir.Type).?, + .f16 => mlir.FloatType(.f16).init(ctx).as(mlir.Type).?, + .f32 => mlir.FloatType(.f32).init(ctx).as(mlir.Type).?, + .f64 => mlir.FloatType(.f64).init(ctx).as(mlir.Type).?, + .i4 => mlir.IntegerType(.i4).init(ctx).as(mlir.Type).?, + .i8 => mlir.IntegerType(.i8).init(ctx).as(mlir.Type).?, + .i16 => mlir.IntegerType(.i16).init(ctx).as(mlir.Type).?, + .i32 => mlir.IntegerType(.i32).init(ctx).as(mlir.Type).?, + .i64 => mlir.IntegerType(.i64).init(ctx).as(mlir.Type).?, + .u4 => mlir.IntegerType(.u4).init(ctx).as(mlir.Type).?, + .u8 => mlir.IntegerType(.u8).init(ctx).as(mlir.Type).?, + .u16 => mlir.IntegerType(.u16).init(ctx).as(mlir.Type).?, + .u32 => mlir.IntegerType(.u32).init(ctx).as(mlir.Type).?, + .u64 => mlir.IntegerType(.u64).init(ctx).as(mlir.Type).?, + .c64 => mlir.ComplexType(.c64).init(ctx).as(mlir.Type).?, + .c128 => mlir.ComplexType(.c128).init(ctx).as(mlir.Type).?, + }; + } + + pub fn toDType(mlir_type: mlir.Type) dtype.DataType { + const mapping = .{ + .{ .bool, mlir.IntegerType(.i1) }, + + .{ .f8e4m3b11fnuz, mlir.FloatType(.f8e4m3b11fnuz) }, + .{ .f8e4m3fn, mlir.FloatType(.f8e4m3fn) }, + .{ .f8e4m3fnuz, mlir.FloatType(.f8e4m3fnuz) }, + .{ .f8e5m2, mlir.FloatType(.f8e5m2) }, + .{ .f8e5m2fnuz, mlir.FloatType(.f8e5m2fnuz) }, + .{ .bf16, mlir.FloatType(.bf16) }, + .{ .f16, mlir.FloatType(.f16) }, + .{ .f32, mlir.FloatType(.f32) }, + .{ .f64, mlir.FloatType(.f64) }, + + .{ .i4, mlir.IntegerType(.i4) }, + .{ .i8, mlir.IntegerType(.i8) }, + .{ .i16, mlir.IntegerType(.i16) }, + .{ .i32, mlir.IntegerType(.i32) }, + .{ .i64, mlir.IntegerType(.i64) }, + + .{ .u4, mlir.IntegerType(.u4) }, + .{ .u8, mlir.IntegerType(.u8) }, + .{ .u16, mlir.IntegerType(.u16) }, + .{ .u32, mlir.IntegerType(.u32) }, + .{ .u64, mlir.IntegerType(.u64) }, + + .{ .c64, mlir.ComplexType(.c64) }, + .{ .c128, mlir.ComplexType(.c128) }, + }; + + inline for (mapping) |entry| { + const dt, const mlirT = entry; + if (mlir_type.as(mlirT)) |_| { + return dt; + } + } + + meta.panic("Could not convert mlir.Type to DataType: {}", .{mlir_type}); + } + }; + + pub const Attribute = struct { + pub fn fromData(data: dtype.Data, ctx: mlir.Context) mlir.Attribute { + switch (data) { + .bool => |val| { + return mlir.IntegerAttribute(.i1).init(ctx, @intFromBool(val)).as(mlir.Attribute).?; + }, + inline .f8e4m3b11fnuz, .f8e4m3fn, .f8e4m3fnuz, .f8e5m2, .f8e5m2fnuz => |val, tag| { + const float_type = @field(mlir.FloatTypes, @tagName(tag)); + const float_attr = mlir.FloatAttribute(float_type).init(ctx, val.toF32()); + return float_attr.as(mlir.Attribute).?; + }, + inline .i4, .i8, .i16, .i32, .i64, .u4, .u8, .u16, .u32, .u64 => |val, tag| { + const int_type = @field(mlir.IntegerTypes, @tagName(tag)); + const int_attr = mlir.IntegerAttribute(int_type).init(ctx, @intCast(val)); + return int_attr.as(mlir.Attribute).?; + }, + inline else => |_, tag| meta.panic("Unsupported data type: {any}", .{tag}), + } + } + }; + + pub const DenseIntOrFPElementsAttribute = struct { + pub fn fromData(data: dtype.Data, result_type: mlir.Type) mlir.Attribute { + return switch (data.dataType()) { + .bool => mlir.DenseIntOrFPElementsAttribute(.bool).init(result_type, data.constSlice()).as(mlir.Attribute).?, + .i8 => mlir.DenseIntOrFPElementsAttribute(.i8).init(result_type, data.constSlice()).as(mlir.Attribute).?, + .i16 => mlir.DenseIntOrFPElementsAttribute(.i16).init(result_type, data.constSlice()).as(mlir.Attribute).?, + .i32 => mlir.DenseIntOrFPElementsAttribute(.i32).init(result_type, data.constSlice()).as(mlir.Attribute).?, + .i64 => mlir.DenseIntOrFPElementsAttribute(.i64).init(result_type, data.constSlice()).as(mlir.Attribute).?, + .u8 => mlir.DenseIntOrFPElementsAttribute(.u8).init(result_type, data.constSlice()).as(mlir.Attribute).?, + .u16 => mlir.DenseIntOrFPElementsAttribute(.u16).init(result_type, data.constSlice()).as(mlir.Attribute).?, + .u32 => mlir.DenseIntOrFPElementsAttribute(.u32).init(result_type, data.constSlice()).as(mlir.Attribute).?, + .u64 => mlir.DenseIntOrFPElementsAttribute(.u64).init(result_type, data.constSlice()).as(mlir.Attribute).?, + .bf16 => mlir.DenseIntOrFPElementsAttribute(.bf16).init(result_type, data.constSlice()).as(mlir.Attribute).?, + .f16 => mlir.DenseIntOrFPElementsAttribute(.f16).init(result_type, data.constSlice()).as(mlir.Attribute).?, + .f32 => mlir.DenseIntOrFPElementsAttribute(.f32).init(result_type, data.constSlice()).as(mlir.Attribute).?, + .f64 => mlir.DenseIntOrFPElementsAttribute(.f64).init(result_type, data.constSlice()).as(mlir.Attribute).?, + inline else => |tag| meta.panic("Unsupported data type: {any}", .{tag}), + }; + } + }; +}; diff --git a/zml/module.zig b/zml/module.zig new file mode 100644 index 0000000..a6578f5 --- /dev/null +++ b/zml/module.zig @@ -0,0 +1,1371 @@ +const builtin = @import("builtin"); +const std = @import("std"); + +const runfiles = @import("runfiles"); + +const xla_pb = @import("//xla:xla_proto"); +const meta = @import("meta.zig"); +const mlir = @import("mlir.zig"); +const ops = @import("ops.zig"); +const pjrt = @import("pjrtx.zig"); +const protobuf = @import("io/protobuf"); +const asynk = @import("async"); +const aio = @import("aio.zig"); + +const dialect = @import("mlir/dialects"); + +const assert = std.debug.assert; +const Context = @import("context.zig").Context; +const Location = mlir.Location; +const Platform = @import("platform.zig").Platform; +const Target = @import("platform.zig").Target; +const Tensor = @import("tensor.zig").Tensor; +const ShapeOf = @import("tensor.zig").ShapeOf; +const Shape = @import("shape.zig").Shape; +const Buffer = @import("buffer.zig").Buffer; +const Bufferized = @import("buffer.zig").Bufferized; +const Tracer = @import("tools/tracer.zig").Tracer; + +const log = std.log.scoped(.zml_module); + +pub const CompilationContext = struct { + _platform: Platform, + + _mlir_ctx: mlir.Context, + _mlir_registry: mlir.Registry, + _mlir_canonicalizer: mlir.PassManager, + + _module: mlir.Module, + + _blocks: std.BoundedArray(mlir.Block, 64), + _fn_cache: FnCache, + _allocator: std.mem.Allocator, + + _buffer_to_arg: TensorToBlockArg = .{}, + _unique_id: u64 = 10000, + _tracer: Tracer, + + const TensorToBlockArg = std.AutoHashMapUnmanaged(Tensor._Id, struct { mlir.Value, Tensor._Donation }); + threadlocal var _current: ?*CompilationContext = null; + + pub fn init(allocator: std.mem.Allocator, name: []const u8, platform: Platform) !CompilationContext { + const mlir_registry = mlir.Registry.init() catch unreachable; + inline for (.{ "func", "stablehlo" }) |d| { + mlir.DialectHandle.fromString(d).insertDialect(mlir_registry); + } + var mlir_ctx = mlir.Context.initWithRegistry(mlir_registry, false) catch unreachable; + mlir_ctx.loadAllAvailableDialects(); + + const loc = mlir_ctx.location(@src()).named(mlir_ctx, "main"); + const module = mlir.Module.init(loc); + module.op().setAttributeByName("sym_name", mlir.StringAttribute.init(mlir_ctx, name).as(mlir.Attribute).?); + + var canonicalizer = try mlir.PassManager.init(mlir_ctx); + { + var opm = canonicalizer.asOpPassManager(); + try opm.addPipeline("canonicalize"); + try opm.addPipeline("cse"); + try opm.addPipeline("canonicalize"); + } + + return .{ + ._platform = platform, + ._mlir_ctx = mlir_ctx, + ._mlir_registry = mlir_registry, + ._mlir_canonicalizer = canonicalizer, + ._module = module, + ._blocks = .{}, + ._fn_cache = FnCache.init(allocator), + ._allocator = allocator, + ._tracer = Tracer.init("ai.zml.compilation"), + }; + } + + pub fn deinit(self: *CompilationContext) void { + self._fn_cache.deinit(); + self._mlir_ctx.deinit(); + self._mlir_registry.deinit(); + self._buffer_to_arg.deinit(self._allocator); + } + + pub fn activate(self: *CompilationContext) void { + _current = self; + } + + pub fn deactivate(self: *CompilationContext) void { + std.debug.assert(_current != null and _current.? == self); + _current = null; + } + + pub fn current() *CompilationContext { + return _current.?; + } + + pub fn target(self: *const CompilationContext) Target { + return self._platform.target; + } + + pub fn targetIs(self: *const CompilationContext, value: Target) bool { + return self.target() == value; + } + + pub fn mlirCtx(self: *const CompilationContext) mlir.Context { + return self._mlir_ctx; + } + + pub fn currentBlock(self: *const CompilationContext) ?mlir.Block { + return if (self._blocks.len > 0) self._blocks.get(self._blocks.len - 1) else null; + } + + pub fn openBlock(self: *CompilationContext, args: []const mlir.Type, locs: []const mlir.Location) !mlir.Block { + const block = try mlir.Block.init(args, locs); + self.pushBlock(block); + return block; + } + + pub fn closeBlock(self: *CompilationContext, block: *mlir.Block) void { + const popped = self._blocks.pop(); + std.debug.assert(block.equals(popped)); + } + + fn pushBlock(self: *CompilationContext, block: mlir.Block) void { + self._blocks.appendAssumeCapacity(block); + } + + /// Transform a Tensor -> Tensor function into an Mlir block. + /// `blkctx` represents values from outside the block that can be accessed inside the block. + pub fn makeBlock( + self: *CompilationContext, + comptime func: anytype, + comptime S: ops.BlockSignature, + blkctx: S.BlkCtx, + args: S.Args, + ) mlir.Block { + const N = S.nIn; + const locations = .{mlir.Location.unknown(self.mlirCtx())} ** N; + var input_types: [N]mlir.Type = undefined; + fillMlirTypes(&args, self.mlirCtx(), &input_types); + + var block = self.openBlock(&input_types, &locations) catch unreachable; + defer self.closeBlock(&block); + + // Here we want to create the block with the correct mlir types. + // but we don't want to use the values themselves. + // So we create a copy of the arguments, and replace values + // by the block arguments. + var blk_args = args; + assert(assignBlockArguments(&blk_args, block, 0) == N); + + const loc = self.mlirCtx().location(@src()); + const block_res = @call(.auto, func, S.blkArgs(blkctx, blk_args)); + + var block_res_values: [S.nOut]mlir.Value = undefined; + self.extractValues(&block_res, &block_res_values); + const block_ret = dialect.stablehlo.returns_(self.mlirCtx(), &block_res_values, loc); + block.addOperationsRecursive(block_ret); + + return block; + } + + /// Generate an MLIR function from a ZML function. + /// The caller is responsible to have properly created the input + /// tensors with unique tensor ids. + pub fn generateBytecode( + self: *CompilationContext, + allocator: std.mem.Allocator, + fn_name: [:0]const u8, + comptime func: anytype, + model: *const ModuleSignature(func).ModelT, + args: *const ModuleSignature(func).ArgsT, + opts: struct { add_donations_attributes: bool = false }, + ) error{OutOfMemory}!MlirFn { + const frame = self._tracer.frameStart("generateBytecode.emit"); + errdefer self._tracer.frameEnd(frame, "generateBytecode.emit"); + + // Note: only temp allocations are done in the arena, + // the other allocations are managed by the caller. + var arena_state = std.heap.ArenaAllocator.init(allocator); + defer arena_state.deinit(); + const arena = arena_state.allocator(); + + const model_tensor_count = countTensors(model); + const args_tensor_count = countTensors(args); + + const tensor_count = model_tensor_count + args_tensor_count; + + const loc = self.mlirCtx().location(@src()); + + const locations = try arena.alloc(mlir.Location, tensor_count); + for (locations) |*l| l.* = mlir.Location.unknown(self.mlirCtx()); + var input_types = try arena.alloc(mlir.Type, tensor_count); + fillMlirTypes(model, self.mlirCtx(), input_types[0..model_tensor_count]); + fillMlirTypes(args, self.mlirCtx(), input_types[model_tensor_count..]); + + // Note: this isn't stricly necessary. We call `countTensor` on `fn_res`. + // But it forces user to have simpler function. + const out_tensor_count = comptime ops.staticCountTensors(ModuleSignature(func).ReturnT) orelse @compileError("Can't use " ++ @typeName(ModuleSignature(func).ReturnT) ++ " in an MLIR function, because it has a variable number of tensors"); + const fn_res_types = try allocator.alloc(mlir.Type, out_tensor_count); + const fn_res_shapes = try allocator.alloc(Shape, out_tensor_count); + const fn_res_donations = try allocator.alloc(Tensor._Donation, out_tensor_count); + var fn_body = self.openBlock(input_types, locations) catch unreachable; + { + defer self.closeBlock(&fn_body); + // Note: we could shrink self._buffer_to_arg once we called `func`. + // But for now we are only compiling one function per CompilationContext. + // So we don't need to do this since we won't reuse self._buffer_to_arg anyway. + // const n = self._buffer_to_arg.count(); + // defer self._buffer_to_arg.shrinkRetainingCapacity(n); + + try self._buffer_to_arg.ensureUnusedCapacity(self._allocator, @intCast(tensor_count)); + const assigned_model_count = self.mapBlockArguments(model, fn_body, 0); + const assigned_args_count = self.mapBlockArguments(args, fn_body, assigned_model_count); + assert(assigned_model_count == model_tensor_count); + assert(assigned_args_count == tensor_count); + + const fn_res = forward: { + self.activate(); + defer self.deactivate(); + break :forward @call(.auto, func, .{model.*} ++ args.*); + }; + + var fn_res_values: [out_tensor_count]mlir.Value = undefined; + self.extractValuesAndTypes(&fn_res, &fn_res_values, fn_res_types, fn_res_shapes, fn_res_donations); + const fn_ret = dialect.func.return_(self.mlirCtx(), &fn_res_values, loc); + fn_body.addOperationsRecursive(fn_ret); + } + + // Donations attributes only make sense on the main function. + const attrs: []const mlir.Attribute = if (opts.add_donations_attributes) + try self.addDonationsAttribute(arena, fn_res_donations, tensor_count) + else + &.{}; + + const mlir_fn = dialect.func.func(self.mlirCtx(), .{ + .sym_name = fn_name, + .args = input_types[0..], + .arg_attrs = attrs, + .results = fn_res_types, + .block = fn_body, + .location = loc, + }); + + self._tracer.frameEnd(frame, "generateBytecode.emit"); + const canonicalize_frame = self._tracer.frameStart("generateBytecode.canonicalize"); + defer self._tracer.frameEnd(canonicalize_frame, "generateBytecode.canonicalize"); + self._mlir_canonicalizer.runOnOp(mlir_fn) catch |err| switch (err) { + error.InvalidMlir => { + log.err("Failed to canonicalize invalid mlir: {}", .{mlir_fn.mlirFormatter(.{})}); + // user errors should have triggered a panic before we reach this. + @panic("ZML generated invalid mlir. Please open a bug report"); + }, + }; + + return .{ + .mlir_fn = mlir_fn, + .name = fn_name, + .n_model = @intCast(model_tensor_count), + .n_args = @intCast(args_tensor_count), + .res_types = fn_res_types, + .res_shapes = fn_res_shapes, + .res_donations = fn_res_donations, + }; + } + + /// Given a list of donations mapping output buffers to input buffers, + /// generate donation attribute for each `n_args` input argument. + fn addDonationsAttribute(self: *const CompilationContext, allocator: std.mem.Allocator, donations: []const Tensor._Donation, n_args: usize) ![]mlir.Attribute { + const empty = mlir.DictionaryAttribute.init(self.mlirCtx(), &.{}).as(mlir.Attribute).?; + + const arg_attrs = try allocator.alloc(mlir.Attribute, n_args); + @memset(arg_attrs, empty); + + var n_donations: usize = 0; + for (donations, 0..) |donation, index| { + switch (donation) { + .no_buffer => {}, + // This is an input buffer that has been returned, + // but without explicitly calling `reuseBuffer`. + // So we assume the intent was to return a new buffer. + .input_buffer => {}, + .arg => |a| { + n_donations += 1; + meta.assert(arg_attrs[a].eql(empty), "Donation error ! Argument {} has been donated twice ! To {} and to {}", .{ a, index, arg_attrs[a] }); + arg_attrs[a] = mlir.DictionaryAttribute.init(self.mlirCtx(), &.{ + mlir.NamedAttribute.init( + mlir.Identifier.get(self.mlirCtx(), "tf.aliasing_output"), + mlir.IntegerAttribute(.i32).init(self.mlirCtx(), @intCast(index)).as(mlir.Attribute).?, + ), + }).as(mlir.Attribute).?; + // log.debug("attribute: {}", .{arg_attrs[a]}); + }, + } + } + + if (n_donations == 0) return &.{}; + return arg_attrs; + } + + test addDonationsAttribute { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const allocator = arena.allocator(); + + const s = Shape.init(.{8}, .f16); + + const Local = struct { + bias: Tensor, + + pub fn forward(self: @This(), x: Tensor) Tensor { + const y = x.add(self.bias); + return y.reuseBuffer(x); + } + }; + + const model: Local = .{ + .bias = zml.Tensor{ ._shape = s, ._id = .{ .buffer_id = 0 } }, + }; + + var comp = try zml.module.CompilationContext.init(allocator, "test", platform); + defer comp.deinit(); + var tensor_args = .{Tensor{ ._shape = s, ._id = .{ .arg_id = 1234 } }}; + const f = try comp.generateBytecode(allocator, "test.generateBytecode.Local.forward", Local.forward, &model, &tensor_args, .{ .add_donations_attributes = true }); + + var mlir_bytecode: std.ArrayListUnmanaged(u8) = .{}; + try mlir_bytecode.writer(allocator).print("{}", .{f.mlir_fn.mlirFormatter(.{})}); + + // Check that the `x` input argument gives its buffer to the result tensor. + // `%arg0` is the bias of the model, `%arg1` is `x`. + try std.testing.expectEqual(1, f.n_model); + try std.testing.expectEqual(1, f.n_args); + std.testing.expect(std.mem.indexOf(u8, mlir_bytecode.items, "%arg1: tensor<8xf16> {tf.aliasing_output = 0 : i32}") != null) catch |err| { + log.warn("Didn't produced the expected IR:\n{s}", .{mlir_bytecode.items}); + return err; + }; + } + + /// Generates an MLIR `func.call` of the given function. + /// If the function has not been seen yet, we generate MLIR for it, + /// in a independent function. + /// The main benefit of this is to generate MLIR that maps more closely + /// to the Zig code, but compilation speed stays similar. + pub fn callFunc( + self: *CompilationContext, + func_name: [:0]const u8, + comptime func: anytype, + model: *const ModuleSignature(func).ModelT, + args: *ModuleSignature(func).ArgsT, + ) ModuleSignature(func).ReturnT { + var arena_state = std.heap.ArenaAllocator.init(self._allocator); + defer arena_state.deinit(); + const arena = arena_state.allocator(); + + // first, do the "compile" and check the bytecode + // the result of this will also have the correct tags of the result shapes + const dummy_result = self.generateMlirBytecodeForFunction( + arena, + func_name, + func, + model, + args, + ) catch unreachable; // TODO: do we like unreachable? + const bytecode_hash = hashArgs(dummy_result.bytecode_tmp); + + const key: FnCache.Key = .{ .fn_ptr = &func, .input_hash = bytecode_hash }; + const function = self._fn_cache.getEntry(key) orelse b: { + const full_name: [:0]const u8 = if (std.mem.eql(u8, "main", func_name)) + arena.dupeZ(u8, func_name) catch unreachable + else + std.fmt.allocPrintZ(arena, "{s}.{s}_{x}", .{ @typeName(ModuleSignature(func).ModelT), func_name, key.input_hash }) catch unreachable; + + log.info("addFuncToModule {any} {s}", .{ key, full_name }); + + const value = self.addFuncToModule( + arena, + full_name, + func, + model, + args, + ) catch unreachable; + + break :b self._fn_cache.addEntry(key, value) catch unreachable; + }; + + // Note: we won't increase the size of the cache until next `call` so + // we can use the memory there without worrying about fragmentation. + + const loc = self.mlirCtx().location(@src()); + + const values = arena.alloc(mlir.Value, function.n_model + function.n_args) catch unreachable; + extractValues(model, values[0..function.n_model]); + extractValues(args, values[function.n_model..]); + + const op = dialect.func.call(self.mlirCtx(), function.name, values, function.res_types, loc); + var res: meta.FnResult(func) = undefined; + assignResults(&res, function.res_shapes, op); + return res; + } + + /// Visit the given struct and recursively associate the `block` arguments with the `value` field of each encountered Tensor. + /// + /// This is done so that we have a mapping between the arguments of the kernel associated with a module and the actual Tensors + /// stored in the Module. + /// Caller need to allocate required memory in self._buffer_to_arg. + pub fn mapBlockArguments(self: *CompilationContext, v: anytype, block: mlir.Block, start: usize) usize { + const LocalContext = struct { + index: usize, + block: mlir.Block, + self: *CompilationContext, + }; + var context = LocalContext{ .self = self, .block = block, .index = start }; + meta.visit((struct { + fn cb(ctx: *LocalContext, tensor: *const Tensor) void { + const arg_value = ctx.block.argument(ctx.index); + // log.debug("mapping {} to arg {}", .{ tensor._id, ctx.index }); + + const res = ctx.self._buffer_to_arg.getOrPutAssumeCapacity(tensor._id); + if (res.found_existing) { + std.debug.panic("Failed compilation because received two tensors arguments with the same ID: {} and {}({}).", .{ res.key_ptr.*, tensor, tensor._id }); + } else { + res.value_ptr.* = .{ arg_value, .{ .arg = @intCast(ctx.index) } }; + } + ctx.index += 1; + } + }).cb, &context, v); + return context.index; + } + + /// Create tensor from the given shapes. + /// Each created tensor will receive a unique id, local to this CompilationContext. + pub fn tensorFromShapes(self: *CompilationContext, ArgsT: type, allocator: std.mem.Allocator, args_shapes: anytype) ArgsT { + const Local = struct { + fn tensorFromShape(arg_id: *u64, shape: Shape) Tensor { + defer arg_id.* += 1; + return Tensor{ + ._shape = shape, + ._id = .{ .arg_id = arg_id.* }, + ._donation = .input_buffer, + }; + } + }; + var tensor_args: ArgsT = undefined; + try meta.mapAlloc(Local.tensorFromShape, allocator, &self._unique_id, args_shapes, &tensor_args); + return tensor_args; + } + + /// Visit the given struct and extract the mlir.Value and mlir.Type associated with each tensor found. + pub fn extractValuesAndTypes(self: *const CompilationContext, v: anytype, values: []mlir.Value, types: []mlir.Type, shapes: []Shape, donations: []Tensor._Donation) void { + assert(values.len == types.len); + const LocalContext = struct { + self: *const CompilationContext, + index: usize = 0, + values: []mlir.Value, + types: []mlir.Type, + shapes: []Shape, + donations: []Tensor._Donation, + }; + var context = LocalContext{ .self = self, .values = values, .types = types, .shapes = shapes, .donations = donations }; + meta.visit((struct { + fn cb(ctx: *LocalContext, tensor: *const Tensor) void { + const value, const donation = ctx.self.getValueAndDonation(tensor.*); + ctx.values[ctx.index] = value; + ctx.types[ctx.index] = value.getType(); + ctx.shapes[ctx.index] = tensor._shape; + ctx.donations[ctx.index] = donation; + ctx.index += 1; + } + }).cb, &context, v); + assert(context.index == values.len); + } + + pub fn getValueAndDonation(self: *const CompilationContext, tensor: Tensor) struct { mlir.Value, Tensor._Donation } { + return switch (tensor._id) { + .buffer_id, .arg_id => if (self._buffer_to_arg.get(tensor._id)) |res| + .{ res[0], res[1] } + else { + log.err("Found unknown tensor id {}({})", .{ tensor, tensor._id }); + @panic("Found unknown tensor id"); + }, + .mlir => |v| .{ v, tensor._donation }, + }; + } + + /// Visit the given struct and copies the mlir.Value associated with each tensor found. + pub fn extractValues(self: *const CompilationContext, v: anytype, values: []mlir.Value) void { + const LocalContext = struct { + self: *const CompilationContext, + index: usize = 0, + values: []mlir.Value, + }; + var context = LocalContext{ .self = self, .values = values }; + meta.visit((struct { + fn cb(ctx: *LocalContext, tensor: *const Tensor) void { + const value, const donation = ctx.self.getValueAndDonation(tensor.*); + _ = donation; + + ctx.values[ctx.index] = value; + ctx.index += 1; + } + }).cb, &context, v); + assert(context.index == values.len); + } +}; + +/// Visit the given struct and recursively counts the number of tensors found. +pub fn countTensors(v: anytype) usize { + const LocalContext = struct { + count: usize = 0, + }; + var context = LocalContext{}; + meta.visit((struct { + fn cb(inner_context: *LocalContext, _: *const Tensor) void { + inner_context.count += 1; + } + }).cb, &context, v); + return context.count; +} + +/// Visit the given struct and recursively fill the `types` slice with the mlir.Type associated with encountered Tensor. +pub fn fillMlirTypes(v: anytype, mlir_ctx: mlir.Context, types: []mlir.Type) void { + const LocalContext = struct { + index: usize = 0, + mlir_ctx: mlir.Context, + types: []mlir.Type, + }; + var context = LocalContext{ .mlir_ctx = mlir_ctx, .types = types }; + meta.visit((struct { + fn cb(inner_context: *LocalContext, tensor: *const Tensor) void { + inner_context.types[inner_context.index] = mlir.ext.mlirType(inner_context.mlir_ctx, tensor.shape()); + inner_context.index += 1; + } + }).cb, &context, v); + assert(context.index == types.len); +} + +/// Visit the given struct and recursively associate the `block` arguments with the `value` field of each encountered Tensor. +/// +/// This is done so that we have a mapping between the arguments of the kernel associated with a module and the actual Tensors +/// stored in the Module. +fn assignBlockArguments(v: anytype, block: mlir.Block, start: usize) usize { + const LocalContext = struct { index: usize, block: mlir.Block }; + var context = LocalContext{ .block = block, .index = start }; + meta.visit((struct { + fn cb(ctx: *LocalContext, tensor: *Tensor) void { + tensor._id = .{ .mlir = ctx.block.argument(ctx.index) }; + tensor._donation = .{ .arg = @intCast(ctx.index) }; + ctx.index += 1; + } + }).cb, &context, v); + return context.index; +} + +/// Visit the given struct and fill the `buffers` slice with the buffer associated with encountered Tensor. +fn fillBuffers(v: anytype, buffers: []*pjrt.Buffer) void { + const LocalContext = struct { + index: usize, + buffers: []*pjrt.Buffer, + }; + var ctx: LocalContext = .{ + .index = 0, + .buffers = buffers, + }; + meta.visit((struct { + fn cb(inner_context: *LocalContext, buffer: *const Buffer) void { + // meta.assert(!buffer._data.isDeleted(), "Can't use {} (argument buffer {}) because its pjrt buffer has been donated", .{ buffer, inner_context.index }); + inner_context.buffers[inner_context.index] = buffer._data; + inner_context.index += 1; + } + }).cb, &ctx, v); + assert(ctx.index == buffers.len); +} + +/// Visit the given struct and override tensors by creating a new one using the provided PJRT buffers. +pub fn assignRawBuffers(v: anytype, platform: Platform, buffers: []*pjrt.Buffer) void { + const LocalContext = struct { + index: usize, + platform: Platform, + buffers: []*pjrt.Buffer, + }; + var ctx: LocalContext = .{ + .index = 0, + .platform = platform, + .buffers = buffers, + }; + meta.visit((struct { + fn cb(inner_context: *LocalContext, buffer: *Buffer) void { + const i = inner_context.index; + if (i < inner_context.buffers.len) { + buffer.* = Buffer.fromPjrtBuffer(inner_context.platform, inner_context.buffers[i]); + } + inner_context.index += 1; + } + }).cb, &ctx, v); + meta.assert(ctx.index == buffers.len, "Pjrt call returned {} tensors, but the return type {s}, contains {} Buffers. Note that modules need to have a comptime know number of returned tensors.", .{ buffers.len, @typeName(@TypeOf(v)), ctx.index }); +} + +/// Visit the given struct and assign op results to each tensor found. +pub fn assignResults(v: anytype, shapes: ?[]Shape, op: mlir.Operation) void { + const LocalContext = struct { + index: usize, + op: mlir.Operation, + shapes: ?[]Shape, + }; + var context = LocalContext{ .index = 0, .op = op, .shapes = shapes }; + meta.visit((struct { + fn cb(inner_ctx: *LocalContext, tensor: *Tensor) void { + tensor.* = Tensor.fromMlirValue(inner_ctx.op.result(inner_ctx.index)); + if (inner_ctx.shapes) |sh| { + tensor._shape = sh[inner_ctx.index]; + } + inner_ctx.index += 1; + } + }).cb, &context, v); + assert(context.index == op.numResults()); +} + +/// Represents an MLIR module compiled into a PJRT executable. +/// The BaseExe is a plain old struct and doesn't have information +/// about Zig types. +const BaseExe = struct { + /// The platform for which this module was compiled. + platform: Platform, + /// The PJRT executable representing the compiled module. + exe: *pjrt.LoadedExecutable, + /// Number of buffers in the model. + model_buffer_count: usize, + /// Number of buffers in the arguments. + args_buffer_count: usize, + /// Number of buffers in result. + result_buffer_count: usize, +}; + +/// Represents a ZML model, compiled into a PJRT executable. +/// +/// It's not directly callable, as it doesn't have associated model weights. +/// use `prepare` to assign weights and pre allocate memory needed to call. +pub fn Exe(comptime func: anytype) type { + const Signature = ModuleSignature(func); + return struct { + const Self = @This(); + + /// The raw untyped compiled module. + inner: BaseExe, + + /// Packages the given model weight with an `Exe` to produce an `ExeWithWeights` that can be called. + pub fn prepare(self: Self, allocator: std.mem.Allocator, model: Bufferized(Signature.ModelT)) !ExeWithWeights(func) { + return ExeWithWeights(func).initFromModel(allocator, self.inner, model); + } + }; +} + +/// Represents a ZML model, compiled into a PJRT executable, and ready to call. +/// The buffers for the model weights are saved inside the struct and will be used in `call`. +/// You only need to pass the remaining arguments. +pub fn ExeWithWeights(comptime func: anytype) type { + const Signature = ModuleSignature(func); + return struct { + const Self = @This(); + + /// The raw untyped compiled module. + inner: BaseExe, + + /// The allocator used for bookkeeping. + allocator: std.mem.Allocator, + + /// Pre-allocated slice of buffers to use as inputs when the module is called. + input_buffers: []*pjrt.Buffer, + + /// Pre-allocated slice of buffers to use as outputs when the module is called. + output_buffers: []*pjrt.Buffer, + + pub fn initFromModel(allocator: std.mem.Allocator, inner: BaseExe, model: Bufferized(Signature.ModelT)) !Self { + const input_buffers = try allocator.alloc(*pjrt.Buffer, inner.model_buffer_count + inner.args_buffer_count); + errdefer allocator.free(input_buffers); + fillBuffers(&model, input_buffers[0..inner.model_buffer_count]); + + const output_buffers = try allocator.alloc(*pjrt.Buffer, inner.result_buffer_count); + errdefer allocator.free(output_buffers); + + return .{ + .inner = inner, + .allocator = allocator, + .input_buffers = input_buffers, + .output_buffers = output_buffers, + }; + } + + pub fn deinit(self: Self) void { + self.allocator.free(self.input_buffers); + self.allocator.free(self.output_buffers); + } + + pub fn platform(self: Self) Platform { + return self.inner.platform; + } + + pub fn call(self: Self, args: Bufferized(Signature.ArgsT)) Bufferized(Signature.ReturnT) { + fillBuffers(&args, self.input_buffers[self.inner.model_buffer_count..][0..self.inner.args_buffer_count]); + var event: [1]*pjrt.Event = undefined; + + self.inner.exe.execute(self.inner.platform.pjrt_api, .{ + .arguments = &.{self.input_buffers.ptr}, + .num_args = self.input_buffers.len, + .results = &.{self.output_buffers.ptr}, + .events = &event, + // TODO: this allows to tell a specific buffer shouldn't be donated, + // even if it has been marked as "can be donated" during compilation. + .non_donatable_input_indices = &.{}, + }) catch unreachable; + + var result: Bufferized(Signature.ReturnT) = undefined; + assignRawBuffers(&result, self.inner.platform, self.output_buffers); + return result; + } + }; +} + +/// Compiles the given module with the given arguments. +/// The `model` (first fn argument), is treated differently from the other args. +/// This helps to have two separate lifetimes for the model buffers, +/// and for the arguments buffer. +fn compileInternal( + allocator: std.mem.Allocator, + context: *CompilationContext, + comptime func: anytype, + model: ModuleSignature(func).ModelT, + args: ShapeOf(ModuleSignature(func).ArgsT), +) !BaseExe { + var arena_state = std.heap.ArenaAllocator.init(allocator); + defer arena_state.deinit(); + const arena = arena_state.allocator(); + + var timer = std.time.Timer.start() catch null; + const tensor_args = context.tensorFromShapes(ModuleSignature(func).ArgsT, arena, args); + // TODO: this is fast, doesn't make system call, and use mutable state. + // does it need to be async ? + // const f = try CompilationContext.generateBytecode(context, arena, "main", func, &model, &tensor_args, .{ .add_donations_attributes = true }); + const f = try asynk.callGeneric(CompilationContext.generateBytecode, .{ context, arena, "main", func, &model, &tensor_args, .{ .add_donations_attributes = true } }); + context._module.getBody().appendOperation(f.mlir_fn); + + const loaded_executable = loadOrCompilePjrtExecutable(arena, context._platform, context._module) catch |err| { + log.err( + "pjrt-{s} failed to compile following valid MLIR:\n{}\n{}", + .{ @tagName(context._platform.target), context._module.op().mlirFormatter(.{}), err }, + ); + return err; + }; + + log.debug("******** ZML generated MLIR ********", .{}); + log.debug("{}", .{context._module.op().mlirFormatter(.{})}); + + if (timer) |*t| { + const time_ms = @divFloor(t.lap(), std.time.ns_per_ms); + if (time_ms > 1000) log.info("Compilation took {d:.3}s", .{meta.divFloat(f32, time_ms, 1000)}); + } + + return .{ + .platform = context._platform, + .exe = loaded_executable, + .model_buffer_count = f.n_model, + .args_buffer_count = f.n_args, + .result_buffer_count = f.res_types.len, + }; +} + +/// Compiles a Model struct with the given configuration and shapes, for the given platform. +/// The steps are: +/// * lookup at tensors available in the store and create a `model: Model` struct with them +/// * call `model.init(init_args)` to fields of the model that aren't Tensor, ie hyperparemeters/config +/// * generate MLIR by calling `model.forward` with tensor of the given shapes and other arguments +pub fn compile( + allocator: std.mem.Allocator, + comptime Model: type, + init_args: anytype, + comptime func: @TypeOf(.literal), + args_shapes: ShapeOf(ModuleSignature(@field(Model, @tagName(func))).ArgsT), + buffer_store: aio.BufferStore, + platform: Platform, +) !Exe(@field(Model, @tagName(func))) { + var arena_state = std.heap.ArenaAllocator.init(allocator); + defer arena_state.deinit(); + const arena = arena_state.allocator(); + var model = try aio.populateModel(Model, arena, buffer_store); + + // If the Model has a "init" function, call it with the given parameters. + if (@hasDecl(Model, "init")) { + // TODO(Corentin,@Improvement): Add a warning/error if there is no init function but init_args is non-void. + @call(.auto, Model.init, .{@as(*Model, &model)} ++ init_args); + } + + return compileModel(allocator, model, func, args_shapes, platform); +} + +/// Compiles a Model struct with the given configuration and shapes, for the given platform. +/// Generate MLIR by calling `model.forward` with tensor of the given shapes and other arguments +pub fn compileModel( + allocator: std.mem.Allocator, + model: anytype, + comptime func: @TypeOf(.literal), + args_shapes: ShapeOf(ModuleSignature(@field(@TypeOf(model), @tagName(func))).ArgsT), + platform: Platform, +) !Exe(@field(@TypeOf(model), @tagName(func))) { + const Model = @TypeOf(model); + const name = @typeName(Model) ++ "." ++ @tagName(func); + log.info("Compiling {s} with {}", .{ name, args_shapes }); + + var context = try CompilationContext.init(allocator, name, platform); + defer context.deinit(); + + const raw_module = try compileInternal(allocator, &context, @field(Model, @tagName(func)), model, args_shapes); + + return Exe(@field(Model, @tagName(func))){ .inner = raw_module }; +} + +/// Compiles a function with the given configuration and shapes, for the given platform. +/// Generate MLIR by calling the given function with tensor of the given shapes. +pub fn compileFn( + allocator: std.mem.Allocator, + func: anytype, + args: ShapeOf(meta.FnParams(func)), + platform: Platform, +) !ExeWithWeights(FnWithVoidArg(func)) { + const name = @typeName(@TypeOf(func)); + var context = try CompilationContext.init(allocator, name, platform); + defer context.deinit(); + + const Local = struct { + // This is the function we will actually compile. + pub fn forward(_: void, inner_args: meta.FnParams(func)) meta.FnResult(func) { + return @call(.auto, func, inner_args); + } + }; + + const void_model: void = {}; + const raw_module = try compileInternal(allocator, &context, Local.forward, void_model, .{args}); + // But we set the signature so that you can call the module as you would call the function. + return try ExeWithWeights(FnWithVoidArg(func)).initFromModel(allocator, raw_module, void_model); +} + +fn FnWithVoidArg(func: anytype) type { + const fn_info = @typeInfo(@TypeOf(func)).Fn; + const void_param = std.builtin.Type.Fn.Param{ .is_generic = false, .is_noalias = false, .type = void }; + meta.assertComptime(!fn_info.is_generic, "Can't do reflection on generic function: {}", .{@TypeOf(func)}); + return @Type(.{ .Fn = .{ + .calling_convention = fn_info.calling_convention, + .is_generic = false, + .is_var_args = fn_info.is_var_args, + .return_type = fn_info.return_type, + .params = [1]std.builtin.Type.Fn.Param{void_param} ++ fn_info.params, + } }); +} + +fn computeModuleHash(platform: Platform, module: mlir.Module) u64 { + var hasher = std.hash.XxHash64.init(0); + var hasher_writer = xxHash64Writer(&hasher); + const writer = hasher_writer.writer(); + + // Hash the canonicalized IR, without debug information that can change across builds. + module.op().writeBytecode(writer); + //module.op().print(writer, .{ .debug_info = false }); + // Writes can't fail because we are writing to a hasher. + writer.writeAll(platform.pjrt_client.getPlatformName(platform.pjrt_api)) catch unreachable; + const api_version = platform.pjrt_api.version(); + writer.writeInt(i64, api_version.major, .little) catch unreachable; + writer.writeInt(i64, api_version.minor, .little) catch unreachable; + + return hasher.final(); +} + +const max_pjrt_executable_size = 20 * 1024 * 1024; + +fn loadPjrtExecutable(arena: std.mem.Allocator, platform: Platform, module_hash: u64, compilation_cache_location: []const u8) !*pjrt.LoadedExecutable { + const resolved_path = try std.fs.cwd().realpathAlloc(arena, compilation_cache_location); + const compilation_cache_dir = try std.fs.openDirAbsolute(resolved_path, .{}); + var buf: [16]u8 = undefined; + const filename = try std.fmt.bufPrint(&buf, "{x}", .{module_hash}); + const loaded_executable_file = try compilation_cache_dir.openFile(filename, .{}); + defer loaded_executable_file.close(); + + const bytes = try loaded_executable_file.readToEndAlloc(arena, max_pjrt_executable_size); + + return platform.pjrt_client.deserializeAndLoad(platform.pjrt_api, bytes); +} + +fn storePjrtExecutable(arena: std.mem.Allocator, platform: Platform, loaded_executable: *pjrt.LoadedExecutable, module_hash: u64, compilation_cache_location: []const u8) !void { + const resolved_path = try std.fs.cwd().realpathAlloc(arena, compilation_cache_location); + const compilation_cache_dir = try std.fs.openDirAbsolute(resolved_path, .{}); + + const loaded_executable_file = try compilation_cache_dir.createFile(try std.fmt.allocPrint(arena, "{x}", .{module_hash}), .{}); + defer loaded_executable_file.close(); + + var executable = try loaded_executable.getExecutable(platform.pjrt_api); + defer executable.deinit(platform.pjrt_api); + + var serialize_result = try executable.serialize(platform.pjrt_api); + defer serialize_result.deinit(); + + try loaded_executable_file.writeAll(serialize_result.bytes); +} + +fn loadOrCompilePjrtExecutable( + arena: std.mem.Allocator, + platform: Platform, + module: mlir.Module, +) !*pjrt.LoadedExecutable { + const tracer = Tracer.init("ai.zml.compilation"); + const compile_frame = tracer.frameStart("pjrt cached compilation"); + defer tracer.frameEnd(compile_frame, "pjrt cached compilation"); + const module_hash = computeModuleHash(platform, module); + + if (platform.compilation_options.cache_location) |compilation_cache_location| { + log.debug("Loading module from {s}", .{compilation_cache_location}); + return loadPjrtExecutable(arena, platform, module_hash, compilation_cache_location) catch |err| { + log.debug("Failed to load module: {}", .{err}); + return compileModuleToPjrtExecutable(arena, platform, module, module_hash); + }; + } else { + return compileModuleToPjrtExecutable(arena, platform, module, module_hash); + } +} + +fn compileModuleToPjrtExecutable(arena: std.mem.Allocator, platform: Platform, module: mlir.Module, module_hash: u64) !*pjrt.LoadedExecutable { + var options: xla_pb.CompileOptionsProto = .{ + .executable_build_options = .{ + .num_replicas = 1, + .num_partitions = 1, + }, + }; + // Let the arena deinit, zig-protobuf deinit is very slow. + if (platform.compilation_options.xla_dump_to) |xla_dump_to| { + try options.env_option_overrides.append(arena, .{ + .key = .{ .Const = "xla_dump_to" }, + .value = .{ .value = .{ .string_field = .{ .Const = xla_dump_to } } }, + }); + if (platform.compilation_options.xla_dump_fusion_visualization) { + try options.env_option_overrides.append(arena, .{ + .key = .{ .Const = "xla_dump_hlo_as_html" }, + .value = .{ .value = .{ .bool_field = true } }, + }); + try options.env_option_overrides.append(arena, .{ + .key = .{ .Const = "xla_dump_hlo_as_dot" }, + .value = .{ .value = .{ .bool_field = true } }, + }); + try options.env_option_overrides.append(arena, .{ + .key = .{ .Const = "xla_dump_fusion_visualization" }, + .value = .{ .value = .{ .bool_field = true } }, + }); + } + } + switch (platform.target) { + .cuda => cuda_dir: { + // NVIDIA recommends to disable Triton GEMM on JAX: + // https://github.com/NVIDIA/JAX-Toolbox?tab=readme-ov-file#environment-variables + try options.env_option_overrides.append(arena, .{ + .key = .{ .Const = "xla_gpu_enable_triton_gemm" }, + .value = .{ .value = .{ .bool_field = false } }, + }); + var r_ = try runfiles.Runfiles.create(.{ .allocator = arena }) orelse { + log.warn("Bazel runfile not found !", .{}); + break :cuda_dir; + }; + defer r_.deinit(arena); + const source_repo = @import("bazel_builtin").current_repository; + const r = r_.withSourceRepo(source_repo); + const cuda_data_dir = (try r.rlocationAlloc(arena, "libpjrt_cuda/sandbox")).?; + log.info("xla_gpu_cuda_data_dir: {s}", .{cuda_data_dir}); + try options.env_option_overrides.append(arena, .{ + .key = .{ .Const = "xla_gpu_cuda_data_dir" }, + .value = .{ + .value = .{ + .string_field = .{ .Const = cuda_data_dir }, + }, + }, + }); + }, + .rocm => { + // Disable Triton GEMM on ROCM. For some reason it's much, much slower when + // enabled on CDNA and it's used on RDNA. Disable it altogether. + try options.env_option_overrides.append(arena, .{ + .key = .{ .Const = "xla_gpu_enable_triton_gemm" }, + .value = .{ .value = .{ .bool_field = false } }, + }); + }, + else => {}, + } + + const loaded_executable = try platform.pjrt_client.compile(platform.pjrt_api, arena, module, try options.encode(arena)); + errdefer unreachable; // errdefer loaded_executable.deinit(); + + if (platform.compilation_options.cache_location) |compilation_cache_location| { + log.debug("Storing module to {s}", .{compilation_cache_location}); + storePjrtExecutable(arena, platform, loaded_executable, module_hash, compilation_cache_location) catch |err| { + log.debug("Failed to store module: {}", .{err}); + }; + } + + return loaded_executable; +} + +pub const XxHash64Writer = struct { + hasher: *std.hash.XxHash64, + + pub const Error = error{}; + pub const Writer = std.io.Writer(*XxHash64Writer, Error, write); + + pub fn writer(self: *XxHash64Writer) Writer { + return .{ .context = self }; + } + + pub fn write(self: *XxHash64Writer, bytes: []const u8) Error!usize { + self.hasher.update(bytes); + return bytes.len; + } +}; + +pub fn xxHash64Writer(hasher: *std.hash.XxHash64) XxHash64Writer { + return .{ .hasher = hasher }; +} + +pub fn hasTensors(comptime T: type) bool { + if (T == Tensor) return true; + + return switch (@typeInfo(T)) { + inline .Array, .Pointer, .Optional => |info| hasTensors(info.child), + inline .Struct, .Union => |info| { + inline for (info.fields) |field| { + if (hasTensors(field.type)) return true; + } + return false; + }, + else => false, + }; +} + +test "hasTensors" { + comptime { + try std.testing.expect(hasTensors(?Tensor)); + try std.testing.expect(hasTensors(struct { u8, ?Tensor })); + try std.testing.expect(!hasTensors(struct { u8, usize })); + } +} + +pub fn hasConstTensors(comptime T: type, comptime self_const: bool) bool { + if (T == Tensor) return self_const; + + return switch (@typeInfo(T)) { + inline .Array, .Optional => |info| hasTensors(info.child) and self_const, + .Pointer => |ptr_info| hasConstTensors(ptr_info.child, ptr_info.is_const), + inline .Struct, .Union => |info| { + inline for (info.fields) |field| { + if (hasConstTensors(field.type, self_const)) return true; + } + return false; + }, + else => false, + }; +} + +test "hasConstTensors" { + try std.testing.expect(!hasConstTensors(?Tensor, false)); + try std.testing.expect(hasConstTensors(struct { u8, ?Tensor }, true)); + try std.testing.expect(!hasConstTensors(struct { u8, *Tensor }, true)); + try std.testing.expect(hasConstTensors(struct { u8, *const Tensor }, false)); + try std.testing.expect(!hasConstTensors(struct { *Tensor }, false)); + try std.testing.expect(!hasConstTensors(std.meta.Tuple(&[_]type{*Tensor}), false)); + try std.testing.expect(!hasConstTensors(struct { u8, usize }, false)); + try std.testing.expect(hasConstTensors(struct { [5]Tensor, usize }, true)); + try std.testing.expect(!hasConstTensors(struct { [5]Tensor, usize }, false)); +} + +// making this a struct force all fields to be evaluted on creation, +// which gives a better error stacktrace +// than delaying the error to when the object fields are read. +const Sign = struct { + FuncT: type, + ModelT: type, + ArgsT: type, + ReturnT: type, +}; + +pub fn ModuleSignature(comptime func: anytype) Sign { + const FuncT = if (@TypeOf(func) == type) func else @TypeOf(func); + return .{ + .FuncT = FuncT, + .ModelT = @typeInfo(FuncT).Fn.params[0].type orelse @compileError("cannot create,ModuleSignature for function with an 'anytype' parameter"), + .ArgsT = blk: { + const function_info = @typeInfo(FuncT); + if (function_info.Fn.params[1..].len == 0) { + break :blk @TypeOf(.{}); + } + + var argument_field_list: [function_info.Fn.params.len - 1]type = undefined; + for (function_info.Fn.params[1..], 0..) |arg, i| { + const T = arg.type orelse @compileError("cannot create ModuleSignature for function with an 'anytype' parameter"); + argument_field_list[i] = T; + } + + break :blk std.meta.Tuple(&argument_field_list); + }, + .ReturnT = @typeInfo(FuncT).Fn.return_type.?, + }; +} + +pub const MlirFn = struct { + name: [:0]const u8, + n_model: u32, + n_args: u32, + res_types: []mlir.Type, + res_shapes: []Shape, + res_donations: []Tensor._Donation, + mlir_fn: mlir.Operation, +}; + +// TODO(Corentin): Remove that +pub const FnCache = struct { + pub const Key = struct { fn_ptr: *const anyopaque, input_hash: u64 }; + + // TODO: merge arenas + cache: std.AutoHashMapUnmanaged(Key, MlirFn), + // Arena for the cache entries + cache_arena: std.heap.ArenaAllocator, + // Arena for the cache data (name, res_type) + cache_data_arena: std.heap.ArenaAllocator, + + pub fn init(allocator: std.mem.Allocator) FnCache { + return .{ + .cache = .{}, + .cache_arena = std.heap.ArenaAllocator.init(allocator), + .cache_data_arena = std.heap.ArenaAllocator.init(allocator), + }; + } + + pub fn deinit(self: FnCache) void { + self.cache_arena.deinit(); + self.cache_data_arena.deinit(); + } + + pub fn getEntry(self: *const FnCache, key: Key) ?MlirFn { + return self.cache.get(key); + } + + pub fn addEntry(self: *FnCache, key: Key, value: MlirFn) !MlirFn { + var cache_data_allocator = self.cache_data_arena.allocator(); + + const res_types_copy = try cache_data_allocator.dupe(mlir.Type, value.res_types); + errdefer cache_data_allocator.free(res_types_copy); + + const res_shapes_copy = try cache_data_allocator.dupe(Shape, value.res_shapes); + errdefer cache_data_allocator.free(res_shapes_copy); + + const res_donations_copy = try cache_data_allocator.dupe(Tensor._Donation, value.res_donations); + errdefer cache_data_allocator.free(res_donations_copy); + + const name_copy = try cache_data_allocator.dupeZ(u8, value.name); + errdefer cache_data_allocator.free(name_copy); + + const owned_value: MlirFn = .{ + .name = name_copy, + .mlir_fn = value.mlir_fn, + .n_model = value.n_model, + .n_args = value.n_args, + .res_types = res_types_copy, + .res_shapes = res_shapes_copy, + .res_donations = res_donations_copy, + }; + + try self.cache.putNoClobber(self.cache_arena.allocator(), key, owned_value); + return owned_value; + } +}; + +test FnCache { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + + const NN = struct { + const NN_ = @This(); + layer_weights: [3]Tensor, + layer_biases: [3]Tensor, + + pub fn forward(self: NN_, x0: Tensor) Tensor { + var x = x0; + for (self.layer_weights, self.layer_biases) |w, b| { + // TODO use the `call` magic helper + // x = ops.callFunc(ctx, NN_, "reluLayer", .{ w, b, x }); + x = NN_.reluLayer(w, b, x); + } + return x; + } + + pub fn forwardRefImpl(self: NN_, x0: Tensor) Tensor { + var x = x0; + for (self.layer_weights, self.layer_biases) |w, b| { + x = NN_.reluLayer(w, b, x); + } + return x; + } + + pub fn reluLayer(w: Tensor, b: Tensor, x: Tensor) Tensor { + const wx = w.dotGeneral(x, &.{.{ -1, 0 }}, &.{}); + return wx.add(b.broadcastLeft(wx.shape())).relu(); + } + }; + + const x = try zml.Buffer.fromSlice(platform, .{2}, &[_]f16{ -1, 1 }); + const nn: zml.Bufferized(NN) = .{ + .layer_weights = .{ + try zml.Buffer.fromSlice(platform, .{ 2, 2 }, &[_]f16{ 1, -1, 0, 1 }), + try zml.Buffer.fromSlice(platform, .{ 2, 2 }, &[_]f16{ 1, 2, 1, -1 }), + // third layer is different + try zml.Buffer.fromSlice(platform, .{ 3, 2 }, &[_]f16{ 1, 2, 0, 1, -1, 0 }), + }, + .layer_biases = .{ + try zml.Buffer.fromSlice(platform, .{2}, &[_]f16{ 0, 0 }), + try zml.Buffer.fromSlice(platform, .{2}, &[_]f16{ 10, 10 }), + try zml.Buffer.fromSlice(platform, .{3}, &[_]f16{ -10, -10, -10 }), + }, + }; + const res = try zml.testing.compileAndCall(platform, NN.forward, .{ nn, x }); + const expected = try zml.testing.compileAndCall(platform, NN.forwardRefImpl, .{ nn, x }); + try zml.testing.expectClose(expected, res, 1e-4); +} + +pub fn hashArgs(mod: anytype) u64 { + var hasher = std.hash.Wyhash.init(0); + hash(&hasher, mod, .DeepRecursive); + return hasher.final(); +} + +pub fn hashTensor(hasher: *std.hash.Wyhash, tensor: Tensor) void { + // Note: if we enforced 0-init dims then we could hash dims instead. + hashArray(hasher, tensor.dims(), .Shallow); + hash(hasher, tensor.dtype(), .Shallow); +} + +const HashStrategy = std.hash.Strategy; +const tensorAwareHash = hash; // alias for when "hash" is ambiguous + +/// Provides generic hashing for any eligible type. +/// Strategy is provided to determine if pointers should be followed or not. +pub fn hash(hasher: *std.hash.Wyhash, key: anytype, comptime strat: HashStrategy) void { + const Key = @TypeOf(key); + if (Key == Tensor) return hashTensor(hasher, key); + + if (strat == .Shallow and std.meta.hasUniqueRepresentation(Key)) { + hasher.update(std.mem.asBytes(&key)); + return; + } + + switch (@typeInfo(Key)) { + .NoReturn, .Opaque, .Undefined, .Null, .ComptimeFloat, .ComptimeInt, .Type, .EnumLiteral, .Frame, .Void => return, + + // Help the optimizer see that hashing an int is easy by inlining! + // TODO Check if the situation is better after #561 is resolved. + .Int => |int| switch (int.signedness) { + .signed => hash(hasher, @as(@Type(.{ .Int = .{ + .bits = int.bits, + .signedness = .unsigned, + } }), @bitCast(key)), strat), + .unsigned => { + if (std.meta.hasUniqueRepresentation(Key)) { + hasher.update(std.mem.asBytes(&key)); + } else { + // Take only the part containing the key value, the remaining + // bytes are undefined and must not be hashed! + const byte_size = comptime std.math.divCeil(comptime_int, @bitSizeOf(Key), 8) catch unreachable; + hasher.update(std.mem.asBytes(&key)[0..byte_size]); + } + }, + }, + // Note: contrary to Zig we accept hashing floats. + // Typically the float we are going to hash here are hyperparameters, + // and not the result of an operation, so bytes should be the same everytime. + .Float => hasher.update(std.mem.asBytes(&key)), + .Bool => hash(hasher, @intFromBool(key), strat), + .Enum => hash(hasher, @intFromEnum(key), strat), + .ErrorSet => hash(hasher, @intFromError(key), strat), + .AnyFrame, .Fn => hash(hasher, @intFromPtr(key), strat), + .Pointer => |info| switch (info.size) { + .One => switch (strat) { + .Shallow => hash(hasher, @intFromPtr(key), .Shallow), + .Deep => hash(hasher, key.*, .Shallow), + .DeepRecursive => switch (@typeInfo(info.child)) { + .Opaque, .Fn => hash(hasher, @intFromPtr(key), .Shallow), + else => hash(hasher, key.*, .DeepRecursive), + }, + }, + .Slice => { + switch (strat) { + .Shallow => hash(hasher, @intFromPtr(key.ptr), .Shallow), + .Deep => hashArray(hasher, key, .Shallow), + .DeepRecursive => hashArray(hasher, key, .DeepRecursive), + } + hash(hasher, key.len, .Shallow); + }, + .Many, + .C, + => switch (strat) { + .Shallow => hash(hasher, @intFromPtr(key), .Shallow), + else => @compileError( + \\ unknown-length pointers and C pointers cannot be hashed deeply. + \\ Consider providing your own hash function. + ), + }, + }, + .Optional => if (key) |k| hash(hasher, k, strat), + + .Array => hashArray(hasher, key, strat), + + .Vector => |info| { + if (std.meta.hasUniqueRepresentation(Key)) { + hasher.update(std.mem.asBytes(&key)); + } else { + comptime var i = 0; + inline while (i < info.len) : (i += 1) { + hash(hasher, key[i], strat); + } + } + }, + + .Struct => |info| { + inline for (info.fields) |field| { + // We reuse the hash of the previous field as the seed for the + // next one so that they're dependant. + hash(hasher, @field(key, field.name), strat); + } + }, + + .Union => |info| { + if (info.tag_type) |tag_type| { + const tag = std.meta.activeTag(key); + hash(hasher, tag, strat); + inline for (info.fields) |field| { + if (@field(tag_type, field.name) == tag) { + if (field.type != void) { + hash(hasher, @field(key, field.name), strat); + } + // TODO use a labelled break when it does not crash the compiler. cf #2908 + // break :blk; + return; + } + } + unreachable; + } else @compileError("cannot hash untagged union type: " ++ @typeName(Key) ++ ", provide your own hash function"); + }, + + .ErrorUnion => blk: { + const payload = key catch |err| { + hash(hasher, err, strat); + break :blk; + }; + hash(hasher, payload, strat); + }, + } +} + +fn hashArray(hasher: anytype, key: anytype, comptime strat: HashStrategy) void { + for (key) |element| { + hash(hasher, element, strat); + } +} diff --git a/zml/nn.zig b/zml/nn.zig new file mode 100644 index 0000000..9fb426b --- /dev/null +++ b/zml/nn.zig @@ -0,0 +1,937 @@ +//! Common layer definition and functions for Neural Networks (NN) +const std = @import("std"); +const assert = std.debug.assert; +const testing = std.testing; + +const zml = @import("zml.zig"); +const meta = @import("meta.zig"); +const helpers = @import("helpers.zig"); +const ops = @import("ops.zig"); + +const DataType = @import("dtype.zig").DataType; +const Shape = @import("shape.zig").Shape; +const Tensor = @import("tensor.zig").Tensor; + +const log = std.log.scoped(.zml_tensor); + +const cuda = @import("nn/cuda.zig"); + +pub const Linear = struct { + weight: Tensor, + bias: ?Tensor = null, + + pub fn forward(self: Linear, x: Tensor) Tensor { + var y = x.dotGeneral(self.weight.convert(x.dtype()), &.{.{ -1, -1 }}, &.{}); + // If self.weight doesn't have tags, preserve tags from x. + if (y.shape().tag(-1) == Shape.TagUnknown) { + y._shape._tags.set(y.rank() - 1, x.shape().tag(-1)); + } + + // log.debug("Linear({*}): {d} -> {d} -> {d}", .{ self, x.dims(), y.dims(), if (self.bias) |bias| y.add(bias).dims() else y.dims() }); + return if (self.bias) |bias| y.add(bias.broadcastLeft(y.shape())) else y; + } +}; + +pub const TokenEmbedding = struct { + weight: Tensor, + + pub fn forward(self: TokenEmbedding, idx: Tensor) Tensor { + meta.assert(idx.dtype().isInteger(), "TokenEmbedding expects an integer input, received: {}", .{idx}); + meta.assert(self.weight.rank() == 2, "TokenEmbedding expects it's weight Tensor to be a 2D matrix, got {}", .{self.weight}); + return self.weight.gather1d(0, idx, .{}); + } +}; + +pub const Activation = union(enum) { + sigmoid, + tanh, + relu, + leakyReLU: f32, + silu, + gelu, + quick_gelu, + + pub fn forward(self: Activation, x: Tensor) Tensor { + return switch (self) { + .sigmoid => x.sigmoid(), + .tanh => x.tanh(), + .relu => x.relu(), + .silu => x.silu(), + .gelu => x.gelu(), + .quick_gelu => x.quickGelu(), + .leakyReLU => |slope| x.leakyReLU(slope), + }; + } +}; + +pub fn chainModules(module_list: anytype, input: Tensor) Tensor { + const T = @TypeOf(module_list); + switch (@typeInfo(T)) { + .Struct => |struct_info| { + var x = input; + inline for (struct_info.fields) |field| { + x = @field(module_list, field.name).forward(x); + } + return x; + }, + else => @compileError("chainModules only works on a struct with only containing 'module' struct."), + } +} + +/// Layer Normalization +pub const LayerNorm = struct { + weight: Tensor, + bias: ?Tensor = null, + eps: f32 = 1e-5, + + pub fn forward(self: LayerNorm, x: Tensor) Tensor { + const normed = normalizeVariance(x, self.eps); + + var out = normed.mul(self.weight.broadcastLeft(x.shape())); + if (self.bias) |bias| out = out.add(bias.broadcastLeft(x.shape())); + + return out; + } +}; + +/// Center and scale by the variance. +/// normalize(x, eps) = (x - mean(x)) / sqrt(var(x) + eps) +/// Work on the last axis. +pub fn normalizeVariance(x: Tensor, eps: f32) Tensor { + const N: f32 = @floatFromInt(x.dim(-1)); + + // Upcast to improve precision + const xf32 = x.convert(.f32); + const mean = xf32.sum(-1).scale(1.0 / N); + const mean_dev = xf32.sub(mean.broadcastRight(xf32.shape())); + const variance = mean_dev.mul(mean_dev).sum(-1).scale(1.0 / N); + const rsqrt = Tensor.rsqrt(variance.addConstant(eps)); + + return mean_dev.mul(rsqrt.broadcastRight(mean_dev.shape())).convert(x.dtype()); +} + +// ref: https://pytorch.org/docs/stable/generated/torch.nn.functional.normalize.html +// Implementation equivalent to `nn.functional.normalize(tensor, dim=-1)` call +pub fn normalizeL2(input: Tensor, eps: f32) Tensor { + const inv_norm = input.pow(Tensor.scalar(2, input.dtype())).sum(-1).addConstant(eps).rsqrt(); + return input.mul(inv_norm.broad(input.shape())); +} + +test normalizeL2 { + const platform = zml.testing.env(); + + const input = try zml.Buffer.fromSlice(platform, .{ 2, 2 }, &[_]f32{ -0.9686, -1.0058, -1.7808, 0.6698 }); + + const res = try zml.testing.compileAndCall(platform, zml.nn.normalizeL2, .{ input, 1e-12 }); + const expectation = zml.HostBuffer.fromSlice(.{ 2, 2 }, &[_]f32{ -0.6937, -0.7203, -0.9360, 0.3520 }); + try zml.testing.expectClose(expectation, res, 1e-4); +} + +pub const RopeOpts = struct { + /// There are two implementations corresponding to how to split `x` in real/imag parts. + /// * Interleaved means that the real/imag of each scalar is contiguous. + /// * Sequential means that you first read all real values then all imag values. + pub const Implementation = enum { interleaved, sequential }; + + impl: Implementation, + freq_base: f32 = 10_000, +}; + +pub const CosSin = [2]Tensor; + +/// Rotary position embedding modify queries and keys tensor before compute Q * K in self attention. +/// This biases a token to look at token near him. +/// The nice thing with this solution is that you can cache the modified queries and keys directly. +/// See: https://paperswithcode.com/method/rope +pub fn rope(x: Tensor, cos_sin_cache: CosSin, opts: RopeOpts) Tensor { + const cos, const sin = cos_sin_cache; + meta.assert(x.dim(-1) == 2 * cos.dim(-1), "Couldn't compute rope({}, {}, {})", .{ x, cos, sin }); + // broadcast cos / sin to .{ batch, .seq, .half_dim } + const x_real, const x_imag = splitRealImg(x, opts.impl); + const has_tags = cos.shape().tag(0) != Shape.TagUnknown; + const b_cos = if (has_tags) cos.broad(x_real.shape()) else cos.broadcastLeft(x_real.shape()); + const b_sin = if (has_tags) sin.broad(x_real.shape()) else sin.broadcastLeft(x_real.shape()); + + // apply rotation + const y_real = x_real.mul(b_cos).sub(x_imag.mul(b_sin)); + const y_imag = x_real.mul(b_sin).add(x_imag.mul(b_cos)); + + // flatten last dimensions + const y = mergeRealImg(y_real, y_imag, opts.impl); + + return y; +} + +pub fn ropeCosSin(sh: anytype, dtype: DataType, opts: RopeOpts) CosSin { + const shape = Shape.init(sh, dtype); + meta.assert(shape.rank() == 2, "ropeCosSin({}) shape need to exactly have 2 axes", .{shape}); + const seq_len, const head_dim = .{ shape.dim(0), shape.dim(1) }; + meta.assert(@mod(head_dim, 2) == 0, "ropeCosSin requires an even head_dim, got {}", .{head_dim}); + + // compute sin and cos in f32 before downcasting to x type. + const inv_freq = invFreq(head_dim, opts.freq_base, .f32); + var inv_freq_pos = Tensor.outer(Tensor.arange(.{ .end = seq_len }, .f32), inv_freq).convert(shape.dtype()); + inv_freq_pos._shape._tags = shape._tags; + const cos = inv_freq_pos.cos(); + const sin = inv_freq_pos.sin(); + return .{ cos, sin }; +} + +pub fn splitRealImg(x: Tensor, impl: RopeOpts.Implementation) [2]Tensor { + const n = x.dim(-1); + + return switch (impl) { + .sequential => .{ + x.slice1d(-1, .{ .end = @divExact(n, 2) }), + x.slice1d(-1, .{ .start = @divExact(n, 2), .end = n }), + }, + .interleaved => .{ + x.slice1d(-1, .{ .start = 0, .step = 2 }), + x.slice1d(-1, .{ .start = 1, .step = 2 }), + }, + }; +} + +pub fn mergeRealImg(x_real: Tensor, x_imag: Tensor, impl: RopeOpts.Implementation) Tensor { + return switch (impl) { + .sequential => Tensor.concatenate(&.{ x_real, x_imag }, -1), + .interleaved => Tensor.concatenate(&.{ + x_real.appendAxes(.{.interleaved_real_img}), + x_imag.appendAxes(.{.interleaved_real_img}), + }, -1).flatten(-2), + }; +} + +/// {exp( - n * ln(10_000) / N ) | n in [0..N] } +pub fn invFreq(N: i64, theta: f32, dtype: DataType) Tensor { + const freq = -@log(theta) / @as(f32, @floatFromInt(N)); + const range = Tensor.arange(.{ .start = 0, .end = N, .step = 2 }, dtype).scale(freq); + return range.exp(); +} + +test "real/img" { + const platform = zml.testing.env(); + + const Fns = struct { + // fn testSplitMergeIsId(impl: RopeOpts.Implementation) Tensor { + // const x = Tensor.arange(.{ .end = 20 }, .f32).reshape(.{ 5, 4 }); + // const real, const imag = splitRealImg(x, impl); + // const y = mergeRealImg(real, imag, impl); + // return y.cmp(.EQ, x).flatten(0).convert(.i32).sum(-1); + // } + + fn testSplitMergeIsId(impl: RopeOpts.Implementation) Tensor { + const x = Tensor.arange(.{ .end = 20 }, .f32).reshape(.{ 5, 4 }); + const real, const imag = splitRealImg(x, impl); + const y = mergeRealImg(real, imag, impl); + const real2, const imag2 = splitRealImg(y, impl); + return real.cmp(.EQ, real2).flatten(0).convert(.i32).sum(-1).add( + imag.cmp(.EQ, imag2).flatten(0).convert(.i32).sum(-1), + ); + } + + fn testSplitSeqVoid(_: void) Tensor { + const x = Tensor.arange(.{ .end = 20 }, .f32).reshape(.{ 5, 4 }); + const real, const imag = splitRealImg(x, .sequential); + const x_real = Tensor.concatenate(&.{ + Tensor.arange(.{ .start = 0, .end = 20, .step = 4 }, .f32).reshape(.{ 5, 1 }), + Tensor.arange(.{ .start = 1, .end = 20, .step = 4 }, .f32).reshape(.{ 5, 1 }), + }, 1); + const x_imag = Tensor.concatenate(&.{ + Tensor.arange(.{ .start = 2, .end = 20, .step = 4 }, .f32).reshape(.{ 5, 1 }), + Tensor.arange(.{ .start = 3, .end = 20, .step = 4 }, .f32).reshape(.{ 5, 1 }), + }, 1); + + return real.cmp(.EQ, x_real).flatten(0).convert(.i32).sum(-1).add( + imag.cmp(.EQ, x_imag).flatten(0).convert(.i32).sum(-1), + ); + } + + fn testSplitSeq() Tensor { + const x = Tensor.arange(.{ .end = 20 }, .f32).reshape(.{ 5, 4 }); + const real, const imag = splitRealImg(x, .sequential); + const x_real = Tensor.concatenate(&.{ + Tensor.arange(.{ .start = 0, .end = 20, .step = 4 }, .f32).reshape(.{ 5, 1 }), + Tensor.arange(.{ .start = 1, .end = 20, .step = 4 }, .f32).reshape(.{ 5, 1 }), + }, 1); + const x_imag = Tensor.concatenate(&.{ + Tensor.arange(.{ .start = 2, .end = 20, .step = 4 }, .f32).reshape(.{ 5, 1 }), + Tensor.arange(.{ .start = 3, .end = 20, .step = 4 }, .f32).reshape(.{ 5, 1 }), + }, 1); + + return real.cmp(.EQ, x_real).flatten(0).convert(.i32).sum(-1).add( + imag.cmp(.EQ, x_imag).flatten(0).convert(.i32).sum(-1), + ); + } + + fn testSplitInterleaved() Tensor { + const x = Tensor.arange(.{ .end = 20 }, .f32).reshape(.{ 5, 4 }); + const real, const imag = splitRealImg(x, .interleaved); + const x_real = Tensor.arange(.{ .start = 0, .end = 20, .step = 2 }, .f32).reshape(.{ 5, 2 }); + const x_imag = Tensor.arange(.{ .start = 1, .end = 20, .step = 2 }, .f32).reshape(.{ 5, 2 }); + + return real.cmp(.EQ, x_real).flatten(0).convert(.i32).sum(-1).add( + imag.cmp(.EQ, x_imag).flatten(0).convert(.i32).sum(-1), + ); + } + }; + + const d_interleaved = try zml.testing.compileAndCall(platform, Fns.testSplitMergeIsId, .{.interleaved}); + try testing.expectEqual(20, d_interleaved.getValue(i32)); + + const d_sequential = try zml.testing.compileAndCall(platform, Fns.testSplitMergeIsId, .{.sequential}); + try testing.expectEqual(20, d_sequential.getValue(i32)); + + // test the function that accepts 1 void argument + const d_split_seq_void = try zml.testing.compileAndCall(platform, Fns.testSplitSeqVoid, .{{}}); + try testing.expectEqual(20, d_split_seq_void.getValue(i32)); + + // test the function that takes NO arguments + const d_split_seq = try zml.testing.compileAndCall(platform, Fns.testSplitSeq, .{}); + try testing.expectEqual(20, d_split_seq.getValue(i32)); + + // now try compiling and calling ourselves + { + const mod = try zml.compileFn(std.testing.allocator, Fns.testSplitSeq, .{}, platform); + defer mod.deinit(); + const ret = mod.call(.{}); + try testing.expectEqual(20, ret.getValue(i32)); + } + const d_split_interleaved = try zml.testing.compileAndCall(platform, Fns.testSplitInterleaved, .{}); + try testing.expectEqual(20, d_split_interleaved.getValue(i32)); +} + +test "rope" { + const platofrm = zml.testing.env(); + + const TestRope = struct { + fn forward(x: Tensor, opts: RopeOpts) Tensor { + var input = x; + { + // Convert input to the requested format + const real, const imag = splitRealImg(input, .sequential); + input = mergeRealImg(real, imag, opts.impl); + } + const cos_sin = ropeCosSin(.{ input.dim(-2), input.dim(-1) }, input.dtype(), opts); + var res = rope(input, cos_sin, opts).squeeze(0); + + { + // Convert back to sequential + const real, const imag = splitRealImg(res, opts.impl); + res = mergeRealImg(real, imag, .sequential); + } + return res; + } + }; + + // x is made such as the interleaved and sequential reps are the same. + // So the two implementations should give the same results. + const x = try zml.Buffer.fromSlice(platofrm, .{ 1, 5, 4 }, &[_]f32{ 1.0, 0.1, -1.0, -0.5 } ** 5); + const res1 = try zml.testing.compileAndCall(platofrm, TestRope.forward, .{ x, RopeOpts{ .impl = .interleaved } }); + const res2 = try zml.testing.compileAndCall(platofrm, TestRope.forward, .{ x, RopeOpts{ .impl = .sequential } }); + + try zml.testing.expectClose(res1, res2, 1e-4); +} + +/// In neural network we generally care about the relative precision, +/// but on a given dimension, if the output is close to 0, then the precision +/// don't matter as much. +fn approxEq(comptime Float: type, l: Float, r: Float, tolerance: Float) bool { + const closeRel = std.math.approxEqRel(Float, l, r, @floatCast(tolerance)); + const closeAbs = std.math.approxEqAbs(Float, l, r, @floatCast(tolerance / 2)); + return closeRel or closeAbs; +} + +pub const UpsampleMode = enum { + nearest, + // TODO: Linear, + // TODO: Bilinear, + // TODO: Bicubic, + // TODO: Trilinear, +}; + +/// Upsample +pub fn upsample( + input: Tensor, + opts: struct { mode: UpsampleMode, scale_factor: []const f64 }, +) Tensor { + // TODO(james): make `nearest` compatible with resizeBilinear and resizeBicubic, and wrap them here. + // resize* have API which are more explicit, this assume you want to scale the N-2 last axes. + meta.assert(3 <= input.rank() and input.rank() <= 5, "upsample is only implemented for (3,4,5)-D tensors, received {}", .{input}); + meta.assert(opts.scale_factor.len == 1 or opts.scale_factor.len == input.rank() - 2, "scale factors", .{}); + return switch (opts.mode) { + .nearest => { + var scale_factors: [3]f64 = undefined; + switch (opts.scale_factor.len) { + 1 => { + for (0..input.rank() - 2) |i| scale_factors[i] = opts.scale_factor[0]; + }, + else => @memcpy(scale_factors[0..opts.scale_factor.len], opts.scale_factor), + } + return nearest(input, scale_factors[0 .. input.rank() - 2]); + }, + }; +} + +pub fn nearest(input: Tensor, scale_factor: []const f64) Tensor { + var out_shape = input.shape(); + for (scale_factor, 0..) |sf, i| { + out_shape._dims.set(i + 2, @intFromFloat(@floor(@as(f64, @floatFromInt(out_shape.dim(i + 2))) * sf))); + } + // TODO(james): remove this implicit two batching dims + var sd: [3]usize = undefined; + var len_sd: usize = 0; + for (2..input.rank()) |i| { + if (input.dim(i) != out_shape.dim(i)) { + sd[len_sd] = i; + len_sd += 1; + } + } + const spatial_dims = sd[0..len_sd]; + var res = input; + for (spatial_dims) |d| { + const n = out_shape.dim(d); + const ratio = meta.divFloat(f32, input.dim(d), n); + const offsets = Tensor.arange(.{ .end = n }, .f32).addConstant(0.5).scale(ratio).floor().convert(.i32); + res = res.gather1d(d, offsets, .{ .indices_are_sorted = true }); + } + return res; +} + +test nearest { + const platform = zml.testing.env(); + + // 3D Tensor (basic) + { + const input_3d_basic = try zml.Buffer.fromArray(platform, [1][1][2]i32{.{.{ 1, 2 }}}); + const result = try zml.testing.compileAndCall(platform, upsample, .{ input_3d_basic, .{ .scale_factor = &.{3}, .mode = .nearest } }); + try std.testing.expectEqualSlices(i64, &.{ 1, 1, 6 }, result.dims()); + const expected: [1][1][6]i32 = .{.{.{ 1, 1, 1, 2, 2, 2 }}}; + try zml.testing.expectClose(zml.HostBuffer.fromArray(&expected), result, 0); + } + // 3D Tensor (advanced) + { + const input_3d_advanced = try zml.Buffer.fromArray(platform, [2][3][4]i32{ + .{ .{ 1, 2, 3, 4 }, .{ 5, 6, 7, 8 }, .{ 9, 10, 11, 12 } }, + .{ .{ 13, 14, 15, 16 }, .{ 17, 18, 19, 20 }, .{ 21, 22, 23, 24 } }, + }); + const result = try zml.testing.compileAndCall(platform, upsample, .{ input_3d_advanced, .{ .scale_factor = &.{2}, .mode = .nearest } }); + try std.testing.expectEqualSlices(i64, &.{ 2, 3, 8 }, result.dims()); + const expected: [2][3][8]i32 = .{ + .{ + .{ 1, 1, 2, 2, 3, 3, 4, 4 }, + .{ 5, 5, 6, 6, 7, 7, 8, 8 }, + .{ 9, 9, 10, 10, 11, 11, 12, 12 }, + }, + .{ + .{ 13, 13, 14, 14, 15, 15, 16, 16 }, + .{ 17, 17, 18, 18, 19, 19, 20, 20 }, + .{ 21, 21, 22, 22, 23, 23, 24, 24 }, + }, + }; + try zml.testing.expectClose(zml.HostBuffer.fromArray(&expected), result, 0); + } + // 4D Tensor (basic) + { + const input_4d_basic = try zml.Buffer.fromSlice(platform, .{ 1, 1, 2, 2 }, &[_]i32{ 1, 2, 3, 4 }); + const result = try zml.testing.compileAndCall(platform, upsample, .{ input_4d_basic, .{ .scale_factor = &.{ 3, 3 }, .mode = .nearest } }); + try std.testing.expectEqualSlices(i64, &.{ 1, 1, 6, 6 }, result.dims()); + const expected: [1][1][6][6]i32 = .{.{.{ + .{ 1, 1, 1, 2, 2, 2 }, + .{ 1, 1, 1, 2, 2, 2 }, + .{ 1, 1, 1, 2, 2, 2 }, + .{ 3, 3, 3, 4, 4, 4 }, + .{ 3, 3, 3, 4, 4, 4 }, + .{ 3, 3, 3, 4, 4, 4 }, + }}}; + try std.testing.expectEqual(expected, result.getValue([1][1][6][6]i32)); + } + // 4D Tensor (advanced) + { + const input_4d_advanced = try zml.Buffer.fromArray(platform, [2][2][2][2]i32{ .{ + .{ .{ 1, 2 }, .{ 3, 4 } }, + .{ .{ 5, 6 }, .{ 7, 8 } }, + }, .{ + .{ .{ 9, 10 }, .{ 11, 12 } }, + .{ .{ 13, 14 }, .{ 15, 16 } }, + } }); + const result = try zml.testing.compileAndCall(platform, upsample, .{ input_4d_advanced, .{ .scale_factor = &.{ 2, 2 }, .mode = .nearest } }); + try std.testing.expectEqualSlices(i64, &.{ 2, 2, 4, 4 }, result.dims()); + const expected: [2][2][4][4]i32 = .{ + .{ + .{ + .{ 1, 1, 2, 2 }, + .{ 1, 1, 2, 2 }, + .{ 3, 3, 4, 4 }, + .{ 3, 3, 4, 4 }, + }, + .{ + .{ 5, 5, 6, 6 }, + .{ 5, 5, 6, 6 }, + .{ 7, 7, 8, 8 }, + .{ 7, 7, 8, 8 }, + }, + }, + .{ + .{ + .{ 9, 9, 10, 10 }, + .{ 9, 9, 10, 10 }, + .{ 11, 11, 12, 12 }, + .{ 11, 11, 12, 12 }, + }, + .{ + .{ 13, 13, 14, 14 }, + .{ 13, 13, 14, 14 }, + .{ 15, 15, 16, 16 }, + .{ 15, 15, 16, 16 }, + }, + }, + }; + try zml.testing.expectClose(zml.HostBuffer.fromArray(&expected), result, 0); + } + // 5D Tensor (basic) + { + const input_5d = try zml.Buffer.fromSlice(platform, .{ 1, 1, 1, 2, 2 }, &[_]i32{ 1, 2, 3, 4 }); + const result = try zml.testing.compileAndCall(platform, upsample, .{ input_5d, .{ .scale_factor = &.{2}, .mode = .nearest } }); + try std.testing.expectEqualSlices(i64, &.{ 1, 1, 2, 4, 4 }, result.dims()); + const expected: [1][1][2][4][4]i32 = .{ + .{ + .{ + .{ + .{ 1, 1, 2, 2 }, + .{ 1, 1, 2, 2 }, + .{ 3, 3, 4, 4 }, + .{ 3, 3, 4, 4 }, + }, + .{ + .{ 1, 1, 2, 2 }, + .{ 1, 1, 2, 2 }, + .{ 3, 3, 4, 4 }, + .{ 3, 3, 4, 4 }, + }, + }, + }, + }; + try zml.testing.expectClose(zml.HostBuffer.fromArray(&expected), result, 0); + } +} + +pub const ResizeOpts = struct { original_len: ?Tensor = null }; + +pub fn resizeBilinear(image: Tensor, axes: []const i8, dims: []const u63, opt: ResizeOpts) Tensor { + var out = image; + for (axes, dims) |a, d| { + const child_opt: ResizeOpts = .{ + .original_len = if (opt.original_len) |o| o.choose1d(0, a) else null, + }; + out = resizeLinear1d(out, a, d, child_opt); + } + return out; +} + +pub fn resizeLinear1d(image: Tensor, axis: i8, new_len: u63, opt: ResizeOpts) Tensor { + const og_len = opt.original_len orelse Tensor.scalar(image.dim(axis), .f32); + const ratio = og_len.convert(.f32).scale(meta.divFloat(f32, 1, new_len)); + const scaled = Tensor.arange(.{ .end = new_len }, .f32).mul(ratio); + const left = scaled.floor(); + const right = left.addConstant(1); + + const values = image.gatherSlices1d(axis, 2, left.convert(.i32), .{ .indices_are_sorted = true }); + const left_val, const right_val = helpers.mapTensors( + Tensor.squeeze, + values.convert(.f32).chunkExact(2, axis + 1), + .{@as(i64, @intCast(axis + 1))}, + ); + const left_weight = right.sub(scaled).broadcast(left_val.shape(), &.{axis}); + const right_weight = scaled.sub(left).broadcast(left_val.shape(), &.{axis}); + + return left_val.mul(left_weight).add(right_val.mul(right_weight)).convert(image.dtype()); +} + +/// Bicubic interpolation of the given image. +/// Warning as of May 2024 the cpu backend don't optimize this very well +/// and is not able to merge the weighting with the gather, +/// leading to 20x slow down compared to STB implementation. +pub fn resizeBicubic(image: Tensor, axes: []const i8, dims: []const u63, opt: ResizeOpts) Tensor { + var out = image; + for (axes, dims) |a, d| { + const child_opt: ResizeOpts = .{ + .original_len = if (opt.original_len) |o| o.choose1d(0, a) else null, + }; + out = resizeCubic1d(out, a, d, child_opt); + } + return out; +} + +pub fn resizeCubic1d(image: Tensor, axis: i8, new_len: u63, opt: ResizeOpts) Tensor { + // Extract neighboring pixels from the image. + const og_len = opt.original_len orelse Tensor.scalar(image.dim(axis), .f32); + const ratio = og_len.convert(.f32).scale(meta.divFloat(f32, 1, new_len)); + const scaled = Tensor.arange(.{ .end = new_len }, .f32).mul(ratio); + const t = scaled.sub(scaled.floor()); + const pos = Tensor.stack(&.{ + Tensor.scalar(1, .f32).broadcast(t.shape(), &.{}), + t, + t.mul(t), + t.pow(Tensor.scalar(3, .f32)), + }, -1, .features); + std.debug.assert(pos.dim(0) == new_len); + std.debug.assert(pos.dim(1) == 4); + + const context = scaled.floor().addConstant(-1).convert(.i32).maximum(Tensor.scalar(0, .i32)); + const values = image.gatherSlices1d(axis, 4, context, .{ .indices_are_sorted = true }); + + const weights_: [4][4]f32 = .{ + .{ 0, 1, 0, 0 }, + .{ -0.5, 0, 0.5, 0 }, + .{ 1, -2.5, 2, -0.5 }, + .{ -0.5, 1.5, -1.5, 0.5 }, + }; + const weights = zml.Tensor.constantTensor(zml.HostBuffer.fromArray(&weights_)); + + // actually do the interpolation. + // Note: ideally this matmul should be inlined with the gather, but that's currently not the case. + var res = values.convert(.f32).dotGeneral(weights, &.{.{ axis + 1, 1 }}, &.{}); + res = pos.dotGeneral(res, &.{.{ 1, image.rank() }}, &.{.{ 0, axis }}); + + // the current axis is outputted in first position because it's a batching dim, put it back in place. + // if (axis != 0) + // res = res.transpose(Shape.range(image.rank()).swap(0, axis).dims()); + + // verify the shape + const res_shape = image.shape().set(axis, new_len); + // log.debug("resizeCubic1d: ({}, {}, {}, {}) -> {}", .{ image, axis, new_len, opt, res }); + std.debug.assert(std.mem.eql(i64, res_shape.dims(), res.dims())); + return res.convert(image.dtype()); +} + +/// Return causal attention masks for the given shape. +/// The last dimensions are +pub fn causalAttnMask( + attn_shape_: anytype, + dtype: DataType, + attn_window_len: ?u32, +) Tensor { + const attn_shape = Shape.init(attn_shape_, dtype); + meta.assert(attn_shape.rank() == 2, "causalAttnMask({}) shape need to be exactly 2 axes", .{attn_shape}); + const qlen = attn_shape.dim(-2); + const q_idx = Tensor.iota(attn_shape, .i32, -2); + const klen = attn_shape.dim(-1); + const k_idx = Tensor.iota(attn_shape, .i32, -1); + + // all elements > main diagonal must be 0 + // (q_idx - window_len < k_idx <= q_idx) + var mask = k_idx.cmp(.LE, q_idx); + if (attn_window_len) |window_len| { + if (qlen >= window_len or klen >= window_len) { + const window_mask = q_idx.cmp(.LT, k_idx.addConstant(window_len)); + mask = mask.logical(.AND, window_mask); + } + } + mask = mask.convert(dtype); + if (dtype.isFloat()) { + // use log to convert "true" (ie 1) to 0, and "false" (ie 0) to -inf + meta.guard(dtype.isFloat(), @src()); // -inf only exists for floats + mask = mask.log(); + } + return mask; +} + +pub const SdpaOpts = struct { + attn_mask: ?Tensor = null, + scale: ?Tensor = null, + bias: ?Tensor = null, + allow_cudnn: bool = true, + // TODO: put a callback instead of all this field, + // so that +}; + +/// Scaled dot product attention. +/// +/// **Shapes**: +/// - q, result: .{ .h, .q, .hd } +/// - k, v: .{ .h, .k, .hd } +/// +/// Where: +/// - .h is the number of head +/// - .q is the number of queries +/// - .k is the number of keys +/// - .hd is the head dimension +/// +/// .h is allowed to differ from queries and keys as long as the key heads +/// can be repeated to match query heads. +pub fn sdpa(q_: Tensor, k_: Tensor, v_: Tensor, opts: SdpaOpts) Tensor { + var q, var k, var v = .{ q_, k_, v_ }; + + const err_template = "sdpa(q: {}, k: {}, v: {}, attn: {?}) is invalid ! "; + const err_args = .{ q, k, v, opts.attn_mask }; + meta.assert(q.shape().hasTags(.{ .h, .q, .hd }), err_template ++ "q is missing tags {{.h, .q, .hd}}", err_args); + meta.assert(k.shape().hasTags(.{ .h, .k, .hd }), err_template ++ "k is missing tags {{.h, .k, .hd}}", err_args); + meta.assert(v.shape().hasTags(.{ .h, .k, .hd }), err_template ++ "v is missing tags {{.h, .k, .hd}}", err_args); + + if (opts.allow_cudnn and cuda.canUseCudnnSdpa(q.dim(.hd), q.dtype())) { + return cuda.sdpa(q, k, v, opts); + } + + if (q.dim(.h) != k.dim(.h)) { + meta.assert(@mod(q.dim(.h), k.dim(.h)) == 0, err_template ++ "Different number of heads for keys and queries, but can't repeat keys.", err_args); + // Note: we don't try to repeat queries. + // Repeating keys is the interesting optimisation cause it reduces KV cache memory usage. + const num_rep: u63 = @intCast(@divExact(q.dim(.h), k.dim(.h))); + k, v = .{ k.repeat1d(.h, num_rep), v.repeat1d(.h, num_rep) }; + } + const attn_mask = if (opts.attn_mask) |m| m else null; + + const dims = helpers.collectDims(.{ .h, .q, .k, .hd }, &.{ q, k, v, attn_mask }, .strict) catch { + meta.panic(err_template ++ "Inputs have incompatible shapes.", err_args); + }; + const sqrtHeadDim: f16 = 1.0 / std.math.sqrt(@as(f16, @floatFromInt(dims.hd))); + const scale_logit = if (opts.scale) |s| s else Tensor.scalar(sqrtHeadDim, .f16); + k = k.mul(scale_logit.convert(k.dtype())); + + var attn_weights = q.dot(k, .{.hd}); + // log.debug("attn_weights : {}", .{attn_weights}); + // log.debug("attn_mask : {?}", .{attn_mask}); + if (attn_mask) |mask| attn_weights = attn_weights.add(mask.broadcastLeft(attn_weights.shape())); + + attn_weights = attn_weights.convert(.f32); + if (opts.bias) |bias| { + attn_weights = attn_weights.add(bias); + } + attn_weights = attn_weights.softmax(.k).convert(q.dtype()); + + var attn = attn_weights.dot(v, .{.k}); + return attn.transpose(q.shape()); +} + +pub const MemEfficientOps = struct { + scale: ?f32 = null, + query_chunk_size: u32, + key_chunk_size: u32, + opts: SdpaOpts = .{}, +}; + +pub fn sdpaMemEfficient(q_: Tensor, k_: Tensor, v_: Tensor, opts: MemEfficientOps) Tensor { + const q = q_.withTags(.{ .b, .hq, .sq, .hd }); + const k = k_.withTags(.{ .b, .hk, .sk, .hd }); + const v = v_.withTags(.{ .b, .hk, .sk, .hd }); + var sdpa_opts = opts.opts; + if (sdpa_opts.attn_mask) |*attn_mask| attn_mask.* = attn_mask.withTags(.{ .sq, .sk }); + + const sdpa_mem_efficient: SdpaMemEfficient = .{ .q = q, .k = k, .v = v, .opt = .{ + .query_chunk_size = @intCast(@min(q.dim(.sq), opts.query_chunk_size)), + .key_chunk_size = @intCast(@min(k.dim(.sk), opts.key_chunk_size)), + .scale = opts.scale, + .opts = sdpa_opts, + } }; + + // TODO(Corentin): Maybe `withTags` could take a Shape to copy from. + var result = sdpa_mem_efficient.forward(); + result._shape = q_.shape(); + return result; +} + +const SdpaMemEfficient = struct { + q: Tensor, + k: Tensor, + v: Tensor, + opt: MemEfficientOps, + + fn forward(self: SdpaMemEfficient) Tensor { + const n_q_chunks = @divExact(self.q.dim(.sq), self.opt.query_chunk_size); + const res = ops.for_(SdpaMemEfficient.nextQueriesChunk, self, .{ .nq = n_q_chunks }); + // TODO: should "for_" operate on an axis ? + // res: (nq, b, nh, qlen / nq, dim) -> (b, nh, qlen, dim) + return res.transpose(.{ 1, 2, 0, 3, 4 }).flatten(2); + // return res.transpose(.{ .b, .hq, .nq, .sq, .hd }).merge(.{ .nq, .sq }, .sq); + } + + fn nextQueriesChunk(self: SdpaMemEfficient, idx: Tensor) Tensor { + const offset = idx.scale(self.opt.query_chunk_size); + const q_chunk = self.q.dynamicSlice(.{ .sq = .{ .start = offset, .len = self.opt.query_chunk_size } }); + const attn_chunk = if (self.opt.opts.attn_mask) |attn_mask| attn_mask.dynamicSlice1d(0, self.opt.query_chunk_size, offset) else null; + + var chunk: SdpaMemEfficient = self; + chunk.q = q_chunk; + chunk.opt.opts.attn_mask = attn_chunk; + return chunk.scanKeyVal(); + } + + fn scanKeyVal(self: SdpaMemEfficient) Tensor { + const n_chunks = @divExact(self.k.dim(.sk), self.opt.key_chunk_size); + const res = ops.for_(SdpaMemEfficient.nextKeyValChunk, self, .{ .k_chunk = n_chunks }); + const global_max = res.max_value.max(.k_chunk).broad(res.max_value.shape()); + const max_diffs = res.max_value.sub(global_max).exp(); + const attn = res.attn.mul(max_diffs.broad(res.attn.shape())).sum(.k_chunk).squeeze(.k_chunk); + const exp_sum = res.exp_sum.mul(max_diffs.convert(.f32)).sum(.k_chunk).squeeze(.k_chunk).convert(attn.dtype()); + return attn.div(exp_sum.broad(self.q.shape())); + } + + fn nextKeyValChunk(self: SdpaMemEfficient, idx: Tensor) PartialAttn { + const offset = idx.scale(self.opt.key_chunk_size); + const k_chunk = self.k.dynamicSlice(.{ .sk = .{ .start = offset, .len = self.opt.key_chunk_size } }); + const v_chunk = self.v.dynamicSlice(.{ .sk = .{ .start = offset, .len = self.opt.key_chunk_size } }); + const attn_chunk = if (self.opt.opts.attn_mask) |mask| mask.dynamicSlice1d(1, self.opt.key_chunk_size, offset) else null; + + return sdpaChunk(self.q, k_chunk, v_chunk, .{ .attn_mask = attn_chunk }); + } +}; + +pub const PartialAttn = struct { + attn: Tensor, + exp_sum: Tensor, + max_value: Tensor, +}; + +/// Compute softmax over a chunk. +/// Returns intermediary results to allow aggregating later. +pub fn partialSoftmax(self: Tensor, axis: anytype) PartialAttn { + const a = self.axis(axis); + const max_val = self.max(a); + const out = self.sub(max_val.broad(self.shape())).exp(); + return .{ + .attn = out, + .exp_sum = out.convert(.f32).sum(a).squeeze(a), + .max_value = max_val.squeeze(a), + }; +} + +/// Compute sdpa on a chunk, and computes a partial softmax. +/// q: (B, H, Sq, H_dim) ⊙ k: (B, H, Sk, H_dim) -> qk: (B, H, Sq, Sk) +fn sdpaChunk(q: Tensor, k: Tensor, v: Tensor, opts: SdpaOpts) PartialAttn { + // const bs, const num_head, const sk, const h_dim = q.dims[0..4]; + // TODO: rewrite using modern ZML + + // If we have more query heads (hq) than key heads (hk), repeat keys. + const k_rep, const v_rep = if (q.dim(.hq) != k.dim(.hk)) blk: { + const num_rep: u63 = @intCast(@divExact(q.dim(.hq), k.dim(.hk))); + break :blk .{ k.repeat1d(0, num_rep).rename(.{ .hk = .hq }), v.repeat1d(0, num_rep).rename(.{ .hk = .hq }) }; + } else .{ k.rename(.{ .hk = .hq }), v.rename(.{ .hk = .hq }) }; + + var qk = q.dot(k_rep, .{.hd}); + + const sqrtHeadDim: f32 = 1.0 / std.math.sqrt(@as(f32, @floatFromInt(q.dim(.hd)))); + qk = qk.scale(sqrtHeadDim); + + std.debug.assert(qk.rank() == q.rank()); + if (opts.attn_mask) |mask| { + qk = qk.add(mask.broad(qk.shape())); + } + + const partial = partialSoftmax(qk, -1); + const attn = partial.attn.dot(v_rep, .{.sk}); + + return .{ + .attn = attn, + .exp_sum = partial.exp_sum, + .max_value = partial.max_value, + }; +} +test "sdpaMemEfficient without mask" { + if (true) return error.SkipZigTest; + + const platform = zml.testing.env(); + const allocator = std.testing.allocator; + + // Note we use small input vectors to have the tests run reasonably fast, + // but don't expect speed ups with this small sizes. + const rng = try zml.compileFn(allocator, Tensor.Rng.normal, .{ Shape.init(.{ 1, 10, 512, 64 }, .f16), .{ .mean = 0, .stddev = 1 } }, platform); + defer rng.deinit(); + + // Note: it's fine to pass undefined here, cause the arguments have already been baked into the executable. + const q = rng.call(undefined); + const k = rng.call(undefined); + const v = rng.call(undefined); + + const ref_res = try zml.testing.compileAndCallWithTensors(platform, sdpa, .{ + q.shape().withTags(.{ .b, .h, .q, .hd }), + k.shape().withTags(.{ .b, .h, .k, .hd }), + v.shape().withTags(.{ .b, .h, .k, .hd }), + .{ .attn_mask = null, .scale = null, .bias = null }, + }, .{ q, k, v, undefined }); + try std.testing.expectEqualSlices(i64, q.shape().dims(), ref_res.shape().dims()); + + const opts: zml.ShapeOf(MemEfficientOps) = .{ .query_chunk_size = 256, .key_chunk_size = 128, .opts = .{ .attn_mask = null, .scale = null, .bias = null } }; + const res = try zml.testing.compileAndCallWithTensors( + platform, + sdpaMemEfficient, + .{ q.shape(), k.shape(), v.shape(), opts }, + .{ q, k, v, undefined }, + ); + + try zml.testing.expectClose(ref_res, res, 2e-3); +} + +test "sdpaMemEfficient with mask" { + if (true) return error.SkipZigTest; + + const platform = zml.testing.env(); + const allocator = std.testing.allocator; + + // Note we use small input vectors to have the tests run reasonably fast, + // but don't expect speed ups with this small sizes. + const rng = try zml.compileFn(allocator, Tensor.Rng.normal, .{ Shape.init(.{ 1, 10, 512, 64 }, .f16), .{ .mean = 0, .stddev = 1 } }, platform); + defer rng.deinit(); + + const rng_mask = try zml.compileFn(allocator, Tensor.Rng.normal, .{ Shape.init(.{ 512, 512 }, .f16), .{ .mean = 0, .stddev = 1 } }, platform); + defer rng_mask.deinit(); + + // Note: it's fine to pass undefined here, cause the arguments have already been backed into the executable. + const q = rng.call(undefined); + const k = rng.call(undefined); + const v = rng.call(undefined); + const mask = rng_mask.call(undefined); + + const ref_res = try zml.testing.compileAndCall(platform, sdpa, .{ q.withTags(.{ .b, .h, .q, .hd }), k.withTags(.{ .b, .h, .k, .hd }), v.withTags(.{ .b, .h, .k, .hd }), .{ .attn_mask = mask.withTags(.{ .q, .k }), .scale = null, .bias = null } }); + try std.testing.expectEqualSlices(i64, q.shape().dims(), ref_res.shape().dims()); + + const res = try zml.testing.compileAndCall(platform, sdpaMemEfficient, .{ q, k, v, .{ + .query_chunk_size = 256, + .key_chunk_size = 128, + .scale = null, + .opts = .{ .attn_mask = mask, .scale = null, .bias = null, .allow_cudnn = false }, + } }); + + try zml.testing.expectClose(ref_res, res, 2e-3); +} + +/// Options controlling generation. The default values correspond to greedy decoding. +pub const SamplingStrategy = struct { + topk: u32 = 1, + temperature: f32 = 1.0, +}; + +/// Given the output of the last layer of a LM with a `.voc` axis, +/// Compute indices for the next tokens, following the given sampling strategy. +/// Returns an integer tensor with a shape similar to the input, but without the .voc axis. +pub fn sampleTokens(activations: Tensor, opts: SamplingStrategy, rng: Tensor.Rng) struct { Tensor, Tensor.Rng } { + if (opts.topk <= 1) { + const next_tokens = activations.argMax(.voc, .i32).indices.squeeze(.voc); + return .{ next_tokens, rng }; + } + + const topk = activations.topK(opts.topk, .voc, .{}); + // After the topk, we don't have .voc values, anymore, only topk. + var x = topk.values.rename(.{ .voc = .topk }); + if (opts.temperature != 1.0) { + x = x.scale(1 / opts.temperature); + } + + // Gumbel reparametrization trick: + // Adding gumbel noise and taking the argmax is equivalent + // to sampling from the categorical distribution produced by the softmax. + // https://en.wikipedia.org/wiki/Gumbel_distribution#Gumbel_reparametrization_tricks + const next_rng, const gumbel_noise = rng.gumbel(x.shape()); + x = x.add(gumbel_noise); + const topk_idx = x.argMax(.topk, .i32).indices; + + // topk_idx is indices into topk.values ! so in the range [0, topk] + // Convert for the original indices from the full [0, voc] range. + const next_tokens = topk.indices.gather1d(.voc, topk_idx.squeeze(.topk), .{}).squeeze(.voc); + // log.debug("sampleTokens({}) -> {} -> {} -> {}", .{ activations, topk.indices, topk_idx, next_tokens }); + return .{ next_tokens, next_rng }; +} + +test { + _ = cuda; +} diff --git a/zml/nn/cuda.zig b/zml/nn/cuda.zig new file mode 100644 index 0000000..0bffc5f --- /dev/null +++ b/zml/nn/cuda.zig @@ -0,0 +1,143 @@ +const std = @import("std"); + +const Context = @import("../context.zig").Context; +const module = @import("../module.zig"); +const mlir = @import("../mlir.zig"); +const dialect = @import("mlir/dialects"); + +const Tensor = @import("../tensor.zig").Tensor; +const Shape = @import("../shape.zig").Shape; +const SdpaOpts = @import("../nn.zig").SdpaOpts; +const DataType = @import("../dtype.zig").DataType; +const Data = @import("../dtype.zig").Data; +const CompilationContext = module.CompilationContext; + +pub fn canUseCudnnSdpa(head_dim: i64, dtype: DataType) bool { + const ctx = CompilationContext.current(); + // TODO(Corendos): Check cuda version, cudnn version, device compatibility. + if (!ctx.targetIs(.cuda)) return false; + + // NOTE(Corentin): In Cudnn fused MHA head_dim is limited to 128. + if (head_dim > 128) return false; + + // NOTE(Corentin): In Cudnn fused MHA data type is limited to F16 and BF16. + if (dtype != .f16 and dtype != .bf16) return false; + + return true; +} + +fn elementTypeFromDataType(dtype: DataType) [:0]const u8 { + return switch (dtype) { + .f16 => "F16", + .bf16 => "BF16", + else => @panic("Unsupported DataType"), + }; +} + +pub fn sdpa(q_: Tensor, k_: Tensor, v_: Tensor, opts: SdpaOpts) Tensor { + const ctx = CompilationContext.current(); + const q = q_.transpose(.{ .b, .h, .q, .hd }); + var k = k_.transpose(.{ .b, .h, .k, .hd }); + const v = v_.transpose(.{ .b, .h, .k, .hd }); + + const sqrtHeadDim: f32 = 1.0 / std.math.sqrt(@as(f32, @floatFromInt(q.dim(.hd)))); + const scale: f32 = if (opts.scale) |_| 1.0 else sqrtHeadDim; + + if (opts.scale) |s| k = k.mul(s); + + var buffer: [4096]u8 = undefined; + var fba = std.heap.FixedBufferAllocator.init(&buffer); + const allocator = fba.allocator(); + + const backend_config = + std.fmt.allocPrintZ( + allocator, + \\{{ + \\ "operation_queue_id":"0", + \\ "wait_on_operation_queues":[], + \\ "cudnn_fmha_backend_config": {{ + \\ "algorithm": {{ + \\ "algo_id": "0", + \\ "math_type": "TENSOR_OP_MATH", + \\ "tuning_knobs": {{"17": "1", "24": "0"}}, + \\ "is_cudnn_frontend": true, + \\ "workspace_size": "0", + \\ }}, + \\ "fmha_scale": {d}, + \\ "dropout_rate": 0, + \\ "intermediate_tensor_shape": {{ + \\ "element_type": "{s}", + \\ "dimensions": ["{}", "{}", "{}", "{}"], + \\ "tuple_shapes": [], + \\ "layout": {{ + \\ "dim_level_types": [], + \\ "dim_unique": [], + \\ "dim_ordered": [], + \\ "minor_to_major": ["3", "2", "1", "0"], + \\ "tiles": [], + \\ "element_size_in_bits": "0", + \\ "memory_space": "0", + \\ "index_primitive_type": "PRIMITIVE_TYPE_INVALID", + \\ "pointer_primitive_type": "PRIMITIVE_TYPE_INVALID", + \\ "dynamic_shape_metadata_prefix_bytes": "0", + \\ }}, + \\ "is_dynamic_dimension": [false, false, false, false], + \\ }}, + \\ "seed": 0, + \\ "is_flash_attention": true, + \\ "mask_type": "NO_MASK", + \\ "bmm1_dot_dimension_numbers": {{ + \\ "lhs_contracting_dimensions": ["3"], + \\ "rhs_contracting_dimensions": ["3"], + \\ "lhs_batch_dimensions": ["0", "1"], + \\ "rhs_batch_dimensions": ["0", "1"], + \\ }}, + \\ "bmm2_dot_dimension_numbers": {{ + \\ "lhs_contracting_dimensions": ["3"], + \\ "rhs_contracting_dimensions": ["2"], + \\ "lhs_batch_dimensions": ["0", "1"], + \\ "rhs_batch_dimensions": ["0", "1"], + \\ }} + \\ }} + \\}} + , + .{ + scale, + elementTypeFromDataType(q.dtype()), + q.dim(.b), + q.dim(.h), + q.dim(.q), + k.dim(.k), + }, + ) catch unreachable; + + var bias = Tensor.constant(Shape.init(.{ .b = q.dim(.b), .h = q.dim(.h), .q = q.dim(.q), .k = k.dim(.k) }, q.dtype()), Data.init(q.dtype(), 0)); + + if (opts.attn_mask) |attn_mask| { + const mask = attn_mask.withTags(.{ .q, .k }).broad(bias.shape()); + bias = bias.add(mask); + } + if (opts.bias) |b| { + bias = bias.add(b); + } + + const loc = ctx.mlirCtx().location(@src()); + const op = dialect.stablehlo.custom_call( + ctx.mlirCtx(), + &.{ q.value(), k.value(), v.value(), bias.value() }, + .{ + .call_target_name = "__cudnn$fmhaScaleBiasSoftmax", + .backend_config = backend_config, + .api_version = 2, + .has_side_effect = false, + .output_operand_aliases = &.{}, + }, + &.{ + mlir.ext.mlirType(ctx.mlirCtx(), q.shape()), + mlir.RankedTensorType.init(&.{0}, mlir.IntegerType(.u8).init(ctx.mlirCtx()).as(mlir.Type).?).as(mlir.Type).?, + }, + loc, + ); + const result = Tensor._result(q.shape(), op.result(0)).transpose(q_.shape()); + return result; +} diff --git a/zml/ops.zig b/zml/ops.zig new file mode 100644 index 0000000..9a6a1fe --- /dev/null +++ b/zml/ops.zig @@ -0,0 +1,644 @@ +const std = @import("std"); +const mlir = @import("mlir.zig"); +const buffer = @import("buffer.zig"); + +const helpers = @import("helpers.zig"); +const module = @import("module.zig"); +const meta = @import("meta.zig"); + +const CompilationContext = module.CompilationContext; +const Tensor = @import("tensor.zig").Tensor; +const Shape = @import("shape.zig").Shape; +const Data = @import("dtype.zig").Data; +const DataType = @import("dtype.zig").DataType; +const Buffer = buffer.Buffer; +const EnumLiteral = @TypeOf(.enum_literal); + +const dialect = struct { + const stablehlo = @import("mlir/dialects").stablehlo; +}; + +const assert = std.debug.assert; +const log = std.log.scoped(.zml_tensor); + +/// Generate an MLIR call to the given member function with the given tensors. +pub fn call(self: anytype, comptime func: meta.DeclEnum(@TypeOf(self)), args: anytype) @TypeOf(@call(.auto, @field(meta.UnwrapPtr(@TypeOf(self)), @tagName(func)), .{self} ++ args)) { + // TODO: this should use `self.getContext().callFunc(self, args)` + + return @call(.auto, @field(@TypeOf(self), @tagName(func)), .{self} ++ args); +} + +pub fn while_( + comptime cond_fn: anytype, + comptime body_fn: anytype, + blkctx: BlockSign(body_fn).BlkCtx, + inputs: BlockSign(body_fn).Args, +) BlockSign(body_fn).Return { + const CondS = comptime BlockSign(cond_fn); + const BodyS = comptime BlockSign(body_fn); + if (CondS.Args != BodyS.Args) { + @compileError("cond_fn and body_fn signatures don't match ! " ++ @typeName(@TypeOf(cond_fn)) ++ " and " ++ @typeName(@TypeOf(body_fn))); + } + const ctx = CompilationContext.current(); + const cond_block = ctx.makeBlock(cond_fn, CondS, blkctx, inputs); + const body_block = ctx.makeBlock(body_fn, BodyS, blkctx, inputs); + var input_values: [BodyS.nIn]mlir.Value = undefined; + ctx.extractValues(&inputs, &input_values); + + const loc = ctx.mlirCtx().location(@src()); + + const op = mlir.Operation.make(ctx.mlirCtx(), "stablehlo.while", .{ + .variadic_operands = &.{&input_values}, + .result_type_inference = true, + .blocks = &.{ cond_block, body_block }, + // We can't verify right away, cause the weights captured by the while haven't been added yet. + .verify = false, + .location = loc, + }); + + var res: BodyS.Args = inputs; + module.assignResults(&res, null, op); + return res; +} + +test "simple while" { + const CountInts = struct { + step: Tensor, + end: Tensor, + const CountInts = @This(); + + pub fn hasNext(self: CountInts, i: Tensor, sum: Tensor) Tensor { + _ = sum; + return i.cmp(.LT, self.end); + } + + pub fn next(self: CountInts, i: Tensor, sum: Tensor) [2]Tensor { + const r1 = i.add(self.step); + const r2 = sum.add(i); + return .{ r1, r2 }; + } + + pub fn forward(self: CountInts, init_i: Tensor, init_sum: Tensor) [2]Tensor { + const x = init_i.scale(2); + return while_(CountInts.hasNext, CountInts.next, self, .{ x, init_sum }); + } + + pub fn zigForward(step: i64, end: i64, init_i: i64, init_sum: i64) [2]i64 { + const x = init_i * 2; + var i = x; + var sum = init_sum; + while (i < end) { + const r1 = i + step; + const r2 = sum + i; + i, sum = .{ r1, r2 }; + } + return .{ i, sum }; + } + }; + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + + const init_i = try zml.Buffer.fromSlice(platform, .{}, &[_]i64{0}); + const init_sum = try zml.Buffer.fromSlice(platform, .{}, &[_]i64{0}); + const counter = .{ + .step = try zml.Buffer.fromSlice(platform, .{}, &[_]i64{1}), + .end = try zml.Buffer.fromSlice(platform, .{}, &[_]i64{10}), + }; + const res0, const res1 = try zml.testing.compileAndCall(platform, CountInts.forward, .{ counter, init_i, init_sum }); + const last_i = try res0.getValue(i64); + const sum = try res1.getValue(i64); + + try std.testing.expectEqual(10, last_i); + try std.testing.expectEqual(45, sum); + + try std.testing.expectEqual(.{ 10, 45 }, CountInts.zigForward(1, 10, 0, 0)); +} + +pub fn reduce( + comptime body_fn: anytype, + inputs: meta.FnParam(body_fn, 0), + inits: meta.FnParam(body_fn, 0), + axes: []const i64, +) BlockSignNoCtx(body_fn).Return { + // TODO: actualAxes + const BodyS = comptime BlockSignNoCtx(body_fn); + comptime { + if (BodyS.Return != @TypeOf(inputs)) @compileError("reduce body function need to have the following signature `fn (left: T, right: T) T`, got: " ++ @typeName(body_fn)); + } + const ctx = CompilationContext.current(); + const N = comptime @divExact(BodyS.nIn, 2); + var input_values: [N]mlir.Value = undefined; + ctx.extractValues(&inputs, &input_values); + var init_values: [N]mlir.Value = undefined; + ctx.extractValues(&inits, &init_values); + + const body_block = ctx.makeBlock(body_fn, BodyS, {}, .{ inits, inits }); + + const loc = ctx.mlirCtx().location(@src()); + + const op = mlir.Operation.make(ctx.mlirCtx(), "stablehlo.reduce", .{ + .variadic_operands = &.{ &input_values, &init_values }, + .result_type_inference = true, + .blocks = &.{body_block}, + .attributes = &.{ + .{ "dimensions", mlir.DenseArrayAttribute(.i64).init(ctx.mlirCtx(), axes).as(mlir.Attribute).? }, + }, + // We can't verify right away, cause the weights captured by the reduce haven't been added yet. + .verify = false, + .location = loc, + }); + + // `stablehlo.reduce` drops axes. We want to avoid that to propagate tags. + // So we need to broadcast the output of `stablehlo.reduce` to the input shapes. + // To that order, we initialize `result` to `inputs`, then we use meta.visit, + // to find the correct mlir.Value, but we first broadcast before creating the final + // Tensor struct. + var broadcasting_axes: std.BoundedArray(i64, Tensor.MAX_RANK) = .{}; + for (0..Tensor.MAX_RANK) |i| { + if (std.mem.indexOfScalar(i64, axes, @intCast(i)) == null) { + broadcasting_axes.append(@intCast(i)) catch unreachable; + } + } + var res: BodyS.Return = inputs; + const LocalContext = struct { + axes: []const i64, + broadcasting_axes: []const i64, + n_reduced: u8, + op: mlir.Operation, + loc: mlir.Location, + index: usize = 0, + }; + var local_context = LocalContext{ + .axes = axes, + .broadcasting_axes = broadcasting_axes.constSlice(), + .n_reduced = @intCast(axes.len), + .op = op, + .loc = loc, + }; + meta.visit((struct { + fn cb(inner_ctx: *LocalContext, tensor: *Tensor) void { + const val = inner_ctx.op.result(inner_ctx.index); + // compute the target reduced shape + var reduced_shape = tensor.shape(); + for (inner_ctx.axes) |a| { + reduced_shape = reduced_shape.setDim(a, 1); + } + + const mlir_ctx = CompilationContext.current().mlirCtx(); + + const broad_val = dialect.stablehlo.broadcast_in_dim( + mlir_ctx, + val, + inner_ctx.broadcasting_axes[0 .. tensor.rank() - inner_ctx.n_reduced], + mlir.ext.RankedTensorType.fromShape(mlir_ctx, reduced_shape).as(mlir.Type).?, + inner_ctx.loc, + ); + tensor.* = Tensor._result(reduced_shape, broad_val.result(0)); + inner_ctx.index += 1; + } + }).cb, &local_context, &res); + assert(local_context.index == op.numResults()); + return res; +} + +pub const ReduceWindowOpts = struct { + // TODO replace with Shape + window_dimensions: []const i64, + window_strides: []const i64, + base_dilations: []const i64, + window_dilations: []const i64, + padding_values: []const i64, + padding_shape: []const i64, +}; + +pub fn reduceWindow( + comptime body_fn: anytype, + inputs: meta.FnParam(body_fn, 0), + inits: meta.FnParam(body_fn, 0), + opts: ReduceWindowOpts, +) meta.FnResult(body_fn) { + const BodyS = comptime BlockSignNoCtx(body_fn); + comptime { + if (BodyS.Return != @TypeOf(inputs)) @compileError("reduce body function need to have the following signature `fn (left: T, right: T) T`, got: " ++ @typeName(body_fn)); + } + const ctx = CompilationContext.current(); + const body_block = ctx.makeBlock(body_fn, BodyS, {}, .{ inits, inits }); + const N = comptime @divExact(BodyS.nIn, 2); + var input_values: [N]mlir.Value = undefined; + ctx.extractValues(&inputs, &input_values); + var init_values: [N]mlir.Value = undefined; + ctx.extractValues(&inits, &init_values); + + const loc = ctx.mlirCtx().location(@src()); + + const pad_shape = mlir.RankedTensorType.init(opts.padding_shape, mlir.ext.Type.fromDType(ctx.mlirCtx(), .i64)).as(mlir.Type).?; + const op = mlir.Operation.make(ctx.mlirCtx(), "stablehlo.reduce_window", .{ + .variadic_operands = &.{ input_values[0..], init_values[0..] }, + .result_type_inference = true, + .blocks = &.{body_block}, + .attributes = &.{ + .{ "window_dimensions", mlir.DenseArrayAttribute(.i64).init(ctx.mlirCtx(), opts.window_dimensions).as(mlir.Attribute).? }, + .{ "window_strides", mlir.DenseArrayAttribute(.i64).init(ctx.mlirCtx(), opts.window_strides).as(mlir.Attribute).? }, + .{ "base_dilations", mlir.DenseArrayAttribute(.i64).init(ctx.mlirCtx(), opts.base_dilations).as(mlir.Attribute).? }, + .{ "window_dilations", mlir.DenseArrayAttribute(.i64).init(ctx.mlirCtx(), opts.window_dilations).as(mlir.Attribute).? }, + .{ "padding", mlir.DenseIntOrFPElementsAttribute(.i64).init(pad_shape, std.mem.sliceAsBytes(opts.padding_values)).as(mlir.Attribute).? }, + }, + .location = loc, + }); + + var res: BodyS.Return = inputs; + module.assignResults(&res, null, op); + return res; +} + +/// Runs a given function for several steps, and returns a stack of each step output. +/// The step outputs will be stacked along the first axis. +pub fn for_(comptime func: anytype, blk_ctx: BlockSign(func).BlkCtx, num_steps_: anytype) BlockSign(func).Return { + const num_steps: u32, const step_tag = blk: { + const dims, const tags = Shape.parseDimensions(num_steps_); + meta.assert(dims.len == 1, "zml.for_ only supports one num_step, Received: {any}", .{num_steps_}); + break :blk .{ @intCast(dims.get(0)), tags.get(0) }; + }; + const S = comptime BlockSign(func); + + const ForBlk = struct { + blk_ctx: S.BlkCtx, + step_tag: @TypeOf(step_tag), // This is a Shape.Tag, but we rather keep it private + num_steps: u32, + const Self = @This(); + + fn next(self: Self, res: S.Return, idx: Tensor) struct { S.Return, Tensor } { + const step_res = @call(.auto, func, .{ self.blk_ctx, idx }); + var buf: [@sizeOf(S.Return) * 2]u8 = undefined; + var fba = std.heap.FixedBufferAllocator.init(&buf); + return .{ + meta.zip(updateResBuffer, fba.allocator(), &[_]S.Return{ res, step_res }, .{idx}) catch unreachable, + idx.addConstant(1), + }; + } + + fn done(self: Self, res: S.Return, idx: Tensor) Tensor { + _ = res; + return idx.cmp(.LT, Tensor.scalar(self.num_steps, idx.dtype())); + } + + fn updateResBuffer(inputs: []const Tensor, idx: Tensor) Tensor { + meta.internalAssert(inputs.len == 2, "too many tensors", .{}); + const res, const step_res = inputs[0..2].*; + return res.dynamicUpdateSlice1d(step_res.insertAxes(0, .{._}), 0, idx); + } + + /// Prepare buffer to store all results steps. + fn prep(self: Self, x: Tensor) Tensor { + var shape = x.shape(); + shape._dims.insert(0, self.num_steps) catch unreachable; + shape._tags.insert(0, self.step_tag) catch unreachable; + return Tensor.constant(shape, x.dtype().zero()); + } + + fn wrapFirstStep(x: Tensor, tag_: @TypeOf(step_tag)) Tensor { + var shape = x.shape(); + shape._dims.insert(0, 1) catch unreachable; + shape._tags.insert(0, tag_) catch unreachable; + return x.reshape(shape); + } + }; + + // This first step won't appear in the generated MLIR, + // it's only used to infer the output shapes. + const first_step = @call(.auto, func, .{ blk_ctx, Tensor.scalar(0, .i32) }); + log.debug("for_ first_step: {}", .{first_step}); + // Optimize for small num reps + if (num_steps == 1) { + // return helpers.mapTensors(ForBlk.wrapFirstStep, first_step, .{ step_tag }); + return first_step; + } + + const allocator = CompilationContext.current()._allocator; + if (num_steps <= 4) { + var steps: [4]S.Return = undefined; + steps[0] = first_step; + for (1..num_steps) |i| { + steps[i] = @call(.auto, func, .{ blk_ctx, Tensor.scalar(i, .i32) }); + } + + const res = meta.zip(Tensor.stack, allocator, steps[0..num_steps], .{ 0, step_tag }) catch unreachable; + return res; + } + + const for_blk: ForBlk = .{ .blk_ctx = blk_ctx, .step_tag = step_tag, .num_steps = num_steps }; + var result_buffers: @TypeOf(first_step) = undefined; + try meta.mapAlloc(ForBlk.prep, allocator, for_blk, first_step, &result_buffers); + + return while_( + ForBlk.done, + ForBlk.next, + for_blk, + .{ + result_buffers, + Tensor.scalar(0, .i32), + }, + )[0]; +} + +test for_ { + const Squares = struct { + const Squares = @This(); + + pub fn sq(self: Squares, i: Tensor) Tensor { + _ = self; + const f = i.convert(.f32); + return f.mul(f); + } + + pub fn forward(num_steps: u63) Tensor { + return for_(Squares.sq, .{}, .{num_steps}); + } + }; + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + + // Just one baby step + { + const squares = try zml.testing.compileAndCall(platform, Squares.forward, .{1}); + try std.testing.expectEqual(0, squares.getValue(f32)); + } + // Wow 4 in rows ! + { + const squares = try zml.testing.compileAndCall(platform, Squares.forward, .{4}); + try std.testing.expectEqual([_]f32{ 0, 1, 4, 9 }, try squares.getValue([4]f32)); + } + // AGI is coming, computing 10 squares as it's nothing. + { + const squares = try zml.testing.compileAndCall(platform, Squares.forward, .{10}); + try std.testing.expectEqual( + [_]f32{ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 }, + try squares.getValue([10]f32), + ); + } +} + +pub fn if_2(pred: Tensor, comptime Closure: type, blkctx: BlockSignNoArgs(@field(Closure, "then")).BlkCtx) BlockSignNoArgs(@field(Closure, "then")).Return { + return if_(pred, @field(Closure, "then"), @field(Closure, "else_"), blkctx); +} + +pub fn if_( + pred: Tensor, + comptime true_branch_fn: anytype, + comptime false_branch_fn: anytype, + blkctx: BlockSignNoArgs(true_branch_fn).BlkCtx, +) BlockSignNoArgs(true_branch_fn).Return { + const TrueBlockSignature = comptime BlockSignNoArgs(true_branch_fn); + const FalseBlockSignature = comptime BlockSignNoArgs(false_branch_fn); + if (TrueBlockSignature.Return != FalseBlockSignature.Return) { + @compileError("true_branch_fn and false_branch_fn return types don't match ! " ++ @typeName(TrueBlockSignature.Return) ++ " and " ++ @typeName(FalseBlockSignature.Return)); + } + const ctx = CompilationContext.current(); + const true_branch_block = ctx.makeBlock(true_branch_fn, TrueBlockSignature, blkctx, {}); + const false_branch_block = ctx.makeBlock(false_branch_fn, TrueBlockSignature, blkctx, {}); + const loc = ctx.mlirCtx().location(@src()); + + const op = mlir.Operation.make(ctx.mlirCtx(), "stablehlo.if", .{ + .operands = &.{pred.value()}, + .result_type_inference = true, + .blocks = &.{ true_branch_block, false_branch_block }, + // We can't verify right away, cause the weights captured by the if haven't been added yet. + .verify = false, + .location = loc, + }); + + var res: TrueBlockSignature.Return = undefined; + module.assignResults(&res, null, op); + return res; +} + +test "if" { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + const allocator = std.testing.allocator; + + const IfMod = struct { + pub fn forward(pred: Tensor, a: Tensor, b: Tensor) Tensor { + const result = if_(pred.convert(.bool), condTrue, condFalse, .{ a, b }); + return result; + } + + pub fn condTrue(a: Tensor, b: Tensor) Tensor { + return a.matmul(b); + } + + pub fn condFalse(a: Tensor, b: Tensor) Tensor { + return b.matmul(a); + } + }; + + { + const pred = Shape.init(.{}, .i32); + const a = Shape.init(.{ 4, 4 }, .f32); + const b = Shape.init(.{ 4, 4 }, .f32); + const mod = try zml.compileFn(allocator, IfMod.forward, .{ pred, a, b }, platform); + defer mod.deinit(); + } +} + +pub fn sort( + comptime comp_fn: anytype, + blkctx: BlockSign(comp_fn).BlkCtx, + inputs: [@divExact(BlockSign(comp_fn).nIn, 2)]Tensor, + dimension: i64, + is_stable: bool, +) [@divExact(BlockSign(comp_fn).nIn, 2)]Tensor { + const BodyS = comptime BlockSign(comp_fn); + var inits: BlockSign(comp_fn).Args = undefined; + inline for (0..@divExact(BlockSign(comp_fn).nIn, 2)) |i| { + const arg_shape = Shape.init(.{}, inputs[i].dtype()); + // Note: the id doesn't matter cause makeBlock will correctly fill it. + inits[i * 2] = Tensor{ ._shape = arg_shape, ._id = undefined, ._donation = .no_buffer }; + inits[i * 2 + 1] = Tensor{ ._shape = arg_shape, ._id = undefined, ._donation = .no_buffer }; + } + const ctx = CompilationContext.current(); + const block = ctx.makeBlock(comp_fn, BodyS, blkctx, inits); + var input_values: [@divExact(BodyS.nIn, 2)]mlir.Value = undefined; + ctx.extractValues(&inputs, &input_values); + + const loc = ctx.mlirCtx().location(@src()).namedFmt(ctx.mlirCtx(), "sort(dimension={d}, is_stable={})", .{ dimension, is_stable }); + + const op = mlir.Operation.make(ctx.mlirCtx(), "stablehlo.sort", .{ + .variadic_operands = &.{&input_values}, + .result_type_inference = true, + .blocks = &.{block}, + .attributes = &.{ + .{ "dimension", mlir.IntegerAttribute(.i64).init(ctx.mlirCtx(), dimension).as(mlir.Attribute).? }, + .{ "is_stable", mlir.BoolAttribute.init(ctx.mlirCtx(), is_stable).as(mlir.Attribute).? }, + }, + .location = loc, + }); + + var res: [@divExact(BlockSign(comp_fn).nIn, 2)]Tensor = undefined; + inline for (0..@divExact(BlockSign(comp_fn).nIn, 2)) |i| { + res[i] = Tensor._result(inputs[i].shape(), op.result(i)); + } + return res; +} + +pub const BlockSignature = struct { + BlkCtx: type, + Args: type, + FullArgs: type, + Return: type, + nIn: usize, + nOut: usize, + + pub inline fn blkArgs(self: BlockSignature, blk_ctx: self.BlkCtx, args: self.Args) self.FullArgs { + if (self.BlkCtx == void) return args; + if (self.Args == void) return blk_ctx; + return .{blk_ctx} ++ args; + } +}; + +const BlockType = enum { default, no_ctx, no_args }; + +pub inline fn BlockSign(comptime func: anytype) BlockSignature { + return _BlockSign(func, .default); +} + +pub inline fn BlockSignNoCtx(comptime func: anytype) BlockSignature { + return _BlockSign(func, .no_ctx); +} + +pub inline fn BlockSignNoArgs(comptime func: anytype) BlockSignature { + return _BlockSign(func, .no_args); +} + +pub fn fnInfo(comptime func: anytype) std.builtin.Type.Fn { + if (@TypeOf(func) == type) { + if (@typeInfo(func) == .Struct and @hasDecl(func, "forward")) { + return fnInfo(func.forward); + } + @compileError("Given type doesn't have a forward function: " ++ @typeName(func)); + } + const type_info = @typeInfo(@TypeOf(func)); + const err_msg = "`func` must be a function and return one or more `Tensor`. Got: "; + if (type_info != .Fn or type_info.Fn.return_type == null) { + @compileError(err_msg ++ @typeName(@TypeOf(func))); + } + return type_info.Fn; +} + +fn _BlockSign(comptime func: anytype, blk_type: BlockType) BlockSignature { + const fn_info = fnInfo(func); + const err_msg = "`func` must be a function and return one or more `Tensor`. Got: "; + + var full_args: [fn_info.params.len]type = undefined; + const arg_start = switch (blk_type) { + .default => 1, + .no_ctx => 0, + .no_args => fn_info.params.len, + }; + var n_tensors: usize = 0; + // var n_inner_tensors: usize = 0; + inline for (fn_info.params, 0..) |arg, i| { + const ArgType = if (arg.type) |T| T else @compileError(err_msg ++ @typeName(@TypeOf(func))); + full_args[i] = ArgType; + if (i >= arg_start) { + n_tensors += staticCountTensors(ArgType) orelse @compileError("Can't use " ++ @typeName(ArgType) ++ " in an MLIR function, because it has a variable number of tensors"); + } + + // if (arg.type) |ArgType| { + // full_args[i] = ArgType; + // if (i >= arg_start) { + // n_tensors += staticCountTensors(ArgType) orelse @compileError("Can't use " ++ @typeName(ArgType) ++ " in an MLIR function, because it has a variable number of tensors"); + // } + // } else { + // // anytype are considered to not have tensors. + // // violation of this will be detected when calling `compile()` but not at Zig compile time. + // full_args[i] = void; + // } + } + const FullArgs = std.meta.Tuple(&full_args); + const BlkCtx = switch (blk_type) { + .default => full_args[0], + .no_ctx => void, + .no_args => FullArgs, + }; + const Args = switch (blk_type) { + .default => std.meta.Tuple(full_args[1..]), + .no_ctx => FullArgs, + .no_args => void, + }; + + const xx = .{ + .BlkCtx = BlkCtx, + .Args = Args, + .FullArgs = FullArgs, + .Return = fn_info.return_type.?, + .nIn = n_tensors, + .nOut = staticCountTensors(fn_info.return_type.?) orelse @compileError("Can't use " ++ @typeName(fn_info.return_type.?) ++ " in an MLIR function, because it has a variable number of tensors"), + }; + return xx; +} + +pub fn staticIsOnlyTensors(comptime T: type) bool { + if (T == Tensor) return true; + + return switch (@typeInfo(T)) { + .Array => |array_info| staticIsOnlyTensors(array_info.child), + .Pointer => |ptr_info| ptr_info.size == .One and staticIsOnlyTensors(ptr_info.child), + .Struct => |struct_info| { + inline for (struct_info.fields) |field| { + if (!staticIsOnlyTensors(field.type)) return false; + } + return true; + }, + else => false, + }; +} + +pub fn staticCountTensors(comptime T: type) ?usize { + if (T == Tensor) return 1; + + return switch (@typeInfo(T)) { + .Array => |array_info| array_info.len * (staticCountTensors(array_info.child) orelse return null), + .Pointer => |ptr_info| { + const n = staticCountTensors(ptr_info.child) orelse return null; + if (ptr_info.size != .One and n > 0) return null; + return n; + }, + .Struct => |struct_info| { + var count: usize = 0; + inline for (struct_info.fields) |field| { + count += staticCountTensors(field.type) orelse return null; + } + return count; + }, + else => 0, + }; +} + +/// Produces a custom call to `name` that takes a tensor and returns it. +/// +/// For example, this can be used to extract tokens quickly if they run on a loop on the +/// GPU. +pub fn identityCustomCall(name: [:0]const u8, input: Tensor, context: *anyopaque) Tensor { + const address: [8]u8 = @bitCast(@intFromPtr(context)); + var backend_config: [8:0]u8 = undefined; + @memcpy(backend_config[0..8], address[0..8]); + const ctx = CompilationContext.current(); + + const loc = ctx.mlirCtx().location(@src()).namedFmt(ctx.mlirCtx(), "name={s}", .{name}); + + const op = dialect.stablehlo.custom_call( + ctx.mlirCtx(), + &.{input.value()}, + .{ + .api_version = 1, + .has_side_effect = false, + .call_target_name = name, + .backend_config = backend_config[0..], + .output_operand_aliases = &.{0}, + }, + &.{input.value().getType()}, + loc, + ); + return Tensor._result(input.shape(), op.result(0)); +} diff --git a/zml/pjrtx.zig b/zml/pjrtx.zig new file mode 100644 index 0000000..1e8fd96 --- /dev/null +++ b/zml/pjrtx.zig @@ -0,0 +1,357 @@ +const builtin = @import("builtin"); +const std = @import("std"); + +const mlir = @import("mlir"); +const pjrt = @import("pjrt"); +const dtype = @import("dtype.zig"); +const meta = @import("meta.zig"); +const asynk = @import("async"); + +pub const Profiler = pjrt.Profiler; +pub const ApiError = pjrt.ApiError; +pub const ErrorCode = pjrt.ErrorCode; + +const Target = @import("platform.zig").Target; + +const log = std.log.scoped(.zml); + +pub const Device = pjrt.Device; +pub const DeviceDescription = pjrt.DeviceDescription; +pub const Api = pjrt.Api; +pub const NamedValue = pjrt.NamedValue; +pub const ClientInitError = pjrt.ClientInitError; +pub const CompileError = std.mem.Allocator.Error || ApiError; +pub const Error = pjrt.Error; +pub const GetCostAnalysisError = pjrt.GetCostAnalysisError; +pub const SerializeResult = pjrt.SerializeResult; +pub const Executable = pjrt.Executable; +pub const ExecuteError = ApiError; + +fn InnerMixin(comptime innerT: type) type { + return struct { + inline fn inner(self: anytype) if (@typeInfo(@TypeOf(self)).Pointer.is_const) *const innerT else *innerT { + return @ptrCast(self); + } + }; +} + +pub const Client = opaque { + const inner = InnerMixin(pjrt.Client).inner; + + pub fn init(api: *const Api, create_options: []const NamedValue) ClientInitError!*Client { + return @ptrCast(try pjrt.Client.init(api, create_options)); + } + + pub fn deinit(self: *Client, api: *const Api) void { + self.inner().deinit(api); + } + + pub fn getPlatformName(self: *const Client, api: *const Api) []const u8 { + return self.inner().getPlatformName(api); + } + + pub fn getDevices(self: *const Client, api: *const Api) []const *const Device { + return self.inner().getDevices(api); + } + + pub fn getAddressableDevices(self: *const Client, api: *const Api) []const *const Device { + return self.inner().getAddressableDevices(api); + } + + pub const BufferFromHostBufferArgs = pjrt.Client.BufferFromHostBufferArgs; + pub fn bufferFromHostBuffer(self: *const Client, api: *const Api, args: BufferFromHostBufferArgs) !*Buffer { + const buffer, const event_ = try self.inner().bufferFromHostBuffer(api, args); + const event: *Event = @ptrCast(event_); + try event.await_(api); + return @ptrCast(buffer); + } + + pub fn deserializeAndLoad(self: *const Client, api: *const Api, bytes: []const u8) ApiError!*LoadedExecutable { + return @ptrCast(try asynk.call(pjrt.Client.deserializeAndLoad, .{ self.inner(), api, bytes })); + } + + pub const CreateViewOfDeviceBufferArgs = pjrt.Client.CreateViewOfDeviceBufferArgs; + pub fn createViewOfDeviceBuffer(self: *const Client, api: *const Api, args: CreateViewOfDeviceBufferArgs) ApiError!*Buffer { + var args_ = args; + args_.on_delete_callback = args_.on_delete_callback orelse &(struct { + fn call(_: ?*anyopaque, _: ?*anyopaque) callconv(.C) void {} + }.call); + const buf = try self.inner().createViewOfDeviceBuffer(api, args_); + return @ptrCast(buf); + } + + fn downgradeStableHLO(self: Client, operation: mlir.Operation) mlir.Operation { + var cloned = operation.clone() catch unreachable; + cloned.walk(.pre_order, .{ .api_version = self.getApiVersion() }, struct { + const OpsStaticMap = std.StaticStringMap([]const [:0]const u8); + const convertPre40Ops = OpsStaticMap.initComptime(.{ + .{ "stablehlo.broadcast", &.{"broadcast_sizes"} }, + .{ "stablehlo.dynamic_slice", &.{"slice_sizes"} }, + .{ "stablehlo.fft", &.{"fft_length"} }, + .{ "stablehlo.pad", &.{ "edge_padding_low", "edge_padding_high", "interior_padding" } }, + .{ "stablehlo.reverse", &.{"dimensions"} }, + .{ "stablehlo.slice", &.{ "start_indices", "limit_indices", "strides" } }, + .{ "stablehlo.transpose", &.{"permutation"} }, + }); + const convertOps = OpsStaticMap.initComptime(.{ + .{ "stablehlo.broadcast_in_dim", &.{"broadcast_dimensions"} }, + .{ "stablehlo.convolution", &.{ "window_strides", "rhs_dilation", "lhs_dilation", "window_reversal" } }, + .{ "stablehlo.dynamic_broadcast_in_dim", &.{ "broadcast_dimensions", "known_expanding_dimensions", "known_nonexpanding_dimensions" } }, + .{ "stablehlo.dynamic_convolution", &.{ "window_strides", "rhs_dilation", "lhs_dilation", "window_reversal" } }, + .{ "stablehlo.gather", &.{"slice_sizes"} }, + .{ "stablehlo.map", &.{"dimensions"} }, + .{ "stablehlo.reduce", &.{"dimensions"} }, + .{ "stablehlo.reduce_window", &.{ "window_dimensions", "window_strides", "base_dilations", "window_dilations" } }, + .{ "stablehlo.select_and_scatter", &.{ "window_dimensions", "window_strides" } }, + }); + + fn convert(map: OpsStaticMap, op: mlir.Operation) void { + if (map.get(op.name().str())) |attrs| { + for (attrs) |attr_name| { + if (op.getAttributeByName(attr_name)) |attr| { + if (attr.as(mlir.DenseArrayAttribute(.bool))) |attr_| { + op.setAttributeByName(attr_name, attr_.toElements().as(mlir.Attribute).?); + } else if (attr.as(mlir.DenseArrayAttribute(.i64))) |attr_| { + op.setAttributeByName(attr_name, attr_.toElements().as(mlir.Attribute).?); + } + } + } + } + } + + fn walk(wctx: anytype, op: mlir.Operation) mlir.Operation.WalkResult { + // Keep in sync with https://github.com/openxla/xla/blob/a05ff095226aa2301903c2b475017b248d2c5ef3/xla/pjrt/mlir_to_hlo.cc#L101 + if (wctx.api_version.minor < 40) { + convert(convertPre40Ops, op); + } + convert(convertOps, op); + + return .advance; + } + }.walk); + return cloned; + } + + fn compileSync(self: *const Client, api: *const Api, allocator: std.mem.Allocator, module: mlir.Module, compile_options_pb: []const u8) CompileError!*LoadedExecutable { + var buffer = std.ArrayList(u8).init(allocator); + defer buffer.deinit(); + // Note: we may need to restore IR downgrade if we need to support old pjrt plugins. + module.op().writeBytecode(buffer.writer()); + + return @ptrCast(try self.inner().compile(api, .{ + .bytecode = buffer.items, + .bytecode_format = .mlir, + .compile_options_pb = compile_options_pb, + })); + } + + fn compileSync2(self: *const Client, api: *const Api, module: []const u8, compile_options_pb: []const u8) CompileError!*LoadedExecutable { + return @ptrCast(try self.inner().compile(api, .{ + .bytecode = module, + .bytecode_format = .mlir, + .compile_options_pb = compile_options_pb, + })); + } + + pub fn compile(self: *const Client, api: *const Api, allocator: std.mem.Allocator, module: mlir.Module, compile_options_pb: []const u8) CompileError!*LoadedExecutable { + return try asynk.call(compileSync, .{ self, api, allocator, module, compile_options_pb }); + } + + pub fn compile2(self: *const Client, api: *const Api, module: []const u8, compile_options_pb: []const u8) CompileError!*LoadedExecutable { + return try asynk.call(compileSync2, .{ self, api, module, compile_options_pb }); + } + + /// Returns the Profiler for this API. + /// Not all platform have a profiling api, for those the profiler object will do nothing. + /// Platforms with known profiler extensions: cuda, xpu + pub fn getProfiler(self: *const Client, api: *const Api, options: pjrt.Profiler.Options) pjrt.Profiler { + return self.inner().getProfiler(api, options); + } + + // pub fn getGpuCustomCallRegistry(self: Client) ?GpuCustomCallRegistry { + // return switch (self.inner) { + // inline else => |v, tag| if (v.getGpuCustomCallRegistry()) |registry| GpuCustomCallRegistry.wrap(tag, registry) else null, + // }; + // } + + // pub fn getGpuCustomCallRegistry(self: *const Client, api: *const Api) ?*GpuCustomCallRegistry { + // if (api.lookupExtension(c.PJRT_Gpu_Custom_Call, c.PJRT_Extension_Type_Gpu_Custom_Call)) |ext| { + // return .{ .custom_call_register = ext.custom_call.? }; + // } + // log.warn("No Gpu Custom Call registry found for platform: {}", .{self}); + // return null; + // } +}; + +// pub const GpuCustomCallRegistry = struct { +// pub usingnamespace WrapperMixin(GpuCustomCallRegistry, pjrt.GpuCustomCallRegistry); + +// inner: GpuCustomCallRegistry.UnionType, + +// pub fn registerCustomCall(self: GpuCustomCallRegistry, api_version: usize, name: []const u8, func: pjrt.CustomCallSignature) ApiError!void { +// return switch (self.inner) { +// inline else => |v| v.registerCustomCall(api_version, name, func), +// }; +// } +// }; + +pub const Buffer = opaque { + const inner = InnerMixin(pjrt.Buffer).inner; + + pub const BufferType = pjrt.BufferType; + + pub fn BufferTypeFromDType(dt: dtype.DataType) BufferType { + return switch (dt) { + .bool => .PRED, + .f8e4m3b11fnuz => .F8E4M3B11FNUZ, + .f8e4m3fn => .F8E4M3FN, + .f8e4m3fnuz => .F8E4M3FNUZ, + .f8e5m2 => .F8E5M2, + .f8e5m2fnuz => .F8E5M2FNUZ, + .bf16 => .BF16, + .f16 => .F16, + .f32 => .F32, + .f64 => .F64, + .i8 => .S8, + .i4 => .S4, + .i16 => .S16, + .i32 => .S32, + .i64 => .S64, + .u4 => .U4, + .u8 => .U8, + .u16 => .U16, + .u32 => .U32, + .u64 => .U64, + .c64 => .C64, + .c128 => .C128, + }; + } + + pub const HostBufferSemantics = pjrt.HostBufferSemantics; + pub const MemoryLayoutType = pjrt.MemoryLayoutType; + + pub fn deinit(self: *Buffer, api: *const Api) void { + self.inner().deinit(api); + } + + pub fn delete(self: *Buffer, api: *const Api) void { + self.inner().delete(api); + } + + pub fn toHostBuffer(self: *const Buffer, api: *const Api, dst: []u8) ApiError!void { + var event = try self.inner().toHostBuffer(api, dst); + try event.await_(api); + } + + pub fn getDimensions(self: *const Buffer, api: *const Api) []const i64 { + return self.inner().getDimensions(api); + } + + pub fn getElementType(self: *const Buffer, api: *const Api) BufferType { + return self.inner().getElementType(api); + } + + pub fn isDeleted(self: *const Buffer, api: *const Api) bool { + return self.inner().isDeleted(api); + } + + pub fn getDevice(self: *const Buffer, api: *const Api) ApiError!*Device { + return @ptrCast(try self.inner().getDevice(api)); + } + + pub fn getOpaqueDeviceMemoryDataPointer(self: *const Buffer, api: *const Api) ApiError!*anyopaque { + return self.inner().getOpaqueDeviceMemoryDataPointer(api); + } +}; + +pub const Event = opaque { + pub const inner = InnerMixin(pjrt.Event).inner; + + pub fn deinit(self: *Event, api: *const Api) void { + self.inner().deinit(api); + } + + pub fn isReady(self: *const Event, api: *const Api) bool { + return self.inner().isReady(api); + } + + pub fn getEventError(self: *const Event, api: *const Api) ApiError!?*Error { + return self.inner().getEventError(api); + } + + pub fn await_(self: *Event, api: *const Api) !void { + defer self.deinit(api); + try self.inner().await_(api); + + var ctx = struct { + err: ?*pjrt.Error = null, + notif: asynk.Notification, + ready: bool = false, + }{ + .notif = try asynk.Notification.init(), + }; + defer ctx.notif.deinit(); + + try self.inner().onReady(api, &(struct { + fn call(err: ?*pjrt.Error, user_arg: ?*anyopaque) callconv(.C) void { + const ctx_: *@TypeOf(ctx) = @ptrCast(@alignCast(user_arg.?)); + ctx_.err = err; + @atomicStore(bool, &ctx_.ready, true, .seq_cst); + ctx_.notif.notify() catch @panic("Unable to notify"); + } + }.call), &ctx); + + while (!ctx.ready) { + try ctx.notif.wait(); + } + if (ctx.err) |e| { + defer e.deinit(api); + return e.getCode(api).toApiError(); + } + } +}; + +pub const LoadedExecutable = opaque { + const inner = InnerMixin(pjrt.LoadedExecutable).inner; + + pub fn deinit(self: *LoadedExecutable, api: *const Api) void { + self.inner().deinit(api); + } + + pub fn delete(self: *LoadedExecutable, api: *const Api) void { + self.inner().delete(api); + } + + pub fn isDeleted(self: *const LoadedExecutable, api: *const Api) bool { + return self.inner().isDeleted(api); + } + + pub fn getAddressableDevices(self: *const LoadedExecutable, api: *const Api) []*const Device { + return self.inner().getAddressableDevices(api); + } + + pub fn execute(self: *const LoadedExecutable, api: *const Api, args: struct { + arguments: []const [*]const *const Buffer, + num_args: usize, + results: []const [*]*Buffer, + events: []*Event, + non_donatable_input_indices: []const i64 = &.{}, + }) ExecuteError!void { + try self.inner().execute(api, .{ + .num_args = args.num_args, + .arguments = @ptrCast(args.arguments), + .results = @ptrCast(args.results), + .events = @ptrCast(args.events), + .non_donatable_input_indices = args.non_donatable_input_indices, + }); + + for (args.events) |event| { + // TODO(Corentin): Maybe better handle the error here. + event.await_(api) catch return error.Unknown; + } + } + + pub fn getExecutable(self: *LoadedExecutable, api: *const Api) ApiError!*Executable { + return try self.inner().getExecutable(api); + } +}; diff --git a/zml/platform.zig b/zml/platform.zig new file mode 100644 index 0000000..60f1ef5 --- /dev/null +++ b/zml/platform.zig @@ -0,0 +1,72 @@ +const builtin = @import("builtin"); +const std = @import("std"); + +const aio = @import("aio.zig"); +const meta = @import("meta.zig"); +const module = @import("module.zig"); +const pjrt = @import("pjrtx.zig"); +const pjrt_core = @import("pjrt"); + +pub const Target = enum { + cpu, + cuda, + rocm, + tpu, +}; + +pub const available_targets = switch (builtin.os.tag) { + .macos => [_]Target{ + .cpu, + }, + .linux => [_]Target{ + .cpu, + .cuda, + .rocm, + .tpu, + }, + else => [_]Target{}, +}; + +pub const CompilationOptions = struct { + xla_dump_to: ?[]const u8 = null, + xla_dump_fusion_visualization: bool = false, + cache_location: ?[]const u8 = null, +}; + +pub const Platform = struct { + target: Target, + pjrt_api: *const pjrt.Api, + pjrt_client: *pjrt.Client, + compilation_options: CompilationOptions = .{}, + + pub fn init(target: Target, api: *const pjrt.Api) !Platform { + const pjrt_client = try pjrt.Client.init(api, &.{}); + return .{ + .target = target, + .pjrt_api = api, + .pjrt_client = pjrt_client, + .compilation_options = .{}, + }; + } + + pub fn getDevices(self: Platform) []const *const pjrt_core.Device { + return self.pjrt_client.getAddressableDevices(self.pjrt_api); + } + + pub fn withCompilationOptions(self: Platform, opts: CompilationOptions) Platform { + var res = self; + res.compilation_options = opts; + return res; + } + + pub fn deinit(self: *Platform) void { + self.pjrt_client.deinit(self.pjrt_api); + } + + /// Returns the Profiler for this API. + /// Not all platform have a profiling api, for those the profiler object will do nothing. + /// Platforms with known profiler extensions: cuda, xpu + pub fn getProfiler(self: Platform, options: pjrt_core.Profiler.Options) pjrt_core.Profiler { + return self.pjrt_client.getProfiler(self.pjrt_api, options); + } +}; diff --git a/zml/posix.h b/zml/posix.h new file mode 100644 index 0000000..8b05b1a --- /dev/null +++ b/zml/posix.h @@ -0,0 +1 @@ +#include diff --git a/zml/posix.zig b/zml/posix.zig new file mode 100644 index 0000000..9ebd48f --- /dev/null +++ b/zml/posix.zig @@ -0,0 +1,16 @@ +const std = @import("std"); +const c = @import("c"); + +pub fn madvise(ptr: [*]align(std.mem.page_size) u8, length: usize, advice: u32) std.posix.MadviseError!void { + switch (std.posix.errno(c.madvise(ptr, @intCast(length), @intCast(advice)))) { + .SUCCESS => return, + .ACCES => return error.AccessDenied, + .AGAIN => return error.SystemResources, + .BADF => unreachable, // The map exists, but the area maps something that isn't a file. + .INVAL => return error.InvalidSyscall, + .IO => return error.WouldExceedMaximumResidentSetSize, + .NOMEM => return error.OutOfMemory, + .NOSYS => return error.MadviseUnavailable, + else => |err| return std.posix.unexpectedErrno(err), + } +} diff --git a/zml/quantization.zig b/zml/quantization.zig new file mode 100644 index 0000000..5fa09ab --- /dev/null +++ b/zml/quantization.zig @@ -0,0 +1,125 @@ +const std = @import("std"); +const zml = @import("zml.zig"); + +const Allocator = std.mem.Allocator; +const module = zml.module; + +pub fn Q4_0(comptime dtype: zml.DataType) type { + return struct { + const Self = @This(); + + const QuantType = zml.io.gguf.quants.QuantType.q4_0; + + quant_buffer: zml.Tensor, + + pub fn compile( + allocator: Allocator, + ctx: *zml.Context, + input: zml.Tensor, + shape: zml.Shape, + ) !module.CompiledModule(Self.forward) { + std.debug.assert(input.dtype() == .u8); + std.debug.assert(input.rank() == 1); + return module.compile( + allocator, + ctx, + Self.forward, + Self{ .quant_buffer = input }, + .{shape}, + ) catch unreachable; + } + + /// Each block is composed of a f16 scale and 32 4-bit values. + const block_stride = 18; + + pub fn forward(self: Self, shape: zml.Shape) zml.Tensor { + const input = self.quant_buffer; + const block_count: u63 = @intCast(@divExact(input.dim(0), block_stride)); + const scales = extractScales(block_count, input); + const weights = extractWeights(block_count, input); + + return scales.reshape(.{ block_count, 1 }) + .broadcastLeft(zml.Shape.init(.{ block_count, 32 }, .f32)) + .mul(weights) + .convert(dtype) + .reshape(.{block_count * 32}) + .reshape(shape); + } + + pub fn scaleIndices(block_count: u63) zml.Tensor { + // indices1 is the offsets of the scale bytes, repeated block_count times. + const indices1 = zml.Tensor.arange(.{ .start = 0, .end = 2 }, .i32).repeat1d(0, block_count); + + // indices2 is the offsets of the blocks, repeated for each scale byte, repeated block_count times. + const indices2 = zml.Tensor.arange(.{ .start = 0, .end = block_stride * block_count, .step = block_stride }, .i32) + .reshape(.{ block_count, 1 }).broadcastLeft(zml.Shape.init(.{ block_count, 2 }, .i32)).reshape(.{2 * block_count}); + + // indices is the sum of the two, which is the offsets to all the bytes we are interested in. + return indices1.add(indices2); + } + + pub fn weightIndices(block_count: u63) zml.Tensor { + // indices1 is the offsets of the data bytes, repeated block_count times. + const indices1 = zml.Tensor.arange(.{ .start = 2, .end = 18 }, .i32).repeat1d(0, block_count); + + // indices2 is the offsets of the blocks, repeated for each data byte, repeated block_count times. + const indices2 = zml.Tensor.arange(.{ .start = 0, .end = block_stride * block_count, .step = block_stride }, .i32) + .reshape(.{ block_count, 1 }).broadcastLeft(zml.Shape.init(.{ block_count, 16 }, .i32)).reshape(.{16 * block_count}); + + // indices is the sum of the two, which is the offsets to all the bytes we are interested in. + return indices1.add(indices2); + } + + pub fn extractScales(block_count: u63, input: zml.Tensor) zml.Tensor { + // The goal here is to get the first two bytes of every 18-bytes block in the input. For that, + // we generate a list of indices that we will use to gather from the input. + + // indices1 is the offsets of the scale bytes, repeated block_count times. + const indices1 = zml.Tensor.arange(.{ .start = 0, .end = 2 }, .i32).repeat1d(0, block_count); + + // indices2 is the offsets of the blocks, repeated for each scale byte, repeated block_count times. + const indices2 = zml.Tensor.arange(.{ .start = 0, .end = block_stride * block_count, .step = block_stride }, .i32) + .reshape(.{ block_count, 1 }).broadcastLeft(zml.Shape.init(.{ block_count, 2 }, .i32)).reshape(.{2 * block_count}); + + // indices is the sum of the two, which is the offsets to all the bytes we are interested in. + const indices = indices1.add(indices2); + + // We select the values we are interested in with the indices, group them by pair and bitcast them to f16, then convert them to f32. + const scales = input.gather1d(0, indices, .{ .indices_are_sorted = true }).reshape(.{ block_count, 2 }).bitCast(.f16).convert(.f32); + + return scales; + } + + pub fn extractWeights(block_count: u63, input: zml.Tensor) zml.Tensor { + // The goal here is to get everything but the first two bytes of every 18-bytes block in the input. For that, + // we generate a list of indices that we will use to gather from the input. + + // indices1 is the offsets of the data bytes, repeated block_count times. + const indices1 = zml.Tensor.arange(.{ .start = 2, .end = 18 }, .i32).repeat1d(0, block_count); + + // indices2 is the offsets of the blocks, repeated for each data byte, repeated block_count times. + const indices2 = zml.Tensor.arange(.{ .start = 0, .end = block_stride * block_count, .step = block_stride }, .i32) + .reshape(.{ block_count, 1 }).broadcastLeft(zml.Shape.init(.{ block_count, 16 }, .i32)).reshape(.{16 * block_count}); + + // indices is the sum of the two, which is the offsets to all the bytes we are interested in. + const indices = indices1.add(indices2); + + // NOTE(Corendos): i4 is not supported by bitcast convert, so we need the following workaround. + + // We select the values we are interested in with the indices, these are our quantized_weights. + const quantized_weights = input.gather1d(0, indices, .{ .indices_are_sorted = true }); + const lb_weights = quantized_weights + .logical(.And, zml.Tensor.constant(.{16 * block_count}, zml.Data.init(.u8, 0xf))) + .bitCast(.i8); + const hb_weights = quantized_weights + .shiftRightLogical(zml.Tensor.constant(.{16 * block_count}, zml.Data.init(.u8, 4))).bitCast(.i8); + const weights = zml.Tensor.concatenate( + &.{ lb_weights.reshape(.{ block_count, 16 }), hb_weights.reshape(.{ block_count, 16 }) }, + 1, + ) + .sub(zml.Tensor.constant(.{ block_count, 32 }, zml.Data.init(.i8, 8))) + .convert(.f32); + return weights; + } + }; +} diff --git a/zml/shape.zig b/zml/shape.zig new file mode 100644 index 0000000..784ca67 --- /dev/null +++ b/zml/shape.zig @@ -0,0 +1,1023 @@ +const builtin = @import("builtin"); +const std = @import("std"); +const testing = std.testing; + +const meta = @import("meta.zig"); +const DataType = @import("dtype.zig").DataType; + +const EnumLiteral = @TypeOf(.enum_literal); +const log = std.log.scoped(.shape); + +test { + std.testing.refAllDecls(@This()); +} + +/// Represent the shape of a tensor. +pub const Shape = struct { + pub const MAX_RANK: u8 = 8; + + pub const Tag = [*:0]const u8; + pub const TagUnknown = "_".ptr; + const TagLast = "last".ptr; + + // Note: we can't make those public otherwise `refAllDeclsRecursive` + // will try to compile `std.BoundedArray.Writer` and will produce a compile error. + const DimsArray = std.BoundedArray(i64, MAX_RANK); + const TagsArray = std.BoundedArray(Tag, MAX_RANK); + const AxesArray = std.BoundedArray(u3, MAX_RANK); + + const UnknownTags: TagsArray = .{ .len = 0, .buffer = [_]Tag{TagUnknown} ** MAX_RANK }; + + _dtype: DataType, + _dims: DimsArray = .{}, + _tags: TagsArray = UnknownTags, + + pub fn parseDimensions(v: anytype) struct { DimsArray, TagsArray } { + const T = @TypeOf(v); + + if (T == Shape) { + return .{ v._dims, v._tags }; + } + + if (comptime meta.isSliceOfAny(T, meta.isInteger)) { + var dims_ = DimsArray.init(0) catch unreachable; + var tags_ = TagsArray.init(0) catch unreachable; + for (v) |d| { + dims_.appendAssumeCapacity(@intCast(d)); + tags_.appendAssumeCapacity(TagUnknown); + } + return .{ dims_, tags_ }; + } + + if (comptime meta.isStruct(T)) { + var dims_: DimsArray = .{}; + var tags_: TagsArray = .{}; + inline for (std.meta.fields(T)) |field| { + const fv = @field(v, field.name); + if (comptime meta.isInteger(field.type)) { + dims_.appendAssumeCapacity(@intCast(fv)); + } else if (comptime isAutoDim(fv)) { + dims_.appendAssumeCapacity(-1); + } else { + meta.compileError("Field {s} should be an integer or an auto dimension", .{field.name}); + } + if (comptime meta.isTuple(T)) { + tags_.appendAssumeCapacity(TagUnknown); + } else { + tags_.appendAssumeCapacity(toTag(field)); + } + } + + return .{ dims_, tags_ }; + } + + meta.compileError("Wrong type, got {}", .{T}); + } + + test parseDimensions { + const ref = Shape.init(.{ .a = 0, .b = 1 }, .f32); + const dims_, const tags_ = parseDimensions(.{ .a = 0, .b = 1 }); + + try testing.expectEqualSlices(i64, ref.dims(), dims_.constSlice()); + try testing.expectEqualSlices(Tag, ref.tags(), tags_.constSlice()); + } + + pub fn parseAxes(self: Shape, v: anytype) struct { AxesArray, TagsArray } { + const T = @TypeOf(v); + + if (T == Shape) { + return self.parseAxes(self.tags()); + } + + var axes_ = AxesArray.init(0) catch unreachable; + var tags_ = TagsArray.init(0) catch unreachable; + + if (comptime meta.isSliceOfAny(T, isAxisConvertible)) { + for (v) |d| { + axes_.appendAssumeCapacity(self.axis(d)); + tags_.appendAssumeCapacity(self.tag(d)); + } + return .{ axes_, tags_ }; + } + + if (comptime meta.isTupleOfAny(T, isAxisConvertible)) { + inline for (std.meta.fields(T)) |field| { + axes_.appendAssumeCapacity(self.axis(@field(v, field.name))); + tags_.appendAssumeCapacity(self.tag(@field(v, field.name))); + } + return .{ axes_, tags_ }; + } + + meta.compileError("Wrong type, got {}. Expected .{{.a, .b}}", .{T}); + } + + pub fn parseTags(v: anytype) TagsArray { + const T = @TypeOf(v); + meta.assertComptime(meta.isTupleOf(T, EnumLiteral), "Wrong type, got {}. Expected .{{ .a, .b }}", .{T}); + var tags_ = TagsArray.init(0) catch unreachable; + inline for (v) |field| { + tags_.appendAssumeCapacity(toTag(field)); + } + return tags_; + } + + /// Create a shape from a struct literal, eg: + /// Shape.init(.{ .h = 1024, .w = 512, .c = 3 }); + /// Shape.init(.{ 1024, 512, 3 }); + pub fn init(dimz: anytype, dt: DataType) Shape { + var res: Shape = .{ ._dtype = dt }; + res._dims, res._tags = parseDimensions(dimz); + return res; + } + + /// Creates a Shape with dims set to `.{0, 1, 2, ..., rank-1}`. + pub fn range(rank_: usize, dt: DataType) Shape { + var res: Shape = .{ ._dtype = dt }; + for (0..rank_) |i| { + res._dims.append(@intCast(i)) catch { + meta.panic("Too many dimensions! Max: {d}, passed: {d}", .{ res._dims.capacity(), rank_ }); + }; + res._tags.append(TagUnknown) catch unreachable; + } + return res; + } + + pub fn dtype(self: Shape) DataType { + return self._dtype; + } + + pub fn rank(self: Shape) u4 { + self.ensureDimsAndTagsAreSync(); + return self._dims.len; + } + + pub fn dim(self: Shape, ax: anytype) i64 { + self.ensureDimsAndTagsAreSync(); + return self._dims.get(self.axis(ax)); + } + + pub fn dims(self: *const Shape) []const i64 { + self.ensureDimsAndTagsAreSync(); + return self._dims.constSlice(); + } + + fn isAxisConvertible(comptime T: type) bool { + return meta.isInteger(T) or isTagConvertible(T); + } + + fn isTagConvertible(comptime T: type) bool { + return switch (T) { + EnumLiteral => true, + std.builtin.Type.StructField => true, + Tag => true, + else => false, + }; + } + + fn toTag(v: anytype) Tag { + const T = @TypeOf(v); + return switch (T) { + EnumLiteral => @tagName(v).ptr, + std.builtin.Type.StructField => v.name.ptr, + Tag => v, + else => meta.compileError("Value should be an EnumLiteral, a Shape.Tag or a StructField, got {}", .{T}), + }; + } + + inline fn ensureDimsAndTagsAreSync(self: Shape) void { + meta.assert(self._dims.len == self._tags.len, "Tags and dims have diverged! dims={d} tags={d}", .{ self._dims.len, self._tags.len }); + } + + pub fn tag(self: Shape, ax: anytype) Tag { + self.ensureDimsAndTagsAreSync(); + return self._tags.get(self.axis(ax)); + } + + /// Returns a printable name for a given axis. + /// Either the tag itself, or a digit if it's not tagged. + pub fn debugTag(self: Shape, ax: usize) []const u8 { + const t = self.tag(ax); + if (t != TagUnknown) return std.mem.span(t); + + return "01234567"[ax .. ax + 1]; + } + + pub fn setTag(self: Shape, ax: anytype, tag_: anytype) Shape { + var res = self; + res._tags.set(self.axis(ax), toTag(tag_)); + return res; + } + + pub fn tags(self: *const Shape) []const Tag { + self.ensureDimsAndTagsAreSync(); + return self._tags.constSlice(); + } + + pub fn hasTag(self: Shape, tag_: anytype) ?u3 { + return self.axisFromTagMaybe(toTag(tag_)); + } + + pub fn hasTags(self: Shape, tagz: anytype) bool { + const T = @TypeOf(tagz); + + if (comptime meta.isSliceOf(T, Tag) or meta.isSliceOf(T, EnumLiteral)) { + for (tagz) |t| { + if (self.hasTag(t) == null) { + return false; + } + } + return true; + } + + if (comptime meta.isTupleOf(T, Tag) or meta.isTupleOf(T, EnumLiteral)) { + inline for (tagz) |t| { + if (self.hasTag(t) == null) { + return false; + } + } + return true; + } + + meta.compileError("Expected tuple of tags, got {any}", .{T}); + } + + pub fn isFullyTagged(self: Shape) bool { + for (self._tags.constSlice()) |t| { + if (t == TagUnknown) return false; + } + return true; + } + + pub fn axis(self: Shape, axis_: anytype) u3 { + self.ensureDimsAndTagsAreSync(); + + const T = @TypeOf(axis_); + if (comptime meta.isInteger(T)) { + return self.axisFromInt(@intCast(axis_)); + } + + if (comptime isTagConvertible(T)) { + return self.axisFromTag(toTag(axis_)); + } + + meta.compileError("Wrong axis type, expected .literal, or an integer, got: {any}", .{T}); + } + + pub fn axes(self: Shape, axes_: anytype) AxesArray { + self.ensureDimsAndTagsAreSync(); + + const T = @TypeOf(axes_); + + if (T == Shape) { + return self.axes(axes_.tags()); + } + + var res = AxesArray.init(0) catch unreachable; + + if (comptime meta.isSliceOfAny(T, meta.isInteger) or meta.isSliceOf(T, Tag)) { + for (axes_) |ax| { + res.appendAssumeCapacity(self.axis(ax)); + } + return res; + } + + if (comptime meta.isStruct(T)) { + inline for (std.meta.fields(T)) |field| { + res.appendAssumeCapacity(self.axis(@field(axes_, field.name))); + } + return res; + } + + meta.compileError("Wrong type, got {}", .{T}); + } + + fn axisFromInt(self: Shape, d: isize) u3 { + const rank_: i8 = self.rank(); + if (d < 0) { + return @intCast(d + rank_); + } + if (d > rank_) { + meta.panic("Tensor doesn't have dimension: {d}", .{d}); + } + return @intCast(d); + } + + fn axisFromTagMaybe(self: Shape, d: Tag) ?u3 { + if (d == TagUnknown) { + return null; + } + if (@inComptime()) { + for (0.., self.tags()) |tagIndex, t| { + const a: []const u8 = std.mem.span(t); + const b: []const u8 = std.mem.span(d); + if (std.mem.eql(u8, a, b)) { + return @intCast(tagIndex); + } + } + return null; + } + if (std.mem.indexOfScalar(Tag, self.tags(), d)) |d_| { + return @intCast(d_); + } + return null; + } + + fn axisFromTag(self: Shape, d: Tag) u3 { + meta.assert(d != TagUnknown, "The unknown tag .{s} can't be used to fetch axis in {}", .{ d, self }); + return self.axisFromTagMaybe(d) orelse { + meta.panic("Tensor {} doesn't have dimension with tag: {s}", .{ self, d }); + }; + } + + test axis { + try testing.expectEqual(1, Shape.init(.{ 5, 2 }, .f32).axis(1)); + try testing.expectEqual(1, Shape.init(.{ 5, 2 }, .f32).axis(-1)); + try testing.expectEqual(1, Shape.init(.{ .a = 5, .b = 2 }, .f32).axis(.b)); + } + + /// The number of element inside a Tensor described by this shape. + pub fn count(self: Shape) usize { + var res: i64 = 1; + for (self.dims()) |d| { + meta.assert(d >= 0, "Can't count elements in shape with negative dimension: {}", .{self}); + res *= d; + } + return @intCast(res); + } + + /// Total size in bytes needed to represent this shape. + pub fn byteSize(self: Shape) usize { + return self.dtype().sizeOf() * self.count(); + } + + // Aliases + pub const numel = count; + + /// Compares the two shapes described, ignoring tagging. + pub fn eql(self: Shape, other: Shape) bool { + return std.mem.eql(i64, self.dims(), other.dims()) and self.dtype() == other.dtype(); + } + + /// Compares the two shapes described, ignoring tagging and dtype. + pub fn eqlDims(self: Shape, other: Shape) bool { + return std.mem.eql(i64, self.dims(), other.dims()); + } + + /// Compares the two shapes described including tags. + pub fn eqlWithTags(self: Shape, other: Shape) bool { + return self.eql(other) and std.mem.eql(Tag, self.tags(), other.tags()) and self.dtype() == other.dtype(); + } + + /// Format the shape. + /// Default format: "Shape({.a=10, .b=20}, dtype=.f32)" + /// Bare format {_}: "{.a=10, .b=20}, dtype=.f32" + pub fn format( + self: Shape, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, + ) !void { + _ = options; + const bare_fmt = fmt.len == 1 and fmt[0] == '_'; + _ = try writer.write(if (bare_fmt) "{" else "Shape({"); + + for (self.dims(), 0..) |d, i| { + const prefix = if (i == 0) "" else ","; + const t = self.tag(i); + if (t != TagUnknown) { + try writer.print("{s}.{s}={d}", .{ prefix, t, d }); + } else { + try writer.print("{s}{d}", .{ prefix, d }); + } + } + _ = try writer.print("}}, dtype=.{s}", .{@tagName(self.dtype())}); + if (!bare_fmt) _ = try writer.write(")"); + } + + pub fn reshape(self: Shape, new_shape_: anytype) Shape { + var new_shape: Shape = .{ ._dtype = self.dtype() }; + new_shape._dims, new_shape._tags = parseDimensions(new_shape_); + new_shape.inferMissingAxis(self.count()); + meta.assert(self.count() == new_shape.count(), "Can't reshape {d} to {d}", .{ self.dims(), new_shape.dims() }); + return new_shape; + } + + fn inferMissingAxis(self: *Shape, n_: usize) void { + meta.assert(std.mem.count(i64, self.dims(), &.{-1}) < 2, "Cannot infer multiple dimensions when reshaping to: {}", .{self.*}); + + const inferred_ax = std.mem.indexOfScalar(i64, self.dims(), -1) orelse return; + // We can't use `self.count()` yet cause we have negative dims. + var tmp_count: i64 = 1; + for (self.dims()) |d| { + if (d > 0) { + tmp_count *= d; + } + } + const n: i64 = @intCast(n_); + // Abort, `reshape` will panic with more context. + if (@mod(n, tmp_count) != 0) { + return; + } + self._dims.set(inferred_ax, @divExact(n, tmp_count)); + } + + test reshape { + const x = Shape.init(.{ 2, 5, 3 }, .f32); + { + const res = x.reshape(.{ .auto, 3 }); + try testing.expectEqualSlices(i64, &.{ 10, 3 }, res.dims()); + } + { + const res = x.reshape(.{ 10, -1 }); + try testing.expectEqualSlices(i64, &.{ 10, 3 }, res.dims()); + } + { + const res = x.reshape(.{-1}); + try testing.expectEqualSlices(i64, &.{30}, res.dims()); + } + } + + pub fn setDim(self: Shape, ax: anytype, d: i64) Shape { + var res = self; + res._dims.set(self.axis(ax), d); + return res; + } + + pub const set = setDim; + + fn isAutoDim(v: anytype) bool { + return toTag(v) == toTag(.auto); + } + + fn isDynDim(v: anytype) bool { + return toTag(v) == toTag(.dyn); + } + + /// Inserts one ore more axes with the given dimensions, before the given axis. + /// Negative axis is interpreted wrt the current shape. + /// `.last` axis can be used to insert at the end (ie to append). + /// ``` + /// .{10, 11, 12}.insert(1, 2) -> .{10, 2, 11, 12} + /// .{10, 11, 12}.insert(-1, 2) -> .{10, 11, 2, 12} + /// .{10, 11, 12}.insert(.last, 2) -> .{10, 11, 12, 2} + /// ``` + pub fn insert(self: Shape, axis_: anytype, dimz: anytype) Shape { + const dims_, const tags_ = parseDimensions(dimz); + const ax = if (@TypeOf(axis_) == EnumLiteral and axis_ == .last) + self.rank() + else + self.axis(axis_); + + var res = self; + res._dims.insertSlice(ax, dims_.constSlice()) catch unreachable; + res._tags.insertSlice(ax, tags_.constSlice()) catch unreachable; + return res; + } + + test insert { + try testing.expectEqualSlices(i64, &.{ 10, 1, 11, 12 }, Shape.init(.{ 10, 11, 12 }, .f32).insert(1, .{1}).dims()); + try testing.expectEqualSlices(i64, &.{ 10, 11, 12, 1, 13 }, Shape.init(.{ 10, 11, 12, 13 }, .f32).insert(-1, .{1}).dims()); + try testing.expectEqualSlices(i64, &.{ 10, 11, 12, 13, 1 }, Shape.init(.{ 10, 11, 12, 13 }, .f32).insert(.last, .{1}).dims()); + } + + pub fn insertTag(self: Shape, axis_: anytype, d: i64, tag_: anytype) Shape { + meta.assert(self.rank() < MAX_RANK - 1, "Can't insert new axis in {}, it's already at max rank.", .{self}); + + const ax = if (@TypeOf(axis_) == EnumLiteral and axis_ == .last) + self.rank() + else + self.axis(axis_); + + var res = self; + res._dims.insert(ax, d) catch unreachable; + res._tags.insert(ax, toTag(tag_)) catch unreachable; + return res; + } + + pub fn append(self: Shape, v: anytype) Shape { + var res = self; + const dims_, const tags_ = parseDimensions(v); + res._dims.appendSliceAssumeCapacity(dims_.constSlice()); + res._tags.appendSliceAssumeCapacity(tags_.constSlice()); + return res; + } + + test append { + try testing.expectEqualSlices( + i64, + &.{ 10, 11, 12, 1 }, + Shape.init(.{ 10, 11, 12 }, .f32).append(.{1}).dims(), + ); + + try testing.expect( + Shape.init(.{ .a = 10, .b = 11, .c = 12 }, .f32).eqlWithTags( + Shape.init(.{ .a = 10, .b = 11 }, .f32).append(.{ .c = 12 }), + ), + ); + } + + pub fn appendDim(self: Shape, d: i64, tag_: ?Tag) Shape { + var res = self; + res._dims.appendAssumeCapacity(d); + res._tags.appendAssumeCapacity(if (tag_) |t| t else TagUnknown); + return res; + } + + pub fn remove(self: Shape, d: anytype) Shape { + var res = self; + const d_ = self.axis(d); + _ = res._dims.orderedRemove(d_); + _ = res._tags.orderedRemove(d_); + return res; + } + + pub const drop = remove; + + test remove { + try std.testing.expectEqualSlices(i64, &.{ 10, 12 }, Shape.init(.{ 10, 11, 12 }, .f32).remove(1).dims()); + try std.testing.expectEqualSlices(i64, &.{ 10, 11, 12 }, Shape.init(.{ 10, 11, 12, 13 }, .f32).remove(-1).dims()); + } + + pub fn transpose(self: Shape, permutations: anytype) Shape { + std.debug.assert(self.rank() == permutations.len); + const permutations_ = self.axes(permutations); + var res = self; + for (permutations_.constSlice(), 0..) |permutation, i| { + res._dims.set(i, self.dim(permutation)); + res._tags.set(i, self.tag(permutation)); + } + return res; + } + + test transpose { + try testing.expect( + Shape.init(.{ 12, 11, 10 }, .f32).eql( + Shape.init(.{ 10, 11, 12 }, .f32).transpose(.{ 2, 1, 0 }), + ), + ); + + try testing.expect( + Shape.init(.{ .a = 10, .c = 12, .b = 11, .d = 13 }, .f32).eqlWithTags( + Shape.init(.{ .a = 10, .b = 11, .c = 12, .d = 13 }, .f32).transpose(.{ 0, 2, 1, 3 }), + ), + ); + } + + /// Tag each ax of this shape with tags from a tuple. + pub fn withTags(self: Shape, tagz: anytype) Shape { + const T = @TypeOf(tagz); + + if (T == Shape) { + return self.withTags(tagz.tags()); + } + + var res = self; + + if (comptime meta.isSliceOf(T, Tag) or meta.isSliceOf(T, EnumLiteral)) { + meta.assert(tagz.len == self.rank(), "Not enough tags for shape {}, got {any}", .{ self, tagz }); + for (tagz, 0..) |tag_, i| { + res._tags.set(i, toTag(tag_)); + } + return res; + } + + if (comptime meta.isTupleOf(T, Tag) or meta.isTupleOf(T, EnumLiteral)) { + meta.assert(tagz.len == self.rank(), "Not enough tags for shape {}, got {}", .{ self, tagz }); + inline for (tagz, 0..) |tag_, i| { + res._tags.set(i, toTag(tag_)); + } + return res; + } + + meta.compileError("Expected a tuple of enum literals eg: .{ .a, .b, .c } got: {any}", .{@TypeOf(tagz)}); + } + + test withTags { + { + const tagged = Shape.init(.{ 0, 1 }, .f32).withTags(.{ .a, .b }); + try testing.expectEqual(0, tagged.axis(.a)); + try testing.expectEqual(1, tagged.axis(.b)); + } + { + const tagged = Shape.init(.{ 0, 1, 2 }, .f32).withTags(.{ ._, .a, .b }); + try testing.expectEqual(1, tagged.axis(.a)); + try testing.expectEqual(2, tagged.axis(.b)); + } + { + const tagged = Shape.init(.{ 0, 1, 2, 3 }, .f32).withTags(.{ ._, ._, .a, .b }); + try testing.expectEqual(2, tagged.axis(.a)); + try testing.expectEqual(3, tagged.axis(.b)); + } + } + + /// Tag the last axes of this shape with tags from a tuple. + pub fn withPartialTags(self: Shape, tagz: anytype) Shape { + const T = @TypeOf(tagz); + + if (T == Shape) { + return self.withPartialTags(tagz.tags()); + } + + var res = self; + + if (comptime meta.isSliceOf(T, Tag) or meta.isSliceOf(T, EnumLiteral)) { + meta.assert(tagz.len <= self.rank(), "Too many tags for shape {}, got {any}", .{ self, tagz }); + for (tagz, self.rank() - tagz.len..) |tag_, i| { + res._tags.set(i, toTag(tag_)); + } + return res; + } + + if (comptime meta.isTupleOf(T, Tag) or meta.isTupleOf(T, EnumLiteral)) { + meta.assert(tagz.len <= self.rank(), "Too many tags for shape {}, got {}", .{ self, tagz }); + inline for (tagz, self.rank() - tagz.len..) |tag_, i| { + res._tags.set(i, toTag(tag_)); + } + return res; + } + + meta.compileError("Expected a tuple of enum literals eg: .{ .a, .b, .c } got: {any}", .{@TypeOf(tagz)}); + } + + test withPartialTags { + { + const tagged = Shape.init(.{ 0, 1 }, .f32).withPartialTags(.{ .a, .b }); + try testing.expectEqual(0, tagged.axis(.a)); + try testing.expectEqual(1, tagged.axis(.b)); + } + { + const tagged = Shape.init(.{ 0, 1, 2 }, .f32).withPartialTags(.{ .a, .b }); + try testing.expectEqual(1, tagged.axis(.a)); + try testing.expectEqual(2, tagged.axis(.b)); + } + { + const tagged = Shape.init(.{ 0, 1, 2, 3, 4 }, .f32).withPartialTags(.{ .a, .b }); + try testing.expectEqual(3, tagged.axis(.a)); + try testing.expectEqual(4, tagged.axis(.b)); + } + { + const tagged = Shape.init(.{ 0, 1, 2, 3, 4, 5, 6 }, .f32).withPartialTags(.{ .a, .b, .c }); + try testing.expectEqual(4, tagged.axis(.a)); + try testing.expectEqual(5, tagged.axis(.b)); + try testing.expectEqual(6, tagged.axis(.c)); + } + } + + pub fn withDtype(self: Shape, dt: DataType) Shape { + var res = self; + res._dtype = dt; + return res; + } + + /// Renames some of the tags in this shape. + /// Shape.init(.{ .a = 10, .b = 20 }).rename(.{ .b = .batch }); // .{ .a = 10, .batch = 20 }; + pub fn rename(self: Shape, renames: anytype) Shape { + const T = @TypeOf(renames); + meta.assertComptime(meta.isStructOfAny(T, isAxisConvertible), "Must pass a struct of enum literals. Passed: {any}", .{T}); + var res = self; + inline for (std.meta.fields(T)) |field| { + res._tags.set(self.axis(field), toTag(@field(renames, field.name))); + } + return res; + } + + test rename { + { + const tagged = Shape.init(.{ .a = 0, .b = 1 }, .f32).rename(.{ .a = .x, .b = .y }); + try testing.expectEqual(0, tagged.dim(.x)); + try testing.expectEqual(1, tagged.dim(.y)); + } + { + const tagged = Shape.init(.{ .a = 0, .b = 1, .c = 2 }, .f32).rename(.{ .a = .x, .c = .z }); + try testing.expectEqual(0, tagged.dim(.x)); + try testing.expectEqual(1, tagged.dim(.b)); + try testing.expectEqual(2, tagged.dim(.z)); + } + } + + pub fn computeStrides(self: Shape, base_stride: u32) std.BoundedArray(i64, MAX_RANK) { + const rk = self.rank(); + var strides: std.BoundedArray(i64, MAX_RANK) = .{ .len = @intCast(self.rank()) }; + if (rk == 0) return strides; + strides.buffer[rk - 1] = base_stride; + for (1..rk) |i| { + const j = @as(usize, rk) - 1 - i; + strides.buffer[j] = self._dims.get(j + 1) * strides.buffer[j + 1]; + } + return strides; + } + + /// Returns the permutation needed to transpose this shape + /// so that the given axes are contiguous. + pub fn contiguousPerm(self: Shape, axes_: anytype) AxesArray { + const axes__, _ = self.parseAxes(axes_); + var perms = AxesArray.init(0) catch unreachable; + for (0..self.rank()) |i| { + if (std.mem.indexOfScalar(u3, axes__.constSlice(), @intCast(i))) |_| { + continue; + } + perms.appendAssumeCapacity(@intCast(i)); + } + perms.appendSliceAssumeCapacity(axes__.constSlice()); + return perms; + } + + test contiguousPerm { + const abc = Shape.init(.{ .a = 10, .b = 11, .c = 12 }, .f32); + try testing.expect( + Shape.init(.{ .b = 11, .c = 12, .a = 10 }, .f32).eqlWithTags( + abc.transpose(abc.contiguousPerm(.{.a}).constSlice()), + ), + ); + try testing.expect( + Shape.init(.{ .c = 12, .b = 11, .a = 10 }, .f32).eqlWithTags( + abc.transpose(abc.contiguousPerm(.{ .b, .a }).constSlice()), + ), + ); + const abcd = Shape.init(.{ .a = 10, .b = 11, .c = 12, .d = 13 }, .f32); + try testing.expect( + Shape.init(.{ .a = 10, .c = 12, .b = 11, .d = 13 }, .f32).eqlWithTags( + abcd.transpose(abcd.contiguousPerm(.{ .b, .d }).constSlice()), + ), + ); + + const abcde = Shape.init(.{ .a = 10, .b = 11, .c = 12, .d = 13, .e = 14 }, .f32); + try testing.expect( + Shape.init(.{ .a = 10, .b = 11, .d = 13, .c = 12, .e = 14 }, .f32).eqlWithTags( + abcde.transpose(abcde.contiguousPerm(.{ .b, .d, .c, .e }).constSlice()), + ), + ); + } + + /// Splits the given axis in several axes. + /// eg: `Shape.init(.{ .a = 10, .b = 3 }).split(.a, .{.a1 = 5, .a2 = 2}); -> .{.a1 = 5, .a2 = 2, .b = 3}` + /// The number of elements in the split shape must match the number of element + /// in the target axis. + pub fn splitAxis(self: Shape, axis_: anytype, split_shape_: anytype) Shape { + const ax = self.axis(axis_); + const dims_, const tags_ = parseDimensions(split_shape_); + var new_shape = self; + new_shape._dims.replaceRange(ax, 1, dims_.constSlice()) catch unreachable; + new_shape._tags.replaceRange(ax, 1, tags_.constSlice()) catch unreachable; + new_shape.inferMissingAxis(self.count()); + return new_shape; + } + + test splitAxis { + try testing.expect( + Shape.init(.{ .a1 = 5, .a2 = 2, .b = 3 }, .f32).eql( + Shape.init(.{ .a = 10, .b = 3 }, .f32).splitAxis(.a, .{ .a1 = 5, .a2 = 2 }), + ), + ); + try testing.expect( + Shape.init(.{ .a1 = 5, .a2 = 2, .b = 3 }, .f32).eql( + Shape.init(.{ .a = 10, .b = 3 }, .f32).splitAxis(.a, .{ .a1 = .auto, .a2 = 2 }), + ), + ); + } + + pub fn splitAxes(self: Shape, axes_: anytype) Shape { + const T = @TypeOf(axes_); + meta.assertComptime(meta.isStruct(T), "Must pass struct of enum literals like .{ .a = .{ .a1, .a2 } }. Passed: {any}", .{T}); + + var res = self; + inline for (std.meta.fields(T)) |field| { + res = res.splitAxis(field, @field(axes_, field.name)); + } + return res; + } + + test splitAxes { + try testing.expect( + Shape.init(.{ .a1 = 5, .a2 = 2, .b = 3 }, .f32).eql( + Shape.init(.{ .a = 10, .b = 3 }, .f32).splitAxes(.{ .a = .{ .a1 = 5, .a2 = .auto } }), + ), + ); + try testing.expect( + Shape.init(.{ .a1 = 5, .a2 = 2, .b = 3 }, .f32).eql( + Shape.init(.{ .a = 10, .b = 3 }, .f32).splitAxes(.{ .a = .{ .a1 = 5, .a2 = .auto } }), + ), + ); + } + + /// Merge the given axes into one axis. + /// eg: `Shape.init(.{.a1 = 5, .a2 = 2, .b = 3}).merge(.{ .a = .{ .a1, .a2 }); -> .{ .a = 10, .b = 3 }` + pub fn mergeAxis(self: Shape, axis_: anytype, axes_: anytype) Shape { + const axes__ = self.axes(axes_); + + const first_axis = axes__.get(0); + const last_axis = axes__.get(axes__.len - 1); + + var new_dim: i64 = 1; + for (axes__.constSlice(), first_axis..) |ax, counter| { + new_dim *= self.dim(ax); + meta.assert(ax == counter, "Can't merge shape {} along non-contiguous axes {any}", .{ self, axes_ }); + } + + var new_shape = self; + new_shape._dims.set(first_axis, new_dim); + new_shape._dims.replaceRange(first_axis + 1, self.dims()[first_axis + 1 ..].len, self.dims()[last_axis + 1 ..]) catch unreachable; + new_shape._tags.set(first_axis, if (comptime isTagConvertible(@TypeOf(axis_))) toTag(axis_) else TagUnknown); + new_shape._tags.replaceRange(first_axis + 1, self.dims()[first_axis + 1 ..].len, self.tags()[last_axis + 1 ..]) catch unreachable; + return new_shape; + } + + test mergeAxis { + try testing.expect( + Shape.init(.{ .a = 10, .b = 3, .c = 4 }, .f32).eqlWithTags( + Shape.init(.{ .a1 = 5, .a2 = 2, .b = 3, .c = 4 }, .f32).mergeAxis(.a, .{ .a1, .a2 }), + ), + ); + try testing.expect( + Shape.init(.{ .a = 5, .c = 6 }, .f32).eqlWithTags( + Shape.init(.{ .a = 5, .b1 = 2, .b2 = 3 }, .f32).mergeAxis(.c, .{ .b1, .b2 }), + ), + ); + try testing.expect( + Shape.init(.{ .a = 10, .b = 3 }, .f32).eqlWithTags( + Shape.init(.{ .a1 = 5, .a2 = 2, .b = 3 }, .f32).mergeAxis(.a, .{ toTag(.a1), toTag(.a2) }), + ), + ); + try testing.expect( + Shape.init(.{ .a = 10, .b = 3 }, .f32).eqlWithTags( + Shape.init(.{ .a1 = 5, .a2 = 2, .b = 3 }, .f32).mergeAxis(toTag(.a), @as([]const Tag, &.{ toTag(.a1), toTag(.a2) })), + ), + ); + try testing.expect( + Shape.init(.{ .a = 10, .b = 3 }, .f32).eqlWithTags( + Shape.init(.{ .a1 = 5, .a2 = 2, .b = 3 }, .f32).mergeAxis(.a, @as([]const usize, &.{ 0, 1 })), + ), + ); + } + + pub fn mergeAxes(self: Shape, axes_: anytype) Shape { + const T = @TypeOf(axes_); + meta.assertComptime(meta.isStruct(T), "Must pass struct of enum literals like .{ .a = .{ .a1, .a2 } }. Passed: {any}", .{T}); + + var res = self; + inline for (std.meta.fields(T)) |field| { + meta.assertComptime(meta.isTupleOfAny(field.type, isAxisConvertible) or meta.isSliceOfAny(field.type, isAxisConvertible), "Must pass struct of axes. Passed: {any}", .{field.type}); + res = res.mergeAxis(field, @field(axes_, field.name)); + } + return res; + } + + test mergeAxes { + try testing.expect( + Shape.init(.{ .a = 10, .b = 3 }, .f32).eqlWithTags( + Shape.init(.{ .a1 = 5, .a2 = 2, .b = 3 }, .f32).mergeAxes(.{ .a = .{ .a1, .a2 } }), + ), + ); + try testing.expect( + Shape.init(.{ .a = 10, .b = 3 }, .f32).eqlWithTags( + Shape.init(.{ .a1 = 5, .a2 = 2, .b = 3 }, .f32).mergeAxes(.{ .a = .{ toTag(.a1), toTag(.a2) } }), + ), + ); + try testing.expect( + Shape.init(.{ .a = 10, .b = 3 }, .f32).eqlWithTags( + Shape.init(.{ .a1 = 5, .a2 = 2, .b = 3 }, .f32).mergeAxes(.{ .a = .{ 0, 1 } }), + ), + ); + try testing.expect( + Shape.init(.{ .a = 10, .b = 3 }, .f32).eqlWithTags( + Shape.init(.{ .a1 = 5, .a2 = 2, .b = 3 }, .f32).mergeAxes(.{ .a = @as([]const usize, &.{ 0, 1 }) }), + ), + ); + } + + /// Parses an anytype argument of the form `val` or `.{ .a = val }`.l + /// Helps offering consistent API through ZML. + // pub fn parseTaggedValue( + // T: type, + // default_tag: EnumLiteral, + // d: anytype, + // ) struct { Tag, T } { + // const err_msg = "Expected one tagged dimension, received a tuple: " ++ @typeName(@TypeOf(d)); + // return switch (@typeInfo(@TypeOf(d))) { + // .Int, .ComptimeInt => .{ toTag(default_tag), @intCast(d) }, + // .Struct => |struct_info| { + // if (struct_info.fields.len != 1) @compileError(err_msg); + // const name = struct_info.fields[0].name; + // return .{ name.ptr, @intCast(@field(d, name)) }; + // }, + // else => @compileError(err_msg), + // }; + // } + + /// Parses a list of tags `.{ .a, .b, .c }` into a `[]Tag` + // pub inline fn parseTagList(comptime axes_: anytype) []Tag { + // switch (@typeInfo(@TypeOf(axes_))) { + // .Struct, .Array => { + // var _tags: [axes_.len]Tag = undefined; + // inline for (axes_, &_tags) |a, *t| t.* = toTag(a); + // return &_tags; + // }, + // else => @compileError("Expected a tuple of enum literal, but found " ++ @tagName(@TypeOf(axes))), + // } + // } + + /// Parses a comptime struct into a struct similarly to Shape.init, + /// but with a custom type in place of the `i64` dimensions. + /// Helps offering consistent API through ZML. + // pub fn parseShapedValue(T: type, value: anytype) struct { + // std.BoundedArray(Tag, MAX_RANK), + // std.BoundedArray(T, MAX_RANK), + // } { + // const too_long_err = std.fmt.comptimePrint("Received too many axes, maximum supported is {d}", .{MAX_RANK}); + + // var _tags: [MAX_RANK]Tag = [_]Tag{TagUnknown} ** MAX_RANK; + // const struct_info = switch (@typeInfo(@TypeOf(value))) { + // .Struct => |struct_info| struct_info, + // else => return .{ + // .{ .len = 0, .buffer = _tags }, + // std.BoundedArray(T, MAX_RANK).fromSlice(value) catch @panic(too_long_err), + // }, + // }; + + // meta.assertComptime(struct_info.fields.len <= MAX_RANK, too_long_err, .{}); + + // var values: std.BoundedArray(T, MAX_RANK) = .{}; + // inline for (struct_info.fields) |field| { + // if (T == Tag) { + // values.appendAssumeCapacity(toTag(@field(value, field.name))); + // } else { + // // If you have an error here it means Zig wasn't able to convert between the + // // value you passed and the expected `T`. + // values.appendAssumeCapacity(@field(value, field.name)); + // } + // } + // if (!struct_info.is_tuple) { + // inline for (struct_info.fields, 0..) |field, i| { + // _tags[i] = toTag(field); + // } + // } + // return .{ + // .{ .len = struct_info.fields.len, .buffer = _tags }, + // values, + // }; + // } + + fn intersectTags(a: []const Tag, b: []const Tag) TagsArray { + var res = TagsArray.init(0) catch unreachable; + for (a) |tag_| { + if (std.mem.indexOfScalar(Tag, b, tag_)) { + res.appendAssumeCapacity(tag_); + } + } + return res; + } + + pub fn parseStruct(T: type, v: anytype) struct { std.BoundedArray(T, MAX_RANK), TagsArray } { + const V = @TypeOf(v); + + var vals_: std.BoundedArray(T, MAX_RANK) = .{}; + var tags_: TagsArray = .{}; + + if (comptime meta.isSliceOf(V, T)) { + for (v) |d| { + vals_.appendAssumeCapacity(d); + } + return .{ vals_, tags_ }; + } + + if (comptime meta.isStruct(V)) { + const fields = std.meta.fields(V); + meta.assertComptime(fields.len <= MAX_RANK, "Too many fields in struct {} ({d}). Max supported is {d}.", .{ V, fields.len, MAX_RANK }); + inline for (fields) |field| { + const fv = @field(v, field.name); + vals_.appendAssumeCapacity(fv); + + if (!comptime meta.isTuple(V)) { + tags_.appendAssumeCapacity(toTag(field)); + } + } + return .{ vals_, tags_ }; + } + + meta.compileError("parseStruct expects struct or tuple, got {}", .{V}); + } + + test parseStruct { + const vals_, const tags_ = parseStruct(f32, .{ .a = 0.1, .b = 1.2 }); + + try testing.expectEqualSlices(f32, &.{ 0.1, 1.2 }, vals_.constSlice()); + try testing.expectEqualSlices(Tag, &.{ "a".ptr, "b".ptr }, tags_.constSlice()); + } + + test "comptimeShape" { + comptime { + const s = Shape.init(.{ .a = 5, .b = 6, .c = 7 }, .f32); + try std.testing.expectEqual(3, s.rank()); + try std.testing.expectEqual(4 * 5 * 6 * 7, s.byteSize()); + try std.testing.expectEqual(1, s.axis(.b)); + } + + // comptime only the shape + { + const s = comptime Shape.init(.{ .a = 5, .b = 6, .c = 7 }, .f32); + try std.testing.expectEqual(3, s.rank()); + try std.testing.expectEqual(4 * 5 * 6 * 7, s.byteSize()); + try std.testing.expectEqual(1, s.axis(.b)); + } + } +}; diff --git a/zml/tensor.zig b/zml/tensor.zig new file mode 100644 index 0000000..901450b --- /dev/null +++ b/zml/tensor.zig @@ -0,0 +1,3330 @@ +const builtin = @import("builtin"); +const std = @import("std"); +const assert = std.debug.assert; +const testing = std.testing; + +const pjrt = @import("pjrtx.zig"); +const meta = @import("meta.zig"); +const mlir = @import("mlir.zig"); +const ops = @import("ops.zig"); +const module = @import("module.zig"); + +const Location = mlir.Location; +const CompilationContext = module.CompilationContext; +const Shape = @import("shape.zig").Shape; +const Buffer = @import("buffer.zig").Buffer; +const HostBuffer = @import("hostbuffer.zig").HostBuffer; +const Data = @import("dtype.zig").Data; +const DataType = @import("dtype.zig").DataType; +const Platform = @import("platform.zig").Platform; +const EnumLiteral = @TypeOf(.enum_literal); + +const dialect = struct { + const stablehlo = @import("mlir/dialects").stablehlo; +}; + +const scoped_log = std.log.scoped(.zml_tensor); + +/// Represents an abstract Tensor object, which can be the input, +/// output, weight or activations of a neural network. +/// Tensor are abstract in the sense they only represent a computation, +/// but not a specific memory buffer. +/// Tensor namespace contains most of linear algebra needed to +/// represent mathematical operations. +/// More operations are available in `zml.nn` and `zml.torch` namespaces. +pub const Tensor = struct { + _shape: Shape, + _id: _Id, + _donation: _Donation = .no_buffer, + + pub const _Donation = union(enum) { no_buffer, input_buffer, arg: u16 }; + pub const _Id = union(enum) { mlir: mlir.Value, buffer_id: u64, arg_id: u64 }; + + pub const MAX_RANK = Shape.MAX_RANK; + + /// Returns the current compilation context. + pub fn getContext(self: Tensor) *CompilationContext { + _ = self; + return CompilationContext.current(); + } + + pub fn format( + self: Tensor, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, + ) !void { + _ = fmt; + _ = options; + try writer.print("Tensor({_})", .{self._shape}); + } + + /// Returns the shape of a Tensor. + pub fn shape(self: Tensor) Shape { + return self._shape; + } + + /// Returns the datatype of a Tensor. + pub fn dtype(self: Tensor) DataType { + return self._shape.dtype(); + } + + /// Returns the rank of a Tensor. + pub inline fn rank(self: Tensor) u4 { + return self._shape.rank(); + } + + /// Returns the number of element of a Tensor. + pub fn count(self: Tensor) usize { + return self._shape.count(); + } + + /// Returns the size in bytes of a Tensor. + pub fn byteSize(self: Tensor) usize { + return self._shape.byteSize(); + } + + /// Internal use + /// + /// Creates a tensor from a Shape and an mlir.Value. + pub fn _result(sh: Shape, val: mlir.Value) Tensor { + const res: Tensor = .{ + ._shape = sh, + ._id = .{ .mlir = val }, + }; + + if (builtin.mode == .Debug) { + // Check that the MLIR value actually have the same shape. + const other = fromMlirValue(val); + meta.internalAssert(sh.eql(other._shape), "Created a {} from Mlir value but expected {}", .{ other._shape, res._shape }); + } + + return res; + } + + /// Creates a Tensor from a mlir.Value + /// + /// The shape is derived from the type of the mlir.Value. + pub fn fromMlirValue(val: mlir.Value) Tensor { + const ranked_tensor = val.getType().as(mlir.RankedTensorType).?; + const n = ranked_tensor.getRank(); + + meta.assert(n <= MAX_RANK, "Can't represent MLIR tensor of rank {}, max supported rank is {}.", .{ n, MAX_RANK }); + + var sh: Shape = .{ ._dtype = mlir.ext.Type.toDType(ranked_tensor.getElementType()) }; + for (0..n) |i| { + sh._dims.appendAssumeCapacity(ranked_tensor.getDimension(i)); + } + sh._tags.resize(n) catch unreachable; + + return .{ ._shape = sh, ._id = .{ .mlir = val } }; + } + + /// Returns the dimension of axis 'axis_'. + /// + /// 'axis_' can be a signed integer or a tag. + pub fn dim(self: Tensor, axis_: anytype) i64 { + return self._shape.dim(axis_); + } + + /// Returns the dimensions of a Tensor as a slice. + pub fn dims(self: *const Tensor) []const i64 { + return self._shape.dims(); + } + + /// Returns the index of axis 'axis_'. + /// + /// 'axis_' can be a signed integer or a tag. + pub fn axis(self: Tensor, axis_: anytype) u3 { + return self._shape.axis(axis_); + } + + /// Returns a Tensor tagged with the tags in 'tagz'. + pub fn withTags(self: Tensor, tagz: anytype) Tensor { + var res = self; + res._shape = self._shape.withTags(tagz); + return res; + } + + /// Returns a Tensor tagged partially with the tags in 'tagz'. + /// + /// If 'tagz' is of length n, the n last dimensions of the Tensor will be tagged. + pub fn withPartialTags(self: Tensor, tagz: anytype) Tensor { + var res = self; + res._shape = self._shape.withPartialTags(tagz); + return res; + } + + /// Returns a Tensor with new tag names. + pub fn rename(self: Tensor, renames: anytype) Tensor { + var res = self; + res._shape = self._shape.rename(renames); + return res; + } + + /// Returns the mlir.Value associated with the Tensor. + /// + /// This will fail if used outside of a compilation context. + pub fn value(self: Tensor) mlir.Value { + return self.getContext().getValueAndDonation(self)[0]; + } + /// Tell PJRT compiler that memory should be reuse between the two tensors. + /// The compiler is already aggressively reusing tensors for intermediate results, + /// but this API allows to reuse buffer between input and output arguments + /// of a given function. + /// Note this is visible from the outside. The caller of a function with donations + /// is not allowed to reuse the donated input buffer after the call. + /// For `reuseBuffer` to be effective, it needs to propagate all the way through the output. + pub fn reuseBuffer(self: Tensor, origin: Tensor) Tensor { + // Note: check donation docs, this may be too permissive. + meta.assert(self.byteSize() == origin.byteSize(), "Can't reuse buffers between tensors of different size: {} and {}", .{ self, origin }); + + // TODO: should we store all donations inside the context ? + var res = self; + res._donation = self.getContext().getValueAndDonation(origin)[1]; + + return res; + } + + /// Returns a slice containing the strides for a Tensor. + pub inline fn computeStrides(self: Tensor) []const i64 { + return self._shape.computeStrides(self.dtype().sizeOf()).constSlice(); + } + + var _global_tensor_counter: u64 = 0; + + /// Internal use + pub fn reserveIdRange(len: u32) u64 { + return @atomicRmw(u64, &_global_tensor_counter, .Add, len, .seq_cst); + } + + /// Internal use + pub fn setUniqueId(self: *Tensor) void { + self._id = .{ .buffer_id = reserveIdRange(1) }; + } + + /// Returns a Tensor containing the absolute value of each element of the input Tensor. + pub fn abs(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.abs(self.getContext().mlirCtx(), self.value(), loc); + const dt = switch (self.dtype()) { + .c64 => .f32, + .c128 => .f64, + else => self.dtype(), + }; + + return _result(self._shape.withDtype(dt), op.result(0)); + } + + /// Returns a Tensor whose elements have been bitcast to a target datatype. + /// + /// The Tensor shape needs to be compatible with the target datatype. + pub fn bitCast(self: Tensor, dt: DataType) Tensor { + const src_bit_size = self.dtype().bitSizeOf(); + const tgt_bit_size = dt.bitSizeOf(); + var res_shape = if (src_bit_size == tgt_bit_size) + self._shape + else if (src_bit_size > tgt_bit_size) gt: { + const new_dim = std.math.divExact(u16, src_bit_size, tgt_bit_size) catch std.debug.panic("bitcast expects target datatype to be a multiple of source datatype when upcasting, got {} (bitsize of {}) and {} (bitsize of {})", .{ self.dtype(), src_bit_size, dt, tgt_bit_size }); + var res = self._shape; + res = res.append(.{ .bitcast = new_dim }); + break :gt res; + } else lt: { + // several contiguous elements of self maps to one element of the result + meta.assert(self.dim(-1) * src_bit_size == tgt_bit_size, "bitcast expects elements of the input tensor last dimension to map to one element of the target datatype, got {0} elements (bitsize of {0}x{1}={2}) and {3} (bitsize of {4})", .{ self.dim(-1), src_bit_size, self.dim(-1) * src_bit_size, dt, tgt_bit_size }); + break :lt self._shape.remove(-1); + }; + + res_shape = res_shape.withDtype(dt); + + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "bitCast({})", .{dt}); + const op = dialect.stablehlo.bitcast_convert( + self.getContext().mlirCtx(), + self.value(), + mlir.ext.RankedTensorType.fromShape(self.getContext().mlirCtx(), res_shape).as(mlir.Type).?, + loc, + ); + + return _result(res_shape, op.result(0)); + } + + /// Returns a Tensor containing the element-wise number of leading 0 bits in the input Tensor. + pub fn countLeadingZeros(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.count_leading_zeros(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, op.result(0)); + } + + /// Returns a Tensor containing booleans indicating if each element of the input Tensor is finite. + pub fn isFinite(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.is_finite(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape.withDtype(.bool), op.result(0)); + } + + /// Returns a Tensor containing the element-wise logistic operation on the input Tensor. + pub fn logistic(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.logistic(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, op.result(0)); + } + + /// Returns a Tensor containing the element-wise number of bits set in the input Tensor. + pub fn popcnt(self: Tensor) Tensor { + meta.assert(self.dtype().isInteger(), "popcnt expects tensor type to be an integer, got {}", .{self.dtype()}); + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.popcnt(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, op.result(0)); + } + + /// Returns a Tensor containing the sign of the input Tensor element-wise. + pub fn sign(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.sign(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, op.result(0)); + } + + /// Returns a Tensor containing the element-wise remainder of dividend 'self' and divisor 'other'. + pub fn remainder(self: Tensor, other: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.remainder(self.getContext().mlirCtx(), self.value(), other.value(), loc); + return _result(self._shape, op.result(0)); + } + + /// Returns a Tensor containing the element-wise remainder of dividend 'self' and divisor 'other'. + /// + /// See https://pytorch.org/docs/stable/generated/torch.fmod.html for more details. + pub fn fmod(self: Tensor, divisor: f32) Tensor { + return self.remainder(Tensor.scalar(divisor, .f32).broadcast(self._shape, &.{})); + } + + /// Returns a Tensor containing the element-wise left-shift operation of 'self' by 'other'. + pub fn shiftLeft(self: Tensor, other: Tensor) Tensor { + return binaryOp("shiftLeft", dialect.stablehlo.shift_left)(self, other); + } + + /// Returns a Tensor containing the element-wise arithmetic right-shift operation of 'self' by 'other'. + pub fn shiftRightArithmetic(self: Tensor, other: Tensor) Tensor { + return binaryOp("shiftRightArithmetic", dialect.stablehlo.shift_right_arithmetic)(self, other); + } + + /// Returns a Tensor containing the element-wise logical right-shift operation of 'self' by 'other'. + pub fn shiftRightLogical(self: Tensor, other: Tensor) Tensor { + return binaryOp("shiftRightLogical", dialect.stablehlo.shift_right_logical)(self, other); + } + + /// Returns the Cholesky decomposition of the input Tensor. + /// + /// 'lower' controls the form of the outut Tensor. The output will be lower-triangular if 'lower' is true + /// and upper-triangular otherwise. + pub fn cholesky(self: Tensor, lower: bool) Tensor { + meta.assert(self.rank() <= 2, "cholesky expects tensor rank to be <= 2, got {}", .{self.rank()}); + + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "lower={}", .{lower}); + const op = dialect.stablehlo.cholesky(self.getContext().mlirCtx(), self.value(), lower, loc); + return _result(self._shape, op.result(0)); + } + + /// Solves the system of linear equations formed by the input tensors. + pub fn triangularSolve(self: Tensor, other: Tensor, opts: dialect.stablehlo.TriangularSolveOpts) Tensor { + meta.assert(self.dtype() == other.dtype(), "triangularSolve expects tensors to be of the same type, got {} and {}", .{ self.dtype(), other.dtype() }); + meta.assert(self.rank() <= 2 and self.rank() == other.rank(), "triangularSolve expects tensors to have the same rank and be <= 2, got {} and {}", .{ self.rank(), other.rank() }); + + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "opts={}", .{opts}); + const op = dialect.stablehlo.triangular_solve(self.getContext().mlirCtx(), self.value(), other.value(), loc, opts); + return _result(self._shape, op.result(0)); + } + + /// Returns a Tensor containing the element-wise rounding towards the nearest integer, breaking ties away from zero, of the input Tensor. + pub fn roundNearestAfz(self: Tensor) Tensor { + meta.assert(self.dtype().isFloat(), "roundNearestAfz expects tensor type to be a float, got {}", .{self.dtype()}); + + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.round_nearest_afz(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, op.result(0)); + } + + /// Returns a Tensor containing the element-wise rounding towards the nearest integer, breaking ties towards the even integer, of the input Tensor. + pub fn roundNearestEven(self: Tensor) Tensor { + meta.assert(self.dtype().isFloat(), "roundNearestEven expects tensor type to be a float, got {}", .{self.dtype()}); + + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.round_nearest_even(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, op.result(0)); + } + + /// Returns a Tensor of complex number converted from a pair of real and imaginary Tensors. + pub fn complex(re: Tensor, im: Tensor) Tensor { + meta.assert(re._shape.eql(im._shape), "complex expects tensor shapes to match, got {} and {}", .{ re._shape, im._shape }); + meta.assert(re.dtype() == .f32 or re.dtype() == .f64, "complex expects tensors type to be f32 or f64, got {}", .{re.dtype()}); + + const loc = re.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.complex(re.getContext().mlirCtx(), re.value(), im.value(), loc); + const dt: DataType = if (re.dtype() == .f32) .c64 else .c128; + return _result(re._shape.withDtype(dt), op.result(0)); + } + + /// Returns a Tensor containing the element-wise real part of the input Tensor. + /// + /// Tensor type can float or complex. + pub fn real(self: Tensor) Tensor { + meta.assert(self.dtype().isComplex() or self.dtype().isFloat(), "real expects tensor type to be a float or a complex, got {}", .{self.dtype()}); + + if (self.dtype().isFloat()) { + return self; + } + + const dt: DataType = switch (self.dtype()) { + .c64 => .f32, + .c128 => .f64, + else => unreachable, + }; + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.real(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape.withDtype(dt), op.result(0)); + } + + /// Returns a Tensor containing the element-wise imaginary part of the input Tensor. + /// + /// Tensor type can float or complex. + pub fn imag(self: Tensor) Tensor { + meta.assert(self.dtype().isFloat() or self.dtype().isComplex(), "imag expects tensor type to be a float or a complex, got {}", .{self.dtype()}); + + // Real tensors don't have imaginary part. + if (self.dtype().isFloat()) { + return Tensor.constant(self._shape, self.dtype().zero()); + } + + const dt: DataType = switch (self.dtype()) { + .bf16, .f16, .f32, .f64 => self.dtype(), + .c64 => .f32, + .c128 => .f64, + else => unreachable, + }; + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.imag(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape.withDtype(dt), op.result(0)); + } + + /// Returns the Fast Fourier Transform (FFT) of the input Tensor. + pub fn fft(self: Tensor, opts: dialect.stablehlo.FftOpts) Tensor { + // TODO: support tagged API. + + meta.assert(1 <= opts.length.len and opts.length.len <= 3, "fft expects 'opts.length' length to be between 1 and 3 (inclusive), got {}", .{opts.length.len}); + meta.assert(opts.length.len <= self.rank(), "fft expects 'opts.length' length to be less than tensor rank, got {} and {}", .{ opts.length.len, self.rank() }); + + const sh = switch (opts.kind) { + .FFT, .IFFT => blk: { + meta.assert(self.dtype().isComplex(), "fft({any}) expects tensor type to be complex, got {}", .{ opts, self.dtype() }); + + break :blk self._shape; + }, + .RFFT => blk: { + meta.assert(self.dtype() == .f32 or self.dtype() == .f64, "fft({}) expects tensor type to be f32 or f64, got {}", .{ opts, self.dtype() }); + meta.assert(std.mem.eql(i64, self.dims()[self.rank() - opts.length.len ..], opts.length), "fft({}) expects tensor last dimensions to match given lengths, got {} and {}", .{ opts, self.dims()[self.rank() - opts.length.len ..].len, opts.length.len }); + + const dt: DataType = switch (self.dtype()) { + .f32 => .c64, + else => .c128, + }; + const shape_ = self._shape.setDim(-1, @divExact(self.dim(-1), 2) + 1); + break :blk shape_.withDtype(dt); + }, + .IRFFT => blk: { + meta.assert(self.dtype().isComplex(), "fft({any}) expects tensor type to be complex, got {}", .{ opts, self.dtype() }); + meta.assert(std.mem.eql(i64, self.dims()[self.rank() - opts.length.len ..], opts.length), "fft({any}) expects tensor last dimensions to match given lengths, got {} and {}", .{ opts, self.dims()[self.rank() - opts.length.len ..].len, opts.length.len }); + + const dt: DataType = switch (self.dtype()) { + .c64 => .f32, + else => .f64, + }; + const shape_ = self._shape.setDim(-1, @divExact(self.dim(-1) - 1, 2)); + break :blk shape_.withDtype(dt); + }, + }; + + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "opts={}", .{opts}); + const op = dialect.stablehlo.fft(self.getContext().mlirCtx(), self.value(), loc, opts); + return _result(sh, op.result(0)); + } + + pub const Rng = struct { + _state: Tensor, + algorithm: dialect.stablehlo.RngAlgorithm.Type = .DEFAULT, + + pub fn shape() ShapeOf(Rng) { + return .{ + ._state = Shape.init(.{2}, .u64), + }; + } + + pub fn init(platform: Platform, seed: u128) !Buffer.From(Rng) { + const bits: [2]u64 = @bitCast(seed); + return .{ + ._state = try Buffer.fromSlice(platform, Shape.init(.{2}, .u64), &bits), + .algorithm = undefined, + }; + } + + /// Returns a Tensor of the given shape, filled with uniform random bits, and a new Rng state. + /// + /// The given Rng state should not be used anymore (or you'll get the same numbers again). + /// The output is guaranteed to be deterministic function of `self` Rng state, + /// but it is not guaranteed to be deterministic between implementations. + pub fn bitGenerator(self: Rng, sh: Shape) struct { Rng, Tensor } { + const ctx = CompilationContext.current(); + const loc = ctx.mlirCtx().location(@src()).namedFmt(ctx.mlirCtx(), "rand.bitGen({})", .{sh}); + const op = dialect.stablehlo.rng_bit_generator( + ctx.mlirCtx(), + self.algorithm, + self._state.value(), + mlir.ext.mlirType(ctx.mlirCtx(), self._state._shape), + mlir.ext.mlirType(ctx.mlirCtx(), sh), + loc, + ); + return .{ self.update(op.result(0)), _result(sh, op.result(1)) }; + } + + fn update(self: Rng, new_state: mlir.Value) Rng { + return .{ + ._state = _result(self._state._shape, new_state).reuseBuffer(self._state), + .algorithm = self.algorithm, + }; + } + + /// Returns a Tensor of the given shape, filled with uniformly sampled floating point numbers from an interval, + /// and a new Rng state. + /// + /// https://en.wikipedia.org/wiki/Continuous_uniform_distribution + pub fn uniform( + self: Rng, + shape_: Shape, + opts: struct { min: f64 = 0, max: f64 = 1 }, + ) struct { Rng, Tensor } { + const dt = if (shape_.dtype().isFloat()) shape_.dtype() else .f32; + + const mantissa_bit_count = @import("dtype.zig").mantissaSize(dt); + const bit_count: usize = dt.bitSizeOf(); + const rng_bit_count = if (mantissa_bit_count < 8) 8 else bit_count; + const uint_dtype: DataType = switch (bit_count) { + 8 => .u8, + 16 => .u16, + 32 => .u32, + 64 => .u64, + else => meta.panic("uniform don't support non-byte aligned dtype. Got: {}", .{shape_}), + }; + + const rng, const bits = self.bitGenerator(shape_.withDtype(uint_dtype)); + + // Erase bits outside of mantissa. + var float_bits = bits.shiftRightLogical(scalar(rng_bit_count - mantissa_bit_count, uint_dtype)); + + // Set exponent bits to represent e^0 (eg 127 for f32). + float_bits = float_bits.logical(.OR, scalar(1, dt).bitCast(uint_dtype)); + + // float_bits now uniformly represents number in [1, 2[ range. + // Let's convert to floats, and substract one to go to [0, 1[ range. + var floats = float_bits.bitCast(dt).sub(scalar(1, dt)); + floats = floats.mul(scalar(opts.max - opts.min, dt)).addConstant(opts.min); + + // Convert back to integer if needed. + return .{ rng, floats.convert(shape_.dtype()) }; + } + + test uniform { + const zml = @import("zml.zig"); + const Stats = struct { + const Stats = @This(); + + mean: Tensor, + variance: Tensor, + min: Tensor, + max: Tensor, + + pub fn uniformStats( + rand: Rng, + shape_: Shape, + opts: struct { min: f64, max: f64 }, + ) struct { Rng, Stats } { + const rng, const data = rand.uniform(shape_, .{ .min = opts.min, .max = opts.max }); + const mean_ = data.mean(0); + const variance = data.sub(mean_.broad(data.shape())).pow(Tensor.scalar(2, .f32)).mean(0); + return .{ rng, .{ + .mean = mean_, + .variance = variance, + .min = data.min(0), + .max = data.max(0), + } }; + } + }; + + const platform = zml.testing.env(); + // Compute stats over a uniform distribution on [-2, 10]. + const rand, const stats = try zml.testing.compileAndCall( + platform, + Stats.uniformStats, + .{ + try Rng.init(platform, 1234), + Shape.init(.{1024}, .f32), + .{ .min = -2, .max = 10 }, + }, + ); + // Check the Rng state has been modified. + try std.testing.expect(try rand._state.getValue(i128) != 1234); + + // Check the mean and variance are close to theoritical values. + const mean_ = try stats.mean.getValue(f32); + try std.testing.expectApproxEqAbs(4, mean_, 0.03); + + const variance = try stats.variance.getValue(f32); + try std.testing.expectApproxEqAbs(12.0 * 12.0 / 12.0, variance, 0.01); + + // Check that no value is outside of the interval + // and we have samples close to the edges. + const min_ = try stats.min.getValue(f32); + try std.testing.expect(min_ >= -2); + try std.testing.expectApproxEqAbs(-2, min_, 0.05); + + const max_ = try stats.max.getValue(f32); + try std.testing.expect(max_ < 10); + try std.testing.expectApproxEqAbs(10, max_, 0.05); + } + + /// Returns a Tensor of the given shape, filled with floating point numbers sampled from a normal distribution. + /// + /// Note: this uses stablehlo.rng which is deprecated. + /// https://github.com/openxla/stablehlo/blob/main/rfcs/20240503-opset-deprecations.md + pub fn normal(sh: Shape, opts: struct { mean: f64 = 0, stddev: f64 = 1 }) Tensor { + meta.assert(sh.dtype().isFloat(), "normal expects tensor type to be a float, got {}", .{sh.dtype()}); + + const ctx = CompilationContext.current().mlirCtx(); + const loc = ctx.location(@src()).namedFmt(ctx, "rand.normal({}, opts={})", .{ sh, opts }); + const a = Tensor.constant(.{}, Data.init(sh.dtype(), opts.mean)); + const b = Tensor.constant(.{}, Data.init(sh.dtype(), opts.stddev)); + const res_shape = Tensor.constantTensor(HostBuffer.fromSlice(.{sh.rank()}, sh.dims())); + const op = dialect.stablehlo.rng(ctx, a.value(), b.value(), res_shape.value(), .NORMAL, loc); + return _result(sh, op.result(0)); + } + + /// Returns a Tensor of the given shape, filled with floating point numbers sampled from a Gumbel distribution, and a new Rng state. + /// + /// Often used in ML because of the reparametrization tricks. + /// Sampling from a gumbel distribution is equivalent to sample + /// from a softmax distribution, but doesn't require to compute the sum of exponentials. + /// https://en.wikipedia.org/wiki/Gumbel_distribution#Gumbel_reparametrization_tricks + /// See `sampleTokens` for a practical use case. + /// Note: we only implement the μ=0, β=1 version. + pub fn gumbel(self: Rng, shape_: Shape) struct { Rng, Tensor } { + const rand, const u = self.uniform( + shape_, + // We don't want 0 to be sampled otherwise `log` will return -inf. + .{ .min = std.math.floatEps(f64), .max = 1 }, + ); + return .{ rand, u.log().scale(-1).log().scale(-1) }; + } + + test gumbel { + const zml = @import("zml.zig"); + const Stats = struct { + const Stats = @This(); + + mean: Tensor, + variance: Tensor, + actual_dist: Tensor, + + pub fn gumbelStats(rand: Rng, target_dist: Tensor) struct { Rng, Stats } { + const s = Shape.init(.{ .n = 1024, .d = 4 }, .f32); + const rng, const data = rand.gumbel(s); + const flat = data.flattenAll(); + const mean_ = flat.mean(0); + const variance = flat.sub(mean_.broad(flat.shape())).pow(Tensor.scalar(2, .f32)).mean(0); + + // Test out the gumbel reparametrization trick + var x = target_dist.log().withTags(.{.d}).broad(s); + x = x.add(data); + const samples = x.argMax(.d, .i32).indices.squeeze(.d); + + // count 0, 1, 2 and 3 in samples: + // - map 0 to 1, 1 to 2**16, 2 to 2**32, 3 to N**58 + // - sum in u64 + // - split to [4]u16 + const powers = blk: { + var powers: [4]u64 = undefined; + for (&powers, 0..) |*p, i| p.* = std.math.pow(u64, 2, i * 16); + break :blk powers; + }; + const values = Tensor.constantTensor(HostBuffer.fromArray(&powers)).withTags(.{.d}); + const counts = values.gather1d(.d, samples, .{}).sum(.d).bitCast(.u16); + const actual_dist = counts.reshape(target_dist.shape()).convert(target_dist.dtype()).divByConst(s.dim(.n)); + return .{ rng, .{ .mean = mean_, .variance = variance, .actual_dist = actual_dist } }; + } + }; + + const platform = zml.testing.env(); + const tgt_dist = [_]f32{ 2.0, 1.0, 4.0, 3.0 }; + const rand, const stats = try zml.testing.compileAndCall(platform, Stats.gumbelStats, .{ + try Rng.init(platform, 1234), try HostBuffer.fromArray(&tgt_dist).toDevice(platform), + }); + // Check the Rng state has been modified. + try std.testing.expect(try rand._state.getValue(i128) != 1234); + + // Check the mean and variance are close to theoritical values. + const mean_ = try stats.mean.getValue(f32); + try std.testing.expectApproxEqAbs(0.5772, mean_, 0.02); + + const variance = try stats.variance.getValue(f32); + const pi = std.math.pi; + try std.testing.expectApproxEqAbs(pi * pi / 6.0, variance, 0.03); + + // Check the distribution obtained with the gumbel trick matches the target distribution. + const actual_dist = try stats.actual_dist.getValue([4]f32); + scoped_log.debug("tgt_dist: {d}, actual_dist: {d}", .{ tgt_dist, actual_dist }); + for (tgt_dist, actual_dist) |tgt, actual| { + // We normalize tgt_dist to make it a well formed distribution. + // We didn't do it before calling gumbel, because the gumbel trick + // doesn't require normalized distributions as input. + try std.testing.expectApproxEqAbs(tgt / 10.0, actual, 0.05); + } + } + }; + + /// Returns a Tensor containing the element-wise conversion to another floating point type. + pub fn reducePrecision(self: Tensor, exponent_bits: i32, mantissa_bits: i32) Tensor { + meta.assert(self.dtype().isFloat(), "reducePrecision expects tensor type to be a float, got {}", .{self.dtype()}); + meta.assert(1 <= exponent_bits, "reducePrecision expects 'exponent_bits' to be >= 1, got {}", .{exponent_bits}); + meta.assert(0 <= mantissa_bits, "reducePrecision expects 'mantissa_bits' to be positive, got {}", .{mantissa_bits}); + + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "reducePrecision(exponent_bits={}, mantissa_bits={})", .{ exponent_bits, mantissa_bits }); + const op = dialect.stablehlo.reduce_precision(self.getContext().mlirCtx(), self.value(), exponent_bits, mantissa_bits, loc); + return _result(self._shape, op.result(0)); + } + + inline fn convolution(self: Tensor, other: Tensor, opts: dialect.stablehlo.ConvolutionOpts, loc: mlir.Location) Tensor { + meta.assert(self.rank() == other.rank(), "convolution expects tensor ranks to match, got {} and {}", .{ self.rank(), other.rank() }); + const N = self.rank(); + meta.guard(opts.window_strides.len == N - 2, @src()); + for (opts.window_strides) |s| meta.guard(0 < s, @src()); + meta.guard(opts.lhs_dilation.len == N - 2, @src()); + for (opts.lhs_dilation) |d| meta.guard(0 < d, @src()); + meta.guard(opts.rhs_dilation.len == N - 2, @src()); + for (opts.rhs_dilation) |d| meta.guard(0 < d, @src()); + meta.guard(opts.window_reversal.len == N - 2, @src()); + meta.guard(@rem(self.dim(opts.input_batch_dimension), opts.batch_group_count) == 0, @src()); + meta.guard(@rem(self.dim(opts.input_feature_dimension), opts.feature_group_count) == 0, @src()); + meta.guard(opts.input_spatial_dimensions.len == N - 2, @src()); + meta.guard(opts.input_batch_dimension != opts.input_feature_dimension, @src()); + meta.guard(0 <= opts.input_batch_dimension and opts.input_batch_dimension < N, @src()); + meta.guard(0 <= opts.input_feature_dimension and opts.input_feature_dimension < N, @src()); + for (opts.input_spatial_dimensions, 0..) |d, i| { + meta.guard(d != opts.input_batch_dimension, @src()); + meta.guard(d != opts.input_feature_dimension, @src()); + meta.guard(0 <= d and d < N, @src()); + if (i < opts.input_spatial_dimensions.len - 1) continue; + meta.guard(std.mem.indexOfScalar(i64, opts.input_spatial_dimensions[i + 1 ..], d) == null, @src()); + } + meta.guard(other.dim(opts.kernel_input_feature_dimension) == @divTrunc(self.dim(opts.input_feature_dimension), opts.feature_group_count), @src()); + meta.guard(@rem(other.dim(opts.kernel_output_feature_dimension), opts.batch_group_count) == 0, @src()); + meta.guard(@rem(other.dim(opts.kernel_output_feature_dimension), opts.feature_group_count) == 0, @src()); + meta.guard(opts.kernel_spatial_dimensions.len == N - 2, @src()); + meta.guard(opts.kernel_input_feature_dimension != opts.kernel_output_feature_dimension, @src()); + meta.guard(0 <= opts.kernel_input_feature_dimension and opts.kernel_input_feature_dimension < N, @src()); + meta.guard(0 <= opts.kernel_output_feature_dimension and opts.kernel_output_feature_dimension < N, @src()); + for (opts.kernel_spatial_dimensions, 0..) |d, i| { + meta.guard(d != opts.kernel_input_feature_dimension, @src()); + meta.guard(d != opts.kernel_output_feature_dimension, @src()); + meta.guard(0 <= d and d < N, @src()); + if (i < opts.kernel_spatial_dimensions.len - 1) continue; + meta.guard(std.mem.indexOfScalar(i64, opts.kernel_spatial_dimensions[i + 1 ..], d) == null, @src()); + } + meta.guard(opts.output_spatial_dimensions.len == N - 2, @src()); + meta.guard(opts.output_batch_dimension != opts.output_feature_dimension, @src()); + meta.guard(0 <= opts.output_batch_dimension and opts.output_batch_dimension < N, @src()); + meta.guard(0 <= opts.output_feature_dimension and opts.output_feature_dimension < N, @src()); + for (opts.output_spatial_dimensions, 0..) |d, i| { + meta.guard(d != opts.output_batch_dimension, @src()); + meta.guard(d != opts.output_feature_dimension, @src()); + meta.guard(0 <= d and d < N, @src()); + if (i < opts.output_spatial_dimensions.len - 1) continue; + meta.guard(std.mem.indexOfScalar(i64, opts.output_spatial_dimensions[i + 1 ..], d) == null, @src()); + } + meta.guard(0 < opts.feature_group_count, @src()); + meta.guard(0 < opts.batch_group_count, @src()); + meta.guard(opts.feature_group_count == 1 or opts.batch_group_count == 1, @src()); + var used_opts = opts; + used_opts.pad_shape = &.{ @intCast(N - 2), 2 }; + used_opts.precision_config = &.{ .DEFAULT, .DEFAULT }; + + var new_shape = self._shape; + var res_dim: i64 = undefined; + + for (0..N) |i| { + if (i == @as(usize, @intCast(opts.output_batch_dimension))) { + res_dim = @divTrunc(self.dim(opts.input_batch_dimension), opts.batch_group_count); + } else if (i == @as(usize, @intCast(opts.output_feature_dimension))) { + res_dim = other.dim(opts.kernel_output_feature_dimension); + } else { + // calculate spatial dimension value + const spatial_dim: usize = std.mem.indexOfScalar(i64, opts.output_spatial_dimensions, @as(i64, @intCast(i))).?; + const lhs_dim = opts.input_spatial_dimensions[spatial_dim]; + const rhs_dim = opts.kernel_spatial_dimensions[spatial_dim]; + const dilated_input_shape_lhs_dim: i64 = if (self.dim(lhs_dim) == 0) 0 else (self.dim(lhs_dim) - 1) * opts.lhs_dilation[spatial_dim] + 1; + const left_pad_value, const right_pad_value = if (opts.pad_value.len == 1) + .{ opts.pad_value[0], opts.pad_value[0] } + else + .{ opts.pad_value[2 * spatial_dim], opts.pad_value[2 * spatial_dim + 1] }; + const padded_input_shape_lhs_dim = left_pad_value + dilated_input_shape_lhs_dim + right_pad_value; + const dilated_window_shape_lhs_dim: i64 = if (other.dim(rhs_dim) == 0) 0 else (other.dim(rhs_dim) - 1) * opts.rhs_dilation[spatial_dim] + 1; + const is_empty_window_lhs_dim = padded_input_shape_lhs_dim == 0 or dilated_window_shape_lhs_dim > padded_input_shape_lhs_dim; + res_dim = if (is_empty_window_lhs_dim) 0 else @divTrunc(padded_input_shape_lhs_dim - dilated_window_shape_lhs_dim, opts.window_strides[spatial_dim]) + 1; + } + + new_shape = new_shape.set(i, res_dim); + } + + // inferred shape '[1, 256, 1, 12008]' is incompatible with return type of operation '[1, 256, 1, 11978]' + const op = dialect.stablehlo.convolution( + self.getContext().mlirCtx(), + self.value(), + other.value(), + used_opts, + mlir.ext.RankedTensorType.fromShape(self.getContext().mlirCtx(), new_shape).as(mlir.Type).?, + loc, + ); + + return _result(new_shape, op.result(0)); + } + + /// Returns a Tensor containing the result of the 1D convolution of 'input' by 'kernel'. + pub fn conv1d( + input: Tensor, + kernel: Tensor, + opts: struct { + window_strides: i64 = 1, + padding: []const i64 = &.{ 0, 0 }, + lhs_dilation: i64 = 1, + rhs_dilation: i64 = 1, + window_reversal: bool = false, + input_batch_dimension: i64 = 0, + input_feature_dimension: i64 = 1, + input_spatial_dimensions: i64 = 2, + kernel_output_feature_dimension: i64 = 0, + kernel_input_feature_dimension: i64 = 1, + kernel_spatial_dimensions: i64 = 2, + output_batch_dimension: i64 = 0, + output_feature_dimension: i64 = 1, + output_spatial_dimensions: i64 = 2, + feature_group_count: i64 = 1, + batch_group_count: i64 = 1, + }, + ) Tensor { + const loc = input.getContext().mlirCtx().location(@src()).namedFmt(input.getContext().mlirCtx(), "opts={}", .{opts}); + return input.convolution(kernel, .{ + .window_strides = &.{opts.window_strides}, + .pad_value = opts.padding, + .lhs_dilation = &.{opts.lhs_dilation}, + .rhs_dilation = &.{opts.rhs_dilation}, + .window_reversal = &.{opts.window_reversal}, + .input_batch_dimension = opts.input_batch_dimension, + .input_feature_dimension = opts.input_feature_dimension, + .input_spatial_dimensions = &.{opts.input_spatial_dimensions}, + .kernel_input_feature_dimension = opts.kernel_input_feature_dimension, + .kernel_output_feature_dimension = opts.kernel_output_feature_dimension, + .kernel_spatial_dimensions = &.{opts.kernel_spatial_dimensions}, + .output_batch_dimension = opts.output_batch_dimension, + .output_feature_dimension = opts.output_feature_dimension, + .output_spatial_dimensions = &.{opts.output_spatial_dimensions}, + .feature_group_count = opts.feature_group_count, + .batch_group_count = opts.batch_group_count, + }, loc); + } + + /// Returns a Tensor containing the result of the 2D convolution of 'input' by 'kernel'. + /// Defaults values correspond to a (B, C_in, W, H) image, (C_out, C_in, W, H) kernel weights and (B, C_out, W, H) output. + pub fn conv2d( + input: Tensor, + kernel: Tensor, + opts: struct { + window_strides: []const i64 = &.{ 1, 1 }, + padding: []const i64 = &.{ 0, 0, 0, 0 }, + lhs_dilation: []const i64 = &.{ 1, 1 }, + rhs_dilation: []const i64 = &.{ 1, 1 }, + window_reversal: []const bool = &.{ false, false }, + input_batch_dimension: i64 = 0, + input_feature_dimension: i64 = 1, + input_spatial_dimensions: []const i64 = &.{ 2, 3 }, + kernel_input_feature_dimension: i64 = 1, + kernel_output_feature_dimension: i64 = 0, + kernel_spatial_dimensions: []const i64 = &.{ 2, 3 }, + output_batch_dimension: i64 = 0, + output_feature_dimension: i64 = 1, + output_spatial_dimensions: []const i64 = &.{ 2, 3 }, + feature_group_count: i64 = 1, + batch_group_count: i64 = 1, + }, + ) Tensor { + const loc = input.getContext().mlirCtx().location(@src()).namedFmt(input.getContext().mlirCtx(), "opts={}", .{opts}); + return input.convolution(kernel, .{ + .window_strides = opts.window_strides, + .pad_value = opts.padding, + .lhs_dilation = opts.lhs_dilation, + .rhs_dilation = opts.rhs_dilation, + .window_reversal = opts.window_reversal, + .input_batch_dimension = opts.input_batch_dimension, + .input_feature_dimension = opts.input_feature_dimension, + .input_spatial_dimensions = opts.input_spatial_dimensions, + .kernel_input_feature_dimension = opts.kernel_input_feature_dimension, + .kernel_output_feature_dimension = opts.kernel_output_feature_dimension, + .kernel_spatial_dimensions = opts.kernel_spatial_dimensions, + .output_batch_dimension = opts.output_batch_dimension, + .output_feature_dimension = opts.output_feature_dimension, + .output_spatial_dimensions = opts.output_spatial_dimensions, + .feature_group_count = opts.feature_group_count, + .batch_group_count = opts.batch_group_count, + }, loc); + } + + /// Returns a Tensor containing the element-wise addition of the input Tensors. + pub fn add(self: Tensor, other: Tensor) Tensor { + return binaryOp("add", dialect.stablehlo.add)(self, other); + } + + /// Returns a Tensor containing the element-wise subtraction of the input Tensors. + pub fn sub(self: Tensor, other: Tensor) Tensor { + return binaryOp("subtract", dialect.stablehlo.subtract)(self, other); + } + + /// Returns a Tensor containing the element-wise multiplication of the input Tensors. + pub fn mul(self: Tensor, other: Tensor) Tensor { + return binaryOp("mul", dialect.stablehlo.multiply)(self, other); + } + + /// Returns a Tensor containing the element-wise division of the input Tensors. + pub fn div(self: Tensor, other: Tensor) Tensor { + return binaryOp("div", dialect.stablehlo.divide)(self, other); + } + + /// Returns a Tensor containing the element-wise exponentiation of the input Tensors. + pub fn pow(self: Tensor, other: Tensor) Tensor { + return binaryOp("pow", dialect.stablehlo.power)(self, other); + } + + /// Returns a Tensor containing the element-wise maximum operation of the input Tensors. + pub fn maximum(self: Tensor, other: Tensor) Tensor { + return binaryOp("maximum", dialect.stablehlo.maximum)(self, other); + } + + /// Returns a Tensor containing the element-wise minimum operation of the input Tensors. + pub fn minimum(self: Tensor, other: Tensor) Tensor { + return binaryOp("minimum", dialect.stablehlo.minimum)(self, other); + } + + /// Returns a Tensor containing the element-wise addition of the input Tensor with a constant. + pub fn addConstant(self: Tensor, b: anytype) Tensor { + return self.add(Tensor.scalar(b, self.dtype())); + } + + /// Returns a Tensor containing the element-wise division of the input Tensor by a constant. + pub fn divByConst(self: Tensor, b: anytype) Tensor { + return self.div(Tensor.scalar(b, self.dtype())); + } + + /// Returns a Tensor containing the element-wise multiplication of the input Tensor by a constant. + pub inline fn scale(self: Tensor, val: anytype) Tensor { + return self.mul(Tensor.scalar(val, self.dtype())); + } + + pub const LogicalOp = enum { OR, XOR, AND }; + + /// Returns a Tensor containing the element-wise logical operation of the input Tensors. + pub fn logical(self: Tensor, comptime logical_op: LogicalOp, other: Tensor) Tensor { + return switch (logical_op) { + .OR => binaryOp("or", dialect.stablehlo.or_)(self, other), + .XOR => binaryOp("xor", dialect.stablehlo.xor)(self, other), + .AND => binaryOp("and", dialect.stablehlo.and_)(self, other), + }; + } + + /// Returns a Tensor containing the element-wise floor operation of the input Tensor. + pub fn floor(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + return _result(self._shape, dialect.stablehlo.floor(self.getContext().mlirCtx(), self.value(), loc).result(0)); + } + + /// Returns a Tensor containing the element-wise ceil operation of the input Tensor. + pub fn ceil(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + return _result(self._shape, dialect.stablehlo.ceil(self.getContext().mlirCtx(), self.value(), loc).result(0)); + } + + /// Returns a Tensor containing the element-wise conversion to another type. + pub fn convert(self: Tensor, dt: DataType) Tensor { + if (dt == self.dtype()) { + return self; + } + + const res_type = mlir.RankedTensorType.init(self.dims(), mlir.ext.Type.fromDType(self.getContext().mlirCtx(), dt)).as(mlir.Type).?; + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "dtype={}", .{dt}); + + const op = dialect.stablehlo.convert(self.getContext().mlirCtx(), self.value(), res_type, loc); + return _result(self._shape.withDtype(dt), op.result(0)); + } + + /// Returns a Tensor containing the element-wise rounding operation of the input Tensor. + pub fn round(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const sine_op = dialect.stablehlo.round_nearest_even(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, sine_op.result(0)); + } + + /// Returns a Tensor containing the element-wise clamping operation of the input Tensor. + pub fn clamp(self: Tensor, min_: Tensor, max_: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.clamp(self.getContext().mlirCtx(), min_.value(), self.value(), max_.value(), loc); + return _result(self._shape, op.result(0)); + } + + /// See torch.matmul + pub fn matmul(lhs: Tensor, rhs: Tensor) Tensor { + return @import("torch.zig").matmul(lhs, rhs); + } + + /// Matrix multiplication, where contracting axes are specified using their tags. + /// eg dot(.{ .a, .b, .c }, .{ .a, .c, .d }, .{ .c }) -> .{ .a, .c, .d } + /// Axes with the same tag on both sides, and which aren't contracting, + /// are considered "batching axes". + pub fn dot(lhs: Tensor, rhs: Tensor, comptime contracting: anytype) Tensor { + var contracting_axes: [contracting.len][2]i8 = undefined; + inline for (contracting, 0..) |c, i| { + contracting_axes[i] = .{ lhs.axis(c), rhs.axis(c) }; + } + + var batching_axes: [MAX_RANK][2]i8 = undefined; + var n_batching: u8 = 0; + for (lhs._shape.tags(), 0..) |l, li| { + meta.assert(l != Shape.TagUnknown, "Can't use `dot(..., {any})` on {any}, it need to be explictily tagged.", .{ contracting, lhs }); + + for (rhs._shape.tags(), 0..) |r, ri| { + meta.assert(r != Shape.TagUnknown, "Can't use `dot(..., {any})` on {any}, it need to be explictily tagged.", .{ contracting, rhs }); + + if (l == r) { + for (contracting_axes) |ct| { + if (l == lhs._shape.tag(ct[0])) { + break; + } + } else { + // tag is both in lhs and rhs but not in contracting -> it's a batching dim. + batching_axes[n_batching] = .{ @intCast(li), @intCast(ri) }; + n_batching += 1; + } + } + } + } + + return dotGeneral(lhs, rhs, contracting_axes[0..], batching_axes[0..n_batching]); + } + + test dot { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + + var comp = try zml.module.CompilationContext.init(std.heap.page_allocator, "test", platform); + defer comp.deinit(); + + comp.activate(); + defer comp.deactivate(); + + inline for (.{ + .{ .{ .c = 20 }, .{ .c = 20 }, .{.c}, .{} }, + .{ + .{ .a = 20, .b = 21, .c = 22 }, + .{ .a = 20, .d = 23, .c = 22 }, + .{.c}, + .{ .a = 20, .b = 21, .d = 23 }, + }, + .{ + .{ .a = 20, .b = 21, .c = 22 }, + .{ .c = 22, .d = 23, .e = 24 }, + .{.c}, + .{ .a = 20, .b = 21, .d = 23, .e = 24 }, + }, + .{ + .{ .a = 20, .b = 21, .c = 22 }, + .{ .c = 22, .d = 23, .a = 20 }, + .{ .c, .a }, + .{ .b = 21, .d = 23 }, + }, + }) |testcase| { + const x_shape, const y_shape, const ctr, const z_shape = testcase; + const x = Tensor.constant(x_shape, .{ .f32 = 0.0 }); + const y = Tensor.constant(y_shape, .{ .f32 = 0.0 }); + const z = x.dot(y, ctr); + + try zml.testing.expectEqualShapes(Shape.init(z_shape, .f32), z.shape()); + } + } + + /// Generalized matrix multiplication of two tensors along the specified axes. + /// In this version batching dimensions need to be explicitly specified. + /// The result shape is made of (batching_axes ++ lhs_result_axes ++ rhs_result_axes. + /// Where "result axes" are non-contracting, non-batching axes of each input tensor. + pub fn dotGeneral(lhs: Tensor, rhs: Tensor, contracting_axes: []const [2]i8, batching_axes: []const [2]i8) Tensor { + meta.assert(lhs.dtype() == rhs.dtype(), "dotGeneral expects tensors to be of the same type, got {} and {}", .{ lhs.dtype(), rhs.dtype() }); + + const Axes = std.BoundedArray(i64, MAX_RANK); + + var res_shape: Shape = .{ ._dtype = lhs.dtype() }; + // Validate batching axes + var lhs_batching_axes: Axes = .{}; + var rhs_batching_axes: Axes = .{}; + for (batching_axes) |b_axes| { + const l, const r = b_axes; + meta.assert(lhs._shape.dim(l) == rhs._shape.dim(r), "dotGeneral expects batching dimensions to be equal, got {} and {} in {} and {}", .{ l, r, lhs, rhs }); + var t = lhs._shape.tag(l); + if (t == Shape.TagUnknown) t = rhs._shape.tag(r); + res_shape = res_shape.appendDim(lhs._shape.dim(l), t); + lhs_batching_axes.appendAssumeCapacity(lhs._shape.axis(l)); + rhs_batching_axes.appendAssumeCapacity(rhs._shape.axis(r)); + } + + // Validate contracting axes + var lhs_contracting_axes: Axes = .{}; + var rhs_contracting_axes: Axes = .{}; + for (contracting_axes) |c_axes| { + const l, const r = c_axes; + meta.assert(lhs._shape.dim(l) == rhs._shape.dim(r), "dotGeneral expects contracting dimensions to be equal, got {} and {} in {} and {}", .{ l, r, lhs, rhs }); + lhs_contracting_axes.appendAssumeCapacity(lhs._shape.axis(l)); + rhs_contracting_axes.appendAssumeCapacity(rhs._shape.axis(r)); + } + + // Result shape is obtained by concatenating batching dimensions, (already done) + // then dimensions from lhs axes that aren't contracting nor batching, + // then dimensions from rhs axes that aren't contracting nor batching. + for (0..lhs.rank()) |l| { + if (std.mem.indexOfScalar(i64, lhs_contracting_axes.constSlice(), @intCast(l))) |_| { + continue; + } + if (std.mem.indexOfScalar(i64, lhs_batching_axes.constSlice(), @intCast(l))) |_| { + continue; + } + res_shape = res_shape.appendDim(lhs._shape.dim(l), lhs._shape.tag(l)); + } + for (0..rhs.rank()) |r| { + if (std.mem.indexOfScalar(i64, rhs_contracting_axes.constSlice(), @intCast(r))) |_| { + continue; + } + if (std.mem.indexOfScalar(i64, rhs_batching_axes.constSlice(), @intCast(r))) |_| { + continue; + } + res_shape = res_shape.appendDim(rhs._shape.dim(r), rhs._shape.tag(r)); + } + + const loc = lhs.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.dot_general( + lhs.getContext().mlirCtx(), + lhs.value(), + rhs.value(), + mlir.ext.mlirType(lhs.getContext().mlirCtx(), res_shape), + loc, + .{ + .lhs_batching_dimensions = lhs_batching_axes.constSlice(), + .rhs_batching_dimensions = rhs_batching_axes.constSlice(), + .lhs_contracting_dimensions = lhs_contracting_axes.constSlice(), + .rhs_contracting_dimensions = rhs_contracting_axes.constSlice(), + .precision = &.{ .DEFAULT, .DEFAULT }, + }, + ); + return _result(res_shape, op.result(0)); + } + + /// Returns a Tensor containing the sigmoid function applied to each element of the input Tensor. + pub fn sigmoid(self: Tensor) Tensor { + // until the metal plugin supports `stablehlo.logistics`, implement in the way JAX does it + const one = Tensor.constant(&.{}, self.dtype().one()).broadcast(self._shape, &.{}); + return one.div(one.add(self.negate().exp())); + } + + /// Returns a Tensor containing the ReLU activation function applied to each element of the input Tensor. + pub fn relu(self: Tensor) Tensor { + return self.maximum(Tensor.constant(self.dims(), self.dtype().zero())); + } + + /// Returns a Tensor containing the leaky-ReLU activation function applied to each element of the input Tensor. + /// + /// LeakyReLU(x) = max(0,x) + negative_slope * min(0,x) + /// ref: https://paperswithcode.com/method/leaky-relu + pub fn leakyReLU(self: Tensor, negative_slope: f32) Tensor { + const below_zero = self.scale(negative_slope).minimum(Tensor.scalar(0, self.dtype())); + return self.relu().add(below_zero); + } + + test leakyReLU { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + + const input = try zml.Buffer.fromSlice(platform, .{2}, &[_]f32{ -0.6884, 1.6795 }); + const res = try zml.testing.compileAndCall(platform, leakyReLU, .{ input, 0.1 }); + + const expectation = zml.HostBuffer.fromArray(&[2]f32{ -0.0688, 1.6795 }); + try zml.testing.expectClose(expectation, res, 1e-4); + } + + /// Returns a Tensor containing the SwiGLU activation function applied to the input Tensor. + pub fn swiglu(self: Tensor, beta: f32, w: Tensor, b: Tensor) Tensor { + const sigmoid_tensor = self.mul(Tensor.constant(self._shape, Data.init(self.dtype(), beta))).sigmoid(); + const one_minus_sigmoid_tensor = Tensor.constant(self._shape, Data.init(self.dtype(), 1)).sub(sigmoid_tensor); + + return self.mul(sigmoid_tensor).add(one_minus_sigmoid_tensor.mul(w.matmul(self).add(b))); + } + + /// Returns a Tensor containing the Gaussian Error Linear Units (GeLU) activation function applied to each element of the input Tensor. + /// + /// We use an approximation of the erf function using tanh: + /// gelu(x) ≃ 0.5 * x * (1 + tanh(sqrt(2 / pi) * (x + 0.044715 * x^3))) + /// see: https://paperswithcode.com/method/gelu + pub fn gelu(x: Tensor) Tensor { + const scaled_x_cube = x.mul(x).mul(x).scale(0.044715); + const one = Tensor.constant(x._shape, x.dtype().one()); + const one_plus_tanh = Tensor.add(x, scaled_x_cube).scale(std.math.sqrt(2.0 / std.math.pi)).tanh().add(one); + return one_plus_tanh.mul(x).scale(0.5); + } + + /// Returns a Tensor containing an approximation of the Gaussian Error Linear Units (GeLU) activation function applied to each element of the input Tensor. + /// + /// It's an even more crude approximation than gelu. + pub fn quickGelu(x: Tensor) Tensor { + return x.scale(1.702).sigmoid().mul(x); + } + + /// Returns a Tensor containing the Sigmoid Linear Unit (SiLU) activation function applied to each element of the input Tensor. + /// + /// silu(x) = x σ(x) + /// https://paperswithcode.com/method/silu + pub fn silu(x: Tensor) Tensor { + return x.mul(x.sigmoid()); + } + + /// Returns a Tensor containing the softmax function applied to each element of the input Tensor. + pub fn softmax(self: Tensor, axis_: anytype) Tensor { + const a = self.axis(axis_); + const exp_diff_max = self.sub(self.max(a).broad(self._shape)).exp(); + return exp_diff_max.div(exp_diff_max.sum(a).broad(self._shape)); + } + + /// Returns a Tensor containing the log of the sum of exponential over the given axis. + pub fn logSumExp(self: Tensor, axis_: anytype) Tensor { + const a = self.axis(axis_); + // stabilization: shift `self` by it's max value before passing to exponent. + const M = self.max(a); + const log_sum_exp = log(sum(exp(self.sub(M.broad(self._shape))), a)); + // restore the shift again + return M.add(log_sum_exp); + } + + /// Returns a Tensor containing the sum of elements over the given axis. + pub fn sum(self: Tensor, axis_: anytype) Tensor { + const a = self.axis(axis_); + return ops.reduce( + struct { + pub fn acc(x: Tensor, res: Tensor) Tensor { + return res.add(x.convert(res.dtype())); + } + }.acc, + self, + Tensor.scalar(0, self.dtype()), + &.{a}, + ); + } + + /// Returns a Tensor containing the mean of elements over the given axis. + pub fn mean(self: Tensor, axis_: anytype) Tensor { + return self.sum(axis_).divByConst(self.dim(axis_)); + } + + /// Returns a transposed Tensor computed using the given axes. + pub fn transpose(self: Tensor, axes_: anytype) Tensor { + const axes__ = self.axes(axes_).constSlice(); + const default_perm = [MAX_RANK]i64{ 7, 6, 5, 4, 3, 2, 1, 0 }; + const no_op = [MAX_RANK]i64{ 0, 1, 2, 3, 4, 5, 6, 7 }; + + const permutation: []const i64 = if (axes__.len == 0) + default_perm[MAX_RANK - self.rank() ..] + else + toI64(axes__); + + meta.assert(permutation.len == self.rank(), "transpose expects input tensor rank and 'axes_' length to be equal, got {} and {}", .{ self.rank(), permutation.len }); + + if (std.mem.eql(i64, permutation, no_op[0..self.rank()])) { + return self; + } + + const res_shape = self._shape.transpose(permutation); + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "tr({any})", .{axes_}); + const op = dialect.stablehlo.transpose( + self.getContext().mlirCtx(), + self.value(), + mlir.ext.mlirType(self.getContext().mlirCtx(), res_shape), + loc, + .{ .permutation = toI64(permutation) }, + ); + return _result(res_shape, op.result(0)); + } + + /// Returns a Tensor with the given axis unflattened. + /// + /// unflatten((d0, d1, axis_m, d3), 2, n) -> (d0, d1, n, d2_m, d3) + pub fn unflatten(self: Tensor, axis_: i8, n: i64) Tensor { + meta.assert(self.rank() < Tensor.MAX_RANK, "unflatten expects input tensor rank to be less than {}, got {}", .{ Tensor.MAX_RANK, self.rank() }); + + const a = if (axis_ >= 0) self.axis(axis_) else self.axis(axis_) + 1; + const new_dim = std.math.divExact(i64, self.dim(a), n) catch std.debug.panic("unflatten expects chosen dimension to be divisible by 'n' but {} is not divisible by {}", .{ self.dim(a), n }); + const new_shape = self._shape.set(a, n).insert(a + 1, .{ ._ = new_dim }); + + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "axis={}, n={}", .{ axis_, n }); + const reshaped_val = dialect.stablehlo.reshape( + self.getContext().mlirCtx(), + self.value(), + mlir.ext.RankedTensorType.fromShape(self.getContext().mlirCtx(), new_shape), + loc, + ); + return _result(new_shape, reshaped_val.result(0)); + } + + /// Splits the given axis in several axes. + /// eg: `Tensor.init(.{ .a = 10, .b = 3 }).split(.a, .{.a1 = 5, .a2 = 2});` + /// The number of elements in the split shape must match the number of element + /// in the target axis. + pub fn splitAxis(self: Tensor, ax: anytype, split_shape: anytype) Tensor { + const new_shape = self._shape.splitAxis(ax, split_shape); + + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "splitAxis({}, {any})", .{ ax, split_shape }); + const reshaped_val = dialect.stablehlo.reshape( + self.getContext().mlirCtx(), + self.value(), + mlir.ext.RankedTensorType.fromShape(self.getContext().mlirCtx(), new_shape), + loc, + ); + return _result(new_shape, reshaped_val.result(0)); + } + + /// Merges two or more contiguous axes into one axis. + pub fn merge(self: Tensor, merges_: anytype) Tensor { + return self.reshape(self._shape.mergeAxes(merges_)); + } + + /// Merges two or more non-contiguous axes into one axis. + /// Will make a transpose if needed. + /// .{ .a, .b, .c }.mergeTranspose(.{ .a, .c }, .ac) -> .{ .b, .ac } + pub fn mergeTranspose(self: Tensor, axes_: anytype, merged: EnumLiteral) Tensor { + const cont = self.contiguous(axes_); + return cont.reshape(cont._shape.mergeAxis(axes_, merged)); + } + + /// Transposes the input Tensor, such has the given axes end up in contiguous position. + /// .{ .a, .b, .c, .d }.contiguous(.{ .c, .a }) -> .{ .b, .d, .c, .a } + pub fn contiguous(self: Tensor, axes_: anytype) Tensor { + const perm = self._shape.contiguousPerm(axes_); + return self.transpose(perm.constSlice()); + } + + /// Flattens the given axis and the next one, into one new axis. + pub fn flatten(self: Tensor, axis_: anytype) Tensor { + const old_shape = self._shape; + const a = self.axis(axis_); + // meta.assert(a + 1 < self.rank(), "Can't flatten {} on the last axis {}.", .{ self, axis }); + const new_shape = old_shape.remove(a + 1).set(a, old_shape.dim(a) * old_shape.dim(a + 1)); + + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "axis={}", .{axis_}); + + const reshaped_val = dialect.stablehlo.reshape( + self.getContext().mlirCtx(), + self.value(), + mlir.ext.RankedTensorType.fromShape(self.getContext().mlirCtx(), new_shape), + loc, + ); + // log.debug("flatten({d}, {d}) -> {d}", .{ self.dims(), axis_, new_shape[0 .. self.rank() - 1] }); + return _result(new_shape, reshaped_val.result(0)); + } + + pub inline fn flattenAll(self: Tensor) Tensor { + return self.reshape(.{self.count()}); + } + + pub const Slice = struct { + single: ?i64 = null, + start: i64 = 0, + end: ?i64 = null, + step: i64 = 1, + }; + + /// Slices the input Tensor over the given axis using the given parameters. + pub fn slice1d(self: Tensor, axis_: anytype, s: Slice) Tensor { + var slices = [_]Slice{.{}} ** MAX_RANK; + slices[self.axis(axis_)] = s; + return self.slice(slices[0..self.rank()]); + } + + /// Slices the input Tensor using the given parameters. + pub fn slice(self: Tensor, slices: []const Slice) Tensor { + var start_indices: [MAX_RANK]i64 = undefined; + var strides: [MAX_RANK]i64 = undefined; + var limit_indices: [MAX_RANK]i64 = undefined; + var res_shape: Shape = self._shape; + + for (slices, 0..) |s, a| { + meta.assert(s.step > 0, "slice expects 'step' to be positive, got {} at index {}", .{ s.step, a }); + + const args: Slice = .{ + .start = self.wrapIndex(a, s.start), + .end = if (s.end) |end| self.wrapIndex(a, end) else self.dim(a), + .step = s.step, + }; + start_indices[a] = args.start; + limit_indices[a] = args.end.?; + strides[a] = args.step; + res_shape = res_shape.setDim(a, std.math.divCeil(i64, args.end.? - args.start, args.step) catch unreachable); + } + + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "slices={any}", .{slices}); + const result_type = mlir.ext.RankedTensorType.fromShape(self.getContext().mlirCtx(), res_shape).as(mlir.Type).?; + const slice_op = dialect.stablehlo.slice(self.getContext().mlirCtx(), self.value(), start_indices[0..self.rank()], limit_indices[0..self.rank()], strides[0..self.rank()], result_type, loc); + + return _result(res_shape, slice_op.result(0)); + } + + inline fn wrapIndex(self: Tensor, axis_: usize, idx: i64) i64 { + return if (idx < 0) self.dim(axis_) + idx else idx; + } + + pub fn choose1d(self: Tensor, axis_: i64, i: i64) Tensor { + return self.slice1d(axis_, .{ .start = i, .end = i + 1 }).squeeze(axis_); + } + + /// Concatenates the input Tensors along the given axis. + pub fn concatenate(tensors: []const Tensor, axis_: i64) Tensor { + meta.assert(tensors.len <= 32, "concatenate only supports up to 32 tensors, got {}", .{tensors.len}); + // TODO taggedVal + var buffer: [32]mlir.Value = undefined; + std.debug.assert(tensors.len <= buffer.len); + std.debug.assert(tensors.len > 0); + const a = tensors[0].axis(axis_); + // TODO(Corendos): Check that tensor axes match. + + var concatenated_dim: i64 = 0; + for (tensors, 0..) |t, i| { + buffer[i] = t.value(); + concatenated_dim += t.dim(a); + } + + const res_shape = tensors[0]._shape.set(a, concatenated_dim); + const loc = tensors[0].getContext().mlirCtx().location(@src()).namedFmt(tensors[0].getContext().mlirCtx(), "axis={}", .{axis_}); + const op = dialect.stablehlo.concatenate(tensors[0].getContext().mlirCtx(), buffer[0..tensors.len], a, loc); + // log.debug("concatenate({}, {}, {d}) -> {d}", .{ tensors[0], tensors[1], a, res_shape }); + return _result(res_shape, op.result(0)); + } + + /// Concatenates the input Tensors along a new axis. The Tensors must have the same shape. + /// For x, y, z of shape .{ .a = 10, .b = 11, .c = 12 }: + /// - Tensor.stack(&.{x, y, z}, .b, .layers) -> .{ .a, .layers, .b, .c } + /// - Tensor.stack(&.{x, y, z}, 1, .layers) -> .{ .a, .layers, .b, .c } + /// - Tensor.stack(&.{x, y, z}, .last, .layers) -> .{ .a, .b, .c, .layers } + pub fn stack(tensors: []const Tensor, axis_: anytype, tag: anytype) Tensor { + // Note: we could ask the compilation context for some memory instead of stack allocating + meta.assert(tensors.len <= 32, "stack only supports up to 32 tensors, got {}", .{tensors.len}); + + const shape0 = tensors[0]._shape; + const res_shape = shape0.insertTag(axis_, 1, tag); + + for (tensors[1..]) |tensor| { + meta.assert(shape0.eqlWithTags(tensor._shape), "stack expects tensor shapes to match, got {} and {}", .{ tensor._shape, shape0 }); + } + + var reshaped: [32]Tensor = undefined; + for (tensors, 0..) |tensor, i| { + reshaped[i] = tensor.reshape(res_shape); + } + + // Be careful here: we need to resolve ax before calling concatenate, + // because we added an axis, so all + const ax = if (@TypeOf(axis_) == EnumLiteral and axis_ == .last) + shape0.rank() + else + shape0.axis(axis_); + + return Tensor.concatenate(reshaped[0..tensors.len], ax); + } + + /// Repeats a Tensor several times along the given axis. + /// + /// * repeat1d(x, concat(&.{x, x, x, x}, axis); + /// * repeat1d([0, 1, 2, 3], 0, 2) = [0, 1, 2, 3, 0, 1, 2, 3] + pub fn repeat1d(self: Tensor, axis_: anytype, n_rep: u63) Tensor { + if (n_rep == 1) { + return self; + } + + const a = self.axis(axis_); + const broadshape = self._shape.insert(a + 1, .{n_rep}); + const repeat_dims = Shape.range(self.rank() + 1, self.dtype()).remove(a + 1); + + var res = self.broadcast(broadshape, repeat_dims.dims()).flatten(a); + // Restor the tag that has been lost by flatten. + res._shape._tags.set(a, self._shape.tag(a)); + + return res; + } + + /// Repeats a Tensor several times along the given axes. + pub fn repeat(self: Tensor, n_reps: []const u63) Tensor { + // TODO: this should support the tagged syntax: x.repeat(.{ .a = 3, .b = 2}); + meta.assert(n_reps.len == self.rank(), "repeat expects tensor rank and 'n_reps' length to be equal, got {} and {}", .{ self.rank(), n_reps.len }); + + var res = self; + for (n_reps, 0..) |n_rep, a| { + if (n_rep == 1) continue; + + res = res.repeat1d(a, n_rep); + } + return res; + } + + /// Repeats in line each value along the given axis. + /// + /// * stutter1d([0, 1, 2, 3], 0, 2) = [0, 0, 1, 1, 2, 2, 3, 3] + pub fn stutter1d(self: Tensor, axis_: i64, n_rep: u63) Tensor { + const a = self.axis(axis_); + const broadshape = self._shape.insert(a + 1, .{n_rep}); + const stutter_dims = Shape.range(self.rank() + 1, self.dtype()).remove(a + 1); + + return self.broadcast(broadshape, stutter_dims.dims()).flatten(a); + } + + /// Repeats in line each value along the given axes. + pub fn stutter(self: Tensor, n_reps: []const u63) Tensor { + meta.assert(n_reps.len == self.rank(), "stutter expects tensor rank and 'n_reps' length to be equal, got {} and {}", .{ self.rank(), n_reps.len }); + + var res = self; + for (n_reps, 0..) |n_rep, a| { + if (n_rep == 1) continue; + res = res.stutter1d(@intCast(a), n_rep); + } + return res; + } + + /// Returns a Tensor containing the element-wise negation of the input Tensor. + pub fn negate(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const negate_op = dialect.stablehlo.negate(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, negate_op.result(0)); + } + + /// Returns a Tensor containing the element-wise cosine of the input Tensor. + pub fn cos(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const cosine_op = dialect.stablehlo.cosine(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, cosine_op.result(0)); + } + + /// Returns a Tensor containing the element-wise sine of the input Tensor. + pub fn sin(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const sine_op = dialect.stablehlo.sine(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, sine_op.result(0)); + } + + /// Returns a Tensor containing the element-wise exponential operation of the input Tensor. + pub fn exp(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.exponential(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, op.result(0)); + } + + /// Returns a Tensor containing the element-wise logarithm operation of the input Tensor. + pub fn log(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.log(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, op.result(0)); + } + + /// Returns a Tensor containing the element-wise square-root of the input Tensor. + pub fn sqrt(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const sqrt_op = dialect.stablehlo.sqrt(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, sqrt_op.result(0)); + } + + /// Returns a Tensor containing the element-wise reverse square-root of the input Tensor. + pub fn rsqrt(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const rsqrt_op = dialect.stablehlo.rsqrt(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, rsqrt_op.result(0)); + } + + /// Returns a Tensor containing the element-wise hyperbolic tangent of the input Tensor. + pub fn tanh(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const tanh_op = dialect.stablehlo.tanh(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, tanh_op.result(0)); + } + + /// Returns a Tensor containing the element-wise exponential minus one operation of the input Tensor. + pub fn exponentialMinusOne(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const expm1_op = dialect.stablehlo.exponential_minus_one(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, expm1_op.result(0)); + } + + pub const ArangeArgs = struct { + start: i64 = 0, + end: i64, + step: i64 = 1, + }; + + /// Returns a Tensor containing evenly spaced values within a given interval. + pub fn arange(args: ArangeArgs, dt: DataType) Tensor { + meta.assert(args.start < args.end, "arange expects 'args.start' to be less than 'args.end', got {} and {}", .{ args.start, args.end }); + meta.assert(args.step > 0, "arange expects 'args.step' to be positive, got {}", .{args.step}); + + const ctx = CompilationContext.current(); + const loc = ctx.mlirCtx().location(@src()).namedFmt(ctx.mlirCtx(), "{}, dtype={}", .{ args, dt }); + + const n_steps = std.math.divCeil(i64, args.end - args.start, args.step) catch unreachable; + const sh = Shape.init(.{n_steps}, dt); + var op = dialect.stablehlo.iota(ctx.mlirCtx(), 0, mlir.ext.mlirType(ctx.mlirCtx(), sh), loc); + var res = _result(sh, op.result(0)); + + if (args.step != 1) { + res = res.scale(args.step); + } + + if (args.start != 0) { + res = res.addConstant(args.start); + } + + return res; + } + + /// Returns a Tensor containing values in increasing order starting from 0 along the given axis. + pub fn iota(sh: Shape, dt: DataType, axis_: anytype) Tensor { + const ctx = CompilationContext.current(); + const loc = ctx.mlirCtx().location(@src()).namedFmt(ctx.mlirCtx(), "iota({}, {})", .{ sh, axis_ }); + + const a = sh.axis(axis_); + const res_shape = sh.withDtype(dt); + var op = dialect.stablehlo.iota(ctx.mlirCtx(), @intCast(a), mlir.ext.RankedTensorType.fromShape(ctx.mlirCtx(), res_shape).as(mlir.Type).?, loc); + return _result(res_shape, op.result(0)); + } + + pub const LinspaceArgs = struct { + start: f64, + end: f64, + steps: i64, + }; + + /// Returns a Tensor containing 'args.steps' values evenly spaced from 'args.start' to 'args.end', inclusive. + pub fn linspace(args: LinspaceArgs, dt: DataType) Tensor { + meta.assert(args.start < args.end, "linspace expects 'args.start' to be less than 'args.end', got {} and {}", .{ args.start, args.end }); + meta.assert(args.steps > 0, "linspace expects 'args.steps' to be positive, got {}", .{args.steps}); + meta.assert(dt.isFloat(), "linspace expects type to be a float, got {} (hint: use arange instead)", .{dt}); + + const ctx = CompilationContext.current(); + const loc = ctx.mlirCtx().location(@src()).namedFmt(ctx.mlirCtx(), "linspace({}, dtype={})", .{ args, dt }); + + const sh = Shape.init(.{args.steps}, dt); + var iota_op = dialect.stablehlo.iota(ctx.mlirCtx(), 0, mlir.ext.mlirType(ctx.mlirCtx(), sh), loc); + var res = _result(sh, iota_op.result(0)); + + if (args.steps != 1) { + res = res.scale(args.steps); + } + + if (args.start != 0) { + res = res.addConstant(args.start); + } + + return res; + } + + /// Returns a 0d Tensor with the given value. + pub fn scalar(val: anytype, dt: DataType) Tensor { + return Tensor.constant(.{}, Data.init(dt, val)); + } + + /// Returns a constant Tensor with the given value. + pub fn constant(dimz: anytype, val: Data) Tensor { + const sh = Shape.init(dimz, val.dataType()); + const singleton_sh = Shape.init(.{}, val.dataType()); + const ctx = CompilationContext.current().mlirCtx(); + const loc = ctx.location(@src()).namedFmt(ctx, "dims={d}, value={}", .{ sh, val }); + const result_type = mlir.ext.RankedTensorType.fromShape(ctx, singleton_sh); + const elem_type = mlir.ext.denseElementAttrType(val.dataType()); + var constant_op = dialect.stablehlo.constant(ctx, result_type, elem_type, val.constSlice(), loc); + if (sh.rank() > 0) { + constant_op = dialect.stablehlo.broadcast_in_dim(ctx, constant_op.result(0), &.{}, mlir.ext.RankedTensorType.fromShape(ctx, sh).as(mlir.Type).?, loc); + } + return _result(sh, constant_op.result(0)); + } + + /// Embeds a buffer with concrete values into an Mlir program. + pub fn constantTensor(val: HostBuffer) Tensor { + const ctx = CompilationContext.current().mlirCtx(); + const result_type = mlir.ext.RankedTensorType.fromShape(ctx, val.shape()); + const loc = ctx.location(@src()); + const elem_type = mlir.ext.denseElementAttrType(val.dtype()); + const constant_op = dialect.stablehlo.constant(ctx, result_type, elem_type, val.data, loc); + return _result(val.shape(), constant_op.result(0)); + } + + /// Returns a Tensor containing the result of the outer product between the input Tensors. + pub fn outer(self: Tensor, other: Tensor) Tensor { + meta.assert(self.rank() < 2 and other.rank() < 2 and self.rank() + other.rank() != 0, "outer expects tensor ranks to be at most 1, got {} and {}", .{ self.rank(), other.rank() }); + + if (self.rank() + other.rank() == 1) { + return self.mul(other); + } + + const dimz = .{ self.dim(0), other.dim(0) }; + const left = self.broadcast(Shape.init(dimz, self.dtype()), &.{0}); + const right = other.broadcast(Shape.init(dimz, other.dtype()), &.{1}); + return left.mul(right); + } + + /// Creates a 2D Tensor with its diagonal set to the input vector. + pub fn diag(self: Tensor) Tensor { + meta.assert(self.rank() == 1, "diag only supports tensor of rank 1, got {}", .{self.rank()}); // TODO: support 2D tensors + // + const indices = Tensor.arange(.{ .end = self.dim(0) }, .i64); + const sh = Shape.init(.{ self.dim(0), self.dim(0) }, self.dtype()); + const indices_1 = indices.broadcast(sh, &.{1}); + const indices_0 = indices.broadcast(sh, &.{0}); + + const loc = self.getContext().mlirCtx().location(@src()); + // TODO: handle more complex cases (2D, specifying `diagonal` index). + const op = dialect.stablehlo.select( + self.getContext().mlirCtx(), + indices_1.cmp(.EQ, indices_0).value(), + self.broadcast(sh, &.{1}).value(), + Tensor.constant(self.dims(), self.dtype().zero()).value(), + loc, + ); + return _result(sh, op.result(0)); + } + + /// Given a tensor and a shape of the same rank, + /// will "broadcast" the given axes, so that `self` has the given shape. + /// This happens by virtually repeating the data several time along each give axes. + /// Note: most of the time the optimizer will make it so that the broadcast doesn't trigger a copy. + /// Note: the tags of the return tensor will be from the `output_shape`. + /// This means if you use and un-tagged broadcast on a tagged tensor, + /// you will lose the tags. + /// To avoid use favorise `.broad(shape)` when working with tagged tensors. + pub fn broadcast(self: Tensor, output_shape: Shape, axes_: []const i64) Tensor { + const res_shape = output_shape.withDtype(self.dtype()); + + const result_type = mlir.ext.RankedTensorType.fromShape(self.getContext().mlirCtx(), res_shape).as(mlir.Type).?; + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "broadcast({any}, axes={d})", .{ res_shape, axes_ }); + const broadcast_op = dialect.stablehlo.broadcast_in_dim(self.getContext().mlirCtx(), self.value(), axes_, result_type, loc); + + return _result(res_shape, broadcast_op.result(0)); + } + + /// Broadcasts a Tensor to the given shape, adding axes at the beginning. + pub fn broadcastLeft(self: Tensor, output_shape: Shape) Tensor { + meta.assert(self.rank() <= output_shape.rank(), "broadcastLeft expects tensor rank to be less than output tensor rank, got {} and {}", .{ self.rank(), output_shape.rank() }); + + const a = output_shape.rank() - self.rank(); + if (self.rank() == output_shape.rank() and std.mem.eql(i64, self.dims(), output_shape.dims())) { + return self; + } + + return self.broadcast(output_shape, Shape.range(output_shape.rank(), output_shape.dtype()).dims()[a..]); + } + + /// Broadcasts a Tensor to the given shape, adding axes at the end. + pub fn broadcastRight(self: Tensor, output_shape: Shape) Tensor { + meta.assert(self.rank() <= output_shape.rank(), "broadcastRight expects tensor rank to be less than output tensor rank, got {} and {}", .{ self.rank(), output_shape.rank() }); + + if (self.rank() == output_shape.rank() and self._shape.eql(output_shape)) { + return self; + } + + return self.broadcast(output_shape, Shape.range(self.rank(), output_shape.dtype()).dims()); + } + + /// Broadcasts a Tensor to the given shape, extending dimensions if needed. + pub fn broad(self: Tensor, other: Shape) Tensor { + // Non ambiguous broadcasting + if (self._shape.rank() == 0 or self._shape.rank() == other.rank()) { + return self.broadcast(other, Shape.range(self._shape.rank(), self.dtype()).dims()); + } + + // check that each axis of self maps to an axis of other + var axes_: std.BoundedArray(i64, MAX_RANK) = .{}; + for (self._shape.tags()) |t| { + if (t != Shape.TagUnknown) { + if (other.hasTag(t)) |ax| { + axes_.appendAssumeCapacity(@intCast(other.axis(ax))); + } else { + std.debug.panic("Can't broadcast {} to {}", .{ self, other }); + } + } + } + return self.broadcast(other, axes_.constSlice()); + } + + /// Reshapes the input Tensor with the given shape. + pub fn reshape(self: Tensor, output_shape_: anytype) Tensor { + const output_shape = self._shape.reshape(output_shape_); + const tensor_type = mlir.ext.RankedTensorType.fromShape(self.getContext().mlirCtx(), output_shape); + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "reshape({any})", .{output_shape}); + const reshape_value = dialect.stablehlo.reshape(self.getContext().mlirCtx(), self.value(), tensor_type, loc); + return _result(output_shape, reshape_value.result(0)); + } + + pub const Pad1dOpts = struct { low: i64, high: i64, interior: i64 = 0 }; + + /// Pads the input Tensor with the given value over the given axis. + pub fn pad1d(self: Tensor, axis_: i8, pad_value: anytype, opts: Pad1dOpts) Tensor { + const ZEROS = [_]i64{0} ** MAX_RANK; + var padding_low = ZEROS; + var padding_high = ZEROS; + var padding_interior = ZEROS; + const a = self.axis(axis_); + padding_low[a] = opts.low; + padding_high[a] = opts.high; + padding_interior[a] = opts.interior; + + const rk = self.rank(); + return self.pad( + pad_value, + .{ .low = padding_low[0..rk], .high = padding_high[0..rk], .interior = padding_interior[0..rk] }, + ); + } + + /// Pads the input Tensor with the given values. + pub fn pad(self: Tensor, pad_value: anytype, opts: dialect.stablehlo.PadOpts) Tensor { + meta.assert(opts.low.len == self.rank(), "pad expects tensor rank and 'opts.low' length to be equal, got {} and {}", .{ self.rank(), opts.low.len }); + meta.assert(opts.high.len == self.rank(), "pad expects tensor rank and 'opts.high' length to be equal, got {} and {}", .{ self.rank(), opts.high.len }); + const ZEROS = [_]i64{0} ** MAX_RANK; + const interior = opts.interior orelse ZEROS[0..self.rank()]; + + var new_shape = self._shape; + + for (0..self.rank()) |i| { + const d = self.dim(i) + opts.low[i] + (@max(self.dim(i) - 1, 0) * interior[i]) + opts.high[i]; + new_shape = new_shape.set(i, d); + } + + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "pad(value={}, opts={})", .{ pad_value, opts }); + var full_opts = opts; + full_opts.interior = opts.interior orelse ZEROS[0..self.rank()]; + const pad_value_tensor = Tensor.scalar(pad_value, self.dtype()); + const pad_op = dialect.stablehlo.pad(self.getContext().mlirCtx(), self.value(), pad_value_tensor.value(), full_opts, loc); + + return _result(new_shape, pad_op.result(0)); + } + + /// Inserts 1-dim axes at the given position, with the given tags. + /// `.{.a = 5, .b = 4}.insert(.b, .{ .c, .d }) -> .{ .a = 5, .c = 1, .d = 1, .b = 4 }` + pub fn insertAxes(self: Tensor, axis_: anytype, tags: anytype) Tensor { + const tags_ = Shape.parseTags(tags); + const ax = if (@TypeOf(axis_) == EnumLiteral and axis_ == .last) + self.rank() + else + self.axis(axis_); + + var res_shape = self._shape; + const ones = [_]i64{1} ** MAX_RANK; + res_shape._dims.insertSlice(ax, ones[0..tags_.len]) catch unreachable; + res_shape._tags.insertSlice(ax, tags_.constSlice()) catch unreachable; + + return self.reshape(res_shape); + } + + /// Appends a 1-dim axis, with the given tag. + pub fn appendAxes(self: Tensor, t: anytype) Tensor { + meta.assert(self.rank() < Tensor.MAX_RANK - t.len, "appendAxis expects tensor rank to be small enough in order to extend it, got {} and {} (max is {})", .{ self.rank(), t.len, Tensor.MAX_RANK }); + + return self.insertAxes(.last, t); + } + + /// Drops a 1-dim axis at the given index + pub fn squeeze(self: Tensor, axis_: anytype) Tensor { + const a = self.axis(axis_); + meta.assert(self.dim(a) == 1, "squeeze expects axis to be squeezed to have a dimension of 1, got {}", .{self.dim(a)}); + + const new_shape = self._shape.remove(a); + // log.debug("squeeze({}, {d}={d}) -> ({})", .{ self, axis, a, new_shape }); + + return _result(new_shape, self.reshape(new_shape).value()); + } + + /// Returns a Tensor with the given axes reversed. + pub fn reverse(self: Tensor, axes_: anytype) Tensor { + const actual_axes = self._shape.axes(axes_); + + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "reverse({any})", .{axes_}); + const reverse_op = dialect.stablehlo.reverse(self.getContext().mlirCtx(), self.value(), toI64(actual_axes.constSlice()), loc); + return _result(self._shape, reverse_op.result(0)); + } + + /// Returns a Tensor with the given axes reversed. + pub fn reverseMany(self: Tensor, axes_: []const i64) Tensor { + const actual_axes = self._shape.axes(axes_).constSlice(); + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "reverse({d})", .{actual_axes}); + const reverse_op = dialect.stablehlo.reverseMany(self.getContext().mlirCtx(), self.value(), @ptrCast(actual_axes), loc); + return _result(self._shape, reverse_op.result(0)); + } + + pub const GatherOpts = struct { indices_are_sorted: bool = false }; + + /// Gathers along a given axis with 1d indices. + /// ([A, B, C, D], .c, [N]) -> (A, B, N, D) + /// ([A, B, C, D], .c, [N, M]) -> (A, B, N, M, D) + pub fn gather1d(self: Tensor, axis_: anytype, indices: Tensor, opts: GatherOpts) Tensor { + // TODO: handle batching dims + meta.assert(self.rank() > 0 and self.rank() - 1 < MAX_RANK - indices.rank(), "Can't gather1d({}, {}) the resulting shape would have too many axes", .{ self, indices }); + + const a = self.axis(axis_); + if (indices.rank() > 1) { + const flattened_gather = self.gather1d(a, indices.flattenAll(), opts); + var tgt_shape = self._shape.drop(a); + for (0..indices.rank()) |i| { + tgt_shape._dims.insert(@intCast(a + i), indices.dim(i)) catch unreachable; + tgt_shape._tags.insert(@intCast(a + i), indices._shape._tags.get(i)) catch unreachable; + } + return flattened_gather.reshape(tgt_shape); + } + + meta.assert(indices.rank() == 1, "gather1d expects 'indices' tensor rank to be equal to 1, got {}", .{indices.rank()}); + + const res_shape = self._shape.set(a, indices.dim(0)); + const slice_sizes = self._shape.set(a, 1); + const offset_dims = Shape.range(self.rank(), self.dtype()).drop(a); + + const loc = self.getContext().mlirCtx().location(@src()); + const gather_op = dialect.stablehlo.gather( + self.getContext().mlirCtx(), + self.value(), + indices.value(), + slice_sizes.dims(), + loc, + .{ + .offset_dims = offset_dims.dims(), + .collapsed_slice_dims = &.{a}, + .operand_batching_dims = &.{}, + .start_indices_batching_dims = &.{}, + .start_index_map = &.{a}, + .index_vector_dim = indices.rank(), + .indices_are_sorted = opts.indices_are_sorted, + }, + ); + return _result(res_shape, gather_op.result(0)); + } + + /// Gathers slices along the given axes with runtime indices. + /// * slice_shape represents the shape of the slices to extract, + /// it must be smaller than original shape. + /// It must use a subset of self axes. + /// If slice_shape is **not** tagged, then it must have the same rank than self. + /// * `indices` represents a set of coordinates. + /// The coordinates are read from the `.coord` axis, or last axis if `.coord` is not found. + /// The coordinate axis must have `slice_shape.rank()` dims. + /// The coordinates represent the "top-left" corner of the slice to extract. + /// * the output tensor starts with axes from `indices`. + /// * if the input tensor has tagged axes, matching `indices` axes, + /// they will be considered "batching" axes. + /// + /// Sample input/output shapes: + /// * gatherSlices([A, B, C, D], .{.b=B', .c=C'}, [N, 2]) -> [N, A, B', C', D] + /// * gatherSlices(x(a,b,c,d), .{.b=B', .c=C'}, g(n,m)) = z(n, a, b', c', d) = x(a, g(n, 0) + b', g(n, 1) + c', d) + /// + /// Note: the axis order of the result is different from gather1d. + /// This is because gatherSlices, favorizes contiguous copy of the extracted slices, + /// while gather1d, always copy values one by one, and as such don't have the same issues. + /// In our example the contiguous dimension .d is not sliced + /// and gatherSlices can copy data by group of C'*D elements. + pub fn gatherSlices(self: Tensor, slice_shape: Shape, indices: Tensor, opts: GatherOpts) Tensor { + // scoped_log.debug("gatherSlice({}, {_}, {})", .{ self, slice_shape, indices }); + + const tagged_api = slice_shape.isFullyTagged(); + if (tagged_api) { + for (slice_shape.tags()) |t| { + meta.assert(self._shape.hasTag(t) != null, "gatherSlices expects `slices_shape` to only use tags from `self`. But {s} wasn't found in {}", .{ t, self }); + } + } else { + // For untagged api, we require all slices to be specified. + // Note: we could relax this and right align the slice. + meta.assert(slice_shape.rank() == self.rank(), "gatherSlices expects `slice_shape.rank()` to match `self.rank()`. Got: gatherSlices({}, slice={_}). To avoid specifying all axes in `slice_shape`, you can use tags.", .{ self, slice_shape }); + } + + const index_coord_axis = indices._shape.hasTag(.coord) orelse indices._shape.axis(-1); + meta.assert(indices.dim(index_coord_axis) == slice_shape.rank(), "gatherSlices({}, slice={_}, indices) expects 'indices' to be a tensor [..., {}], got {}", .{ self, slice_shape, slice_shape.rank(), indices }); + + // Compute result shape + var res_shape = indices._shape.remove(index_coord_axis).withDtype(self.dtype()); + var slice_dims = self._shape._dims; + var self_batch_axes: std.BoundedArray(i64, MAX_RANK) = .{}; + var indices_batch_axes: std.BoundedArray(i64, MAX_RANK) = .{}; + var start_index_map: std.BoundedArray(i64, MAX_RANK) = .{}; + var self_offset_axes: std.BoundedArray(i64, MAX_RANK) = .{}; + for (self._shape.tags(), 0..self.rank()) |t, self_ax| { + const maybe_slice_ax: ?u3 = if (tagged_api) slice_shape.hasTag(t) else @intCast(self_ax); + + if (tagged_api and indices._shape.hasTag(t) != null) { + // tag is both in self and indices -> it's a batching dim + // Note: tags are required for batching. + self_batch_axes.appendAssumeCapacity(@intCast(self_ax)); + indices_batch_axes.appendAssumeCapacity(indices._shape.axis(t)); + slice_dims.set(self_ax, 1); + meta.assert(slice_shape.hasTag(t) == null, "gatherSlices expect axes to be either batches or slices axes. Axis {s} has been found both in `slices={_}` and `indices={}`", .{ t, slice_shape, indices }); + } else if (maybe_slice_ax) |slice_ax| { + // Specified axes contains the start offset of the slices, + // and are collected in `start_index_map`. + const slice_dim = slice_shape.dim(slice_ax); + meta.assert(slice_dim <= self._shape.dim(self_ax), "gatherSlices expects `slice_shape` to be smaller than `self.shape()`. On axis {s}, got {} > {}.", .{ t, slice_shape, self._shape }); + slice_dims.set(self_ax, slice_dim); + res_shape = res_shape.appendDim(slice_dim, t); + start_index_map.appendAssumeCapacity(@intCast(self_ax)); + self_offset_axes.appendAssumeCapacity(res_shape.rank() - 1); + } else { + // non-batching, non-indexed axes + res_shape = res_shape.appendDim(self.dim(self_ax), t); + self_offset_axes.appendAssumeCapacity(res_shape.rank() - 1); + } + } + + const loc = self.getContext().mlirCtx().location(@src()); + const gather_op = dialect.stablehlo.gather( + self.getContext().mlirCtx(), + self.value(), + indices.value(), + slice_dims.constSlice(), + loc, + .{ + .offset_dims = self_offset_axes.constSlice(), + .collapsed_slice_dims = &.{}, + .operand_batching_dims = self_batch_axes.constSlice(), + .start_indices_batching_dims = indices_batch_axes.constSlice(), + .start_index_map = start_index_map.constSlice(), + .index_vector_dim = index_coord_axis, + .indices_are_sorted = opts.indices_are_sorted, + }, + ); + return _result(res_shape, gather_op.result(0)); + } + + test gatherSlices { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + + { + // Only test shapes + var comp = try zml.module.CompilationContext.init(std.heap.page_allocator, "test", platform); + defer comp.deinit(); + comp.activate(); + defer comp.deactivate(); + + inline for (.{ + .{ .{ .a = 10 }, .{}, .{ ._ = 0 }, .{ .a = 10 } }, + .{ .{ .a = 10 }, .{ .a = 7 }, .{ ._ = 1 }, .{ .a = 7 } }, + .{ .{ .a = 10 }, .{ .a = 7 }, .{ .n = 8, ._ = 1 }, .{ .n = 8, .a = 7 } }, + .{ .{ .a = 10 }, .{ .a = 7 }, .{ .coord = 1, .n = 8 }, .{ .n = 8, .a = 7 } }, + // tags aren't required. + .{ .{10}, .{7}, .{ .n = 8, ._ = 1 }, .{ .n = 8, ._ = 7 } }, + .{ .{ .a = 10, .b = 20 }, .{ .a = 7 }, .{ ._ = 1 }, .{ .a = 7, .b = 20 } }, + .{ .{ .a = 10, .b = 20 }, .{ .a = 7 }, .{ .n = 8, ._ = 1 }, .{ .n = 8, .a = 7, .b = 20 } }, + .{ .{ .a = 10, .b = 20 }, .{ .a = 7 }, .{ .n = 8, .coord = 1, .m = 9 }, .{ .n = 8, .m = 9, .a = 7, .b = 20 } }, + .{ .{ .a = 10, .b = 20 }, .{ .b = 17 }, .{ .n = 8, ._ = 1 }, .{ .n = 8, .a = 10, .b = 17 } }, + .{ .{ .a = 10, .b = 20 }, .{ .a = 7, .b = 17 }, .{ .n = 8, ._ = 2 }, .{ .n = 8, .a = 7, .b = 17 } }, + // Note: currently the order of the axes in the slice is not used. + .{ .{ .a = 10, .b = 20 }, .{ .b = 17, .a = 7 }, .{ .n = 8, ._ = 2 }, .{ .n = 8, .a = 7, .b = 17 } }, + .{ .{ .a = 10, .b = 20, .c = 20 }, .{ .b = 17 }, .{ .n = 8, ._ = 1 }, .{ .n = 8, .a = 10, .b = 17, .c = 20 } }, + // batching dims + .{ .{ .a = 10, .b = 20 }, .{ .b = 17 }, .{ .a = 10, ._ = 1 }, .{ .a = 10, .b = 17 } }, + .{ .{ .b = 200, .a = 100, .c = 300 }, .{ .c = 300 }, .{ .a = 100, .b = 200, ._ = 1 }, .{ .a = 100, .b = 200, .c = 300 } }, + }) |testcase| { + const x_shape, const slice_dims, const idx_shape, const res_shape = testcase; + const x = Tensor.constant(x_shape, .{ .f16 = 0 }); + const slice_shape = Shape.init(slice_dims, .u16); + const idx = Tensor.constant(idx_shape, .{ .i32 = 0 }); + const y = gatherSlices(x, slice_shape, idx, .{}); + try zml.testing.expectEqualShapes(Shape.init(res_shape, .f16), y.shape()); + try std.testing.expect(y.value().owner().verify()); + + // The batching dims test case doesn't pass. + // The weird part is that the MLIR seems valid, but pjrt doesn't accept it. + // TODO: https://github.com/zml/zml/issues/400 + const mod = zml.compileFn(std.testing.allocator, gatherSlices, .{ x.shape(), slice_shape, idx.shape(), .{ .indices_are_sorted = true } }, platform); + + if (mod) |m| { + m.deinit(); + } else |err| { + if (@hasField(@TypeOf(idx_shape), "a")) { + scoped_log.warn("Skipping compilation test of gather with batching dims: https://github.com/zml/zml/issues/400", .{}); + } else { + return err; + } + } + } + } + + // Test with actual values. + const range = try zml.HostBuffer.arange(std.testing.allocator, .{ .end = 2 * 4 * 6 }, .u16); + defer range.deinit(std.testing.allocator); + const operand = try range.reshape(.{ .a = 2, .b = 4, .c = 6 }).toDevice(platform); + defer operand.deinit(); + const start_indices = (try zml.Buffer.fromArray(platform, [2][2]i32{ .{ 2, 1 }, .{ 0, 3 } })).withTags(.{ .n, ._ }); + defer start_indices.deinit(); + + const result = try zml.testing.compileAndCall(platform, gatherSlices, .{ operand, Shape.init(.{ .b = 2, .c = 3 }, .u16), start_indices, .{} }); + + const expected = zml.HostBuffer.fromArray(&[2][2][2][3]u16{ + .{ + .{ .{ 13, 14, 15 }, .{ 19, 20, 21 } }, + .{ .{ 37, 38, 39 }, .{ 43, 44, 45 } }, + }, + .{ + .{ .{ 3, 4, 5 }, .{ 9, 10, 11 } }, + .{ .{ 27, 28, 29 }, .{ 33, 34, 35 } }, + }, + }); + try zml.testing.expectClose(expected, result, 0); + } + + /// Returns a Tensor containing the maximum over a given axis. + pub fn max(self: Tensor, axis_: anytype) Tensor { + const a = self.axis(axis_); + return ops.reduce( + struct { + pub fn cmp(x: Tensor, res: Tensor) Tensor { + return res.maximum(x.convert(res.dtype())); + } + }.cmp, + self, + Tensor.scalar(0, self.dtype()), + &.{a}, + ); + } + + /// Returns a Tensor containing the minimum over a given axis. + pub fn min(self: Tensor, axis_: anytype) Tensor { + const a = self.axis(axis_); + return ops.reduce( + struct { + pub fn cmp(x: Tensor, res: Tensor) Tensor { + return res.minimum(x.convert(res.dtype())); + } + }.cmp, + self, + Tensor.scalar(0, self.dtype()), + &.{a}, + ); + } + + pub const ArgMaxRes = struct { + values: Tensor, + indices: Tensor, + + fn cmp(left: ArgMaxRes, right: ArgMaxRes) ArgMaxRes { + const left_val = left.values; + const right_val = right.values; + const left_idx = left.indices; + const right_idx = right.indices; + + const left_gt_right = left_val.cmp(.GT, right_val); + const is_nan = left_val.cmp(.NE, left_val); + const left_gt_or_nan = left_gt_right.logical(.OR, is_nan); + // we are bubbling up Nan. + const max_val = left_gt_or_nan.select(left_val, right_val); + + // If left_val == right_val: keep the smallest idx. + const is_same = left_val.cmp(.EQ, right_val); + const is_first = left_idx.cmp(.LT, right_idx); + const is_same_but_first = is_same.logical(.AND, is_first); + const keep_left_idx = left_gt_or_nan.logical(.OR, is_same_but_first); + const max_idx = keep_left_idx.select(left_idx, right_idx); + + return .{ .values = max_val, .indices = max_idx }; + } + }; + + /// Returns two Tensors containing the maximum and the index of this maximum over a given axis. + /// + /// Stable argmax: + /// * bubbles up Nan + /// * in case of equality the smallest index matching the maximum + pub fn argMax(x: Tensor, axis_: anytype, index_dtype: DataType) ArgMaxRes { + meta.assert(index_dtype.isInteger(), "argMax expect index type to be an integer, got {}", .{index_dtype}); + + const a = x.axis(axis_); + + return ops.reduce( + ArgMaxRes.cmp, + .{ .values = x, .indices = Tensor.arange(.{ .end = x.dim(a) }, index_dtype).broadcast(x._shape.withDtype(index_dtype), &.{a}) }, + .{ .values = Tensor.constant(&.{}, x.dtype().minValue()), .indices = Tensor.scalar(0, index_dtype) }, + &.{a}, + ); + } + + pub const SortRes = ArgMaxRes; + + /// Returns two Tensors. The first contains the sorted values and the second one contains the sorted indices. + pub fn sort(self: Tensor, axis_: i64, opts: struct { descending: bool = false }) SortRes { + const a = self.axis(axis_); + const indices = Tensor.arange(.{ .end = self.dim(a) }, .i32).broadcast(self._shape, &.{a}); + const res = ops.sort( + struct { + fn call(direction: dialect.stablehlo.ComparisonDirection.Direction, lhs: Tensor, rhs: Tensor, _: Tensor, _: Tensor) Tensor { + return lhs.cmp(direction, rhs); + } + }.call, + if (opts.descending) .GT else .LT, + .{ self, indices }, + self.axis(axis_), + true, + ); + return .{ .values = res[0], .indices = res[1] }; + } + + /// Returns a Tensor containing the indices corresponding to the sorted values over the given axis. + pub fn argsort(self: Tensor, axis_: i64, opts: struct { descending: bool = false }) Tensor { + return self.sort(axis_, .{ .descending = opts.descending }).indices; + } + + /// Returns a Tensor representing the result of Top-K over the given axis. + pub fn topK(self: Tensor, k: u32, axis_: anytype, opts: struct { descending: bool = true }) SortRes { + const a = self.axis(axis_); + const result = self.sort(a, .{ .descending = opts.descending }); + return .{ + .values = result.values.slice1d(a, .{ .end = k }), + .indices = result.indices.slice1d(a, .{ .end = k }), + }; + } + + pub const MaxPoolRes = ArgMaxRes; + + /// Computes the 1d maxPool operation on the input Tensor. + pub fn maxPool1d(self: Tensor, opts: struct { + window_dimensions: i64, + window_strides: ?i64, + base_dilations: i64 = 1, + window_dilations: i64 = 1, + padding: []const i64 = &.{0}, + }) MaxPoolRes { + // TODO migrate to the following syntax. + // maxPool(.{.a = .{ .stride = 5, .dilation = 2, .padding = .{0, 1} }, + // .b = .{ .stride = 8, .dilation = 2, .padding = .{0, 1} }), + // maxPool(.{ + // .stride = .{ .a = 5, .b = 8 }, + // .dilation = .{ .a = 2, .b = 2 }, + // .padding = .{ .a = .{ 0, 2 }, .b = .{0, 2} + // }) + + meta.assert(opts.padding.len == 1 or opts.padding.len == 2 * self.rank(), "maxPool1d expects 'opts.padding' length to be a single integer or to be equal to the double of input tensor rank, got {} (input tensor rank is {})", .{ opts.padding.len, self.rank() }); + + // Note: the problem is initPoolArg assuming last axis + // TODO: support maxPool on non last axis + const a = self.axis(-1); + + const window_dimensions = initPoolArg(self.rank(), &.{opts.window_dimensions}); + const window_strides = if (opts.window_strides) |ws| initPoolArg(self.rank(), &.{ws}) else window_dimensions; + const base_dilation = initPoolArg(self.rank(), &.{opts.base_dilations}); + const window_dilations = initPoolArg(self.rank(), &.{opts.window_dilations}); + + return ops.reduceWindow( + MaxPoolRes.cmp, + .{ .values = self, .indices = iota(self._shape, .i32, a) }, + .{ .values = Tensor.constant(.{}, self.dtype().minValue()), .indices = Tensor.scalar(0, .i32) }, + .{ + .window_dimensions = window_dimensions[0..self.rank()], + .window_strides = window_strides[0..self.rank()], + .base_dilations = base_dilation[0..self.rank()], + .window_dilations = window_dilations[0..self.rank()], + .padding_values = opts.padding, + .padding_shape = &.{ @intCast(self.rank()), 2 }, + }, + ); + } + + /// Computes the 2d maxPool operation on the input Tensor. + pub fn maxPool2d(self: Tensor, opts: struct { + window_dimensions: []const i64, + window_strides: ?[]const i64 = null, + base_dilations: []const i64 = &.{ 1, 1 }, + window_dilations: []const i64 = &.{ 1, 1 }, + padding: []const i64 = &.{0}, + }) MaxPoolRes { + // TODO: rewrite using modern ZML, add ops.reduceWindow + meta.guard(self.rank() == 3 or self.rank() == 4, @src()); + meta.guard(opts.window_dimensions.len == 2, @src()); + meta.guard(opts.window_strides == null or opts.window_strides.?.len == 2, @src()); + meta.guard(opts.base_dilations.len == 2, @src()); + meta.guard(opts.window_dilations.len == 2, @src()); + meta.assert(opts.padding.len == 1 or opts.padding.len == 2 * self.rank(), "Padding needs to either be a single integer, or to be 2x time the number of input rank. In maxPool({}, .padding={d})", .{ self, opts.padding }); + + // TODO: support maxPool on non last axis + // Note: the problem is initPoolArg assuming last axis + const a = self.axis(-1); + + const window_dimensions = initPoolArg(self.rank(), opts.window_dimensions); + const window_strides = if (opts.window_strides) |ws| initPoolArg(self.rank(), ws) else window_dimensions; + const base_dilation = initPoolArg(self.rank(), opts.base_dilations); + const window_dilations = initPoolArg(self.rank(), opts.window_dilations); + + return ops.reduceWindow( + MaxPoolRes.cmp, + .{ .values = self, .indices = iota(self._shape, .i32, a) }, + .{ .values = Tensor.constant(.{}, self.dtype().minValue()), .indices = Tensor.scalar(0, .i32) }, + .{ + .window_dimensions = window_dimensions[0..self.rank()], + .window_strides = window_strides[0..self.rank()], + .base_dilations = base_dilation[0..self.rank()], + .window_dilations = window_dilations[0..self.rank()], + .padding_values = opts.padding, + .padding_shape = &.{ @intCast(self.rank()), 2 }, + }, + ); + } + + pub inline fn axes(self: Tensor, axes_: anytype) std.BoundedArray(u3, Tensor.MAX_RANK) { + return self._shape.axes(axes_); + } + + pub fn chunkAlloc(self: Tensor, allocator: std.mem.Allocator, chunks: i64, axis_: i64) ![]Tensor { + const a = self.axis(axis_); + const length = self.dim(a); + const chunk_size: i64 = @divFloor(length, chunks); + const full_chunks: i64 = @divFloor(length, chunk_size); + const tail_chunk_size: i64 = @rem(length, chunk_size); + + const n_chunks = if (tail_chunk_size > 0) full_chunks + 1 else full_chunks; + const result = try allocator.alloc(Tensor, @intCast(n_chunks)); + self.chunk(result, axis_); + return result; + } + + pub fn chunkExact(self: Tensor, n_chunks: comptime_int, axis_: i64) [n_chunks]Tensor { + const a = self.axis(axis_); + const length = self.dim(a); + _ = @divExact(length, n_chunks); + var res: [n_chunks]Tensor = undefined; + self.chunk(&res, a); + return res; + } + + pub fn chunk(self: Tensor, chunks: []Tensor, axis_: i64) void { + const a = self.axis(axis_); + const length = self.dim(a); + const n_chunks: i64 = @intCast(chunks.len); + const chunk_size: i64 = @divFloor(length, n_chunks); + const full_chunks: usize = @intCast(@divFloor(length, chunk_size)); + const tail_chunk_size: i64 = @mod(length, chunk_size); + for (0..full_chunks) |i| { + const start: i64 = @as(i64, @intCast(i)) * chunk_size; + chunks[i] = self.slice1d(a, .{ .start = start, .end = start + chunk_size }); + } + if (tail_chunk_size != 0) { + const start: i64 = @as(i64, @intCast(full_chunks)) * chunk_size; + chunks[full_chunks] = self.slice1d(a, .{ .start = start }); + } + } + + pub fn split(self: Tensor, allocator: std.mem.Allocator, split_size_or_sections: []const i64, axis_: i64) ![]Tensor { + meta.assert(split_size_or_sections.len > 0, "split expects 'split_size_or_sections' length to be positive, got {}", .{split_size_or_sections.len}); + + const a = self.axis(axis_); + const length = self.dim(a); + if (split_size_or_sections.len != 1) { + var split_sum: i64 = 0; + for (split_size_or_sections) |n| split_sum += n; + meta.assert(split_sum == length, "split expects sum of 'split_size_or_sections' values and axis dimension to be equal, got {} and {}", .{ split_sum, length }); + } + + return switch (split_size_or_sections.len) { + 1 => { + var chunk_count: i64 = @divFloor(length, split_size_or_sections[0]); + if (@as(usize, @intCast(length)) % @as(usize, @intCast(split_size_or_sections[0])) != 0) { + chunk_count += 1; + } + const res = try allocator.alloc(Tensor, @intCast(chunk_count)); + self.chunk(res, a); + return res; + }, + else => { + const res = try allocator.alloc(Tensor, split_size_or_sections.len); + errdefer allocator.dealloc(res); + + var start: i64 = 0; + for (split_size_or_sections, 0..) |n, i| { + res[i] = self.slice1d(a, .{ .start = start, .end = start + n }); + start += n; + } + return res; + }, + }; + } + + /// Slices the input Tensor along a specific axis, with a start offset known at runtime. + pub fn dynamicSlice1d(self: Tensor, axis_: i8, len: u63, start_indices: Tensor) Tensor { + meta.assert(start_indices.rank() == 0, "dynamicSlice1d expects 'start_indices' tensor rank to be equal to 0, got {}", .{start_indices.rank()}); + + const a = self.axis(axis_); + const new_shape = self._shape.set(a, len); + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "axis={}, len={}", .{ axis_, len }); + var indices: [Tensor.MAX_RANK]mlir.Value = undefined; + for (0..self.rank()) |i| { + indices[i] = if (i == a) + start_indices.value() + else + constant(.{}, start_indices.dtype().zero()).value(); + } + + const op = dialect.stablehlo.dynamicSlice( + self.getContext().mlirCtx(), + self.value(), + new_shape.dims(), + indices[0..self.rank()], + loc, + ); + + return _result(new_shape, op.result(0)); + } + + /// Slices a Tensor across many axes, with runtime known offsets. + /// + /// Due to the nature of stablehlo, the length of the slices need to be known when compiling the IR. + /// When using the tagged API it is allowed to not specify some axes. + /// But with the non-tagged API all slices need to be specified. + /// Examples: + /// ``` + /// Tensor(.{.a=20,.b=30,.c=40 }).dynamicSlice(.{ .a = .{ .start = a_off, .len = 11}); + /// Tensor(.{.a=20,.b=30,.c=40 }).dynamicSlice(.{ + /// .a = .{ .start = a_off, .len = 11 }, + /// .b = .{ .start = b_off, .len = 12 }, + /// }); + /// Tensor(.{ 20,30,40}).dynamicSlice(.{.{ .start = scalar(0, .i32), .len = 20 }, .{ .start = b_off, .len = 12 }, .{ .start = scalar(0, .i32), .len = 40 }}); + /// ``` + pub fn dynamicSlice(self: Tensor, slices_: anytype) Tensor { + // TODO: the untagged api is a bit verbose. Should I allow: `Tensor(.{ 20,30,40}).dynamicSlice(.{.{}, .{ .start = b_off, .len = 12 }, .{}});` ?? + // + const DynSlice = struct { start: Tensor, len: i64 }; + const slices, const slices_tags = Shape.parseStruct(DynSlice, slices_); + + // TODO use slices and slices_tags for the format. + // Currently this prints: "dynSlice(struct{q: struct{start: tensor.Tensor, comptime len: comptime_int = 1}}{ .q = struct{start: tensor.Tensor, comptime len: comptime_int = 1}{ .start = Tensor({1,10}, dtype=.i64), .len = 1 } })" + // which is kinda ugly. + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "dynSlice({any})", .{slices_}); + + const idx_dtype = if (slices.len > 0) slices.get(0).start.dtype() else .i32; + const zero = Tensor.scalar(0, idx_dtype).value(); + var offset_values = [_]mlir.Value{zero} ** MAX_RANK; + var res_shape = self._shape; + for (slices.constSlice(), 0..) |slice_, i| { + const offset = slice_.start; + const len = slice_.len; + if (slices_tags.len == 0) { + meta.assert(self.rank() == slices.len, "dynamicSlice expects tensor rank and 'slices_' length to be equal, got {} and {}", .{ self.rank(), slices.len }); + + offset_values[i] = offset.value(); + res_shape._dims.set(i, len); + + meta.assert(len <= self.dim(i), "dynamicSlice expects slices 'len' to be less than or equal to their corresponding dimension in input tensor, got {} and {} for index {}", .{ len, self.dim(i), i }); + } else { + const t = slices_tags.get(i); + const a = res_shape.hasTag(t) orelse meta.panic("dynamicSlice expects input tensor to have tags used in 'slices_' but {s} is missing (input shape is {})", .{ t, self._shape }); + + meta.assert(len <= self.dim(a), "dynamicSlice expects slices 'len' to be less than their corresponding dimension in input tensor, got {} and {} for axis {s}", .{ len, self.dim(a), t }); + + offset_values[a] = offset.value(); + res_shape._dims.set(a, len); + } + } + const op = dialect.stablehlo.dynamicSlice(self.getContext().mlirCtx(), self.value(), res_shape.dims(), offset_values[0..self.rank()], loc); + return _result(res_shape, op.result(0)); + } + + /// Updates a slice of the input Tensor along a specific axis using the given 'update' Tensor, with a start offset known at runtime. + pub fn dynamicUpdateSlice1d(self: Tensor, update: Tensor, axis_: i64, offset: Tensor) Tensor { + const placeholder = Tensor.scalar(0, .i32); + var start_indices = [_]Tensor{placeholder} ** MAX_RANK; + start_indices[self.axis(axis_)] = offset; + return self.dynamicUpdateSlice(start_indices[0..self.rank()], update); + } + + /// Updates a part of the input Tensor using the given 'update' Tensor, with runtime known offsets. + /// + /// The offsets are specified similarly to the dynamicSlice api. + /// It's semantically equivalent to: + /// self.dynamicSlice(offsets_) := update + /// Examples: + /// ``` + /// Tensor(.{ .a = 2, .b = 5 }).dynamicUpdateSlice(.{ .a = scalar(1, .i32) }, Tensor(.{ .b = 5 })); + /// ``` + pub fn dynamicUpdateSlice(self: Tensor, offset_: anytype, update_: Tensor) Tensor { + meta.assert(self.dtype() == update_.dtype(), "dynamicUpdateSlice expects input and 'update_' tensors to be of the same type, got {} and {}", .{ self.dtype(), update_.dtype() }); + + const offset, const offset_tags = Shape.parseStruct(Tensor, offset_); + // log.debug("offset: {any}, offset_tags: {any}", .{ offset, offset_tags }); + for (offset.constSlice(), 0..) |start_idx, i| { + meta.assert(start_idx.rank() == 0, "dynamicUpdateSlice expects 'offset_' tensor ranks to be equal to 0, got {} at index {}", .{ start_idx.rank(), i }); + } + + const tagged_api = update_._shape.isFullyTagged() and self._shape.isFullyTagged() and offset_tags.len > 0; + // When using tags, we can safely insert axis with a 1-dim. + // the offset into the inserted axis will need to be specified through indices. + var update = update_; + if (tagged_api) { + // Check that all update tags are known. + for (update._shape._tags.constSlice()) |t| { + meta.assert(self._shape.hasTag(t) != null, "dynamicUpdateSlice expects 'update_' tensor tags to be a subset of input tensor tags but {s} is missing (input shape is {})", .{ t, self._shape }); + } + + var update_shape = self._shape; + var prev_ax: i8 = -1; + for (self._shape.tags(), 0..) |t, self_ax| { + if (update._shape.hasTag(t)) |up_ax| { + meta.assert(up_ax == prev_ax + 1, "dynamicUpdateSlice expects 'update_' and input tensor axis to have the same order, got {} and {}. (hint: you need to explicitly transpose 'update_')", .{ update_._shape, self._shape }); + + update_shape._dims.set(self_ax, update.dim(up_ax)); + prev_ax = up_ax; + } else { + update_shape._dims.set(self_ax, 1); + } + } + update = update.reshape(update_shape); + } + + meta.assert(self.rank() == update.rank(), "dynamicUpdateSlice expects input and computed update tensors to have the same rank, got {} and {} (hint: it's probably an issue on our side)", .{ self.rank(), update.rank() }); + + for (self.dims(), update.dims(), 0..) |self_d, up_d, ax| { + const t = self._shape.debugTag(ax); + meta.assert(up_d <= self_d, "dynamicUpdateSlice expects 'update_' dimensions to be less than or equal to their corresponding dimension in input tensor, got {} and {} for axis .{s}", .{ up_d, self_d, t }); + + if (tagged_api and up_d < self_d) { + const axis_has_offset = std.mem.indexOfScalar(Shape.Tag, offset_tags.constSlice(), self._shape._tags.get(ax)) != null; + + meta.assert(axis_has_offset, "dynamicUpdateSlice expects 'update_' dimensions to be equal to their corresponding dimension in input tensor, got {} and {} for axis .{s} (hint: you need to provide an offset)", .{ up_d, self_d, t }); + } + } + + const idx_dtype = if (offset.len > 0) offset.get(0).dtype() else .i32; + const zero = Tensor.scalar(0, idx_dtype).value(); + var offset_values: [MAX_RANK]mlir.Value = undefined; + if (offset_tags.len == 0) { + // Without offset tags we need the same number of offset than rank. + meta.assert(self.rank() == offset.len, "dynamicUpdateSlice expects input tensor rank and 'offset_' length to be equal, got {} and {}", .{ self.rank(), offset.len }); + + for (offset.constSlice(), 0..) |idx, i| { + offset_values[i] = idx.value(); + } + } else { + // If an axis isn't specified, update the full slice. + // This is only allowed when using tagged sliced. + offset_values = .{zero} ** MAX_RANK; + for (offset.constSlice(), offset_tags.constSlice()) |start, t| { + const a = self._shape.hasTag(t) orelse meta.panic("dynamicUpdateSlice expects input tensor to have tags used in 'offset_' but {s} is missing (input shape is {})", .{ t, self._shape }); + offset_values[a] = start.value(); + } + } + + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.dynamic_update_slice( + self.getContext().mlirCtx(), + self.value(), + update.value(), + offset_values[0..self.rank()], + loc, + ); + return _result(self._shape, op.result(0)); + } + + test dynamicUpdateSlice { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + + { + const x = try zml.Buffer.fromArray(platform, [10]f32{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + const y = try zml.Buffer.fromArray(platform, [2]f32{ -1, -1 }); + const idx = try zml.Buffer.scalar(platform, 4, .i32); + const res = try zml.testing.compileAndCall( + platform, + struct { + pub fn forward(x_: Tensor, idx_: struct { a: Tensor }, y_: Tensor) Tensor { + return x_.dynamicUpdateSlice(idx_, y_); + } + }.forward, + .{ x.withTags(.{.a}), .{ .a = idx }, y.withTags(.{.a}) }, + ); + try testing.expectEqual([10]f32{ 0, 1, 2, 3, -1, -1, 6, 7, 8, 9 }, try res.getValue([10]f32)); + } + + { + // Updates 2D, tagged api + const x = try zml.Buffer.fromArray(platform, [2][5]f32{ .{ 0, 1, 2, 3, 4 }, .{ 5, 6, 7, 8, 9 } }); + const y = try zml.Buffer.fromArray(platform, [2]f32{ -1, -1 }); + const idx = try zml.Buffer.scalar(platform, 3, .i32); + + const res = try zml.testing.compileAndCall( + platform, + struct { + pub fn forward(x_: Tensor, idx_: Tensor, y_: Tensor) Tensor { + return x_.dynamicUpdateSlice(.{ .b = idx_ }, y_); + } + }.forward, + .{ x.withTags(.{ .a, .b }), idx, y.withTags(.{.a}) }, + ); + try testing.expectEqualDeep( + [2][5]f32{ .{ 0, 1, 2, -1, 4 }, .{ 5, 6, 7, -1, 9 } }, + try res.getValue([2][5]f32), + ); + } + + { + // Updates 2D slice, un-tagged api. Note that `y` needs to have a 1 dimension axis. + const x = try zml.Buffer.fromArray(platform, [2][5]f32{ .{ 0, 1, 2, 3, 4 }, .{ 5, 6, 7, 8, 9 } }); + const y = try zml.Buffer.fromArray(platform, [2][1]f32{ .{-1}, .{-1} }); + const idx = try zml.Buffer.scalar(platform, 3, .i32); + const res = try zml.testing.compileAndCall( + platform, + struct { + pub fn forward(x_: Tensor, idx_: Tensor, y_: Tensor) Tensor { + return x_.dynamicUpdateSlice(.{ zml.Tensor.scalar(0, .i32), idx_ }, y_); + } + }.forward, + .{ x, idx, y }, + ); + try testing.expectEqualDeep( + [2][5]f32{ .{ 0, 1, 2, -1, 4 }, .{ 5, 6, 7, -1, 9 } }, + res.getValue([2][5]f32), + ); + } + + { + // Updates 2D, partial update + const x = try zml.Buffer.fromArray(platform, [2][5]f32{ .{ 0, 1, 2, 3, 4 }, .{ 5, 6, 7, 8, 9 } }); + const y = try zml.Buffer.fromArray(platform, [1]f32{-1}); + const idx_a = try zml.Buffer.scalar(platform, 1, .i32); + const idx_b = try zml.Buffer.scalar(platform, 3, .i32); + const res = try zml.testing.compileAndCall( + platform, + struct { + pub fn forward(x_: Tensor, idx_: struct { a: Tensor, b: Tensor }, y_: Tensor) Tensor { + return x_.dynamicUpdateSlice(idx_, y_); + } + }.forward, + .{ x.withTags(.{ .a, .b }), .{ .a = idx_a, .b = idx_b }, y.withTags(.{.a}) }, + ); + try testing.expectEqualDeep( + [2][5]f32{ .{ 0, 1, 2, 3, 4 }, .{ 5, 6, 7, -1, 9 } }, + res.getValue([2][5]f32), + ); + } + + { + // Updates 2D, partial update, un-tagged api. + const x = try zml.Buffer.fromArray(platform, [2][5]f32{ .{ 0, 1, 2, 3, 4 }, .{ 5, 6, 7, 8, 9 } }); + const y = try zml.Buffer.fromArray(platform, [1][1]f32{.{-1}}); + const idx_a = try zml.Buffer.scalar(platform, 1, .i32); + const idx_b = try zml.Buffer.scalar(platform, 3, .i32); + const A = struct { + pub fn forward(x_: Tensor, idx_: [2]Tensor, y_: Tensor) Tensor { + return x_.dynamicUpdateSlice(&idx_, y_); + } + }; + const res = try zml.testing.compileAndCall(platform, A.forward, .{ x, .{ idx_a, idx_b }, y }); + try testing.expectEqualDeep( + [2][5]f32{ .{ 0, 1, 2, 3, 4 }, .{ 5, 6, 7, -1, 9 } }, + res.getValue([2][5]f32), + ); + } + } + + /// Returns a Tensor containing the element-wise result of the given 'cmp' comparison between the two input Tensors. + pub fn cmp(self: Tensor, direction: dialect.stablehlo.ComparisonDirection.Direction, other: Tensor) Tensor { + meta.assert(self.dtype() == other.dtype(), "cmp expects input tensors to be of the same type, got {} and {}", .{ self.dtype(), other.dtype() }); + + if (self.rank() == 0 and other.rank() != 0) return self.broadcast(other._shape, &.{}).cmp(direction, other); + if (self.rank() != 0 and other.rank() == 0) return self.cmp(direction, other.broadcast(self._shape, &.{})); + + meta.assert(self._shape.eql(other._shape), "cmp expects input tensor shapes to match, got {} and {}", .{ self._shape, other._shape }); + + const loc = self.getContext().mlirCtx().location(@src()).namedFmt(self.getContext().mlirCtx(), "cmp(.{s})", .{@tagName(direction)}); + const op = dialect.stablehlo.compare( + self.getContext().mlirCtx(), + self.value(), + other.value(), + dialect.stablehlo.ComparisonDirection.init(self.getContext().mlirCtx(), direction), + getComparisonType(self.getContext().mlirCtx(), self.dtype()), + loc, + ); + + return _result(self._shape.withDtype(.bool), op.result(0)); + } + + /// For each element at index `i`, if `bool_tensor[i] == true`, `output[i] = on_true[i]` + /// otherwise, if `bool_tensor[i] == false`, `output[i] = on_false[i]` + pub fn select(bool_tensor: Tensor, on_true: Tensor, on_false: Tensor) Tensor { + meta.assert(bool_tensor.dtype() == .bool, "select expects input tensor type to be a boolean, got {}", .{bool_tensor.dtype()}); + meta.assert(on_true.dtype() == on_false.dtype(), "select expects 'on_true' and 'on_false' tensor types to be equal, got {} and {}", .{ on_true.dtype(), on_false.dtype() }); + meta.assert(bool_tensor._shape.eqlDims(on_true._shape), "select expects input tensor and 'on_true' tensor dimensions to match, got {} and {}", .{ bool_tensor._shape, on_true._shape }); + meta.assert(bool_tensor._shape.eqlDims(on_false._shape), "select expects input tensor and 'on_false' tensor dimensions to match, got {} and {}", .{ bool_tensor._shape, on_false._shape }); + + const loc = bool_tensor.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.select( + bool_tensor.getContext().mlirCtx(), + bool_tensor.value(), + on_true.value(), + on_false.value(), + loc, + ); + + return _result(on_true._shape, op.result(0)); + } + + /// Returns a Tensor containing the element-wise not logical operation of the input Tensor. + pub fn not(self: Tensor) Tensor { + const loc = self.getContext().mlirCtx().location(@src()); + const op = dialect.stablehlo.not(self.getContext().mlirCtx(), self.value(), loc); + return _result(self._shape, op.result(0)); + } + + /// Returns a Tensor containing boolean indicating if there is a non-zero value over the given axis. + pub fn any(self: Tensor, axis_: i64) Tensor { + const pred = self.cmp(.NE, Tensor.constant(self.dims(), self.dtype().zero())); + const red = ops.reduce( + struct { + pub fn acc(x: Tensor, res: Tensor) Tensor { + return res.logical(.OR, x); + } + }.acc, + pred, + Tensor.scalar(0, pred.dtype()), + &.{self.axis(axis_)}, + ); + return red; + } + + /// Given a set of N vectors of lengths A, B, C, D, + /// returns N tensors of rank N, and shape (A, B, C, D). + /// For any coordinate (a, b, c, d), + /// we have: + /// - res[0][a, b, c, d] == A[a] + /// - res[1][a, b, c, d] == B[b] + /// - res[2][a, b, c, d] == C[c] + /// - res[3][a, b, c, d] == D[d] + /// This is implemented with broadcasting, so typically it won't copy. + /// In Pytorch/Numpy this is know as `meshgrid` with "ij" mode. + /// See torch.meshgrid for the "xy" mode. + pub fn cartesianProduct(comptime N: u3, vectors: [N]Tensor) [N]Tensor { + var out: @TypeOf(vectors) = undefined; + _cartesianProduct(&vectors, &out); + return out; + } + + fn _cartesianProduct(vectors: []const Tensor, out: []Tensor) void { + meta.assert(vectors.len >= 1, "cartesianProduct expects at least one input.", .{}); + meta.assert(vectors.len < Tensor.MAX_RANK, "cartesianProduct expects at most {} input vectors, received {} !", .{ Tensor.MAX_RANK - 1, vectors.len }); + for (vectors) |x| { + meta.assert(x.rank() <= 1, "cartesianProduct expects 0 or 1 rank input vectors. Got: {any}", .{vectors}); + meta.assert(vectors[0].dtype() == x.dtype(), "cartesianProduct expects input vectors to have all the same dtype. Got: {any}", .{vectors}); + } + + var res_shape = Shape.init(.{}, vectors[0].dtype()); + for (vectors) |x| { + if (x.rank() == 0) { + res_shape = res_shape.appendDim(1, null); + } else { + res_shape = res_shape.appendDim(x.dim(0), x.shape().tag(0)); + } + } + + for (out, vectors, 0..) |*o, x, i| { + o.* = x.broadcast(res_shape, &[1]i64{@intCast(i)}); + } + } + + test cartesianProduct { + const zml = @import("zml.zig"); + const client = zml.testing.env(); + + const x = try zml.Buffer.fromSlice(client, .{6}, &[_]i32{ 0, 1, 2, 3, 4, 5 }); + const y = try zml.Buffer.fromSlice(client, .{4}, &[_]i32{ 0, 1, 2, 3 }); + + const Local = struct { + pub fn cartesianProduct2(a: Tensor, b: Tensor) [2]Tensor { + return cartesianProduct(2, .{ a, b }); + } + }; + + { + const xs, const ys = try zml.testing.compileAndCall(client, Local.cartesianProduct2, .{ x, y }); + try std.testing.expectEqualSlices(i64, &.{ 6, 4 }, xs.shape().dims()); + try std.testing.expectEqualSlices(i64, &.{ 6, 4 }, ys.shape().dims()); + try std.testing.expectEqualDeep( + [6][4]i32{ + .{ 0, 0, 0, 0 }, + .{ 1, 1, 1, 1 }, + .{ 2, 2, 2, 2 }, + .{ 3, 3, 3, 3 }, + .{ 4, 4, 4, 4 }, + .{ 5, 5, 5, 5 }, + }, + try xs.getValue([6][4]i32), + ); + try std.testing.expectEqualDeep( + [6][4]i32{ + .{ 0, 1, 2, 3 }, + .{ 0, 1, 2, 3 }, + .{ 0, 1, 2, 3 }, + .{ 0, 1, 2, 3 }, + .{ 0, 1, 2, 3 }, + .{ 0, 1, 2, 3 }, + }, + try ys.getValue([6][4]i32), + ); + } + } + + /// Given a set of N vectors of lengths A, B, C, D, + /// returns 1 tensors of rank N+1, and shape (A, B, C, D, N). + /// For any coordinate (a, b, c, d), + /// we have: + /// - res[a, b, c, d] == (A[a], B[b], C[c], D[d]) + pub fn cartesianProductStacked(vectors: []const Tensor) Tensor { + var out = std.BoundedArray(Tensor, Tensor.MAX_RANK).init(vectors.len) catch unreachable; + _cartesianProduct(vectors, out.slice()); + + return Tensor.stack(out.constSlice(), .last, .coord); + } + + test cartesianProductStacked { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + const x = try zml.Buffer.fromSlice(platform, .{6}, &[_]i32{ 0, 1, 2, 3, 4, 5 }); + const y = try zml.Buffer.fromSlice(platform, .{4}, &[_]i32{ 0, 1, 2, 3 }); + + const Local = struct { + pub fn cartesianProduct2(a: Tensor, b: Tensor) Tensor { + return cartesianProductStacked(&.{ a, b }); + } + }; + + const z = try zml.testing.compileAndCall(platform, Local.cartesianProduct2, .{ x, y }); + try std.testing.expectEqualDeep( + [6][4][2]i32{ + .{ .{ 0, 0 }, .{ 0, 1 }, .{ 0, 2 }, .{ 0, 3 } }, + .{ .{ 1, 0 }, .{ 1, 1 }, .{ 1, 2 }, .{ 1, 3 } }, + .{ .{ 2, 0 }, .{ 2, 1 }, .{ 2, 2 }, .{ 2, 3 } }, + .{ .{ 3, 0 }, .{ 3, 1 }, .{ 3, 2 }, .{ 3, 3 } }, + .{ .{ 4, 0 }, .{ 4, 1 }, .{ 4, 2 }, .{ 4, 3 } }, + .{ .{ 5, 0 }, .{ 5, 1 }, .{ 5, 2 }, .{ 5, 3 } }, + }, + try z.getValue([6][4][2]i32), + ); + } + + fn binaryOp( + op_name: []const u8, + op_fn: fn (mlir.Context, mlir.Value, mlir.Value, mlir.Location) mlir.Operation, + ) fn (Tensor, Tensor) Tensor { + return struct { + pub fn binaryOpHelper(self: Tensor, other: Tensor) Tensor { + meta.assert(self.dtype() == other.dtype(), "{s} expects tensor to be of same type, got {} and {}", .{ op_name, self.dtype(), other.dtype() }); + + if (self.rank() == 0 and other.rank() != 0) { + return binaryOpHelper(self.broad(other._shape), other); + } + + if (self.rank() != 0 and other.rank() == 0) { + return binaryOpHelper(self, other.broad(self._shape)); + } + + meta.assert(self._shape.eql(other._shape), "{s} expects tensor shapes to match, got {} and {}", .{ op_name, self._shape, other._shape }); + + const mlirCtx = self.getContext().mlirCtx(); + const location = mlirCtx.location(@src()); + const ret = @call(.auto, op_fn, .{ mlirCtx, self.value(), other.value(), location }); + return _result(self._shape, ret.result(0)); + } + }.binaryOpHelper; + } +}; + +fn initPoolArg(rank: usize, data: []const i64) [Tensor.MAX_RANK]i64 { + // TODO use shape + var result = [_]i64{1} ** Tensor.MAX_RANK; + const start = rank - data.len; + @memcpy(result[start .. start + data.len], data); + return result; +} + +fn getPoolResDims(dt: DataType, in_dims: []const i64, base_dilations: @Vector(Tensor.MAX_RANK, i64), padding: []const i64, window_dimensions: @Vector(Tensor.MAX_RANK, i64), window_dilations: @Vector(Tensor.MAX_RANK, i64), window_strides: @Vector(Tensor.MAX_RANK, i64)) Shape { + // TODO use shape + var input_dims = [_]i64{1} ** Tensor.MAX_RANK; + @memcpy(input_dims[0..in_dims.len], in_dims); + + const input_dims_: @Vector(Tensor.MAX_RANK, i64) = input_dims; + const splat_one: @Vector(Tensor.MAX_RANK, i64) = @splat(1); + const dilated_input_shape: @Vector(Tensor.MAX_RANK, i64) = (input_dims_ - splat_one) * base_dilations + splat_one; + var pad_slice0: @Vector(Tensor.MAX_RANK, i64) = @splat(padding[0]); + var pad_slice1: @Vector(Tensor.MAX_RANK, i64) = @splat(padding[0]); + if (padding.len > 1) { + var idx: usize = 0; + while (idx < in_dims.len * 2) : (idx += 2) { + pad_slice0[idx / 2] = padding[idx]; + pad_slice1[idx / 2] = padding[idx + 1]; + } + } + const padded_input_shape: @Vector(Tensor.MAX_RANK, i64) = pad_slice0 + dilated_input_shape + pad_slice1; + const dilated_window_shape = (window_dimensions - splat_one) * window_dilations + splat_one; + const dims = @divFloor(padded_input_shape - dilated_window_shape, window_strides) + splat_one; + const dims_arr: [Tensor.MAX_RANK]i64 = @bitCast(dims); + return Shape.init(dims_arr[0..in_dims.len], dt); +} + +fn getComparisonType(ctx: mlir.Context, dtype: DataType) dialect.stablehlo.CompareType { + return dialect.stablehlo.CompareType.init(ctx, switch (dtype) { + .i4, .i8, .i16, .i32, .i64 => .SIGNED, + .bool, .u4, .u8, .u16, .u32, .u64 => .UNSIGNED, + .f8e4m3b11fnuz, .f8e4m3fn, .f8e4m3fnuz, .f8e5m2, .f8e5m2fnuz, .bf16, .f16, .f32, .f64 => .FLOAT, + .c64, .c128 => @panic("Can't compare complex numbers"), + }); +} + +test "Tensor.maxPool1d" { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + + const MaxPool = struct { + pub fn forward(x: zml.Tensor) Tensor.ArgMaxRes { + return x.maxPool1d(.{ + .window_dimensions = 3, + .window_strides = 2, + }); + } + }; + + var data: [20]f32 = undefined; + for (&data, 0..) |*v, i| v.* = @floatFromInt(i); + + const x = try zml.Buffer.fromSlice(platform, .{ 2, 2, 5 }, &data); + const result = try zml.testing.compileAndCall(platform, MaxPool.forward, .{x}); + try zml.testing.expectEqualShapes(Shape.init(.{ 2, 2, 2 }, .f32), result.values.shape()); + try zml.testing.expectEqualShapes(Shape.init(.{ 2, 2, 2 }, .i32), result.indices.shape()); + const buffer = result.values.getValue([2][2][2]f32); + try std.testing.expectEqualDeep( + [2][2][2]f32{ + [2][2]f32{ + [2]f32{ 2, 4 }, + [2]f32{ 7, 9 }, + }, + [2][2]f32{ + [2]f32{ 12, 14 }, + [2]f32{ 17, 19 }, + }, + }, + buffer, + ); +} + +test "Tensor.maxPool2d" { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + + const MaxPool = struct { + pub fn forward(x: Tensor) Tensor.ArgMaxRes { + return x.maxPool2d(.{ + .window_dimensions = &.{ 3, 2 }, + .window_strides = &.{ 2, 1 }, + }); + } + }; + + var data: [100]f32 = undefined; + for (&data, 0..) |*v, i| v.* = @floatFromInt(i); + const x = try zml.Buffer.fromSlice(platform, .{ 2, 2, 5, 5 }, &data); + + const result = try zml.testing.compileAndCall(platform, MaxPool.forward, .{x}); + try zml.testing.expectEqualShapes(Shape.init(.{ 2, 2, 2, 4 }, .f32), result.values.shape()); + try zml.testing.expectEqualShapes(Shape.init(.{ 2, 2, 2, 4 }, .i32), result.indices.shape()); + var buffer: [2][2][2][4]f32 = undefined; + _ = try result.values.toHost(std.mem.asBytes(&buffer)); + try std.testing.expectEqualDeep( + [2][2][2][4]f32{ + .{ + .{ .{ 11, 12, 13, 14 }, .{ 21, 22, 23, 24 } }, + .{ .{ 36, 37, 38, 39 }, .{ 46, 47, 48, 49 } }, + }, + .{ + .{ .{ 61, 62, 63, 64 }, .{ 71, 72, 73, 74 } }, + .{ .{ 86, 87, 88, 89 }, .{ 96, 97, 98, 99 } }, + }, + }, + buffer, + ); +} + +fn disabledTestTensorMaxPool3d() void { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + + const MaxPool = struct { + pub fn forward(x: Tensor) Tensor.ArgMaxRes { + return x.maxPool3d(.{ + .window_dimensions = &.{ 3, 2, 2 }, + .window_strides = &.{ 2, 1, 2 }, + }); + } + }; + + var data: [100]f32 = undefined; + for (&data, 0..) |*v, i| v.* = @floatFromInt(i); + const x = try zml.Buffer.fromSlice(.{ 1, 2, 5, 5, 2 }, &data, platform); + + const result = try zml.testing.compileAndCall(platform, MaxPool.forward, .{x}); + try std.testing.expectEqualSlices(i64, &.{ 1, 2, 2, 4, 1 }, result.values.dims()); + try std.testing.expectEqualSlices(i64, &.{ 1, 2, 2, 4, 1 }, result.indices.dims()); + var buffer: [1][2][2][4][1]f32 = undefined; + _ = result.values.toHost(std.mem.asBytes(&buffer)); + try std.testing.expectEqualDeep( + [1][2][2][4][1]f32{ + .{ + .{ + .{ .{23}, .{25}, .{27}, .{29} }, + .{ .{43}, .{45}, .{47}, .{49} }, + }, + .{ + .{ .{73}, .{75}, .{77}, .{79} }, + .{ .{93}, .{95}, .{97}, .{99} }, + }, + }, + }, + buffer, + ); +} + +test "argMax" { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + const allocator = std.testing.allocator; + const ArgMaxTest = struct { + pub fn forward(x: Tensor) Tensor.ArgMaxRes { + return x.argMax(1, .i32); + } + }; + + const argmax = try zml.compileFn(allocator, ArgMaxTest.forward, .{Shape.init(.{ 1, 5 }, .f32)}, platform); + defer argmax.deinit(); + // Test with tie + { + const x = try zml.Buffer.fromArray(platform, [1][5]f32{.{ 5.0, 4.1, 7.9, 0, 7.9 }}); + const res = argmax.call(.{x}); + const max = res.values.getValue(f32); + const max_idx = res.indices.getValue(i32); + try testing.expectEqual(max, 7.9); + // We should always return the first max found. + try testing.expectEqual(max_idx, 2); + } + + // Test with Nan + { + const x = try zml.Buffer.fromArray(platform, [1][5]f32{.{ 5.0, std.math.nan(f32), 7.9, 0, 7.9 }}); + const res = argmax.call(.{x}); + const max = try res.values.getValue(f32); + const max_idx = try res.indices.getValue(i32); + try testing.expect(std.math.isNan(max)); + try testing.expectEqual(max_idx, 1); + } +} + +fn dynamicSlice1d() void { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena_state.deinit(); + const allocator = arena_state.allocator(); + const T = f32; + + { + defer _ = arena_state.reset(.retain_capacity); + const x = try zml.Buffer.fromArray(platform, [10]T{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + const z = try zml.Buffer.scalar(platform, 4, .i32); + var comp = zml.module.CompilationContext.init(allocator, "test", platform, .{}); + defer comp.deinit(); + var x_tensor = x.shape(); + var args: struct { i8, u63, zml.Shape } = .{ 0, 2, z.shape() }; + var dynamicSlice = try zml.compileRaw(allocator, &comp, Tensor.dynamicSlice1d, &x_tensor, &args); + + var res: [1]*pjrt.Buffer = undefined; + dynamicSlice.call(&.{ x._data, z._data }, &res); + try testing.expectEqual([2]T{ 4, 5 }, try zml.Buffer.fromPjrtBuffer(platform, res[0]).getValue([2]T)); + } + + { + // Strided + var x = try zml.Buffer.fromArray(platform, [2][5]T{ .{ 0, 1, 2, 3, 4 }, .{ 5, 6, 7, 8, 9 } }); + var z = try zml.Buffer.scalar(platform, 3, .i32); + + var comp = zml.module.CompilationContext.init(allocator, "test", platform, .{}); + defer comp.deinit(); + var x_tensor = x.shape(); + var args: struct { i8, u63, zml.Tensor } = .{ 1, 2, z.shape() }; + var dynamicSlice = try zml.compileRaw(allocator, &comp, Tensor.dynamicSlice1d, &x_tensor, &args); + + var res: [1]*pjrt.Buffer = undefined; + dynamicSlice.call(&.{ x._data, z._data }, &res); + try testing.expectEqualSlices(T, &.{ 3, 4, 8, 9 }, &(try zml.Buffer.fromPjrtBuffer(platform, res[0]).getValue([4]T))); + } +} + +test "dynamicUpdateSlice1d" { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena_state.deinit(); + const allocator = arena_state.allocator(); + const T = f32; + + { + const x = try zml.Buffer.fromSlice(platform, .{10}, &[_]T{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + const y = try zml.Buffer.fromSlice(platform, .{2}, &[_]T{ -1, -1 }); + const z = try zml.Buffer.fromSlice(platform, .{}, &[_]i32{4}); + const res = try zml.testing.compileAndCall(platform, Tensor.dynamicUpdateSlice1d, .{ x, y, 0, z }); + try testing.expectEqualSlices(T, &.{ 0, 1, 2, 3, -1, -1, 6, 7, 8, 9 }, &try res.getValue([10]T)); + } + + { + // Partial update: 3 out of 5 elements on the second row + // Note: this seems error prone, but stablehlo allows it. Should we be more restrictive ? + const x = try zml.Buffer.fromSlice(platform, .{ 2, 5 }, &[_]T{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + const y = try zml.Buffer.fromSlice(platform, .{ 1, 3 }, &[_]T{ 0, 0, 0 }); + const z = try zml.Buffer.fromSlice(platform, .{}, &[_]i32{1}); + const res = try zml.testing.compileAndCall(platform, Tensor.dynamicUpdateSlice1d, .{ x, y, 0, z }); + + try testing.expectEqualSlices(T, &.{ 0, 1, 2, 3, 4, 0, 0, 0, 8, 9 }, &try res.getValue([10]T)); + } + + { + // Strided + const x = try zml.Buffer.fromSlice(platform, .{ 2, 5 }, &[_]T{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + const y = try zml.Buffer.fromSlice(platform, .{ 2, 1 }, &[_]T{ 0, 0 }); + const z = try zml.Buffer.fromSlice(platform, .{}, &[_]i32{3}); + const res_dev = try zml.testing.compileAndCall(platform, Tensor.dynamicUpdateSlice1d, .{ x, y, 1, z }); + const res = try res_dev.toHostAlloc(allocator); + + try testing.expectEqualSlices(T, &.{ 0, 1, 2, 0, 4, 5, 6, 7, 0, 9 }, res.items(T)); + } +} + +test "slice" { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + + const x = try zml.Buffer.fromSlice(platform, .{ 2, 5 }, &[_]f32{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + + // Wrap slice1d to hide the anytype in the signature. + const Local = struct { + pub fn slice1dAxis(input: Tensor, ax: i8, slice: Tensor.Slice) Tensor { + return input.slice1d(ax, slice); + } + }; + + { + const res = try zml.testing.compileAndCallWithTensors(platform, Local.slice1dAxis, .{ x.shape(), 0, .{ .end = 1 } }, .{ x, 0, .{ .end = 1 } }); + try testing.expectEqual([5]f32{ 0, 1, 2, 3, 4 }, try res.getValue([5]f32)); + } + { + const res = try zml.testing.compileAndCallWithTensors(platform, Local.slice1dAxis, .{ x.shape(), 1, .{ .start = 1, .step = 2 } }, .{ x, 0, .{ .start = 1, .step = 2 } }); + try testing.expectEqual([4]f32{ 1, 3, 6, 8 }, try res.getValue([4]f32)); + } + { + const res = try zml.testing.compileAndCallWithTensors(platform, Local.slice1dAxis, .{ x.shape(), -1, .{ .start = -2 } }, .{ x, 0, .{ .start = -2 } }); + try testing.expectEqual([4]f32{ 3, 4, 8, 9 }, try res.getValue([4]f32)); + } +} + +test "Tensor.fmod" { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + + const inputs: [2][6]f32 = .{ .{ -3.0, -2, -1, 1, 2, 3 }, .{ 1, 2, 3, 4, 5, -5 } }; + const expectations: [2][6]f32 = .{ .{ -1.0, -0.0, -1.0, 1.0, 0.0, 1.0 }, .{ 1.0000, 0.5000, 0.0000, 1.0000, 0.5000, -0.5000 } }; + const divisors: [2]f32 = .{ 2, -1.5 }; + + inline for (inputs, expectations, divisors) |i, e, d| { + const input = try zml.Buffer.fromSlice(platform, .{6}, &i); + const output = try zml.testing.compileAndCall(platform, Tensor.fmod, .{ input, d }); + + try zml.testing.expectClose(zml.HostBuffer.fromSlice(.{6}, &e), output, 1e-4); + } +} + +test "Tensor.argsort" { + const zml = @import("zml.zig"); + const platform = zml.testing.env(); + + var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena_state.deinit(); + const allocator = arena_state.allocator(); + // 2D Tensor - dim = 1, ascending + { + const x = try zml.Buffer.fromSlice(platform, .{ 2, 5 }, &[_]f32{ -0.9264, 0.7156, 1.0202, 0.3992, 1.2349, 1.0003, -0.1932, 1.3935, 0.7316, 0.0851 }); + const res = try zml.testing.compileAndCall(platform, Tensor.argsort, .{ x, 1, .{} }); + const res_cpu = try res.toHostAlloc(allocator); + try testing.expectEqualSlices(i32, &.{ 0, 3, 1, 2, 4, 1, 4, 3, 0, 2 }, res_cpu.items(i32)); + } + // 3D Tensor, dim = 1, descending + { + const x = try zml.Buffer.fromSlice(platform, .{ 1, 5, 10 }, &[_]f16{ + -0.2505, 1.2520, -0.7041, 0.1066, 1.2773, -1.7246, 0.8389, 1.1094, 0.0601, 1.0684, + 0.9619, 1.3916, 1.2246, -0.1406, 0.3674, -1.2480, -1.7051, -0.0934, 0.3435, 0.4373, + 1.3809, 0.5444, -0.6079, 1.2031, -0.6880, 1.2979, -0.1869, 0.2991, 0.0156, 0.1847, + 0.6626, -0.3040, -0.8726, -1.4805, -1.6943, 1.1055, -2.0078, -0.5288, 0.8813, 0.8008, + 2.0527, 1.1230, 0.5430, 0.2494, -0.9434, 0.7876, 0.1818, 0.9258, -2.4902, 1.5918, + }); + const res_dev = try zml.testing.compileAndCall(platform, Tensor.argsort, .{ x, 1, .{ .descending = true } }); + const res = try res_dev.toHostAlloc(allocator); + try testing.expectEqualSlices(i32, &.{ + 4, 1, 1, 2, 0, 2, 0, 0, 3, 4, + 2, 0, 4, 4, 1, 3, 4, 4, 1, 0, + 1, 4, 2, 0, 2, 4, 2, 2, 0, 3, + 3, 2, 0, 1, 4, 1, 1, 1, 2, 1, + 0, 3, 3, 3, 3, 0, 3, 3, 4, 2, + }, res.items(i32)); + } + // 4D Tensor, dim = 3, ascending + { + const x = try zml.Buffer.fromSlice(platform, .{ 4, 2, 1, 4 }, &[_]i32{ + 89, 31, 22, 42, + 64, 39, 0, 30, + 64, 71, 46, 31, + 89, 82, 78, 86, + 55, 32, 43, 19, + 93, 24, 45, 72, + 64, 86, 62, 88, + 57, 21, 19, 12, + }); + const res_dev = try zml.testing.compileAndCallWithTensors(platform, Tensor.argsort, .{ x.shape(), 3, .{} }, .{ x, 0, .{} }); + const res = try res_dev.toHostAlloc(allocator); + try testing.expectEqualSlices(i32, &.{ + 2, 1, 3, 0, + 2, 3, 1, 0, + 3, 2, 0, 1, + 2, 1, 3, 0, + 3, 1, 2, 0, + 1, 2, 3, 0, + 2, 0, 1, 3, + 3, 2, 1, 0, + }, res.items(i32)); + } +} + +fn parseArrayInfo(T: type) Shape { + return switch (@typeInfo(T)) { + .Array => |arr| { + const s = parseArrayInfo(arr.child); + return s.insert(0, .{arr.len}); + }, + else => .{ ._dtype = DataType.fromZigType(T) }, + }; +} + +pub inline fn toI64(values: anytype) []i64 { + var res: [Tensor.MAX_RANK]i64 = undefined; + for (values, 0..) |val, i| res[i] = @intCast(val); + return res[0..values.len]; +} + +/// Return a clone of a type with Tensors replaced by Shapes. +/// Recursively descends into the type. +/// See also: shapesOf() and its tests, and meta.MapType(). +pub fn ShapeOf(comptime T: type) type { + const M = meta.MapType(Tensor, Shape); + return M.map(T); +} + +/// Return a clone of the argument where each instance of a Tensor is replaced +/// by its Shape. This is similar to ShapeOf(), but with runtime values. +/// See also: meta.mapAlloc(). +pub fn shapesOf(model: anytype, allocator: std.mem.Allocator) !ShapeOf(@TypeOf(model)) { + var shapes: ShapeOf(@TypeOf(model)) = undefined; + try meta.mapAlloc(struct { + fn shapeFromTensorCallback(_: void, tensor: Tensor) Shape { + return tensor.shape(); + } + }.shapeFromTensorCallback, allocator, {}, model, &shapes); + return shapes; +} + +test shapesOf { + const alloc = std.testing.allocator; + + // Tensor in struct + { + const S = struct { + a: Tensor, + }; + const shape = Shape.init(.{ 28, 28 }, .f32); + const s: S = .{ + .a = Tensor{ ._shape = shape, ._id = undefined }, + }; + const shapes = try shapesOf(s, alloc); + try std.testing.expectEqual(shape, shapes.a); + } + + // single Tensor + { + const shape = Shape.init(.{ 28, 28 }, .f32); + const tensor = Tensor{ ._shape = shape, ._id = undefined }; + const shapes = try shapesOf(tensor, alloc); + try std.testing.expectEqual(shape, shapes); + } + + // nn linear layer, no bias + { + const nn = @import("nn.zig"); + const shape = Shape.init(.{ 28, 28 }, .f32); + const layer: nn.Linear = .{ + .weight = Tensor{ ._shape = shape, ._id = undefined }, + .bias = null, + }; + + const shapes = try shapesOf(layer, alloc); + try std.testing.expectEqual(shape, shapes.weight); + try std.testing.expectEqual(null, shapes.bias); + } + + // model + { + const Mnist = struct { + fc1: Layer, + fc2: Layer, + + const Layer = struct { + weight: Tensor, + bias: Tensor, + }; + }; + + const fc1_weight_shape = Shape.init(.{ 500, 784 }, .f32); + const fc1_bias_shape = Shape.init(.{500}, .f32); + const fc2_weight_shape = Shape.init(.{ 10, 500 }, .f32); + const fc2_bias_shape = Shape.init(.{10}, .f32); + const mnist: Mnist = .{ + .fc1 = .{ + .weight = Tensor{ ._shape = fc1_weight_shape, ._id = undefined }, + .bias = Tensor{ ._shape = fc1_bias_shape, ._id = undefined }, + }, + .fc2 = .{ + .weight = Tensor{ ._shape = fc2_weight_shape, ._id = undefined }, + .bias = Tensor{ ._shape = fc2_bias_shape, ._id = undefined }, + }, + }; + + const shapes = try shapesOf(mnist, alloc); + try std.testing.expectEqual(fc1_weight_shape, shapes.fc1.weight); + try std.testing.expectEqual(fc1_bias_shape, shapes.fc1.bias); + try std.testing.expectEqual(fc2_weight_shape, shapes.fc2.weight); + try std.testing.expectEqual(fc2_bias_shape, shapes.fc2.bias); + } +} diff --git a/zml/test_runner.zig b/zml/test_runner.zig new file mode 100644 index 0000000..0ff5ad6 --- /dev/null +++ b/zml/test_runner.zig @@ -0,0 +1,100 @@ +//! Test runner for unit test based on https://github.com/ziglang/zig/blob/master/lib/compiler/test_runner.zig with async +const builtin = @import("builtin"); + +const std = @import("std"); +const asynk = @import("async"); +const io = std.io; +const testing = std.testing; +const assert = std.debug.assert; + +// note: std_options.log_level does not respect testing.log_level +// ref: https://github.com/ziglang/zig/issues/5738 +const log_level: std.log.Level = .warn; + +pub const std_options = .{ + .log_level = log_level, +}; + +var log_err_count: usize = 0; +var fba_buffer: [8192]u8 = undefined; +var fba = std.heap.FixedBufferAllocator.init(&fba_buffer); + +pub fn main() anyerror!void { + testing.log_level = log_level; + try asynk.AsyncThread.main(testing.allocator, asyncMain, .{}); +} + +pub fn asyncMain() void { + const test_fn_list = builtin.test_functions; + var ok_count: usize = 0; + var skip_count: usize = 0; + var fail_count: usize = 0; + const root_node = std.Progress.start(.{ + .root_name = "Test", + .estimated_total_items = test_fn_list.len, + }); + const have_tty = std.io.getStdErr().isTty(); + + var leaks: usize = 0; + + for (test_fn_list, 0..) |test_fn, i| { + testing.allocator_instance = .{}; + defer { + if (testing.allocator_instance.deinit() == .leak) { + leaks += 1; + } + } + + const test_node = root_node.start(test_fn.name, 0); + if (!have_tty) { + std.debug.print("{d}/{d} {s}...", .{ i + 1, test_fn_list.len, test_fn.name }); + } + if (test_fn.func()) |_| { + ok_count += 1; + test_node.end(); + if (!have_tty) std.debug.print("OK\n", .{}); + } else |err| switch (err) { + error.SkipZigTest => { + skip_count += 1; + if (have_tty) { + std.debug.print("{d}/{d} {s}...SKIP\n", .{ i + 1, test_fn_list.len, test_fn.name }); + } else { + std.debug.print("SKIP\n", .{}); + } + test_node.end(); + }, + else => { + fail_count += 1; + if (have_tty) { + std.debug.print("{d}/{d} {s}...FAIL ({s})\n", .{ + i + 1, test_fn_list.len, test_fn.name, @errorName(err), + }); + } else { + std.debug.print("FAIL ({s})\n", .{@errorName(err)}); + } + if (@errorReturnTrace()) |trace| { + std.debug.dumpStackTrace(trace.*); + } + test_node.end(); + }, + } + } + root_node.end(); + if (ok_count == test_fn_list.len) { + std.debug.print("All {d} tests passed.\n", .{ok_count}); + } else { + std.debug.print("{d} passed; {d} skipped; {d} failed.\n", .{ ok_count, skip_count, fail_count }); + } + if (log_err_count != 0) { + std.debug.print("{d} errors were logged.\n", .{log_err_count}); + } + if (leaks != 0) { + std.debug.print("{d} tests leaked memory.\n", .{leaks}); + } + if (leaks != 0 or log_err_count != 0 or fail_count != 0) { + std.process.exit(1); + } + + // Explicit exit 0 to exit from async main thread and main properly + std.process.exit(0); +} diff --git a/zml/testing.zig b/zml/testing.zig new file mode 100644 index 0000000..6f0544a --- /dev/null +++ b/zml/testing.zig @@ -0,0 +1,246 @@ +const std = @import("std"); +const builtin = @import("builtin"); + +const zml = @import("zml.zig"); +const meta = @import("meta.zig"); +const shapesOf = @import("tensor.zig").shapesOf; + +const log = std.log.scoped(.zml_testing); + +var _ctx: ?zml.Context = null; + +pub fn env() zml.Platform { + if (!builtin.is_test) @compileError("Cannot use zml.testing.env outside of a test block"); + if (_ctx == null) { + _test_compile_opts = if (initCacheDir()) + .{ + .cache_location = "/tmp/zml/tests/cache", + .xla_dump_to = "/tmp/zml/tests/", + } + else + .{}; + + _ctx = zml.Context.init() catch unreachable; + } + return _ctx.?.platforms.get(.cpu).?.withCompilationOptions(_test_compile_opts); +} + +var _test_compile_opts: zml.CompilationOptions = .{}; + +fn initCacheDir() bool { + const tmp = std.fs.openDirAbsolute("/tmp", .{}) catch return false; + tmp.makePath("zml/tests/cache") catch return false; + return true; +} + +/// In neural network we generally care about the relative precision, +/// but on a given dimension, if the output is close to 0, then the precision +/// don't matter as much. +pub fn approxEq(comptime Float: type, l: Float, r: Float, tolerance: Float) bool { + const closeRel = std.math.approxEqRel(Float, l, r, @floatCast(tolerance)); + const closeAbs = std.math.approxEqAbs(Float, l, r, @floatCast(tolerance / 2)); + return closeRel or closeAbs; +} + +/// Testing utility. Accepts both Tensor and HostBuffer but Tensor will be copied to the +/// host for comparison ! +pub fn expectClose(left_: anytype, right_: anytype, tolerance: f32) !void { + const allocator = if (builtin.is_test) std.testing.allocator else std.heap.page_allocator; + var left: zml.HostBuffer, const should_free_left = if (@TypeOf(left_) == zml.Buffer) + .{ try left_.toHostAlloc(allocator), true } + else + .{ left_, false }; + + var right: zml.HostBuffer, const should_free_right = if (@TypeOf(right_) == zml.Buffer) + .{ try right_.toHostAlloc(allocator), true } + else + .{ right_, false }; + + defer { + if (should_free_left) left.deinit(allocator); + if (should_free_right) right.deinit(allocator); + } + + if (!std.mem.eql(i64, left.shape().dims(), right.shape().dims())) { + log.err("left.shape() {} != right.shape() {}", .{ left.shape(), right.shape() }); + return error.TestUnexpectedResult; + } + if (left.dtype() != right.dtype() and !(left.dtype() == .f16 and right.dtype() == .bf16)) { + log.err("left.dtype ({}) != right.dtype ({})", .{ left.dtype(), right.dtype() }); + return error.TestUnexpectedResult; + } + switch (left.dtype()) { + inline .f16, .f32, .f64 => |t| { + const L = t.toZigType(); + const left_data = left.items(L); + switch (right.dtype()) { + inline .f16, .bf16, .f32, .f64, .f8e4m3fn => |rt| { + const R = rt.toZigType(); + const right_data = right.items(R); + for (left_data, right_data, 0..) |l, r, i| { + if (!approxEq(L, l, zml.floats.floatCast(L, r), @floatCast(tolerance))) { + log.err("left.data != right_data.\n < {d:.3} \n > {d:.3}\n error at idx {d}: {d:.3} != {d:.3}", .{ center(left_data, i), center(right_data, i), i, left_data[i], right_data[i] }); + return error.TestUnexpectedResult; + } + } + }, + else => unreachable, + } + }, + inline .u8, .u16, .u32, .i16, .i32, .i64 => |t| { + const T = t.toZigType(); + const left_data = left.items(T); + const right_data = right.items(T); + if (!std.mem.eql(T, left_data, right_data)) { + log.err("left.data ({d}) != right.data ({d})", .{ left_data[0..10], right_data[0..10] }); + return error.TestUnexpectedResult; + } + }, + else => unreachable, + } +} + +pub fn expectEqualShapes(expected: zml.Shape, actual: zml.Shape) error{TestExpectedEqual}!void { + if (expected.eqlWithTags(actual)) return; + + std.debug.print("Expected {}, got {}", .{ expected, actual }); + return error.TestExpectedEqual; +} + +/// Compile a function and immediatly call it with the given buffers. +/// The compiled module is discarded after the call. +/// Useful during testing when a module is typically called only once. +pub fn compileAndCall(platform: zml.Platform, func: anytype, buffer_args: zml.Bufferized(meta.FnParams(func))) !zml.Bufferized(zml.meta.FnResult(func)) { + // This simplify test API and also ensure this fn isn't used outside of tests. + const allocator = std.testing.allocator; + var arena = std.heap.ArenaAllocator.init(allocator); + defer arena.deinit(); + + const Local = struct { + pub fn bufferToShape(_: void, x: zml.Buffer) zml.Shape { + return x.shape(); + } + }; + var shape_args: zml.ShapeOf(meta.FnParams(func)) = undefined; + try meta.mapAlloc(Local.bufferToShape, allocator, {}, buffer_args, &shape_args); + + const mod = try zml.compileFn(allocator, func, shape_args, platform); + defer mod.deinit(); + + return mod.call(buffer_args); +} + +/// Compile a function and immediatly call it with the given buffers. +/// The compiled module is discarded after the call. +/// Useful during testing when a module is typically called only once. +pub fn compileAndCallWithTensors(platform: zml.Platform, func: anytype, shape_args: zml.ShapeOf(meta.FnParams(func)), buffer_args: zml.Bufferized(meta.FnParams(func))) !zml.Bufferized(zml.meta.FnResult(func)) { + // This simplify test API and also ensure this fn isn't used outside of tests. + const allocator = std.testing.allocator; + var arena = std.heap.ArenaAllocator.init(allocator); + defer arena.deinit(); + + const mod = try zml.compileFn(allocator, func, shape_args, platform); + defer mod.deinit(); + + return mod.call(buffer_args); +} + +pub fn testLayer(platform: zml.Platform, buffer_store: zml.aio.BufferStore, comptime name: []const u8, layer: anytype, layer_weights: zml.Bufferized(@TypeOf(layer)), tolerance: f32) !void { + try testLayerOut(platform, buffer_store, name, name ++ ".out", layer, layer_weights, tolerance); +} + +pub fn testLayerOut( + platform: zml.Platform, + activations: zml.aio.BufferStore, + comptime name: []const u8, + comptime out_name: []const u8, + layer: anytype, + layer_weights: zml.Bufferized(@TypeOf(layer)), + tolerance: f32, +) !void { + var arena = std.heap.ArenaAllocator.init(std.heap.c_allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + log.info("Testing {s}", .{name}); + + const fwd = @TypeOf(layer).forward; + const FwdSign = zml.module.ModuleSignature(fwd); + + const input_tensors = try zml.aio.populateModelWithPrefix(FwdSign.ArgsT, alloc, activations, name ++ ".in"); + const input_shapes = try shapesOf(input_tensors, alloc); + + const n_in = zml.module.countTensors(&input_tensors); + const n_in_exp = activations.countLayers(name ++ ".in"); + if (n_in != n_in_exp) { + log.warn("Reference models uses {d} inputs, but implementation uses {d}", .{ n_in_exp, n_in }); + } + + const exe = try zml.compileModel(alloc, layer, .forward, input_shapes, platform, .{}); + + const n_out_exp = activations.countLayers(out_name); + if (exe.inner.result_buffer_count != n_out_exp) { + log.warn("Reference models produces {d} outputs, but implementation produces {d}", .{ n_out_exp, exe.inner.result_buffer_count }); + } + const mod = try exe.prepare(alloc, layer_weights); + + const FetchCtx = struct { + store: zml.aio.BufferStore, + index: u32, + prefix: std.ArrayListUnmanaged(u8), + platform: zml.Platform, + + fn fetch(ctx: *@This(), x: zml.Tensor) zml.Buffer { + _ = x; + defer ctx.index += 1; + var full_prefix = ctx.*.prefix; + _ = full_prefix.writer(undefined).print("{d}", .{ctx.index}) catch unreachable; + log.info("prefix: {s}", .{full_prefix.items}); + const host = ctx.store.get(full_prefix.items) orelse { + log.err("Didn't find test input: {s}", .{full_prefix.items}); + @panic("Missing test input"); + }; + return host.toDevice(ctx.platform) catch unreachable; + } + }; + + // Note: zml.populateModelWithPrefix isn't enough, + // because it assumes we have the same structure in the activation file + // than in the function signature. + // But for sake of decoupling the reference implementation + // and ZML code that's not always the case. + { + var input_buffers: zml.Bufferized(FwdSign.ArgsT) = undefined; + var fetch_ctx: FetchCtx = .{ .store = activations, .index = 0, .prefix = .{}, .platform = platform }; + try fetch_ctx.prefix.ensureTotalCapacity(alloc, name.len + 32); + fetch_ctx.prefix.appendSliceAssumeCapacity(name ++ ".in."); + try zml.meta.mapAlloc(FetchCtx.fetch, alloc, &fetch_ctx, input_tensors, &input_buffers); + defer zml.aio.unloadBuffers(input_buffers); + _ = mod.call(input_buffers); + } + + var buf: [1024]u8 = undefined; + for (mod.output_buffers, 0..) |out, i| { + const full_name = std.fmt.bufPrint(&buf, "{s}.{d}", .{ out_name, i }) catch unreachable; + const expected_out = activations.get(full_name) orelse { + log.warn("Output buffer not found: {s}", .{full_name}); + continue; + }; + zml.testing.expectClose(expected_out, zml.Buffer.fromPjrtBuffer(platform, out), tolerance) catch |err| { + log.err("{s}.{d} doesn't match !", .{ out_name, i }); + return err; + }; + } + + log.info("all good for {s} !", .{name}); +} + +pub inline fn expectEqual(expected: anytype, actual: @TypeOf(expected)) !void { + return std.testing.expectEqual(expected, actual); +} + +fn center(slice: anytype, i: usize) @TypeOf(slice) { + const c = 20; + const start = if (i < c) 0 else i - c; + const end = @min(start + 2 * c, slice.len); + return slice[start..end]; +} diff --git a/zml/tokenizer.zig b/zml/tokenizer.zig new file mode 100644 index 0000000..83634a6 --- /dev/null +++ b/zml/tokenizer.zig @@ -0,0 +1,738 @@ +//! Text tokenizer implementations +const std = @import("std"); +const builtin = @import("builtin"); +const testing = std.testing; + +const log = std.log.scoped(.zml_tokenizer); + +const helpers = @import("helpers.zig"); +const meta = @import("meta.zig"); + +/// Byte Pair Encoding tokenizer generally used for LLM. +pub const Tokenizer = struct { + tokens: [][]const u8, + token_lookup: std.StringHashMapUnmanaged(u32), + special_tokens: SpecialTokens, + + scores: []f32, + max_token_len: u32, + normalizer: ?Normalizer, + + arena_state: std.heap.ArenaAllocator, + vocab_size: u32, + next_token_id: u32 = 0, + + pub const SpecialTokens = struct { + eos: u32, + bos: u32, + unk: u32, + pad: u32 = std.math.maxInt(u32), + hard_space: u32 = std.math.maxInt(u32), + }; + + pub fn init( + allocator: std.mem.Allocator, + vocab_size: u32, + max_token_len: u32, + normalizer: ?Normalizer, + special_tokens: SpecialTokens, + alloc_tokens: bool, + ) !Tokenizer { + var arena_state = std.heap.ArenaAllocator.init(allocator); + errdefer arena_state.deinit(); + const arena = arena_state.allocator(); + + var token_lookup: std.StringHashMapUnmanaged(u32) = .{}; + errdefer token_lookup.deinit(arena); + + try token_lookup.ensureTotalCapacity(arena, @intCast(vocab_size)); + + const tokens: [][]const u8 = if (alloc_tokens) try arena.alloc([]u8, vocab_size) else &.{}; + errdefer if (alloc_tokens) arena.free(tokens); + + const scores: []f32 = if (alloc_tokens) try arena.alloc(f32, vocab_size) else &.{}; + errdefer if (alloc_tokens) arena.free(scores); + + return .{ + .tokens = tokens, + .scores = scores, + .max_token_len = max_token_len, + .token_lookup = token_lookup, + .arena_state = arena_state, + .normalizer = normalizer, + .vocab_size = vocab_size, + .special_tokens = special_tokens, + }; + } + + pub fn deinit(self: Tokenizer) void { + self.arena_state.deinit(); + } + + /// Reads a new word directly into the tokenizer arena. + pub fn readTokenInto(self: *Tokenizer, score: f32, len: usize, tok_reader: anytype) !void { + const arena = self.arena_state.allocator(); + + const token = try arena.alloc(u8, len); + const n = try tok_reader.read(token); + std.debug.assert(n == len); + + self.addOwnedToken(score, token); + } + + /// Adds a new token (and copy it) + pub fn addToken(self: *Tokenizer, score: f32, token: []const u8) !void { + const arena = self.arena_state.allocator(); + + self.addOwnedToken(score, try arena.dupe(u8, token)); + } + + /// Adds a new token (without copying it) + pub fn addOwnedToken(self: *Tokenizer, score: f32, token: []const u8) void { + const i = self.next_token_id; + std.debug.assert(i < self.vocab_size); + self.next_token_id += 1; + + self.scores[i] = score; + self.tokens[i] = token; + const v = self.token_lookup.getOrPutAssumeCapacity(token); + if (!v.found_existing) { + v.value_ptr.* = i; + } + } + + pub fn addOwnedTokenByIndex(self: *Tokenizer, i: u32, score: f32, token: []const u8) void { + std.debug.assert(i < self.vocab_size); + self.next_token_id += 1; + self.scores[i] = score; + self.tokens[i] = token; + const v = self.token_lookup.getOrPutAssumeCapacity(token); + if (!v.found_existing) { + v.value_ptr.* = @intCast(i); + } + } + + fn lookup(self: *const Tokenizer, str: []const u8) ?u32 { + return self.token_lookup.get(str); + } + + pub const EncodeOptions = struct { + /// Should the beginning of sentence '' token be added. + add_bos: bool = true, + add_eos: bool = false, + pad_to: u32 = 0, + }; + + pub fn encode(self: *const Tokenizer, allocator: std.mem.Allocator, raw: []const u8, options: EncodeOptions) ![]u32 { + // log.debug("Tokenizer.encode('{s}')", .{raw}); + const input = if (self.normalizer) |n| try n.normalize(allocator, raw) else raw; + defer if (self.normalizer) |_| allocator.free(input); + // log.debug("Tokenizer.encode.normalize -> '{s}'", .{input}); + + // Allocate a buffer that can fit all indices as well as extra character if requested. + // We then slice it so that the token merging code doesn't see the bos token. + const tok_buff_alloc = try allocator.alloc(u32, @max(options.pad_to, input.len + 2)); + const tok_buff = if (options.add_bos) tok_buff_alloc[1..] else tok_buff_alloc; + + const MergeState = union(enum) { ready: u32, nope, hard_space, idk }; + const mergeable = try allocator.alloc(MergeState, tok_buff.len); + + var num_tokens: usize = 0; + var off: usize = 0; + while (off < input.len) { + const utf_len = try std.unicode.utf8ByteSequenceLength(input[off]); + defer off += utf_len; + + mergeable[num_tokens] = .idk; + defer num_tokens += 1; + + const char = input[off..][0..utf_len]; + tok_buff[num_tokens] = self.lookup(char) orelse + // TODO: split unknown token into bytes if model supports it + self.special_tokens.unk; + if (tok_buff[num_tokens] == self.special_tokens.unk) { + log.debug("Token not found for char '{s}' (@{x})", .{ char, char }); + } + if (tok_buff[num_tokens] == self.special_tokens.hard_space) { + mergeable[num_tokens] = .hard_space; + } + } + + var stable_prefix: usize = 0; + var stable_off: usize = 0; + while (true) { + // Step by step visualization of the progress. + // log.debug("tokens: {d} -> {s}", .{ tok_buff[0..num_tokens], try self.decodeWithOpts(allocator, tok_buff[0..num_tokens], .{ .sep = "|" }) }); + var best_score: f32 = -1e10; + var best_token: u32 = 0; + var best_idx: ?usize = null; + var input_off: usize = stable_off; + + // Find best tokens to merge in all available tokens + for (stable_prefix..num_tokens - 1) |i| { + if (tok_buff[i] == self.special_tokens.unk) { + input_off += 1; + continue; + } + const cur_tok = self.tokens[tok_buff[i]]; + defer input_off += cur_tok.len; + + // Lookup merge for current token, if not already done. + switch (mergeable[i]) { + .nope => continue, + .ready => {}, + .hard_space => { + // Since tokens are not allowed to merge through hard sep, + // we don't need to merge the sentence-wide best token. + // We can just merge the best token since beginning. + if (best_idx != null) break; + // OTOH if there was no merge possible since beginning, + // we can skip the beginning in future iterations. + stable_prefix = i + 1; + stable_off = input_off + cur_tok.len; + continue; + }, + .idk => { + const next_tok = self.tokens[tok_buff[i + 1]]; + + // Special tokens can't be concatenated. + if (builtin.mode == .Debug and tok_buff[i] != self.special_tokens.unk) { + // Detects memory corruption of tokens. + if (cur_tok.len == 0 or cur_tok.len > self.max_token_len) @panic("Token looks corrupted !"); + + meta.assert(std.mem.eql(u8, cur_tok, input[input_off..][0..cur_tok.len]), "current token '{s}' not found in input string '{s}' !", .{ cur_tok, input[input_off..] }); + } + const concat_tokens = input[input_off..][0 .. cur_tok.len + next_tok.len]; + // Save the result + mergeable[i] = if (self.lookup(concat_tokens)) |tok| + .{ .ready = tok } + else + .nope; + }, + } + + switch (mergeable[i]) { + .idk, .hard_space => unreachable, + .nope => continue, + .ready => |tok| { + if (self.scores[tok] > best_score) { + best_score = self.scores[tok]; + best_token = tok; + best_idx = i; + } + }, + } + } + + if (best_idx) |bidx| { + // Apply the merge. + tok_buff[bidx] = best_token; + std.mem.copyForwards(u32, tok_buff[bidx + 1 ..], tok_buff[bidx + 2 .. num_tokens]); + std.mem.copyForwards(MergeState, mergeable[bidx + 1 ..], mergeable[bidx + 2 .. num_tokens]); + num_tokens -= 1; + // We got two new merge lookups to do. + mergeable[bidx] = .idk; + if (bidx > 0 and mergeable[bidx - 1] != .hard_space) mergeable[bidx - 1] = .idk; + } else { + // No merge candidate => we are done ! + break; + } + } + + if (options.add_eos) { + tok_buff[num_tokens] = self.special_tokens.eos; + num_tokens += 1; + } + if (options.add_bos) { + tok_buff_alloc[0] = self.special_tokens.bos; + num_tokens += 1; + } + if (num_tokens < options.pad_to) { + for (num_tokens..options.pad_to) |i| { + tok_buff_alloc[i] = self.special_tokens.pad; + } + num_tokens = options.pad_to; + } + + // Release extra memory we don't need anymore. + allocator.free(mergeable); + _ = allocator.resize(tok_buff_alloc, num_tokens); + return tok_buff_alloc[0..num_tokens]; + } + + /// Returns a slice corresponding to the given id. Handles unknown ids and special ids. + pub fn lookupPiece(self: *const Tokenizer, id: usize) []const u8 { + return if (id == self.special_tokens.bos or id == self.special_tokens.eos or id == self.special_tokens.pad) + "" + else if (id == self.special_tokens.unk) + "" + else if (id > self.tokens.len) + std.debug.panic("Unexpected token id: {d}, vocab_size: {d}", .{ id, self.vocab_size }) + else + self.tokens[id]; + } + + /// Converts the given slice of tokens back into bytes. + /// Note that if the tokenizer allows sub-unicode bytes, it's possible + /// the output is not valid utf8. + pub fn decode(self: *const Tokenizer, allocator: std.mem.Allocator, input: []const u32) ![]u8 { + var output = std.ArrayList(u8).init(allocator); + errdefer output.deinit(); + + try self.decodeWithOpts(&output, input, .{}); + return output.toOwnedSlice(); + } + + pub fn decodeWithOpts( + self: *const Tokenizer, + output: *std.ArrayList(u8), + input: []const u32, + opts: struct { sep: []const u8 = "" }, + ) !void { + // Flag used to indicate if the first dummy whitespace has been consumed. + for (input) |id| { + // Retrieve the slice corresponding to the id. + var piece = self.lookupPiece(id); + + // Convert `▁` to a regular space. + if (std.mem.startsWith(u8, piece, Normalizer.space_symbol)) { + piece = piece[Normalizer.space_symbol.len..]; + + // don't output a space at beginning of text. + if (output.items.len > 0) try output.append(' '); + } + + try output.appendSlice(piece); + if (opts.sep.len > 0) try output.appendSlice(opts.sep); + } + } +}; + +test Tokenizer { + const allocator = std.testing.allocator; + const special_tokens: Tokenizer.SpecialTokens = .{ + .unk = 0, + .bos = 1, + .eos = 2, + }; + + var tokenizer = try Tokenizer.init(allocator, 10, 5, .{}, special_tokens, true); + defer tokenizer.deinit(); + + try tokenizer.addToken(10, "hello"); + try tokenizer.addToken(3.5, "world"); + + try testing.expect(tokenizer.lookup("hello") == 0); + try testing.expect(tokenizer.lookup("world") == 1); + + // TODO: test Tokenizer.decode, Tokenizer.encode, Tokenizer.readTokenInto +} + +/// Text normalizer. Most tokenizer assumes the input text have been prepocessed +/// with on of those. +pub const Normalizer = struct { + pub const space_symbol = "▁"; // \xe2\x96\x81 + + flags: packed struct { + escape_whitespaces: bool = true, + remove_extra_whitespaces: bool = true, + add_dummy_prefix: bool = true, + add_dummy_suffix: bool = false, + /// Cheap lower casing. + /// TODO: try to match Python "lower" + lower_case_ascii: bool = false, + /// cheap ascii punct splitting. + // doing this processing ahead of time simplifies the logic + split_on_punct_ascii: bool = false, + } = .{}, + + fn addSlice(data: []const u8, consumed: usize, normalized: *std.ArrayList(u8), normalized_to_origin: *std.ArrayList(usize)) !void { + try normalized.appendSlice(data); + for (data) |_| try normalized_to_origin.append(consumed); + } + + pub const Result = struct { + /// Normalized string + normalized: []const u8, + /// Mapping between chars in the original string and chars in the new string + normalized_to_origin: []const usize, + + pub fn deinit(self: Result, allocator: std.mem.Allocator) void { + allocator.free(self.normalized); + allocator.free(self.normalized_to_origin); + } + }; + + /// Simplifed version of Sentencepiece normalizer. + /// + /// Llama2 uses a normalizer called "identity" so this basically only handles trailing + /// whitespaces and replaces whitespace with the "▁" (U+2581) character. + pub fn normalize(self: Normalizer, allocator: std.mem.Allocator, input: []const u8) ![]const u8 { + const res = try self.normalizeWithMapping(allocator, input); + allocator.free(res.normalized_to_origin); + return res.normalized; + } + + /// Returns both the normalized string and a mapping between the normalized string and the original. + pub fn normalizeWithMapping(self: Normalizer, allocator: std.mem.Allocator, input: []const u8) !Result { + // Number of bytes consumed from the input. + var consumed: usize = 0; + var trimmed_input = input; + + // Skip leading whitespaces. + if (self.flags.remove_extra_whitespaces) { + while (trimmed_input.len != 0) { + if (trimmed_input[0] != ' ') break; + trimmed_input = trimmed_input[1..]; + consumed += 1; + } + } + + // If the trimmed input is empty, we are done. + if (trimmed_input.len == 0) { + return .{ .normalized = &.{}, .normalized_to_origin = &.{} }; + } + + // Pre-allocate outputs + const space = if (self.flags.escape_whitespaces) Normalizer.space_symbol else " "; + const overhead = if (self.flags.split_on_punct_ascii) space.len + 1 else space.len; + var normalized = try std.ArrayList(u8).initCapacity(allocator, trimmed_input.len * overhead + 2 * space.len); + errdefer normalized.deinit(); + var normalized_to_origin = try std.ArrayList(usize).initCapacity(allocator, normalized.capacity); + errdefer normalized_to_origin.deinit(); + + // If the spec asks for it, add a whitespace at the beginning. + if (self.flags.add_dummy_prefix) try addSlice(space, consumed, &normalized, &normalized_to_origin); + + var is_prev_space: bool = true; + var is_prev_word: bool = false; + + while (trimmed_input.len != 0) { + // NOTE(Corendos): This might feel weird but normally the slice we get comes from a normalizing process and can contain multiple codepoints. + // Since we have an "identity" normalizer, each slice is actually a unicode character. + const multibyte_length = try std.unicode.utf8ByteSequenceLength(trimmed_input[0]); + var slice = trimmed_input[0..multibyte_length]; + const origin = consumed; + consumed += multibyte_length; + trimmed_input = trimmed_input[multibyte_length..]; + + if (self.flags.remove_extra_whitespaces and is_prev_space) { + while (slice.len > 0 and slice[0] == ' ') { + slice = slice[1..]; + } + if (slice.len == 0) continue; + } + is_prev_space = slice[slice.len - 1] == ' '; + + if (slice.len == 1) ascii: { + // The more advanced logic only works with ascii atm + var byte = slice[0]; + if (self.flags.escape_whitespaces and byte == ' ') { + // replace the space token by the special token + try addSlice(space, origin, &normalized, &normalized_to_origin); + is_prev_word = false; + break :ascii; + } else if (self.flags.split_on_punct_ascii) { + if (is_prev_word and isPunct(slice)) { + // Insert a space, but continue handling the rest + try addSlice(space, origin, &normalized, &normalized_to_origin); + } + } + if (self.flags.lower_case_ascii) { + byte = std.ascii.toLower(byte); + } + try normalized.append(byte); + try normalized_to_origin.append(origin); + } else { + // we can safely copy to the output. + try addSlice(slice, origin, &normalized, &normalized_to_origin); + } + is_prev_word = !is_prev_space and !isPunct(slice); + } + + // Skip trailing whitespaces + if (self.flags.remove_extra_whitespaces) { + while (std.mem.endsWith(u8, normalized.items, space)) { + const length = normalized.items.len - space.len; + consumed = normalized_to_origin.items[length]; + try normalized.resize(length); + try normalized_to_origin.resize(length); + } + } + + try normalized_to_origin.append(consumed); + + std.debug.assert(normalized_to_origin.items.len == normalized.items.len + 1); + + if (self.flags.add_dummy_suffix) try addSlice(space, consumed, &normalized, &normalized_to_origin); + + return .{ + .normalized = try normalized.toOwnedSlice(), + .normalized_to_origin = try normalized_to_origin.toOwnedSlice(), + }; + } + + pub fn wellKnown(impl: KnownImplementation) Normalizer { + return switch (impl) { + .sentencepiece => .{ .flags = .{ + .escape_whitespaces = true, + .remove_extra_whitespaces = true, + .add_dummy_prefix = true, + .add_dummy_suffix = false, + .lower_case_ascii = false, + .split_on_punct_ascii = false, + } }, + .gpt2 => .{ .flags = .{ + .escape_whitespaces = false, + .remove_extra_whitespaces = true, + .add_dummy_prefix = true, + .add_dummy_suffix = false, + .lower_case_ascii = false, + .split_on_punct_ascii = false, + } }, + }; + } +}; + +pub const KnownImplementation = enum(u8) { + sentencepiece, + gpt2, +}; + +fn isPunct(unicode_char: []const u8) bool { + // TODO use unicode categories + if (unicode_char.len > 1) return false; + + return switch (unicode_char[0]) { + ' ', '\t' => false, + 0...8 => true, + 10...31 => true, + '!'...'/' => true, + ':'...'@' => true, + '['...'`' => true, + '{'...'~' => true, + else => false, + }; +} + +test Normalizer { + try testing.expectEqualSlices(u8, "▁", Normalizer.space_symbol); + + { + const n: Normalizer = .{ .flags = .{ + .escape_whitespaces = false, + .remove_extra_whitespaces = true, + .add_dummy_prefix = true, + .add_dummy_suffix = false, + } }; + const res = try n.normalizeWithMapping(testing.allocator, "Hellŏ world!"); + defer res.deinit(testing.allocator); + + try testing.expectEqualSlices(u8, " Hellŏ world!", res.normalized); + try testing.expectEqualSlices( + usize, + // H e l l ŏ ␣ w o r l d ! + &.{ 0, 0, 1, 2, 3, 4, 4, 6, 8, 9, 10, 11, 12, 13, 14 }, + res.normalized_to_origin, + ); + } + + { + const n: Normalizer = .{ .flags = .{ + .escape_whitespaces = false, + .remove_extra_whitespaces = true, + .add_dummy_prefix = true, + .add_dummy_suffix = true, + } }; + const res = try n.normalize(testing.allocator, "Hello world!"); + defer testing.allocator.free(res); + + try testing.expectEqualSlices(u8, " Hello world! ", res); + } + + { + const n: Normalizer = .{ .flags = .{ + .escape_whitespaces = true, + .remove_extra_whitespaces = false, + .add_dummy_prefix = true, + .add_dummy_suffix = false, + } }; + const res = try n.normalize(testing.allocator, "Hello world!"); + defer testing.allocator.free(res); + + try testing.expectEqualSlices(u8, "▁Hello▁▁world!", res); + } + + { + const n: Normalizer = .{ .flags = .{ + .escape_whitespaces = false, + .remove_extra_whitespaces = true, + .add_dummy_prefix = false, + .add_dummy_suffix = true, + .lower_case_ascii = true, + } }; + const res = try n.normalize(testing.allocator, "Hello world!"); + defer testing.allocator.free(res); + + try testing.expectEqualSlices(u8, "hello world! ", res); + } + + { + const n: Normalizer = .{ .flags = .{ + .escape_whitespaces = false, + .remove_extra_whitespaces = true, + .add_dummy_prefix = false, + .add_dummy_suffix = true, + .split_on_punct_ascii = true, + } }; + const res = try n.normalize(testing.allocator, "Hello world!"); + defer testing.allocator.free(res); + + try testing.expectEqualSlices(u8, "Hello world ! ", res); + } +} + +/// gpt2 had their own way of storing text. +/// Unfortunately this has contaminated other models. +/// This implementation precompupte a mapping between bytes encoded with GPT2 algorithm, +/// into utf8 bytes, and do lookups at runtime. +pub const Gpt2TextDecoder = struct { + const Code = std.BoundedArray(u8, 2); + + // TODO: benchmark this is more efficient than doing the conversion at runtime. + code_to_byte: std.AutoArrayHashMap(Code, u8), + + pub fn init(allocator: std.mem.Allocator) !Gpt2TextDecoder { + var self = Gpt2TextDecoder{ + .code_to_byte = std.AutoArrayHashMap(Code, u8).init(allocator), + }; + try self.code_to_byte.ensureTotalCapacity(256); + errdefer unreachable; + + // The eon + var n: usize = 0; + for (0..256) |index| { + var code: Code = .{ .buffer = .{ 0, 0 }, .len = 0 }; // 0-init + const i: u8 = @intCast(index); + if (isPrintableByte(i)) { + if (std.ascii.isASCII(i)) { + code.appendAssumeCapacity(i); + } else { + const codepoint: u21 = @as(u21, @intCast(i)); + code.len = @intCast(std.unicode.utf8Encode(codepoint, &code.buffer) catch unreachable); + } + } else { + const codepoint: u21 = 256 + @as(u21, @intCast(n)); + code.len = @intCast(std.unicode.utf8Encode(codepoint, &code.buffer) catch unreachable); + n += 1; + } + + self.code_to_byte.putAssumeCapacityNoClobber(code, i); + } + return self; + } + + pub fn deinit(self: *Gpt2TextDecoder) void { + self.code_to_byte.deinit(); + } + + /// Transform bytes representing text under the gpt2 encoding, + /// and write to the `unicode` buffer utf-8 bytes. + pub fn decode(self: Gpt2TextDecoder, unicode: *std.ArrayList(u8), bytes: []const u8) ![]const u8 { + const start = unicode.items.len; + var it = std.unicode.Utf8Iterator{ .i = 0, .bytes = bytes }; + while (it.nextCodepointSlice()) |codepoint| { + const code: Code = switch (codepoint.len) { + 1 => .{ .buffer = .{ codepoint[0], 0 }, .len = 1 }, // 0-init + 2 => .{ .buffer = .{ codepoint[0], codepoint[1] }, .len = 2 }, + else => return error.InvalidInput, + }; + const byte = self.code_to_byte.get(code) orelse return error.InvalidInput; + try unicode.append(byte); + } + return unicode.items[start..]; + } + + inline fn isPrintableByte(c: u8) bool { + return ('!' <= c and c <= '~') or (0xa1 <= c and c <= 0xac) or (0xae <= c and c <= 0xff); + } +}; + +test Gpt2TextDecoder { + var decoder = try Gpt2TextDecoder.init(testing.allocator); + defer decoder.deinit(); + + var out = std.ArrayList(u8).init(testing.allocator); + defer out.deinit(); + + // Ascii is not changed. + try testing.expectEqualStrings("getTitle", try decoder.decode(&out, "getTitle")); + // Leading space are represented with 'Ġ' + try testing.expectEqualStrings(" UINavigationController", try decoder.decode(&out, "ĠUINavigationController")); + // Russian is wild + try testing.expectEqualStrings(" работ", try decoder.decode(&out, "ĠÑĢабоÑĤ")); +} + +/// Open a json file in HF format and load the vocab from it. +pub fn fromHfJson(allocator: std.mem.Allocator, tokenizer_path: []const u8) !Tokenizer { + const file = try std.fs.cwd().openFile(tokenizer_path, .{}); + defer file.close(); + + const file_content = try file.readToEndAlloc(allocator, 32 * 1024 * 1024); + defer allocator.free(file_content); + // TODO create local arena and use parseFromSliceLeaky. + const parsed = try std.json.parseFromSlice(std.json.Value, allocator, file_content, .{ + .duplicate_field_behavior = .use_last, + }); + defer parsed.deinit(); + const info = parsed.value; + + const main_object = switch (info) { + .object => |obj| if (obj.get("added_tokens") == null or obj.get("model") == null) { + return error.InvalidFormat; + } else obj, + else => return error.InvalidFormat, + }; + + // TODO: remove all panics + const added_tokens = main_object.get("added_tokens").?.array; + const vocab = main_object.get("model").?.object.get("vocab").?.object; + const vocab_size: u32 = @intCast(vocab.count() + added_tokens.items.len); + + // TODO not all tokenizer.json are Gpt2 encoded, detect when it's needed or not. + const normalizer = Normalizer.wellKnown(.gpt2); + var decoder = try Gpt2TextDecoder.init(allocator); + defer decoder.deinit(); + + var tokenizer = try Tokenizer.init(allocator, vocab_size, 256, normalizer, undefined, true); + + // Buffer containing all concatenated tokens. + // Reserve a big chunk, to avoid grow event, but release over-allocated memory. + var all_tokens = try std.ArrayList(u8).initCapacity(tokenizer.arena_state.allocator(), 24 * vocab.count()); + defer all_tokens.shrinkAndFree(all_tokens.items.len); + + var it = vocab.iterator(); + while (it.next()) |kv| { + const token = try decoder.decode(&all_tokens, kv.key_ptr.*); + const idx: u32 = @intCast(kv.value_ptr.*.integer); + // std.debug.assert(idx == tokenizer.next_token_id); + tokenizer.addOwnedTokenByIndex(idx, @floatFromInt(vocab_size - idx), token); + } + + for (added_tokens.items) |token_obj| { + const token = try decoder.decode(&all_tokens, token_obj.object.get("content").?.string); + tokenizer.addOwnedTokenByIndex( + @intCast(token_obj.object.get("id").?.integer), + 0, + token, + ); + } + + tokenizer.special_tokens = .{ + .bos = tokenizer.lookup("") orelse tokenizer.lookup("<|begin_of_text|>") orelse @panic("bos token not found !"), + .eos = tokenizer.lookup("") orelse tokenizer.lookup("<|end_of_text|>") orelse @panic("eos token not found !"), + .unk = tokenizer.lookup("") orelse std.math.maxInt(u32), + }; + + return tokenizer; +} diff --git a/zml/tools/BUILD.bazel b/zml/tools/BUILD.bazel new file mode 100644 index 0000000..ab2396e --- /dev/null +++ b/zml/tools/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_zig//zig:defs.bzl", "zig_library") + +cc_library( + name = "macos_c", + srcs = ["macos.c"], + hdrs = ["macos.h"], + visibility = ["//zml/tools:__subpackages__"], +) + +zig_library( + name = "tools", + srcs = ["tracer.zig"], + main = "tools.zig", + visibility = ["//visibility:public"], + deps = select({ + "@platforms//os:macos": [ + ":macos_c", + ], + "//conditions:default": [], + }), +) diff --git a/zml/tools/macos.c b/zml/tools/macos.c new file mode 100644 index 0000000..e59dc63 --- /dev/null +++ b/zml/tools/macos.c @@ -0,0 +1,26 @@ +#include +#include + +void zml_os_signpost_event( + os_log_t log, + os_signpost_id_t signpost_id, + const char *message) +{ + os_signpost_event_emit(log, signpost_id, "zml", "%s", message); +} + +void zml_os_signpost_interval_begin( + os_log_t log, + os_signpost_id_t signpost_id, + const char *message) +{ + os_signpost_interval_begin(log, signpost_id, "zml", "%s", message); +} + +void zml_os_signpost_interval_end( + os_log_t log, + os_signpost_id_t signpost_id, + const char *message) +{ + os_signpost_interval_end(log, signpost_id, "zml", "%s", message); +} diff --git a/zml/tools/macos.h b/zml/tools/macos.h new file mode 100644 index 0000000..0d2f9b4 --- /dev/null +++ b/zml/tools/macos.h @@ -0,0 +1,17 @@ +#include +#include + +void zml_os_signpost_event( + os_log_t log, + os_signpost_id_t signpost_id, + const char *message); + +void zml_os_signpost_interval_begin( + os_log_t log, + os_signpost_id_t signpost_id, + const char *message); + +void zml_os_signpost_interval_end( + os_log_t log, + os_signpost_id_t signpost_id, + const char *message); diff --git a/zml/tools/tools.zig b/zml/tools/tools.zig new file mode 100644 index 0000000..2bc0317 --- /dev/null +++ b/zml/tools/tools.zig @@ -0,0 +1 @@ +pub const Tracer = @import("tracer.zig").Tracer; diff --git a/zml/tools/tracer.zig b/zml/tools/tracer.zig new file mode 100644 index 0000000..ed7d7fe --- /dev/null +++ b/zml/tools/tracer.zig @@ -0,0 +1,61 @@ +const builtin = @import("builtin"); + +pub const Tracer = switch (builtin.os.tag) { + .macos => MacOsTracer, + else => FakeTracer, +}; + +const MacOsTracer = struct { + const c = @import("c"); + + logger: c.os_log_t, + + pub fn init(name: [:0]const u8) MacOsTracer { + const logger = c.os_log_create(name.ptr, c.OS_LOG_CATEGORY_POINTS_OF_INTEREST); + return .{ + .logger = logger, + }; + } + + pub fn event(self: *const MacOsTracer, message: [:0]const u8) void { + const interval_id = c.os_signpost_id_generate(self.logger); + c.zml_os_signpost_event(self.logger, interval_id, message); + } + + pub fn frameStart(self: *const MacOsTracer, message: [:0]const u8) c.os_signpost_id_t { + const interval_id = c.os_signpost_id_generate(self.logger); + c.zml_os_signpost_interval_begin(self.logger, interval_id, message); + return interval_id; + } + + pub fn frameEnd(self: *const MacOsTracer, interval_id: c.os_signpost_id_t, message: [:0]const u8) void { + c.zml_os_signpost_interval_end(self.logger, interval_id, message); + } +}; + +/// Mock tracer for OS which don't have an impl. +const FakeTracer = struct { + pub fn init(name: [:0]const u8) FakeTracer { + _ = name; + return .{}; + } + + pub fn event(self: *const MacOsTracer, message: [:0]const u8) void { + _ = self; + _ = message; + return; + } + + pub fn frameStart(self: *const FakeTracer, message: [:0]const u8) u64 { + _ = self; + _ = message; + return 0; + } + + pub fn frameEnd(self: *const FakeTracer, interval_id: u64, message: [:0]const u8) void { + _ = self; + _ = interval_id; + _ = message; + return; + } +}; diff --git a/zml/torch.zig b/zml/torch.zig new file mode 100644 index 0000000..6fd1742 --- /dev/null +++ b/zml/torch.zig @@ -0,0 +1,278 @@ +const std = @import("std"); +const log = std.log.scoped(.zml_torch); + +const zml = @import("zml.zig"); +const Tensor = zml.Tensor; +const meta = zml.meta; + +/// Multiplies a matrix or a vector with a tensor, +/// following the semantic of pytorch `@` operator. +/// When both sides are matrices, it's the textbook matrix multiplication : +/// `matmul(.{ 8, 9 }, .{ 9, 10 }) -> .{ 8, 10 }` +/// When one of the input is a tensor, it assumes the first dimensions are batches, +/// and the last two ones are used for the regular matmul. +/// * `matmul(.{10}, .{10}) -> .{}` +/// * `matmul(.{10}, .{10}) -> .{}` +pub fn matmul(lhs: Tensor, rhs: Tensor) Tensor { + meta.assert(lhs.rank() >= 1 and rhs.rank() >= 1, "Can't matmul({}, {}) ! The two tensors need to have at least rank 1.", .{ lhs, rhs }); + + const contracting = [_][2]i8{.{ -1, if (rhs.rank() >= 2) rhs.rank() - 2 else 0 }}; + if (lhs.rank() == 1 or rhs.rank() <= 2) { + // When lhs is a vector or rhs is small the torch semantics match the dot_general semantics and life is easy. + return lhs.dotGeneral(rhs, &contracting, &.{}); + } + + meta.assert(lhs.rank() == 2, "Can't matmul({}, {}) ! One of the two tensors need to have a rank less than 2.", .{ lhs, rhs }); + + // Pytorch treats the extra dimensions of rhs has batching dimensions, + // and implicitly broadcast lhs along those. + // We make this broadcasting explicit. + var left_shape = rhs.shape(); + left_shape._dims.set(left_shape.axis(-2), lhs.dim(-2)); + left_shape._tags.set(left_shape.axis(-2), lhs.shape().tag(-2)); + left_shape._dims.set(left_shape.axis(-1), lhs.dim(-1)); + left_shape._tags.set(left_shape.axis(-1), lhs.shape().tag(-1)); + const lhs_broad = lhs.broadcastLeft(left_shape); + + const n_batching_axes = rhs.rank() - lhs.rank(); + var batching: [Tensor.MAX_RANK][2]i8 = undefined; + for (0..n_batching_axes) |i| { + batching[i] = .{ @intCast(i), @intCast(i) }; + } + return lhs_broad.dotGeneral(rhs, &contracting, batching[0..n_batching_axes]); +} + +test matmul { + const platform = zml.testing.env(); + + var comp = try zml.module.CompilationContext.init(std.heap.page_allocator, "test", platform); + defer comp.deinit(); + + comp.activate(); + defer comp.deactivate(); + + // Generated with pytorch + inline for (.{ + .{ .{20}, .{20}, .{} }, + .{ .{20}, .{ 20, 15 }, .{15} }, + .{ .{20}, .{ 11, 20, 15 }, .{ 11, 15 } }, + .{ .{20}, .{ 9, 11, 20, 15 }, .{ 9, 11, 15 } }, + .{ .{20}, .{ 7, 9, 11, 20, 15 }, .{ 7, 9, 11, 15 } }, + .{ .{20}, .{ 5, 7, 9, 11, 20, 15 }, .{ 5, 7, 9, 11, 15 } }, + .{ .{ 12, 20 }, .{20}, .{12} }, + .{ .{ 12, 20 }, .{ 20, 15 }, .{ 12, 15 } }, + .{ .{ 12, 20 }, .{ 11, 20, 15 }, .{ 11, 12, 15 } }, + .{ .{ 12, 20 }, .{ 9, 11, 20, 15 }, .{ 9, 11, 12, 15 } }, + .{ .{ 12, 20 }, .{ 7, 9, 11, 20, 15 }, .{ 7, 9, 11, 12, 15 } }, + .{ .{ 12, 20 }, .{ 5, 7, 9, 11, 20, 15 }, .{ 5, 7, 9, 11, 12, 15 } }, + .{ .{ 10, 12, 20 }, .{20}, .{ 10, 12 } }, + .{ .{ 10, 12, 20 }, .{ 20, 15 }, .{ 10, 12, 15 } }, + .{ .{ 8, 10, 12, 20 }, .{20}, .{ 8, 10, 12 } }, + .{ .{ 8, 10, 12, 20 }, .{ 20, 15 }, .{ 8, 10, 12, 15 } }, + .{ .{ 6, 8, 10, 12, 20 }, .{20}, .{ 6, 8, 10, 12 } }, + .{ .{ 6, 8, 10, 12, 20 }, .{ 20, 15 }, .{ 6, 8, 10, 12, 15 } }, + .{ .{ 4, 6, 8, 10, 12, 20 }, .{20}, .{ 4, 6, 8, 10, 12 } }, + .{ .{ 4, 6, 8, 10, 12, 20 }, .{ 20, 15 }, .{ 4, 6, 8, 10, 12, 15 } }, + }) |testcase| { + const x_shape, const y_shape, const z_shape = testcase; + const x = Tensor.constant(x_shape, .{ .f32 = 0.0 }); + const y = Tensor.constant(y_shape, .{ .f32 = 0.0 }); + const z = matmul(x, y); + + try std.testing.expectEqualSlices(i64, &z_shape, z.dims()); + } +} + +/// Inserts a 1-dim axis at the given position. +/// Negative indexes are handled like pytorch, ie they are relative to the returned shaped: +/// - `.{5, 4}.unsqueeze(1)` returns `.{5, 1, 4}` +/// - `.{5, 4}.unsqueeze(-1)` returns `.{5, 4, 1}` +pub fn unsqueeze( + self: Tensor, + axis_: anytype, +) Tensor { + meta.assert(self.rank() < Tensor.MAX_RANK - 1, "Can't unsqueeze {}, it's already at max rank.", .{self}); + const a = switch (@typeInfo(@TypeOf(axis_))) { + .Int, .ComptimeInt => if (axis_ < 0) + @as(i8, self.rank()) + 1 + axis_ + else + self.axis(axis_), + else => self.axis(axis_), + }; + return self.insertAxes(a, .{._}); +} + +test unsqueeze { + const UnsqueezeTest = struct { + pub fn forward(x: Tensor) Tensor { + var y = x; + y = unsqueeze(y, 0); + y = unsqueeze(y, -1); + y = unsqueeze(y, -1); + return y; + } + }; + const platform = zml.testing.env(); + + const x = try zml.Buffer.fromArray(platform, @as([8]f16, undefined)); + const res = try zml.testing.compileAndCall(platform, UnsqueezeTest.forward, .{x}); + try zml.testing.expectEqualShapes(zml.Shape.init(.{ 1, 8, 1, 1 }, .f16), res.shape()); +} + +/// Given an input images with .{ .c, .w, .h } tags, +/// shuffle values between the channel (.c), width (.w) and height (.h) axes. +/// pixelShuffle(.{ .c, .w, .h }, u) -> .{ .c / u / u, .w * u, .h * u} +/// ref: https://pytorch.org/docs/stable/generated/torch.nn.PixelShuffle.html#pixelshuffle +pub fn pixelShuffle(tensor: Tensor, upscale_factor: u32) Tensor { + const shape = tensor.shape(); + meta.assert(shape.hasTags(.{ .c, .w, .h }), "pixelShuffle({}) is invalide. Missing tags {{.c, .w, .h}}", .{tensor}); + + meta.assert(@mod(shape.dim(.c), upscale_factor * upscale_factor) == 0, "pixelShuffle({}) is invalide. Number of channels {}, isn't divisible by upscale factor {}**2", .{ tensor, shape.dim(.c), upscale_factor }); + + const s = tensor.splitAxis(.c, .{ .c = -1, .upscale_h = upscale_factor, .upscale_w = upscale_factor }); + const perm = s.shape().contiguousPerm(.{ .h, .upscale_h, .w, .upscale_w }); + const cont = s.transpose(perm.constSlice()); + return cont.merge(.{ .h = .{ .h, .upscale_h }, .w = .{ .w, .upscale_w } }).transpose(tensor.shape()); +} + +test pixelShuffle { + const platform = zml.testing.env(); + + const upscale_factor = 3; + var digits: [9 * 4 * 4]i32 = undefined; + for (&digits, 0..) |*d, i| d.* = @intCast(i); + // TODO should we have tags in buffers ? + const input = try zml.Buffer.fromSlice(platform, .{ 1, 9, 4, 4 }, &digits); + const output = try zml.testing.compileAndCallWithTensors( + platform, + pixelShuffle, + .{ zml.Shape.init(.{ .batch_size = 1, .c = 9, .h = 4, .w = 4 }, .i32), upscale_factor }, + .{ input, upscale_factor }, + ); + + const exp = zml.HostBuffer.fromArray(&[1][1][12][12]i32{.{.{ + .{ 0, 16, 32, 1, 17, 33, 2, 18, 34, 3, 19, 35 }, + .{ 48, 64, 80, 49, 65, 81, 50, 66, 82, 51, 67, 83 }, + .{ 96, 112, 128, 97, 113, 129, 98, 114, 130, 99, 115, 131 }, + .{ 4, 20, 36, 5, 21, 37, 6, 22, 38, 7, 23, 39 }, + .{ 52, 68, 84, 53, 69, 85, 54, 70, 86, 55, 71, 87 }, + .{ 100, 116, 132, 101, 117, 133, 102, 118, 134, 103, 119, 135 }, + .{ 8, 24, 40, 9, 25, 41, 10, 26, 42, 11, 27, 43 }, + .{ 56, 72, 88, 57, 73, 89, 58, 74, 90, 59, 75, 91 }, + .{ 104, 120, 136, 105, 121, 137, 106, 122, 138, 107, 123, 139 }, + .{ 12, 28, 44, 13, 29, 45, 14, 30, 46, 15, 31, 47 }, + .{ 60, 76, 92, 61, 77, 93, 62, 78, 94, 63, 79, 95 }, + .{ 108, 124, 140, 109, 125, 141, 110, 126, 142, 111, 127, 143 }, + }}}); + try zml.testing.expectClose(exp, output, 0); +} + +/// Implementation of `torch.roll`. +/// +/// Note: at the difference of Pytorch, shifts need to be explicitly repeated, even if they are the same for all axes. +/// ref: https://pytorch.org/docs/stable/generated/torch.roll.html +pub fn roll(self: Tensor, shifts: []const i64, axes_: []const u8) Tensor { + // TODO(hugo) accept following syntax: x.roll(.{ .a = 5, .b = 8 }) + meta.assert(self.rank() > 0 and shifts.len == axes_.len, "Shifts length ({d}) and dims length ({d}) are not equal, we expect the same length.", .{ shifts.len, axes_.len }); + + if (shifts.len != 1 or axes_.len != 1) { + const tail_shifts = shifts[1..shifts.len]; + const tail_dims = axes_[1..axes_.len]; + const first_dim_rolled = roll(self, &.{shifts[0]}, &.{axes_[0]}); + return roll(first_dim_rolled, tail_shifts, tail_dims); + } + + const a = axes_[0]; + const start = @mod(self.dim(a) - shifts[0], self.dim(a)); + const idx = Tensor.arange(.{ .start = start, .end = start + self.dim(a) }, .f32); + const divisor: f32 = @floatFromInt(self.dim(a)); + return self.gather1d(a, idx.fmod(divisor).convert(.i32), .{}); +} + +test roll { + const platform = zml.testing.env(); + + const input = try zml.Buffer.fromSlice(platform, .{ 4, 2 }, &[_]f32{ 2, 2, 3, 4, 5, 6, 7, 8 }); + const res = try zml.testing.compileAndCall( + platform, + roll, + .{ input, &[_]i64{ 2, 1 }, &[_]u8{ 0, 1 } }, + ); + + const expectation = zml.HostBuffer.fromSlice(.{ 4, 2 }, &[_]f32{ 6, 5, 8, 7, 2, 1, 4, 3 }); + try zml.testing.expectClose(expectation, res, 1e0); +} + +pub const MeshgridIndexing = enum { xy, ij }; + +/// Mimic Pytorch and Numpy api. +/// The .ij mode is just calling to `zml.nn.cartesianProduct` +/// and has simple semantics. +/// The .xy mode swap the role of the first two vectors, it's generally best +/// to rewrite the calling code to use .ij mode if possible. +/// See Numpy docs: +/// https://numpy.org/doc/stable/reference/generated/numpy.meshgrid.html#numpy.meshgrid +/// - In the 2-D case with vectors of length M and N: +/// * for ‘ij’ indexing, outputs are of shape (M, N) +/// * for ‘xy’ indexing, outputs are of shape (N, M) +/// - In the 3-D case with vectors of length M, N and P: +/// * for ‘ij’ indexing, outputs are of shape (M, N, P) +/// * for ‘xy’ indexing, outputs are of shape (N, M, P) +pub fn meshgrid(comptime N: u3, vectors: [N]Tensor, indexing: MeshgridIndexing) [N]Tensor { + meta.assertComptime(vectors.len >= 1, "Invalid meshgrid. No input.", .{}); + meta.assertComptime(vectors.len <= Tensor.MAX_RANK, "Invalid meshgrid(...). Too many inputs: {}", .{vectors.len}); + + if (vectors.len == 1) return vectors; + + return switch (indexing) { + .ij => zml.Tensor.cartesianProduct(N, vectors), + .xy => { + const x, const y = vectors[0..2].*; + var new_vectors = vectors; + new_vectors[0..2].* = .{ y, x }; + var res = zml.Tensor.cartesianProduct(N, new_vectors); + const y_res, const x_res = res[0..2].*; + res[0..2].* = .{ x_res, y_res }; + return res; + }, + }; +} + +test meshgrid { + const platform = zml.testing.env(); + + const x = try zml.Buffer.fromSlice(platform, .{6}, &[_]i32{ 0, 1, 2, 3, 4, 5 }); + const y = try zml.Buffer.fromSlice(platform, .{4}, &[_]i32{ 0, 1, 2, 3 }); + + const Local = struct { + pub fn meshgrid2(a: Tensor, b: Tensor, indexing: MeshgridIndexing) [2]Tensor { + return meshgrid(2, .{ a, b }, indexing); + } + }; + + // Only test .xy mode, sinc .ij is just calling cartesianProduct which + // got its own tests. + { + const xs, const ys = try zml.testing.compileAndCall(platform, Local.meshgrid2, .{ x, y, .xy }); + try std.testing.expectEqualSlices(i64, &.{ 4, 6 }, xs.dims()); + try std.testing.expectEqualSlices(i64, &.{ 4, 6 }, ys.dims()); + try std.testing.expectEqualDeep( + [4][6]i32{ + .{ 0, 1, 2, 3, 4, 5 }, + .{ 0, 1, 2, 3, 4, 5 }, + .{ 0, 1, 2, 3, 4, 5 }, + .{ 0, 1, 2, 3, 4, 5 }, + }, + try xs.getValue([4][6]i32), + ); + try std.testing.expectEqualDeep( + [4][6]i32{ + .{ 0, 0, 0, 0, 0, 0 }, + .{ 1, 1, 1, 1, 1, 1 }, + .{ 2, 2, 2, 2, 2, 2 }, + .{ 3, 3, 3, 3, 3, 3 }, + }, + try ys.getValue([4][6]i32), + ); + } +} diff --git a/zml/zml.zig b/zml/zml.zig new file mode 100644 index 0000000..dcf5ff9 --- /dev/null +++ b/zml/zml.zig @@ -0,0 +1,53 @@ +//! Welcome to the ZML API documentation! +//! ZML provides tools to write high level code describing a neural network, +//! compiling it for various accelerators and targets, and executing it. +//! + +pub const Buffer = @import("buffer.zig").Buffer; +pub const Bufferized = @import("buffer.zig").Bufferized; +pub const CompilationOptions = @import("platform.zig").CompilationOptions; +pub const Context = @import("context.zig").Context; +pub const Data = @import("dtype.zig").Data; +pub const DataType = @import("dtype.zig").DataType; +pub const HostBuffer = @import("hostbuffer.zig").HostBuffer; +pub const Platform = @import("platform.zig").Platform; +pub const Shape = @import("shape.zig").Shape; +pub const ShapeOf = @import("tensor.zig").ShapeOf; +pub const Target = @import("platform.zig").Target; +pub const Tensor = @import("tensor.zig").Tensor; + +// Namespaces +pub const context = @import("context.zig"); +pub const floats = @import("floats.zig"); +pub const helpers = @import("helpers.zig"); +pub const nn = @import("nn.zig"); +pub const module = @import("module.zig"); +pub const meta = @import("meta.zig"); +pub const platform = @import("platform.zig"); +pub const testing = @import("testing.zig"); +pub const torch = @import("torch.zig"); + +pub const tokenizer = @import("tokenizer.zig"); + +pub const call = ops.call; +pub const compile = module.compile; +pub const compileModel = module.compileModel; +pub const compileFn = module.compileFn; + +pub const ops = @import("ops.zig"); +pub const tools = struct { + pub const Tracer = @import("tools/tracer.zig").Tracer; +}; + +pub const aio = @import("aio.zig"); +pub const sentencepiece = @import("aio/sentencepiece.zig"); + +pub const log = std.log.scoped(.zml); + +const std = @import("std"); + +test { + // NOTE : testing entrypoint. + // Don't forget to import your module if you want to declare tests declarations that will be run by //zml:test + std.testing.refAllDecls(@This()); +}