hls4ml
hls4ml copied to clipboard
Automatic precision inference
Description
This introduces the ability to specify auto
as a precision string, that implies hls4ml should infer the precision in some way. This is not exposed by default via the config_from...
functions for now. The goal is to have the framework for inferring types in some ways within hls4ml (e.g., QONNX parser) before fully exposing it to users. An initial inference of precision has been added via the infer_precision_types
optimizer, based on previous attempts by various people. It's not advanced in any way. During testing, I encountered some issues with SeparableConv1D
templates which I fixed.
Type of change
- [x] Bug fix (non-breaking change that fixes an issue) - Only related to the
SeparableConv1D
issue - [x] New feature (non-breaking change which adds functionality)
Tests
There are new tests in test_auto_precision.py
that cover the few use cases.
Checklist
- [x] I have read the guidelines for contributing.
- [x] I have commented my code, particularly in hard-to-understand areas.
- [x] I have made corresponding changes to the documentation.
- [x] My changes generate no new warnings.
- [x] I have installed and run
pre-commit
on the files I edited or added. - [x] I have added tests that prove my fix is effective or that my feature works.
Clang doesn't seem to like this
(fastml39) Jovans-Mac:hls4mlprj_auto_conv2d_Quartus_io_stream jmitrevs$ bash build_lib.sh
In file included from firmware/myproject.cpp:2:
In file included from firmware/parameters.h:11:
firmware/nnet_utils/nnet_conv2d_stream.h:135:5: error: no matching function for call to 'shift_line_buffer_2d'
nnet::shift_line_buffer_2d<data_T, CONFIG_T>(in_elem, line_buffer, shift_buffer);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
firmware/nnet_utils/nnet_conv2d_stream.h:199:13: note: in instantiation of function template specialization 'nnet::compute_output_buffer_2d<nnet::array<ac_fixed<16, 6>, 4>, nnet::array<ac_fixed<35, 15>, 4>, config8>' requested here
compute_output_buffer_2d<data_T, res_T, CONFIG_T>(padds, res, line_buffer, kernel_window, weights, biases);
^
firmware/myproject.cpp:93:11: note: in instantiation of function template specialization 'nnet::conv_2d_cl<nnet::array<ac_fixed<16, 6>, 4>, nnet::array<ac_fixed<35, 15>, 4>, config8>' requested here
nnet::conv_2d_cl<layer7_t, last_layer_result_t, config8>(layer7_out, layer8_out, w8, b8);
^
firmware/nnet_utils/nnet_conv2d_stream.h:69:6: note: candidate template ignored: substitution failure [with data_T = nnet::array<ac_fixed<16, 6>, 4>, CONFIG_T = config8]: zero-length arrays are not permitted in C++
void shift_line_buffer_2d(
^
1 error generated.
clang: error: no such file or directory: 'myproject.o'
while g++ compiles it just fine.
The issue seems to be that this:
model.add(Conv2D(4, kernel_size=(1, 1), activation='relu', name='last_layer')) # Will become PointwiseConv2D
doesn't actually become PointwiseConv2D for Quartus. The bug it uncovered seems tangential to this PR; nevertheless, we need to fix it, either as part of this PR or separately.
is this the same issue that was observed in #878?
is this the same issue that was observed in #878?
I believe so. If you have a filter of size 1, then things like line_buffer[CONFIG_T::filt_height - 1][CONFIG_T::n_chan]
wind up with zero-size arrays.
I made vloncar #53 into your branch with changes for dense and standard convolution. Let me know what you think. If you like the way I made this, I can also add signed/unsigned support to the other precision propagations (like merge, bn, sepconv) either in that PR or a different one.