|  | # "Variables and State" sample | 
|  |  | 
|  | This sample shows how to | 
|  |  | 
|  | 1. Create a TensorFlow program that tracks state with an internal variable | 
|  | 2. Import that program into IREE's compiler | 
|  | 3. Compile that program to an IREE VM bytecode module | 
|  | 4. Load the compiled program using IREE's high level runtime C API | 
|  | 5. Call exported functions on the loaded program to interact with the internal | 
|  | variable | 
|  |  | 
|  | Steps 1-3 are performed in Python via the | 
|  | [`variables_and_state.ipynb`](./variables_and_state.ipynb) | 
|  | [Colab](https://research.google.com/colaboratory/) notebook: | 
|  |  | 
|  | [](https://colab.research.google.com/github/iree-org/iree/blob/main/samples/variables_and_state/variables_and_state.ipynb) | 
|  |  | 
|  | Steps 4-5 are in [`main.c`](./main.c) | 
|  |  | 
|  | The program used to demonstrate tracks a single integer counter and provides | 
|  | a few functions for interacting with it: | 
|  |  | 
|  | ```python | 
|  | class CounterModule(tf.Module): | 
|  | def __init__(self): | 
|  | super().__init__() | 
|  | self.counter = tf.Variable(0) | 
|  |  | 
|  | @tf.function(input_signature=[]) | 
|  | def get_value(self): | 
|  | return self.counter | 
|  |  | 
|  | @tf.function(input_signature=[tf.TensorSpec([], tf.int32)]) | 
|  | def set_value(self, new_value): | 
|  | self.counter.assign(new_value) | 
|  |  | 
|  | @tf.function(input_signature=[tf.TensorSpec([], tf.int32)]) | 
|  | def add_to_value(self, x): | 
|  | self.counter.assign(self.counter + x) | 
|  |  | 
|  | @tf.function(input_signature=[]) | 
|  | def reset_value(self): | 
|  | self.set_value(0) | 
|  | ``` | 
|  |  | 
|  | ## Background | 
|  |  | 
|  | Just like in other programming models, _variables_ in this context are used to | 
|  | represent some persistent state that programs may manipulate. See TensorFlow's | 
|  | [Introduction to Variables](https://www.tensorflow.org/guide/variable) for | 
|  | more information on using variables in TensorFlow. | 
|  |  | 
|  | Mutable variables and internal program state are modeled natively in IREE along | 
|  | with the rest of a program's executable code and data. Variables are not given | 
|  | special treatment - program authors must define explicit exported functions for | 
|  | interacting with them and then invoke these functions as they would any other | 
|  | functions in the compiled programs. | 
|  |  | 
|  | ## Instructions | 
|  |  | 
|  | 1. Run the Colab notebook and download the `counter.mlir` and | 
|  | `counter_vmvx.vmfb` files it generates | 
|  |  | 
|  | 2. Build the `iree_samples_variables_and_state` CMake target (see | 
|  | [here](https://iree.dev/building-from-source/getting-started/) | 
|  | for general instructions on building using CMake) | 
|  |  | 
|  | ``` | 
|  | cmake -B ../iree-build/ -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo . | 
|  | cmake --build ../iree-build/ --target iree_samples_variables_and_state | 
|  | ``` | 
|  |  | 
|  | 3. Run the sample binary: | 
|  |  | 
|  | ``` | 
|  | ../iree-build/samples/variables_and_state/variables-and-state \ | 
|  | /path/to/counter_vmvx.vmfb local-task | 
|  | ``` | 
|  |  | 
|  | ### Changing compilation options | 
|  |  | 
|  | The provided Colab notebook imports the TensorFlow program into MLIR and then | 
|  | compiles it further to an IREE VM bytecode module for IREE's reference CPU | 
|  | executable format named "VMVX". To use a different executable format or backend, | 
|  | set compilation options, or include source code changes to the compiler, you can | 
|  | compile the imported MLIR file using IREE's tools on your own machine. | 
|  |  | 
|  | For example, to use IREE's `cpu` target, which is optimized for CPU execution | 
|  | using LLVM, refer to the | 
|  | [documentation](https://iree.dev/guides/deployment-configurations/cpu/) | 
|  | and compile the imported `counter.mlir` file using `iree-compile`: | 
|  |  | 
|  | ``` | 
|  | ../iree-build/tools/iree-compile \ | 
|  | --iree-hal-target-backends=llvm-cpu \ | 
|  | --iree-input-type=stablehlo \ | 
|  | counter.mlir -o counter_cpu.vmfb | 
|  | ``` | 
|  |  | 
|  | then run the program with that new VM bytecode module: | 
|  |  | 
|  | ``` | 
|  | ../iree-build/samples/variables_and_state/variables-and-state \ | 
|  | /path/to/counter_cpu.vmfb local-task | 
|  | ``` |