Skip to content

[MultiThreshold] Generalize data layouts for node execution#143

Open
iksnagreb wants to merge 3 commits intofastmachinelearning:mainfrom
iksnagreb:feature/generalized_multi_threshold_layouts
Open

[MultiThreshold] Generalize data layouts for node execution#143
iksnagreb wants to merge 3 commits intofastmachinelearning:mainfrom
iksnagreb:feature/generalized_multi_threshold_layouts

Conversation

@iksnagreb
Copy link
Collaborator

The relevant aspect of the data layout annotation seems to be which axis is labeled as the channel dimension "C": We do not actually have to care about the total number and ordering of the other axes, as long as we can find the index of the "C" axis and swap to have "C" at index 1 for node execution (and swap it back afterwards).

Falls back to the default assumption that "C" is at index 1 if there is no layout annotation, which is equivalent to the "NCHW" or "NC" layouts.

This is a rather experimental change which might break existing code and is currently still restricted to the well-known 2-, 3- and 4-dimensional layouts.

This PR is based on #92 which is less experimental and should be merged first (#92 also does not risk breaking existing code as it only adds new special cases).

@maltanar
Copy link
Collaborator

Instead of relying on data layout strings, how about we switch to an attribute axis (like many standard ONNX ops do) to indicate the location (index) of the channels axis? I'd actually prefer to deprecate the old data_layout attribute, and I think we can still keep backwards compatibility by treating data_layout=NCHW as axis=1 and data_layout=NHWC as axis=-1. If the interpretation of the two attributes disagree, the axis one can dominate.

Copy link
Collaborator

@makoeppel makoeppel left a comment

Choose a reason for hiding this comment

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

I think here we only have to rebase. This was already approved and merged by @maltanar. Or were there some new changes? If so I would maybe prefer to create a new branch.

@iksnagreb
Copy link
Collaborator Author

I think here we only have to rebase. This was already approved and merged by @maltanar. Or were there some new changes? If so I would maybe prefer to create a new branch.

Hm, @maltanar contributed some significant improvements to the multithreshold implementation with #201, but I'd argue we want to keep the more general channel axis resolution from this PR. I will rebase and resolve the conflict.

The relevant aspect of the data layout annotation seems to be which axis
is labeled as the channel dimension "C": We do not actually have to care
about the total number and ordering of the other axes, as long as we can
find the index of the "C" axis and swap to have "C" at index 1 for node
execution (and swap it back afterwards).

Falls back to the default assumption that "C" is at index 1 if there is
no layout annotation, which is equivalent to the "NCHW" or "NC" layouts.

This is a rather experimental change which might break existing code and
is currently still restricted to the well-known 2-, 3- and 4-dimensional
layouts.
Note: Only covers data layouts for tensors with less than five axes
@iksnagreb iksnagreb force-pushed the feature/generalized_multi_threshold_layouts branch from c0b4534 to a825dfd Compare January 23, 2026 16:10
@jmitrevs jmitrevs requested a review from maltanar January 29, 2026 18:02
@iksnagreb iksnagreb requested a review from makoeppel February 4, 2026 17:42
# Rearrange the input to the expected (N, C, ...) layout
orig_shape = v.shape
output = multithreshold(v, thresholds, out_scale, out_bias, channels_last)
v = v.swapaxes(cdim, 1)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this always work? Is it an improvement over using the channels_last parameter?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

For 1d, 2d, 3d and 4d input this is fine and matches the previous behavior. Looking at it now, I just realized that in case there is no fallback (>= 5d) or for 0d, it will try indexing into a None. Though, as far as I am aware, this would not affect any model we are supporting at the moment. Still this should be address. I will add a quick workaround, though the entire layout mechanism is long overdue for a proper rework...

Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it possible to just use the channels_last flag?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not really, channels_last can only differentiate between channels at axis 1 or -1, but we had instances where channels could end up at any index, at least temporarily while transforming the model. Usually we always end up with channels last (anything else cannot really be implemented in FINN at the moment), but to get there we might transition through a few mixed-up layouts, but we still want to be able to execute/simulate this.

@iksnagreb iksnagreb requested a review from jmitrevs February 13, 2026 18:06
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