Merge branch 'TestRottoConDeadLock' of chef.heaplab.deib.polimi.it:nnicolosi/Raptor into TestRottoConDeadLock
Validate Operations / validate-operations (push) Has been cancelled
Validate Operations / validate-operations (push) Has been cancelled
This commit is contained in:
@@ -142,6 +142,71 @@ static std::optional<EmitLocalCollectionRun> buildLocalConcat(
|
||||
? std::optional<EmitLocalCollectionRun>(std::move(run)) : std::nullopt;
|
||||
}
|
||||
|
||||
static bool canLoopLocalCollection(
|
||||
const EmitLocalCollectionRun &update, unsigned targetLaneCount) {
|
||||
if (!update.collection || update.concatenatePayloads
|
||||
|| update.families.size() != 1
|
||||
|| !(update.lanes == LaneSet::all(targetLaneCount)))
|
||||
return false;
|
||||
RequirementFamily &requirement = *update.families.front()->requirement;
|
||||
return requirement.targetLanes == update.lanes
|
||||
&& !requirement.producerProjection
|
||||
&& (!requirement.producerLocalOffsets
|
||||
|| requirement.producerLocalOffsets->size() == targetLaneCount);
|
||||
}
|
||||
|
||||
static bool haveSameLocalCollectionContract(
|
||||
const EmitLocalCollectionRun &lhs,
|
||||
const EmitLocalCollectionRun &rhs) {
|
||||
if (lhs.collection != rhs.collection)
|
||||
return false;
|
||||
RequirementFamily &left = *lhs.families.front()->requirement;
|
||||
RequirementFamily &right = *rhs.families.front()->requirement;
|
||||
if (left.producer->payload != right.producer->payload
|
||||
|| left.publicationFragmentType != right.publicationFragmentType)
|
||||
return false;
|
||||
if (lhs.collection->key.kind != FragmentCollectionKind::InsertAssembly)
|
||||
return true;
|
||||
const auto &entries =
|
||||
lhs.collection->key.exchange->program.insertAssembly->entries;
|
||||
const auto &leftEntry = entries[lhs.collectionPosition];
|
||||
const auto &rightEntry = entries[rhs.collectionPosition];
|
||||
return leftEntry.sourceTransform == rightEntry.sourceTransform
|
||||
&& leftEntry.sourceType == rightEntry.sourceType;
|
||||
}
|
||||
|
||||
static void appendLocalUpdates(
|
||||
BoundaryProgram &boundary,
|
||||
SmallVectorImpl<EmitLocalCollectionRun> &updates,
|
||||
unsigned targetLaneCount) {
|
||||
for (size_t index = 0; index < updates.size();) {
|
||||
EmitLocalCollectionRun &first = updates[index];
|
||||
if (!canLoopLocalCollection(first, targetLaneCount)) {
|
||||
boundary.instructions.push_back(std::move(first));
|
||||
++index;
|
||||
continue;
|
||||
}
|
||||
size_t end = index + 1;
|
||||
while (end < updates.size()
|
||||
&& canLoopLocalCollection(updates[end], targetLaneCount)
|
||||
&& haveSameLocalCollectionContract(first, updates[end]))
|
||||
++end;
|
||||
if (end - index == 1) {
|
||||
boundary.instructions.push_back(std::move(first));
|
||||
++index;
|
||||
continue;
|
||||
}
|
||||
EmitLocalCollectionLoopRun run;
|
||||
run.collection = first.collection;
|
||||
run.lanes = first.lanes;
|
||||
for (; index < end; ++index) {
|
||||
run.positions.push_back(updates[index].collectionPosition);
|
||||
run.families.push_back(updates[index].families.front());
|
||||
}
|
||||
boundary.instructions.push_back(std::move(run));
|
||||
}
|
||||
}
|
||||
|
||||
static void appendReceive(BoundaryProgram &boundary,
|
||||
const ScheduledTransferSlice &slice,
|
||||
CollectionTarget target) {
|
||||
@@ -288,8 +353,7 @@ FailureOr<DeferredBoundaryPlan> buildDeferredBoundaryPlan(
|
||||
if (failed(addCoverage(*local.requirement, local.targetLanes, coverage)))
|
||||
return failure();
|
||||
}
|
||||
for (EmitLocalCollectionRun &update : localUpdates)
|
||||
boundary.instructions.push_back(std::move(update));
|
||||
appendLocalUpdates(boundary, localUpdates, exchange->targetLaneCount);
|
||||
for (RequirementFamily &requirement : exchange->requirements)
|
||||
if (!(coverage.lookup(&requirement) == requirement.targetLanes))
|
||||
return exchange->deferred.emitOpError(
|
||||
|
||||
@@ -20,6 +20,12 @@ struct EmitLocalCollectionRun {
|
||||
LaneSet lanes;
|
||||
bool concatenatePayloads = false;
|
||||
};
|
||||
struct EmitLocalCollectionLoopRun {
|
||||
const FragmentCollectionPlan* collection = nullptr;
|
||||
llvm::SmallVector<unsigned> positions;
|
||||
llvm::SmallVector<LocalAvailabilityFamily*> families;
|
||||
LaneSet lanes;
|
||||
};
|
||||
struct EmitReceiveAssemblyRun {
|
||||
const FragmentCollectionPlan* collection = nullptr;
|
||||
llvm::SmallVector<ScheduledTransferSlice> slices;
|
||||
@@ -33,7 +39,8 @@ struct ProduceDeferredResult {
|
||||
};
|
||||
|
||||
using BoundaryInstruction =
|
||||
std::variant<EmitSendRun, EmitLocalCollectionRun, EmitReceiveAssemblyRun,
|
||||
std::variant<EmitSendRun, EmitLocalCollectionRun,
|
||||
EmitLocalCollectionLoopRun, EmitReceiveAssemblyRun,
|
||||
ProduceDeferredResult>;
|
||||
struct BoundaryProgram {
|
||||
BoundaryKey key;
|
||||
|
||||
@@ -507,6 +507,137 @@ static FailureOr<Value> transformAssemblySource(Value fragment, const DeferredIn
|
||||
llvm_unreachable("unknown deferred assembly source transform");
|
||||
}
|
||||
|
||||
static FailureOr<Value> materializeLoopedLocalAssemblySource(
|
||||
RequirementFamily &requirement,
|
||||
const DeferredInsertAssemblyEntryTemplate &entry,
|
||||
Value localOffset, DeferredExchangePlan &exchange,
|
||||
DeferredEmissionContext &context) {
|
||||
Value payload = requirement.producer->payload;
|
||||
auto payloadType = dyn_cast<RankedTensorType>(payload.getType());
|
||||
RankedTensorType sourceType = entry.sourceType;
|
||||
if (entry.sourceTransform
|
||||
== DeferredAssemblySourceTransform::RemoveLeadingUnitDimension
|
||||
&& payloadType && sourceType
|
||||
&& payloadType.getRank() > sourceType.getRank()
|
||||
&& payloadType.getElementType() == sourceType.getElementType()
|
||||
&& payloadType.getShape().take_back(sourceType.getRank())
|
||||
== sourceType.getShape()) {
|
||||
MixedSliceGeometry geometry;
|
||||
int64_t rankDifference = payloadType.getRank() - sourceType.getRank();
|
||||
geometry.offsets.assign(payloadType.getRank(),
|
||||
context.rewriter.getIndexAttr(0));
|
||||
if (payload.getType() != requirement.publicationFragmentType)
|
||||
geometry.offsets.front() = localOffset;
|
||||
geometry.sizes.assign(rankDifference, context.rewriter.getIndexAttr(1));
|
||||
for (int64_t dimension : sourceType.getShape())
|
||||
geometry.sizes.push_back(context.rewriter.getIndexAttr(dimension));
|
||||
geometry.strides.assign(payloadType.getRank(),
|
||||
context.rewriter.getIndexAttr(1));
|
||||
return extractMixedSliceOrIdentity(
|
||||
context.rewriter, exchange.deferred.getLoc(), payload, sourceType,
|
||||
geometry);
|
||||
}
|
||||
auto fragment = materializeSendPayload(
|
||||
requirement, localOffset, nullptr, context,
|
||||
exchange.deferred.getLoc());
|
||||
if (failed(fragment))
|
||||
return failure();
|
||||
return transformAssemblySource(*fragment, entry, exchange, context);
|
||||
}
|
||||
|
||||
static LogicalResult emitLoopedLocalCollectionUpdate(
|
||||
const EmitLocalCollectionLoopRun &run, Value lane, unsigned laneCount,
|
||||
const DeferredResultPlan &resultPlan, DeferredEmissionContext &context) {
|
||||
if (!run.collection || run.positions.size() < 2
|
||||
|| run.positions.size() != run.families.size())
|
||||
return failure();
|
||||
const FragmentCollectionPlan &collection = *run.collection;
|
||||
DeferredExchangePlan &exchange = *collection.key.exchange;
|
||||
const DeferredInsertAssemblyEntryTemplate *entry = nullptr;
|
||||
if (collection.key.kind == FragmentCollectionKind::InsertAssembly)
|
||||
entry = &exchange.program.insertAssembly
|
||||
->entries[run.positions.front()];
|
||||
SmallVector<StaticIntSequence> offsetRows;
|
||||
SmallVector<int64_t> positions;
|
||||
offsetRows.reserve(run.families.size());
|
||||
positions.reserve(run.positions.size());
|
||||
for (auto [position, family] : llvm::zip_equal(run.positions,
|
||||
run.families)) {
|
||||
RequirementFamily &requirement = *family->requirement;
|
||||
offsetRows.push_back(requirement.producerLocalOffsets
|
||||
? *requirement.producerLocalOffsets
|
||||
: StaticIntSequence::uniform(0, laneCount));
|
||||
positions.push_back(position);
|
||||
}
|
||||
auto localOffsets = StaticIntGrid::fromRows(offsetRows);
|
||||
if (failed(localOffsets))
|
||||
return failure();
|
||||
Operation *anchor = exchange.deferred;
|
||||
Location loc = anchor->getLoc();
|
||||
Value runtimeLane = lane ? lane : context.constants.getIndex(0);
|
||||
Value current = context.fragmentCollections.lookup(collection.key);
|
||||
if (!current)
|
||||
current = createCollectionInitial(collection, context);
|
||||
auto loop = buildNormalizedScfFor(
|
||||
context.rewriter, loc, context.constants.getIndex(0),
|
||||
context.constants.getIndex(run.positions.size()),
|
||||
context.constants.getIndex(1), ValueRange {current},
|
||||
[&](OpBuilder &, Location, Value action, ValueRange iterArgs,
|
||||
SmallVectorImpl<Value> &yielded) -> LogicalResult {
|
||||
Value position = lookup(positions, action, anchor, context, loc);
|
||||
Value localOffset = localOffsets->emitLookup(
|
||||
action, runtimeLane, anchor, context.constants, context.rewriter, loc);
|
||||
RequirementFamily &requirement = *run.families.front()->requirement;
|
||||
FailureOr<Value> source = entry
|
||||
? materializeLoopedLocalAssemblySource(
|
||||
requirement, *entry, localOffset, exchange, context)
|
||||
: materializeSendPayload(
|
||||
requirement, localOffset, nullptr, context, loc);
|
||||
if (failed(source))
|
||||
return failure();
|
||||
Value next;
|
||||
if (entry) {
|
||||
if (source->getType() != entry->sourceType)
|
||||
return failure();
|
||||
next = insertMixedSlice(
|
||||
context.rewriter, loc, *source, iterArgs.front(),
|
||||
lookupGeometry(resultPlan.assemblyGeometry, position, runtimeLane,
|
||||
anchor, context, loc));
|
||||
} else {
|
||||
bool grouped = collection.key.kind
|
||||
== FragmentCollectionKind::GroupedLeaf;
|
||||
Value specialization = context.constants.getIndex(0);
|
||||
Value leafPosition = position;
|
||||
if (grouped) {
|
||||
Value divisor = context.constants.getIndex(collection.positionCount);
|
||||
specialization = arith::DivUIOp::create(
|
||||
context.rewriter, loc, position, divisor);
|
||||
leafPosition = arith::RemUIOp::create(
|
||||
context.rewriter, loc, position, divisor);
|
||||
}
|
||||
unsigned leafIndex = collection.key.leafIndex;
|
||||
const DeferredProjectionLeafTemplate &leaf =
|
||||
exchange.program.leaves[leafIndex];
|
||||
auto inserted = insertProjectionFragment(
|
||||
*source, specialization, leafPosition,
|
||||
grouped ? specialization : context.constants.getIndex(0),
|
||||
runtimeLane, iterArgs.front(), leaf,
|
||||
resultPlan.innerGeometry[leafIndex], exchange, grouped, context);
|
||||
if (failed(inserted))
|
||||
return failure();
|
||||
next = *inserted;
|
||||
}
|
||||
if (!next)
|
||||
return failure();
|
||||
yielded.push_back(next);
|
||||
return success();
|
||||
});
|
||||
if (failed(loop))
|
||||
return failure();
|
||||
context.fragmentCollections[collection.key] = loop->results.front();
|
||||
return success();
|
||||
}
|
||||
|
||||
static LogicalResult emitInsertAssemblyUpdate(const EmitReceiveAssemblyRun &run, Value lane, unsigned laneCount,
|
||||
const DeferredResultPlan &resultPlan, DeferredEmissionContext &context) {
|
||||
const FragmentCollectionPlan &collection = *run.collection;
|
||||
@@ -683,6 +814,18 @@ static FailureOr<SmallVector<Value>> emitInstructions(ArrayRef<BoundaryInstructi
|
||||
if (failed(emitted))
|
||||
return exchange->deferred.emitOpError(
|
||||
"failed to update fragment collection from local availability"), failure();
|
||||
} else if (auto update =
|
||||
std::get_if<EmitLocalCollectionLoopRun>(&instruction)) {
|
||||
DeferredExchangePlan *exchange = update->collection->key.exchange;
|
||||
const DeferredResultPlan *resultPlan = findResultPlan(results, exchange);
|
||||
LogicalResult emitted = resultPlan
|
||||
? emitLoopedLocalCollectionUpdate(
|
||||
*update, lane, laneCount, *resultPlan, context)
|
||||
: failure();
|
||||
if (failed(emitted))
|
||||
return exchange->deferred.emitOpError(
|
||||
"failed to update fragment collection from local assembly run"),
|
||||
failure();
|
||||
} else if (auto assembly = std::get_if<EmitReceiveAssemblyRun>(&instruction)) {
|
||||
DeferredExchangePlan *exchange = assembly->collection->key.exchange;
|
||||
const DeferredResultPlan *resultPlan = findResultPlan(results, exchange);
|
||||
|
||||
+10
-6
@@ -168,12 +168,16 @@ static LogicalResult materializeResultfulBatchRun(
|
||||
|
||||
IRMapping mapper;
|
||||
mapper.map(*batch.getLaneArgument(), originalLane);
|
||||
Value localLane = runLaneCount == 1
|
||||
? getOrCreateIndexConstant(rewriter, batch.getOperation(), 0)
|
||||
: arith::SubIOp::create(
|
||||
builder, bodyLoc, originalLane,
|
||||
getOrCreateIndexConstant(
|
||||
rewriter, batch.getOperation(), first.laneStart));
|
||||
Value localLane;
|
||||
if (runLaneCount == 1)
|
||||
localLane = getOrCreateIndexConstant(rewriter, batch.getOperation(), 0);
|
||||
else if (first.laneStart == 0)
|
||||
localLane = originalLane;
|
||||
else
|
||||
localLane = arith::SubIOp::create(
|
||||
builder, bodyLoc, originalLane,
|
||||
getOrCreateIndexConstant(
|
||||
rewriter, batch.getOperation(), first.laneStart));
|
||||
for (auto [index, weight] : llvm::enumerate(batch.getWeights()))
|
||||
mapper.map(*batch.getWeightArgument(index), getBlockOperand(block, scheduledWeights, weight));
|
||||
SmallVector<DeferredInputPlan> inputPlans;
|
||||
|
||||
Reference in New Issue
Block a user