larq / compute-engine

Highly optimized inference engine for Binarized Neural Networks
https://docs.larq.dev/compute-engine
Apache License 2.0
240 stars 33 forks source link

⬆️ TensorFlow@2.10 #749

Closed lgeiger closed 1 year ago

lgeiger commented 1 year ago

What do these changes do?

This PR upgrade our TensorFlow dependency to 2.10

How Has This Been Tested?

CI

Benchmark Results

TODO

Related Issue Number

Closes #748

lgeiger commented 1 year ago

Looks like on ARM32 we are still running into https://github.com/tensorflow/tensorflow/issues/57364. Locally I ran into another build issue when trying to run the end2end tests, but maybe that's not a problem on CI.

lgeiger commented 1 year ago

Unfortunately this update introduces a problem related to flatbuffer version mismatches. TensorFlow 2.10 relies on flatbuffers==2.x whereas TensorFlow 2.9 and earlier relied on flatbuffer==1.12.

We use the generated flatbuffer schema for removing unneeded quantize and dequantize ops at the end of the network here. This means if we naively upgrade to TF 2.10 LCE wouldn't be compatible with any user installed TensorFlow version anymore. E.g. when running with TF 2.9 which requires flatbuffer==1.12 we'd get the following error:

larq_compute_engine/tests/end2end_test.py:24: in convert_keras_model_as_saved_model
    return convert_saved_model(saved_model_dir, **kwargs)
larq_compute_engine/mlir/python/converter.py:163: in convert_saved_model
    tflite_buffer = modify_integer_quantized_model_io_type(
larq_compute_engine/mlir/python/util.py:227: in modify_integer_quantized_model_io_type
    return _convert_model_from_object_to_bytearray(model)
larq_compute_engine/mlir/python/util.py:52: in _convert_model_from_object_to_bytearray
    model_offset = model_object.Pack(builder)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <larq_compute_engine.mlir.python.tflite_schema.ModelT object at 0x7f73d407da30>
builder = <flatbuffers.builder.Builder object at 0x7f737c723970>

    def Pack(self, builder):
        if self.operatorCodes is not None:
            operatorCodeslist = []
            for i in range(len(self.operatorCodes)):
                operatorCodeslist.append(self.operatorCodes[i].Pack(builder))
            ModelStartOperatorCodesVector(builder, len(self.operatorCodes))
            for i in reversed(range(len(self.operatorCodes))):
                builder.PrependUOffsetTRelative(operatorCodeslist[i])
>           operatorCodes = builder.EndVector()
E           TypeError: EndVector() missing 1 required positional argument: 'vectorNumElems'

larq_compute_engine/mlir/python/tflite_schema.py:11853: TypeError

From the top of my head I can think of the following solutions to this problem:

  1. Require TensorFlow 2.10 or newer starting with the next version of LCE or pin LCE releases to a specific version of TensorFlow. This probably is the easiest solutions but not the most user friendly one.
  2. Manually generate a Flatbuffer v1 and v2 version of the schema and chose which one to use at runtime. Not sure how much work it would be to maintain this over time.
  3. Try to not rely on the schema at all on use modify_integer_quantized_model_io_type from the TensorFlow pip package. This likely also removes support for older TensorFlow versions and probably forces us to rely on TensorFlow internal non-stable APIs
lgeiger commented 1 year ago

It looks like we might not even need to restrict the supported version of TensorFlow as long as flatbuffers==2.0 is installed.
E.g. TF 2.3 and older didn't even rely on the flatbuffers pip package so we might be OK just requiring flatbuffers==2.0 as a dependency. For me locally the end2end tests pass with tensorflow==2.9 and flatbuffers==2.0.

Tombana commented 1 year ago

We could also print a runtime warning if version(tensorflow) < 2.10 without aborting completely.