MLIR 24.0.0git
ShardingInterfaceImpl.cpp
Go to the documentation of this file.
1//===- ShardingInterfaceImpl.cpp - Tensor sharding models -----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
14
15using namespace mlir;
16using namespace mlir::tensor;
17using namespace mlir::shard;
18
19namespace {
20// Sharding of tensor.empty/tensor.splat
21template <typename OpTy>
22struct CreatorOpShardingInterface
23 : public ShardingInterface::ExternalModel<CreatorOpShardingInterface<OpTy>,
24 OpTy> {
25 SmallVector<utils::IteratorType> getLoopIteratorTypes(Operation *op) const {
26 auto ndims = mlir::cast<ShapedType>(op->getResult(0).getType()).getRank();
27 return SmallVector<utils::IteratorType>(ndims,
28 utils::IteratorType::parallel);
29 }
30
31 SmallVector<AffineMap> getIndexingMaps(Operation *op) const {
32 MLIRContext *ctx = op->getContext();
33 Value val = op->getResult(0);
34 auto type = dyn_cast<RankedTensorType>(val.getType());
35 if (!type)
36 return {};
37 return SmallVector<AffineMap>(
38 op->getNumOperands() + op->getNumResults(),
39 {AffineMap::getMultiDimIdentityMap(type.getRank(), ctx)});
40 }
41
42 LogicalResult partition(Operation *op, ArrayRef<Value> partitionedOperands,
43 ArrayRef<Sharding> operandShardings,
44 ArrayRef<Sharding> resultShardings,
45 IRMapping &partitionMap,
46 SymbolTableCollection &symbolTable,
47 OpBuilder &builder) const {
48 assert(resultShardings.size() == 1);
49 auto resType = cast<RankedTensorType>(op->getResult(0).getType());
50 mlir::shard::GridOp grid;
51 ShapedType shardType;
52 if (resType.getRank() > 0) {
53 grid = shard::getGrid(op, resultShardings[0].getGridAttr(), symbolTable);
54 shardType =
55 cast<ShapedType>(shard::shardType(resType, grid, resultShardings[0]));
56 } else {
57 shardType = resType;
58 }
59 Operation *newOp = nullptr;
60 // if the sharding introduces a new dynamic dimension, we take it from
61 // the dynamic sharding info. For now bail out if it's not
62 // provided.
63 if (!shardType.hasStaticShape()) {
64 assert(op->getResult(0).hasOneUse());
65 SmallVector<Value> newOperands;
66 auto oldType = cast<ShapedType>(resType);
67 assert(oldType.getRank() == shardType.getRank());
68 int currOldOprndNum = -1;
69 shard::ShardShapeOp shapeForDevice;
70 ValueRange device;
71 Operation *newSharding = nullptr;
72 for (auto i = 0; i < oldType.getRank(); ++i) {
73 if (!oldType.isDynamicDim(i) && shardType.isDynamicDim(i)) {
74 if (!newSharding) {
75 newSharding =
76 ShardingOp::create(builder, op->getLoc(), resultShardings[0]);
77 device =
78 shard::ProcessMultiIndexOp::create(builder, op->getLoc(), grid)
79 .getResults();
80 shapeForDevice = shard::ShardShapeOp::create(
81 builder, op->getLoc(), oldType.getShape(), partitionedOperands,
82 newSharding->getResult(0), device);
83 }
84 newOperands.emplace_back(shapeForDevice.getResult()[i]);
85 } else if (oldType.isDynamicDim(i)) {
86 assert(shardType.isDynamicDim(i));
87 newOperands.emplace_back(partitionedOperands[++currOldOprndNum]);
88 }
89 }
90 newOp = OpTy::create(builder, op->getLoc(), shardType, newOperands);
91 partitionMap.map(op->getResult(0), newOp->getResult(0));
92 } else {
93 // `clone` will populate the mapping of old to new results.
94 newOp = builder.clone(*op, partitionMap);
95 }
96 newOp->getResult(0).setType(shardType);
97
98 return success();
99 }
100};
101} // namespace
102
104 DialectRegistry &registry) {
105
106 registry.addExtension(+[](MLIRContext *ctx, TensorDialect *dialect) {
107 EmptyOp::template attachInterface<CreatorOpShardingInterface<EmptyOp>>(
108 *ctx);
109 SplatOp::template attachInterface<CreatorOpShardingInterface<SplatOp>>(
110 *ctx);
111 });
112}
return success()
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
void map(Value from, Value to)
Inserts a new mapping for 'from' to 'to'.
Definition IRMapping.h:30
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:71
Operation * clone(Operation &op, IRMapping &mapper)
Creates a deep copy of the specified operation, remapping any operands that use values outside of the...
Definition Builders.cpp:581
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition Operation.h:434
Location getLoc()
The source location the operation was defined or derived from.
Definition Operation.h:240
unsigned getNumOperands()
Definition Operation.h:373
MLIRContext * getContext()
Return the context this operation is associated with.
Definition Operation.h:233
unsigned getNumResults()
Return the number of results held by this operation.
Definition Operation.h:431
void setType(Type newType)
Mutate the type of this Value to be of the specified type.
Definition Value.h:116
Type getType() const
Return the type of this value.
Definition Value.h:105
bool hasOneUse() const
Returns true if this value has exactly one use.
Definition Value.h:197
Type shardType(Type type, GridOp grid, Sharding sharding)
Definition ShardOps.cpp:289
shard::GridOp getGrid(Operation *op, FlatSymbolRefAttr gridSymbol, SymbolTableCollection &symbolTableCollection)
Definition ShardOps.h:127
void registerShardingInterfaceExternalModels(DialectRegistry &registry)
Include the generated interface declarations.