tum-ei-eda / mlonmcu

Tool for the deployment and analysis of TinyML applications on TFLM and MicroTVM backends
Apache License 2.0
29 stars 12 forks source link

Refactor Environment Configuration #33

Open PhilippvK opened 2 years ago

PhilippvK commented 2 years ago

I came up with a new sturcture for the environment.yml files (See first comment) and would like to discuss it in this context.

PhilippvK commented 2 years ago

This would be my idea, with the the following major changes:

---
home: "{{ home_dir }}"
logging:
  ... # No changes here
paths:
  ... # No changes here
repos:
  ... # No changes here
frameworks:
  supported:
    - tflm
    - tvm
backend:
  supported:
    # - tflmc
    - tflmi
    - tvmaot
    - tvmrt
    - tvmcg
  use:
    - tvmaot
frontends:
  supported:
    - tflite
    # - packed
    # - onnx
  use:
    - tflite
platforms:
  supported:
    - mlif
    - espidf
  use:
    - mlif
    - espidf
targets:
  supported:
    - etiss_pulpino  # mlif
    - spike  # mlif
    - ovpsim  # mlif
    - host_x86  # mlif
    - corstone300  # mlif
    # espidf targets do not need to be listed here
  use:
    - etiss_pulpino
features:
  supported:
    - gdbserver
    - etissdbg
    - vext
    - trace
    - disable_legalize
    - debug_arena
    - unpacked_api
    - usmp
    - cmsisnn
    - muriscvnn
    # - cmsisnnbyoc
    # - packing
    # - packed
    # - ethosu
  use: []
postprocesses:
  supported:
    - detailed_cycles
    - average_cycles
    - filter_cols
    - features2cols
    - config2cols
    - bytes2kb
    - visualize
  use: []
vars:
  # tvm.make_tool: "ninja"
  llvm.version: "11.1.0"
  runs_per_stage: true
  riscv_gcc.dl_url: "https://syncandshare.lrz.de/dl/fi89JQF89pEiWwP6aQh7cM4H/rv32gcv.tar.xz"
PhilippvK commented 2 years ago

@rafzi What do your thin about this proposal?

PhilippvK commented 2 years ago

One this which is probably missing right now are "wildcards", which would make it easier to just enable all supported components without copying the above list from supported: to use: and to get rid of the need to keep them in sync.

Here are two possible approaches:

PhilippvK commented 2 years ago

Another thing we need to clarify is, how we handle platforms whose targets are resolved dynamically instead of being registered manually. Do the need need to be listed in the environment file as well?

rafzi commented 2 years ago

This change looks good to me.

What do you think about adding a value to components for specifying that they should be used by default?

backend:
  supported:
    - tflmi
    - tvmaot: default
    - tvmrt
    - tvmcg
PhilippvK commented 2 years ago

What do you think about adding a value to components for specifying that they should be used by default?

backend:
  supported:
    - tflmi
    - tvmaot: default
    - tvmrt
    - tvmcg

i think this wouldn’t be valid yaml syntax. And if we would do the following it would look more confusing:

backend:
  supported:
    tflmi:
    tvmaot: default
    tvmrt:
    tvmcg:
PhilippvK commented 2 years ago

In addition there will be scenarios where a value used in use: does not necessarily have to be in supported:.

rafzi commented 2 years ago

I was not sure about the syntax either, but a couple online validators told me that this would be fine. It might be a bit confusing in the parsing logic, but that seems tolerable.

Can you elaborate on the case where "use" might contain values that are not in "supported"? It is sufficiently rare that we could add a special value like "default_but_not_supported_otherwise"?

That structure seems more intuitive to me.

PhilippvK commented 2 years ago

@rafzi

Can you elaborate on the case where "use" might contain values that are not in "supported"? It is sufficiently rare that we could add a special value like "default_but_not_supported_otherwise"?

There are two use-cases:

  1. While the targets managed by MLonMCU (currently part of the platform mlif) need to be explicitly registered in the codebase, this is not the case for other platforms. I.e. during the installation of ESP-IDF, a user can choose which target-families should be supported (./install.sh esp32,esp32c3), MLonMCU would then determine the set of supported targets at runtime (using idf.py list-targets) so they do not need to be enabled/listed by the user. While we could require them to provide a list of usable targets, it is not necessary and would therefore be quite useless.

  2. In theory (never tested it tbh) MLonMCU should provide an extension interface to integrate new Backends, Features etc. at runtime via Python. Those features dependencies would not be handled by MLonMCU, so there is not need to add them to supported:/installed:. (We could fore a user to add them there as well but this would be a step more work, e.g. either adding it to the environment.yml file beforehand or executing something like context.environment.backend.supported.append("..."))

PhilippvK commented 2 years ago

For me the following scheme would be completely fine:

backend:
  supported: &supported_backends
    - tflmi
    - tvmaot
    - tvmrt
    - tvmcg
  use: *supported_backends

Do you habe anything special against it?

rafzi commented 2 years ago

Thanks for elaborating. The naming "install" instead of "supported" would make more sense to me. I don't see a problem when there is nothing to install. The user generally does not know this, so they will list it anyways if they intend to use it and they did not install it themselves.

I don't like your proposed syntax, because it is a lesser known yaml feature and would in typical cases be more verbose and cause duplication. I'd typically only set one backend/frontend/target as default and set some subset of features as default.

To avoid the strange case of

install:
  - abc
  - xyz: default_noinstall

we could instead allow:

install:
  - abc
default: # or more explicit: "default_preinstalled"
  - xyz
PhilippvK commented 2 years ago

@rafzi Unfortunately I do not really understand the usage of default_preinstalled. I do not get how we would use it in-practice...

I'd typically only set one backend/frontend/target as default

It makes sense to have multiple default Platforms as they can be seen as a registry for targets, so if a target name is provided e.g. on the command line, the default platforms will be "ask" if the provide support for the given target name, which has the big advantage that the user does not have to define --platform mlif --platform espidf on the command line to use targets from different platforms in a single session. (The order of these platforms is important because the same target_name might be supported by multiple platforms) Frameworks would ideally also work like this. Each framework (or "Backend registry") provides a number of backends which will be used to resolve the backends for a given backend name. (However it is unlikely that there would be an overlap in backend names)

PhilippvK commented 2 years ago

What we could for example do is to allow grouping e.g backens when listing them in supported::

backend:
  supported:
    tflm: &tflm_backends
      - tflmi
    tvm: &tvm_backends
      - tvmaot
      - tvmrt
      - tvmcg
  default: *tvm_backends  # Use all tvm backens
  # or use only a single backend
  default:
    - tvmaot

However, I agree that the verbosity would then increase again if we would like to add another default value as we can not merge the groups intuitively.

PhilippvK commented 1 year ago

I will start implementing this myself soon to allow a followup for #51 getting rid of all hardcoded component names.