Skip to content

Commit be8fef1

Browse files
committed
[TLERaw] Support NVSHMEM
1 parent c1cb1c6 commit be8fef1

18 files changed

Lines changed: 473 additions & 8 deletions

File tree

include/triton/Conversion/TritonGPUToLLVM/PatternTritonGPUOpToLLVM.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ void populatePrintOpToLLVMPattern(LLVMTypeConverter &typeConverter,
102102
const TargetInfoBase &targetInfo,
103103
PatternBenefit benefit);
104104

105+
void populateExternCallOpToLLVMPattern(LLVMTypeConverter &typeConverter,
106+
RewritePatternSet &patterns,
107+
const TargetInfoBase &targetInfo,
108+
PatternBenefit benefit);
109+
105110
void populateInstrumentationToLLVMPatterns(LLVMTypeConverter &typeConverter,
106111
const TargetInfoBase &targetInfo,
107112
RewritePatternSet &patterns,

include/triton/Dialect/Triton/IR/TritonOps.td

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,32 @@ def TT_MapElementwiseReturnOp: TT_Op<"map_elementwise.return",
845845
let assemblyFormat = "attr-dict ($result^ `:` type($result))?";
846846
}
847847

848+
//
849+
// External Call op
850+
//
851+
def TT_ExternCallOp : TT_Op<"extern_call", [
852+
DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,
853+
ConditionallySpeculatable,
854+
]> {
855+
856+
let description = [{
857+
call an external function $symbol implemented in $libpath/$libname with $args
858+
return $libpath/$libname:$symbol($args...)
859+
}];
860+
861+
let arguments = (ins Variadic<TT_Type>:$srcs, StrAttr:$libname, StrAttr:$libpath, StrAttr:$symbol, BoolAttr:$pure);
862+
863+
let results = (outs Variadic<TT_Type>:$result);
864+
865+
let assemblyFormat = "operands attr-dict `:` functional-type(operands, $result)";
866+
867+
let extraClassDeclaration = [{
868+
// Interface method for ConditionallySpeculatable.
869+
Speculation::Speculatability getSpeculatability();
870+
}];
871+
872+
}
873+
848874
//
849875
// External Elementwise op
850876
//

lib/Conversion/TritonGPUToLLVM/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ add_triton_library(TritonGPUToLLVM
77
AssertOpToLLVM.cpp
88
ControlFlowOpToLLVM.cpp
99
ConvertLayoutOpToLLVM.cpp
10+
ExternCallOpToLLVM.cpp
1011
ElementwiseOpToLLVM.cpp
1112
FuncOpToLLVM.cpp
1213
GatherOpToLLVM.cpp
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#include "mlir/Conversion/LLVMCommon/Pattern.h"
2+
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
3+
#include "mlir/Support/LLVM.h"
4+
#include "triton/Conversion/TritonGPUToLLVM/ElementwiseOpToLLVMBase.h"
5+
#include "triton/Conversion/TritonGPUToLLVM/PatternTritonGPUOpToLLVM.h"
6+
#include "triton/Conversion/TritonGPUToLLVM/TargetInfoBase.h"
7+
#include "triton/Conversion/TritonGPUToLLVM/Utility.h"
8+
#include "triton/Dialect/TritonGPU/IR/Dialect.h"
9+
10+
namespace {
11+
12+
class ExternCallOpConversion
13+
: public ConvertOpToLLVMPattern<triton::ExternCallOp> {
14+
public:
15+
ExternCallOpConversion(const LLVMTypeConverter &converter,
16+
const PatternBenefit &benefit)
17+
: ConvertOpToLLVMPattern<triton::ExternCallOp>(converter, benefit) {}
18+
19+
LogicalResult
20+
matchAndRewrite(triton::ExternCallOp op, OpAdaptor adaptor,
21+
ConversionPatternRewriter &rewriter) const override {
22+
auto loc = op->getLoc();
23+
24+
if (op->getNumResults() > 1) {
25+
llvm::errs() << "ExternCallConversion does not support multi outs.";
26+
return failure();
27+
}
28+
29+
LLVM::LLVMVoidType voidTy = void_ty(op->getContext());
30+
auto newOperands = adaptor.getOperands();
31+
Type retType =
32+
op->getNumResults() == 0
33+
? voidTy
34+
: this->getTypeConverter()->convertType(op->getResult(0).getType());
35+
std::string funcName = op.getSymbol().str();
36+
StringRef libname = op.getLibname();
37+
StringRef libpath = op.getLibpath();
38+
39+
Operation *externCallOp;
40+
Type funcType = mlir::triton::gpu::getFunctionType(retType, newOperands);
41+
LLVM::LLVMFuncOp funcOp = mlir::triton::gpu::appendOrGetExternFuncOp(
42+
rewriter, op, funcName, funcType, libname, libpath);
43+
externCallOp = LLVM::createLLVMCallOp(rewriter, loc, funcOp, newOperands);
44+
45+
if (op->getNumResults() == 0) {
46+
rewriter.eraseOp(op);
47+
} else {
48+
rewriter.replaceOp(op, externCallOp->getResult(0));
49+
}
50+
51+
return success();
52+
}
53+
};
54+
55+
} // namespace
56+
57+
void mlir::triton::populateExternCallOpToLLVMPattern(
58+
LLVMTypeConverter &typeConverter, RewritePatternSet &patterns,
59+
const TargetInfoBase &targetInfo, PatternBenefit benefit) {
60+
patterns.add<ExternCallOpConversion>(typeConverter, benefit);
61+
}

lib/Conversion/TritonToTritonGPU/TritonToTritonGPUPass.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@ void populateTritonPatterns(TritonGPUTypeConverter &typeConverter,
600600
GenericOpPattern<triton::HistogramOp>,
601601
GenericOpPattern<triton::GatherOp>,
602602
GenericOpPattern<triton::ExternElementwiseOp>,
603+
GenericOpPattern<triton::ExternCallOp>,
603604
GenericOpPattern<triton::PrintOp>,
604605
GenericOpPattern<triton::AssertOp>,
605606
GenericOpPattern<triton::AtomicCASOp>,

lib/Dialect/Triton/IR/Ops.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,24 @@ Speculation::Speculatability ExternElementwiseOp::getSpeculatability() {
13131313
return Speculation::NotSpeculatable;
13141314
}
13151315

1316+
// -- ExternCallOp --
1317+
void ExternCallOp::getEffects(
1318+
SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
1319+
&effects) {
1320+
if (getPure())
1321+
return;
1322+
effects.emplace_back(MemoryEffects::Write::get(),
1323+
SideEffects::DefaultResource::get());
1324+
effects.emplace_back(MemoryEffects::Read::get(),
1325+
SideEffects::DefaultResource::get());
1326+
}
1327+
1328+
Speculation::Speculatability ExternCallOp::getSpeculatability() {
1329+
if (getPure())
1330+
return Speculation::Speculatable;
1331+
return Speculation::NotSpeculatable;
1332+
}
1333+
13161334
// -- GatherOp --
13171335
LogicalResult GatherOp::verify() {
13181336
RankedTensorType indicesTy = getIndices().getType();

python/src/ir.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,6 +1673,14 @@ void init_triton_ir(py::module &&m) {
16731673
return self.create<ExternElementwiseOp>(retType, argList, libName,
16741674
libPath, symbol, isPure);
16751675
})
1676+
.def("create_extern_call",
1677+
[](TritonOpBuilder &self, const std::string &libName,
1678+
const std::string &libPath, const std::string &symbol,
1679+
std::vector<Value> &argList, const std::vector<Type> &retTypes,
1680+
bool isPure) -> OpState {
1681+
return self.create<ExternCallOp>(retTypes, argList, libName,
1682+
libPath, symbol, isPure);
1683+
})
16761684
// Built-in instruction
16771685
.def("create_get_program_id",
16781686
[](TritonOpBuilder &self, int axis) -> Value {
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
from .core import call, call_smem
1+
from .core import call, call_smem, call_nvshmem
22

3-
__all__ = ["call", "call_smem"]
3+
__all__ = ["call", "call_smem", "call_nvshmem"]

python/triton/experimental/tle/language/raw/core.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,8 @@ def call_smem(func, args, _semantic=None):
4646
return buffer_tensors[0]
4747
else:
4848
return tl.tuple(buffer_tensors)
49+
50+
51+
@builtin
52+
def call_nvshmem(func, outputs, inputs, _semantic=None):
53+
func.make_cubin()

python/triton/experimental/tle/raw/cuda/runtime.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,24 @@
33
from pathlib import Path
44
import subprocess
55
from typing import Any, Final
6+
import torch
67

78
from triton._C.libtriton import llvm # pyright: ignore[reportMissingImports]
89
from triton._C.libtriton.tle.llvm import parse_llvm_ir # pyright: ignore[reportMissingImports]
910

1011
# TODO: We use cli tools to compile CUDA code temporarily, and plan to replace it with LLVM components Python bindings in the future.
1112
CLANG = os.getenv("CLANG", "clang")
13+
NVCC = os.getenv("NVCC", "nvcc")
1214

1315

1416
class CUDAJITFunction(object):
1517

1618
def __init__(self, fn: Any, file: Path, *args, **kwargs) -> None:
17-
super().__init__(*args, **kwargs)
19+
super().__init__()
1820
self.fn: Final[Any] = fn
1921
self.code: Final[str] = file.read_text()
22+
self.file: Final[Path] = file
23+
self.libs = kwargs.get("library", {})
2024
self.__triton_builtin__: Final[bool] = True
2125

2226
def make_llvm(self, mlir_context) -> str:
@@ -40,3 +44,22 @@ def make_llvm(self, mlir_context) -> str:
4044
llvm_context = llvm.context()
4145
module = parse_llvm_ir(build.stdout.decode(), llvm_context, mlir_context)
4246
return f"{module}"
47+
48+
def make_cubin(self):
49+
src = self.file
50+
dst = Path(src).with_suffix('.o')
51+
include_dirs = []
52+
for lib_name, lib_path in self.libs.items():
53+
# TODO: Remove the method of passing information by setting environment variables.
54+
os.environ[(lib_name + "_home").upper()] = lib_path
55+
include_dirs.append(os.path.join(lib_path, "include"))
56+
include_flags = [f"-I{inc_dir}" for inc_dir in include_dirs]
57+
prop = torch.cuda.get_device_properties(torch.cuda.current_device())
58+
arch = f"-arch=sm_{prop.major}{prop.minor}"
59+
build = subprocess.run([NVCC, "-rdc=true", arch, *include_flags, "--extended-lambda", "-c", "-o", dst, src],
60+
capture_output=True)
61+
assert build.returncode == 0, (f"nvcc failed\nstderr:\n{build.stderr.decode()}")
62+
# TODO: Remove the method of passing information by setting environment variables.
63+
os.environ["USE_NVCC"] = 'True'
64+
os.environ["CUDA_CUBIN"] = str(dst)
65+
return

0 commit comments

Comments
 (0)