Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional verifications of TTIR dialect ops #1399

Merged
merged 1 commit into from
Nov 26, 2024

Conversation

azecevicTT
Copy link
Contributor

  • Refactoring of ElementwiseOpInteface to better reflect intention, with a fix of broadcast shape calculation, considering that the operand that represents the destination shouldn't affect output shape.
  • Check the number of operands for AttrSizedOperandSegments ops with simple traits.
  • Minor refactoring of TTIR_GenericOp.

This addresses #1289, but I would leave it open to track further progress on similar traits and interfaces needed in the TTNN dialect.

Copy link
Contributor

@nsmithtt nsmithtt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great!

@azecevicTT azecevicTT force-pushed the azecevic/ttir-tightening branch from d1246c8 to 9c9d1d3 Compare November 26, 2024 20:40
- Refactoring of ElementwiseOpInteface to better reflect intention, with
  fix of broadcast shape calculation, considering that operand that
represetnts destination shouldn't affect output shape.
- Check number of operands for AttrSizedOperandSegments ops with simple
  traits.
- Minor refactoring of TTIR_GenericOp.

Addresses #1289, but I would
leave it as open to track further progress with similar traits and
interfaces needed in the TTNN dialect.
@azecevicTT azecevicTT force-pushed the azecevic/ttir-tightening branch from 9c9d1d3 to c169963 Compare November 26, 2024 20:41
@azecevicTT azecevicTT enabled auto-merge (squash) November 26, 2024 20:42
@azecevicTT azecevicTT merged commit d7798cf into main Nov 26, 2024
17 checks passed
@@ -172,8 +172,12 @@ def TTIR_DeallocOp : TTIR_Op<"dealloc"> {
// TTIR top level named ops
//===----------------------------------------------------------------------===//

def TwoOperands : ParamNativeOpTrait<"NOperands", "2">;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@azecevicTT Can you leave comment in next PR to clarify that this is needed because eltwise operations accept variadic number of arguments in which case mlir doesn't enforce number of operands required for operation?

return mlir::cast<mlir::RankedTensorType>(val.getType()).getShape();
};

const auto operandSegmentSizes =
Copy link
Contributor

@mtopalovicTT mtopalovicTT Nov 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@azecevicTT I wanted to ask also why the use of auto in whole function?
I understand using it when you can deduce type from rhs (i.e constructor call), but this is overuse imo. Do you have some reason for it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can overuse auto sometimes and I am aware that it can hinder readability sometimes (language servers tends to mitigate this biggest disadvantage nowadays). The biggest advantage (besides the laziness, can't lie about that) is the form of polymorphism that auto gives us. In this example I don't care if the type of operandSegmentSizes is mlir::DenseI32Array, llvm::ArrayRef, llvm::SmallVector, std::vector, std::array, as long as it has indexing operation and size() member function (with reasonable semantics) it's good to go, and I don't have to change anything if the underlying type changes, because I'm committed only to the interface, not the type.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point about not worrying about the underlying type, but do you realistically expect the API to change? I’d also argue that this type of polymorphism can lead to bugs in certain scenarios. For example, imagine you initially use auto with a SmallVector and rely on its indexing operator and size() functionality. Later, the API changes and returns a DenseMap instead, where the indexing operator behaves differently from SmallVector.

I understand the value of auto for lambdas, iterators, and constructor expressions, but beyond that, it feels a bit excessive to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't disagree that it doesn't have disadvantages (basically it's the static version of the duck typing), I just think that benefits that auto brings outweights those disadvantages. The main point is that interfaces are usually more stable than types, your producer is much more likely to change type than interface. Now, in these concrete example I don't expect it to change since the RHS already mentions concrete type in the template, but you can argue that's already a reason in itself to not mention it again in the declaration.
I'm not religious about using auto, I just think it was a nice addition to C++ for a lot of reasons, we should just make a project guidelines when it's ok to use it and when it's not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn’t focusing on this specific type, but the fact that the entire function was using auto is what caught my attention...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants