Skip to content

Commit 2a5050a

Browse files
authored
[mlir][target][nvvm] Perf by stage and store into properties (#126178)
Implement the feature about perf by stage(llvm-ir -> isa, isa->binary). The results will be stored into the properties, then users can use them after using GpuModuleToBinary Pass.
1 parent 8cf4c55 commit 2a5050a

File tree

3 files changed

+67
-7
lines changed

3 files changed

+67
-7
lines changed

mlir/lib/Target/LLVM/NVVM/Target.cpp

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@
3535
#include "llvm/Support/Process.h"
3636
#include "llvm/Support/Program.h"
3737
#include "llvm/Support/TargetSelect.h"
38+
#include "llvm/Support/Timer.h"
3839
#include "llvm/Support/raw_ostream.h"
3940

4041
#include <cstdint>
4142
#include <cstdlib>
43+
#include <optional>
4244

4345
using namespace mlir;
4446
using namespace mlir::NVVM;
@@ -220,6 +222,16 @@ class NVPTXSerializer : public SerializeGPUModuleBase {
220222
std::optional<SmallVector<char, 0>>
221223
moduleToObject(llvm::Module &llvmModule) override;
222224

225+
/// Get LLVMIR->ISA performance result.
226+
/// Return nullopt if moduleToObject has not been called or the target format
227+
/// is LLVMIR.
228+
std::optional<int64_t> getLLVMIRToISATimeInMs();
229+
230+
/// Get ISA->Binary performance result.
231+
/// Return nullopt if moduleToObject has not been called or the target format
232+
/// is LLVMIR or ISA.
233+
std::optional<int64_t> getISAToBinaryTimeInMs();
234+
223235
private:
224236
using TmpFile = std::pair<llvm::SmallString<128>, llvm::FileRemover>;
225237

@@ -235,13 +247,20 @@ class NVPTXSerializer : public SerializeGPUModuleBase {
235247

236248
/// Target options.
237249
gpu::TargetOptions targetOptions;
250+
251+
/// LLVMIR->ISA perf result.
252+
std::optional<int64_t> llvmToISATimeInMs;
253+
254+
/// ISA->Binary perf result.
255+
std::optional<int64_t> isaToBinaryTimeInMs;
238256
};
239257
} // namespace
240258

241259
NVPTXSerializer::NVPTXSerializer(Operation &module, NVVMTargetAttr target,
242260
const gpu::TargetOptions &targetOptions)
243261
: SerializeGPUModuleBase(module, target, targetOptions),
244-
targetOptions(targetOptions) {}
262+
targetOptions(targetOptions), llvmToISATimeInMs(std::nullopt),
263+
isaToBinaryTimeInMs(std::nullopt) {}
245264

246265
std::optional<NVPTXSerializer::TmpFile>
247266
NVPTXSerializer::createTemp(StringRef name, StringRef suffix) {
@@ -256,6 +275,14 @@ NVPTXSerializer::createTemp(StringRef name, StringRef suffix) {
256275
return TmpFile(filename, llvm::FileRemover(filename.c_str()));
257276
}
258277

278+
std::optional<int64_t> NVPTXSerializer::getLLVMIRToISATimeInMs() {
279+
return llvmToISATimeInMs;
280+
}
281+
282+
std::optional<int64_t> NVPTXSerializer::getISAToBinaryTimeInMs() {
283+
return isaToBinaryTimeInMs;
284+
}
285+
259286
gpu::GPUModuleOp NVPTXSerializer::getOperation() {
260287
return dyn_cast<gpu::GPUModuleOp>(&SerializeGPUModuleBase::getOperation());
261288
}
@@ -618,6 +645,10 @@ NVPTXSerializer::compileToBinaryNVPTX(const std::string &ptxCode) {
618645

619646
std::optional<SmallVector<char, 0>>
620647
NVPTXSerializer::moduleToObject(llvm::Module &llvmModule) {
648+
llvm::Timer moduleToObjectTimer(
649+
"moduleToObjectTimer",
650+
"Timer for perf llvm-ir -> isa and isa -> binary.");
651+
moduleToObjectTimer.startTimer();
621652
// Return LLVM IR if the compilation target is `offload`.
622653
#define DEBUG_TYPE "serialize-to-llvm"
623654
LLVM_DEBUG({
@@ -650,6 +681,11 @@ NVPTXSerializer::moduleToObject(llvm::Module &llvmModule) {
650681
getOperation().emitError() << "Failed translating the module to ISA.";
651682
return std::nullopt;
652683
}
684+
685+
moduleToObjectTimer.stopTimer();
686+
llvmToISATimeInMs = moduleToObjectTimer.getTotalTime().getWallTime() * 1000;
687+
moduleToObjectTimer.clear();
688+
moduleToObjectTimer.startTimer();
653689
if (isaCallback)
654690
isaCallback(serializedISA.value());
655691

@@ -669,17 +705,24 @@ NVPTXSerializer::moduleToObject(llvm::Module &llvmModule) {
669705
return SmallVector<char, 0>(bin.begin(), bin.end());
670706
}
671707

708+
std::optional<SmallVector<char, 0>> result;
672709
// Compile to binary.
673710
#if MLIR_ENABLE_NVPTXCOMPILER
674-
return compileToBinaryNVPTX(*serializedISA);
711+
result = compileToBinaryNVPTX(*serializedISA);
675712
#else
676-
return compileToBinary(*serializedISA);
713+
result = compileToBinary(*serializedISA);
677714
#endif // MLIR_ENABLE_NVPTXCOMPILER
715+
716+
moduleToObjectTimer.stopTimer();
717+
isaToBinaryTimeInMs = moduleToObjectTimer.getTotalTime().getWallTime() * 1000;
718+
moduleToObjectTimer.clear();
719+
return result;
678720
}
679721

680722
std::optional<SmallVector<char, 0>>
681723
NVVMTargetAttrImpl::serializeToObject(Attribute attribute, Operation *module,
682724
const gpu::TargetOptions &options) const {
725+
Builder builder(attribute.getContext());
683726
assert(module && "The module must be non null.");
684727
if (!module)
685728
return std::nullopt;
@@ -689,7 +732,16 @@ NVVMTargetAttrImpl::serializeToObject(Attribute attribute, Operation *module,
689732
}
690733
NVPTXSerializer serializer(*module, cast<NVVMTargetAttr>(attribute), options);
691734
serializer.init();
692-
return serializer.run();
735+
std::optional<SmallVector<char, 0>> result = serializer.run();
736+
auto llvmToISATimeInMs = serializer.getLLVMIRToISATimeInMs();
737+
if (llvmToISATimeInMs.has_value())
738+
module->setAttr("LLVMIRToISATimeInMs",
739+
builder.getI64IntegerAttr(*llvmToISATimeInMs));
740+
auto isaToBinaryTimeInMs = serializer.getISAToBinaryTimeInMs();
741+
if (isaToBinaryTimeInMs.has_value())
742+
module->setAttr("ISAToBinaryTimeInMs",
743+
builder.getI64IntegerAttr(*isaToBinaryTimeInMs));
744+
return result;
693745
}
694746

695747
Attribute
@@ -700,7 +752,7 @@ NVVMTargetAttrImpl::createObject(Attribute attribute, Operation *module,
700752
gpu::CompilationTarget format = options.getCompilationTarget();
701753
DictionaryAttr objectProps;
702754
Builder builder(attribute.getContext());
703-
SmallVector<NamedAttribute, 2> properties;
755+
SmallVector<NamedAttribute, 4> properties;
704756
if (format == gpu::CompilationTarget::Assembly)
705757
properties.push_back(
706758
builder.getNamedAttr("O", builder.getI32IntegerAttr(target.getO())));
@@ -709,6 +761,14 @@ NVVMTargetAttrImpl::createObject(Attribute attribute, Operation *module,
709761
properties.push_back(builder.getNamedAttr(gpu::elfSectionName,
710762
builder.getStringAttr(section)));
711763

764+
for (const auto *perfName : {"LLVMIRToISATimeInMs", "ISAToBinaryTimeInMs"}) {
765+
if (module->hasAttr(perfName)) {
766+
IntegerAttr attr = llvm::dyn_cast<IntegerAttr>(module->getAttr(perfName));
767+
properties.push_back(builder.getNamedAttr(
768+
perfName, builder.getI64IntegerAttr(attr.getInt())));
769+
}
770+
}
771+
712772
if (!properties.empty())
713773
objectProps = builder.getDictionaryAttr(properties);
714774

mlir/test/Dialect/GPU/module-to-binary-nvvm.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ module attributes {gpu.container_module} {
1616
}
1717

1818
// CHECK-LABEL:gpu.binary @kernel_module2
19-
// CHECK-ISA:[#gpu.object<#nvvm.target<flags = {fast}>, properties = {O = 2 : i32}, assembly = "{{.*}}">, #gpu.object<#nvvm.target, properties = {O = 2 : i32}, assembly = "{{.*}}">]
19+
// CHECK-ISA:[#gpu.object<#nvvm.target<flags = {fast}>, properties = {LLVMIRToISATimeInMs = {{[0-9]+}} : i64, O = 2 : i32}, assembly = "{{.*}}">, #gpu.object<#nvvm.target, properties = {LLVMIRToISATimeInMs = {{[0-9]+}} : i64, O = 2 : i32}, assembly = "{{.*}}">]
2020
gpu.module @kernel_module2 [#nvvm.target<flags = {fast}>, #nvvm.target] {
2121
llvm.func @kernel(%arg0: i32, %arg1: !llvm.ptr,
2222
%arg2: !llvm.ptr, %arg3: i64, %arg4: i64,

mlir/test/python/dialects/gpu/module-to-binary-nvvm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,5 @@ def testGPUToASMBin():
8282
print(gpu.CompilationTarget(o.format))
8383
# CHECK: b'//\n// Generated by LLVM NVPTX Back-End{{.*}}'
8484
print(o.object)
85-
# CHECK: {O = 2 : i32}
85+
# CHECK: {LLVMIRToISATimeInMs = {{[0-9]+}} : i64, O = 2 : i32}
8686
print(o.properties)

0 commit comments

Comments
 (0)