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

Add general transpose for vivado/vitis #1124

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

calad0i
Copy link
Contributor

@calad0i calad0i commented Nov 13, 2024

Description

Add general N-dimensional transpose for vivado/vitis backend. Resource consumption validated to be unchanged for all 2/3d io_parallel Vivado/Vitis HLS (2020.1/2023.2), and 2d io_stream Vitis HLS.

For Vivado HLS there is a resource overhead for io_sream transpose 2d. Template overload is used to use the original impl for io_stream 2d.

Type of change

  • New feature (non-breaking change which adds functionality)

Tests

test/pytest/test_transpose_concat.py/test_highdim_permute

Checklist

  • I have read the guidelines for contributing.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have made corresponding changes to the documentation.
  • My changes generate no new warnings.
  • I have installed and run pre-commit on the files I edited or added.
  • I have added tests that prove my fix is effective or that my feature works.

@calad0i calad0i added the please test Trigger testing by creating local PR branch label Nov 13, 2024
@calad0i calad0i mentioned this pull request Nov 15, 2024
2 tasks
@jmitrevs
Copy link
Contributor

jmitrevs commented Jan 7, 2025

I would propose the following change with this PR since it's no longer needed:

diff --git a/hls4ml/model/optimizer/passes/convert_to_channels_last.py b/hls4ml/model/optimizer/passes/convert_to_channels_last.py
index 606f42e5..5b1a69f1 100644
--- a/hls4ml/model/optimizer/passes/convert_to_channels_last.py
+++ b/hls4ml/model/optimizer/passes/convert_to_channels_last.py
@@ -103,11 +103,6 @@ class ChannelsLastConverter(OptimizerPass):
                 input = previous_node.name
                 outshape = previous_node.get_output_variable().shape
 
-                if (model.config.config['IOType'] == 'io_stream') and len(outshape) == 3:
-                    raise Exception(
-                        'No 3D transpose available in io_stream, this model cannot be converted to channels-last'
-                    )
-
                 if len(outshape) == 2:
                     attributes = {'perm': [1, 0]}
                 else:

@jmitrevs jmitrevs added please test Trigger testing by creating local PR branch and removed please test Trigger testing by creating local PR branch labels Jan 7, 2025
transpose_config_template = """struct {config_name} {{
static const unsigned dims = {dims};
static const unsigned N = {N};
static const unsigned* const from_shape;
Copy link
Contributor

Choose a reason for hiding this comment

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

I assume you tried various things, and I know C++ can be kind of clunky for stuff like this, but is there an easier/less verbose way to initialize these arrays? Would std::arrays be more readable?

Copy link
Contributor Author

@calad0i calad0i Jan 8, 2025

Choose a reason for hiding this comment

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

This is due to that vivado/vitis cannot handle constexpr array indexing with "variables" (indices can be inferenced, but not literal, like an iterator index in a fixed-boundary for loop).

If we are to drop vivado hls support completely, this can be made constexpr and initialized with one-line, and recursive template unrolling will need to be used in the caller function to do the index mapping, which only works for vitis hls and takes forever on vivado hls. I did not try std::array, as I did not expect it to be more compatible than a constexpr raw array.

transpose_include_list = ['nnet_utils/nnet_array.h', 'nnet_utils/nnet_stream.h']

def permute_config_gen(name: str, shape: tuple[int, ...], perm: tuple[int, ...]):
new_shape = tuple(shape[i] for i in perm)
Copy link
Contributor

Choose a reason for hiding this comment

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

A comment or docstring would be useful to understand how this works.

@jmitrevs
Copy link
Contributor

jmitrevs commented Jan 8, 2025

This PR looks to be quite useful and I think should be quite rapidly merged, since it makes pytorch streaming models more parsable (after removing the no longer needed graceful failure, with this PR).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
please test Trigger testing by creating local PR branch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants