Skip to content

Commit

Permalink
added check for conv implementation (fastmachinelearning#1155)
Browse files Browse the repository at this point in the history
* added check for conv implementation

* Updated node attr key and made case insensitive

* Updated Conv1D and Conv2d optimizer match and default linebuffer values

* format

* Add check for io_parallel and update tests

* Update optimizer match and default values for linebuffer impl.

* format

* Refactor: Replace casefold with lower and use setdefault

* Minor refactor

---------

Co-authored-by: Jovan Mitrevski <[email protected]>
  • Loading branch information
jicampos and jmitrevs authored Feb 4, 2025
1 parent c408145 commit 1ad1ad9
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 62 deletions.
57 changes: 26 additions & 31 deletions hls4ml/backends/catapult/passes/conv_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ class GenerateConvStreamingInstructions(OptimizerPass):
'''Generates the instructions for streaming implementation of CNNs'''

def match(self, node):
return isinstance(node, (Conv1D, SeparableConv1D, Conv2D, SeparableConv2D))
is_match = (
isinstance(node, (Conv1D, SeparableConv1D, Conv2D, SeparableConv2D))
and node.model.config.get_config_value('IOType').lower() == 'io_stream'
and node.get_attr('implementation').lower() == 'encoded'
)
return is_match

def transform(self, model, node):
node_class = node.__class__.__name__
Expand All @@ -18,35 +23,25 @@ def transform(self, model, node):
raise Exception(f'Cannot generate instructions for node {node.name} ({node_class})')

def _generate_1d_instructions(self, node):
if node.model.config.get_config_value('IOType') == 'io_stream':
min_w, instructions = node.model.config.backend.compute_conv1d_instructions(
node.get_input_variable().shape[0],
node.get_input_variable().shape[1],
node.get_attr('filt_width'),
node.get_attr('stride_width'),
)
instructions_str = ','.join(str(i) for i in instructions)
node.set_attr('min_width', min_w)
node.set_attr('instructions', instructions_str)
else:
# these are unused; just put dummy values
node.set_attr('min_width', node.get_attr('in_width'))
node.set_attr('instructions', '0')
min_w, instructions = node.model.config.backend.compute_conv1d_instructions(
node.get_input_variable().shape[0],
node.get_input_variable().shape[1],
node.get_attr('filt_width'),
node.get_attr('stride_width'),
)
instructions_str = ','.join(str(i) for i in instructions)
node.set_attr('min_width', min_w)
node.set_attr('instructions', instructions_str)

def _generate_2d_instructions(self, node):
if node.model.config.get_config_value('IOType') == 'io_stream':
min_h, min_w, instructions = node.model.config.backend.compute_conv2d_instructions(
node.get_input_variable().shape[0],
node.get_input_variable().shape[1],
node.get_input_variable().shape[2],
node.get_attr('filt_height'),
node.get_attr('stride_height'),
)
instructions_str = ','.join(str(i) for i in instructions)
node.set_attr('min_height', min_h)
node.set_attr('min_width', min_w)
node.set_attr('instructions', instructions_str)
else:
node.set_attr('min_height', node.get_attr('in_height'))
node.set_attr('min_width', node.get_attr('in_width'))
node.set_attr('instructions', '0')
min_h, min_w, instructions = node.model.config.backend.compute_conv2d_instructions(
node.get_input_variable().shape[0],
node.get_input_variable().shape[1],
node.get_input_variable().shape[2],
node.get_attr('filt_height'),
node.get_attr('stride_height'),
)
instructions_str = ','.join(str(i) for i in instructions)
node.set_attr('min_height', min_h)
node.set_attr('min_width', min_w)
node.set_attr('instructions', instructions_str)
7 changes: 7 additions & 0 deletions hls4ml/backends/catapult/passes/convolution_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ def format(self, node):
else:
params['fill_fn'] = 'FillConv1DBuffer'

params['min_width'] = node.get_attr('min_width', node.get_attr('in_width'))
params['instructions'] = node.get_attr('instructions', '0')

conv_config = self.template.format(**params)

mult_params = self._default_config_params(node)
Expand Down Expand Up @@ -210,6 +213,10 @@ def format(self, node):
else:
params['fill_fn'] = 'FillConv2DBuffer'

params['min_height'] = node.get_attr('min_height', node.get_attr('in_height'))
params['min_width'] = node.get_attr('min_width', node.get_attr('in_width'))
params['instructions'] = node.get_attr('instructions', '0')

conv_config = self.template.format(**params)

mult_params = self._default_config_params(node)
Expand Down
57 changes: 26 additions & 31 deletions hls4ml/backends/vivado/passes/conv_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ class GenerateConvStreamingInstructions(OptimizerPass):
'''Generates the instructions for streaming implementation of CNNs'''

def match(self, node):
return isinstance(node, (Conv1D, SeparableConv1D, Conv2D, SeparableConv2D))
is_match = (
isinstance(node, (Conv1D, SeparableConv1D, Conv2D, SeparableConv2D))
and node.model.config.get_config_value('IOType').lower() == 'io_stream'
and node.get_attr('implementation').lower() == 'encoded'
)
return is_match

def transform(self, model, node):
node_class = node.__class__.__name__
Expand All @@ -18,35 +23,25 @@ def transform(self, model, node):
raise Exception(f'Cannot generate instructions for node {node.name} ({node_class})')

def _generate_1d_instructions(self, node):
if node.model.config.get_config_value('IOType') == 'io_stream':
min_w, instructions = node.model.config.backend.compute_conv1d_instructions(
node.get_input_variable().shape[0],
node.get_input_variable().shape[1],
node.get_attr('filt_width'),
node.get_attr('stride_width'),
)
instructions_str = ','.join(str(i) for i in instructions)
node.set_attr('min_width', min_w)
node.set_attr('instructions', instructions_str)
else:
# these are unused; just put dummy values
node.set_attr('min_width', node.get_attr('in_width'))
node.set_attr('instructions', '0')
min_w, instructions = node.model.config.backend.compute_conv1d_instructions(
node.get_input_variable().shape[0],
node.get_input_variable().shape[1],
node.get_attr('filt_width'),
node.get_attr('stride_width'),
)
instructions_str = ','.join(str(i) for i in instructions)
node.set_attr('min_width', min_w)
node.set_attr('instructions', instructions_str)

def _generate_2d_instructions(self, node):
if node.model.config.get_config_value('IOType') == 'io_stream':
min_h, min_w, instructions = node.model.config.backend.compute_conv2d_instructions(
node.get_input_variable().shape[0],
node.get_input_variable().shape[1],
node.get_input_variable().shape[2],
node.get_attr('filt_height'),
node.get_attr('stride_height'),
)
instructions_str = ','.join(str(i) for i in instructions)
node.set_attr('min_height', min_h)
node.set_attr('min_width', min_w)
node.set_attr('instructions', instructions_str)
else:
node.set_attr('min_height', node.get_attr('in_height'))
node.set_attr('min_width', node.get_attr('in_width'))
node.set_attr('instructions', '0')
min_h, min_w, instructions = node.model.config.backend.compute_conv2d_instructions(
node.get_input_variable().shape[0],
node.get_input_variable().shape[1],
node.get_input_variable().shape[2],
node.get_attr('filt_height'),
node.get_attr('stride_height'),
)
instructions_str = ','.join(str(i) for i in instructions)
node.set_attr('min_height', min_h)
node.set_attr('min_width', min_w)
node.set_attr('instructions', instructions_str)
7 changes: 7 additions & 0 deletions hls4ml/backends/vivado/passes/convolution_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ def format(self, node):
else:
params['conv_fn'] = 'Conv1DResource'

params['min_width'] = node.get_attr('min_width', node.get_attr('in_width'))
params['instructions'] = node.get_attr('instructions', '0')

conv_config = self.template.format(**params)

mult_params = self._default_config_params(node)
Expand Down Expand Up @@ -239,6 +242,10 @@ def format(self, node):
else:
params['fill_fn'] = 'FillConv2DBuffer'

params['min_height'] = node.get_attr('min_height', node.get_attr('in_height'))
params['min_width'] = node.get_attr('min_width', node.get_attr('in_width'))
params['instructions'] = node.get_attr('instructions', '0')

conv_config = self.template.format(**params)

mult_params = self._default_config_params(node)
Expand Down
4 changes: 4 additions & 0 deletions test/pytest/test_conv1d_narrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ def model():
('io_stream', 'resource', 'Encoded'),
('io_stream', 'latency', 'LineBuffer'),
('io_stream', 'resource', 'LineBuffer'),
('io_parallel', 'resource', 'Encoded'),
('io_parallel', 'latency', 'Encoded'),
('io_parallel', 'resource', 'LineBuffer'),
('io_parallel', 'latency', 'LineBuffer'),
],
)
@pytest.mark.filterwarnings("error")
Expand Down
4 changes: 4 additions & 0 deletions test/pytest/test_conv2d_narrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ def model():
('io_stream', 'resource', 'Encoded'),
('io_stream', 'latency', 'LineBuffer'),
('io_stream', 'resource', 'LineBuffer'),
('io_parallel', 'resource', 'Encoded'),
('io_parallel', 'latency', 'Encoded'),
('io_parallel', 'resource', 'LineBuffer'),
('io_parallel', 'latency', 'LineBuffer'),
],
)
@pytest.mark.filterwarnings("error")
Expand Down

0 comments on commit 1ad1ad9

Please sign in to comment.