[Codegen][GPU] Add TargetDetails for Nvidia Ada Arch (#24616)
Ada architecture seems to be slightly different to the previous
generation. With a different number of streaming multiprocessors. This
PR adds support for RTX 4000s series GPUs.
diff --git a/compiler/plugins/target/CUDA/test/target_device_features.mlir b/compiler/plugins/target/CUDA/test/target_device_features.mlir
index e9683f5..91d4f40 100644
--- a/compiler/plugins/target/CUDA/test/target_device_features.mlir
+++ b/compiler/plugins/target/CUDA/test/target_device_features.mlir
@@ -3,7 +3,7 @@
// RUN: iree-opt --pass-pipeline='builtin.module(iree-hal-assign-target-devices{targetDevices=cuda},iree-hal-transformation-pipeline{serialize-executables=false})' \
// RUN: --iree-cuda-target=ada %s | FileCheck %s --check-prefix=SM89
// RUN: iree-opt --pass-pipeline='builtin.module(iree-hal-assign-target-devices{targetDevices=cuda},iree-hal-transformation-pipeline{serialize-executables=false})' \
-// RUN: --iree-cuda-target=rtx4090 %s | FileCheck %s --check-prefix=SM89
+// RUN: --iree-cuda-target=rtx4090 %s | FileCheck %s --check-prefixes=SM89,RTX4090
// RUN: iree-opt --pass-pipeline='builtin.module(iree-hal-assign-target-devices{targetDevices=cuda},iree-hal-transformation-pipeline{serialize-executables=false})' \
// RUN: --iree-cuda-target=sm_89 --iree-cuda-target-features=+ptx80 %s | FileCheck %s --check-prefix=PTX80
// RUN: iree-opt --pass-pipeline='builtin.module(iree-hal-assign-target-devices{targetDevices=cuda},iree-hal-transformation-pipeline{serialize-executables=false})' \
@@ -16,8 +16,9 @@
// SM89-SAME: subgroup = shuffle|arithmetic, dot = dp4xi8toi32,
// SM89-SAME: mma = [<NV_MMA_SYNC_F32_16x8x16_F16>, <NV_MMA_SYNC_F16_16x8x16_F16>, <NV_MMA_SYNC_F32_16x8x16_BF16>, <NV_WMMA_F32_16x16x16_F16>, <NV_WMMA_F16_16x16x16_F16>],
// SM89-SAME: subgroup_size_choices = [32], max_workgroup_sizes = [1024, 1024, 1024],
-// SM89-SAME: max_thread_count_per_workgroup = 1024, max_workgroup_memory_bytes = 166912,
-// SM89-SAME: max_workgroup_counts = [2147483647, 65535, 65535]>>
+// SM89-SAME: max_thread_count_per_workgroup = 1024, max_workgroup_memory_bytes = 101376,
+// SM89-SAME: max_workgroup_counts = [2147483647, 65535, 65535]>
+// RTX4090: chip = <wgp_count = 128>
// PTX80: target_info = #iree_gpu.target<arch = "sm_89", features = "+ptx80",
// SM120: target_info = #iree_gpu.target<arch = "sm_120", features = "+ptx87",
diff --git a/compiler/src/iree/compiler/Codegen/Dialect/GPU/TargetUtils/KnownTargets.cpp b/compiler/src/iree/compiler/Codegen/Dialect/GPU/TargetUtils/KnownTargets.cpp
index 680d248..64ccd85 100644
--- a/compiler/src/iree/compiler/Codegen/Dialect/GPU/TargetUtils/KnownTargets.cpp
+++ b/compiler/src/iree/compiler/Codegen/Dialect/GPU/TargetUtils/KnownTargets.cpp
@@ -1019,6 +1019,35 @@
return &sm121Wgp;
}
+const WgpDetails *getAdaWgpDetails() {
+ // Ada (sm_89) exposes the same tensor-core instructions as Ampere-class
+ // hardware.
+ static const MMAIntrinsic mmaOps[] = {
+ MMAIntrinsic::NV_MMA_SYNC_F32_16x8x16_F16,
+ MMAIntrinsic::NV_MMA_SYNC_F16_16x8x16_F16,
+ MMAIntrinsic::NV_MMA_SYNC_F32_16x8x16_BF16,
+ MMAIntrinsic::NV_WMMA_F32_16x16x16_F16,
+ MMAIntrinsic::NV_WMMA_F16_16x16x16_F16,
+ };
+ static const WgpDetails adaWgp = {allComputeBits,
+ allStorageBits,
+ allSubgroupOps,
+ allDotProductOps,
+ std::size(mmaOps),
+ mmaOps,
+ 0,
+ nullptr,
+ {32, 32},
+ {1024, 1024, 1024},
+ 1024,
+ // sm_89 caps shared memory at 99 KB per
+ // block (100 KB per SM); the 128 KB figure
+ // is the unified L1+shared size.
+ 99 * 1024,
+ {0x7fffffff, 0xffff, 0xffff}};
+ return &adaWgp;
+}
+
// Reports Ampere-class NVIDIA tensor core capabilities for GPU target
// selection.
const WgpDetails *getAmpereWgpDetails() {
@@ -1136,12 +1165,17 @@
std::optional<TargetDetails> getNVIDIAGPUTargetDetails(StringRef target) {
const WgpDetails *sm120Wgp = getSM120WgpDetails();
const WgpDetails *sm121Wgp = getSM121WgpDetails();
+ const WgpDetails *adaWgp = getAdaWgpDetails();
const WgpDetails *ampereWgp = getAmpereWgpDetails();
const WgpDetails *turingWgp = getTuringWgpDetails();
const WgpDetails *voltaWgp = getVoltaWgpDetails();
const WgpDetails *pascalWgp = getPascalWgpDetails();
static const ChipDetails a100Chip = {108};
+ static const ChipDetails rtx4090Chip = {128};
+ static const ChipDetails rtx4080Chip = {76};
+ static const ChipDetails rtx4070Chip = {46};
+ static const ChipDetails rtx4060Chip = {24};
static const ChipDetails rtx3090tiChip = {84};
static const ChipDetails rtx3090Chip = {82};
static const ChipDetails rtx3080tiChip = {80};
@@ -1153,15 +1187,18 @@
// lists mappings from microarchitectures to compute capabilities.
std::string lowerTarget = target.lower();
- // Treat RTX 40 family aliases as Ada-class devices when no exact chip is
- // named.
- if (StringRef(lowerTarget).starts_with("rtx40")) {
- return TargetDetails{ampereWgp, nullptr};
- }
return llvm::StringSwitch<std::optional<TargetDetails>>(lowerTarget)
// https://www.techpowerup.com/gpu-specs/a100-sxm4-80-gb.c3746
.Case("a100", TargetDetails{ampereWgp, &a100Chip})
+ // https://www.techpowerup.com/gpu-specs/geforce-rtx-4090.c3889
+ .Case("rtx4090", TargetDetails{adaWgp, &rtx4090Chip})
+ // https://www.techpowerup.com/gpu-specs/geforce-rtx-4080.c3888
+ .Case("rtx4080", TargetDetails{adaWgp, &rtx4080Chip})
+ // https://www.techpowerup.com/gpu-specs/geforce-rtx-4070.c3924
+ .Case("rtx4070", TargetDetails{adaWgp, &rtx4070Chip})
+ // https://www.techpowerup.com/gpu-specs/geforce-rtx-4060.c4107
+ .Case("rtx4060", TargetDetails{adaWgp, &rtx4060Chip})
// https://www.techpowerup.com/gpu-specs/geforce-rtx-3090-ti.c3829
.Case("rtx3090ti", TargetDetails{ampereWgp, &rtx3090tiChip})
// https://www.techpowerup.com/gpu-specs/geforce-rtx-3090.c3622
@@ -1179,7 +1216,7 @@
// validation.
.Case("sm_120", TargetDetails{sm120Wgp, nullptr})
.Case("sm_121", TargetDetails{sm121Wgp, nullptr})
- .Cases({"ada", "sm_89"}, TargetDetails{ampereWgp, nullptr})
+ .Cases({"ada", "sm_89"}, TargetDetails{adaWgp, nullptr})
.Cases({"ampere", "sm_80", "sm_86", "sm_87"},
TargetDetails{ampereWgp, nullptr})
.Cases({"turing", "sm_75"}, TargetDetails{turingWgp, nullptr})