2022년 2월 26일 토요일

Build Tensorflow python wheel for Raspberry Pi OS 64bit

Machine learning packages like TensorFlow perform much better on a 64-bit OS than on a 32-bit OS.

If you are going to use TensorFlow on Raspberry Pi, make sure to run it on a 64-bit OS. 

In a previous article, I looked at how to cross-build the Raspberry Pi OS 64-bit version of TensorFlow Lite on your x86 PC and then install it on the Raspberry Pi. Since TensorFlow Lite can be installed not only on Raspberry Pi but also on Android devices using arm CPU, cross-build is often used. Isn't it too difficult to download and build the TensorFlow Lite source code on your Android smartphone? 

In this article, we will look at how to build a TensorFlow Python on Raspberry Pi OS 64-bit . To be honest, I tried to cross-build the TensorFlow package, but it failed due to several issues. 

For Raspberry Pi, 8GB model must be prepared. The reason is that the Basel build requires a lot of memory. If a build error occurs even when using 8GB of memory,

Increase memory using ZRAM

If an error occurs during the Basel build process during the following tasks despite using the 8GB model, increase the memory using zram. It is also faster than using a swap file. And since it reduces the IO of the SD card that occurs when using the swap file, it also helps the life of the SD card.

install zram tool

Since there is already a well-made installation script file, download it from git.

$ git clone https://github.com/StuartIanNaylor/zram-swap-config \
&& cd zram-swap-config
$ sudo ./install.sh


zram settings

Edit the /etc/zram-swap-config.conf file. The description of the item values is as follows.

  • MEM_FACTOR = Percentage of available ram to allocate to all zram swap devices which is divided equally by swap_devices number
  • DRIVE_FACTOR = Virtual uncompressed zram drive size estimate approx alg compression ratio
  • COMP_ALG lz4 is faster than lzo but some distro's show compile and operational difference and in use lzo depending on binary may be faster. Compression rates list below are minimums and generally far bigger in operation but dependent on content.
  • SWAP_DEVICES = number of indivial drives sharing memeory provided by MEM_FACTOR each device support multiple streams 1 large drive is generally better
  • SWAP_PRI = swap_priority for each drive 75 is a high order preference and should be well above other swap drives
  • PAGE_CLUSTER default page cluster is 3 which caches fetches in batches of 8 and helps with HDD paging, with zram mem 0 forces single page fetches This can help reduce latency and increase performance
  • SWAPPINESS default swappiness is 60 but with increased performance of zram swap 80 garners overall performance gain without excessive load Because zram uses compression load is created and even if minimal at intense load periods such as boot any extra load is unwanted Unfortunately there is no dynamic load balancing of swappiness as with zram in general operation SWAPINESS=100 will garner performance benefit If the overall load is reasonable at high load it will cause load to accumulate. If you check my repo there will also be a simple dynamic load based SWAPPINESS governor that will get of the hurdle of a static compromise on swappiness

<from https://github.com/StuartIanNaylor/zram-swap-config>


The following is an example of setting in Raspberry Pi 4B with 8GB memory. Zram is applied to 40% of the memory.

root@raspberrypi:~# cat /etc/zram-swap-config.conf
MEM_FACTOR=40
DRIVE_FACTOR=300
COMP_ALG=lz4
SWAP_DEVICES=1
SWAP_PRI=75
PAGE_CLUSTER=0
SWAPPINESS=90


pi@raspberrypi:~ $ sudo cat /proc/swaps
Filename                                Type            Size            Used            Priority
/dev/zram0                              partition       9600608         0               75
/var/swap                               file            102396          0               -2
pi@raspberrypi:~ $ free -m
               total        used        free      shared  buff/cache   available
Mem:            7813         358        7012          36         441        7306
Swap:           9475           0        9475

Change the /var/swap swap file to use only zram. This operation is performed as the root user (you can omit this operation).


pi@raspberrypi:~ $ sudo su -

SSH is enabled and the default password for the 'pi' user has not been changed.
This is a security risk - please login as the 'pi' user and type 'passwd' to set a new password.

root@raspberrypi:~#
root@raspberrypi:~#
root@raspberrypi:~# dphys-swapfile swapoff \
&& dphys-swapfile uninstall \
&& update-rc.d dphys-swapfile disable
root@raspberrypi:~#
root@raspberrypi:~#
root@raspberrypi:~#
root@raspberrypi:~# free -m
               total        used        free      shared  buff/cache   available
Mem:            7813         363        7004          36         445        7302
Swap:           9375           0        9375

Reboot for zram changes to take effect.


Install required packages to build tensorflow

For reference, the build work was carried out on the Raspberry Pi OS 64-bit Bullseye Desktop version.

First, install the packages required for the build task.

apt-get update
apt-get install -y  \
        build-essential \
        curl \
        git \
        libcurl3-dev \
        libfreetype6-dev \
        libhdf5-serial-dev \
        libzmq3-dev \
        pkg-config \
        rsync \
        software-properties-common \
        sudo \
        unzip \
        zip \
        zlib1g-dev 
apt-get install -y  openjdk-11-jdk \
        openjdk-11-jre-headless 
apt-get install -y  python3-pip

python3 -m pip --no-cache-dir install --upgrade \
    "pip<20.3" \
    setuptools

apt-get install -y \
    python3-dev \
    virtualenv \
    swig \
    gfortran \
    libblas-dev \
    liblapack-dev


python3 -m pip --no-cache-dir install \
    Pillow \
    keras_preprocessing \
    h5py \
    matplotlib \
    mock \
    scipy \
    sklearn \
    pandas \
    portpicker \
    enum34


And install Basel.

mkdir bazel
cd bazel
curl -fSsL -O https://github.com/bazelbuild/bazel/releases/download/4.2.1/bazel-4.2.1-dist.zip
unzip bazel-4.2.1-dist.zip
bash ./compile.sh
cp output/bazel /usr/local/bin/

If Basel is installed properly, you can check as follows.

pi@raspberrypi:~/src/bazel $ bazel --version
bazel 4.2.1- (@non-git)


Copy the TensorFlow source code.

pi@raspberrypi64:~ $ cd src
pi@raspberrypi64:~/src $git clone -b v2.8.0 https://github.com/tensorflow/tensorflow.git
cd tensorflow


It's time to build the python wheel

The following command takes more than 10 hours. Therefore, please avoid working on remote ssh if possible. When the ssh connection is disconnected, the build process is terminated.

pi@raspberrypi:~/src/tensorflow $ sudo bazel build \
--config=monolithic \
--config=noaws \
--config=nohdfs \
--config=nonccl \
--config=v2 \
--define=tflite_pip_with_flex=true \
--define=tflite_with_xnnpack=true \
--ui_actions_shown=64 \
//tensorflow/tools/pip_package:build_pip_package


The build ended after about 10 hours.

......
......
Target //tensorflow/tools/pip_package:build_pip_package up-to-date:
  bazel-bin/tensorflow/tools/pip_package/build_pip_package
INFO: Elapsed time: 53061.319s, Critical Path: 3604.28s
INFO: 11853 processes: 1175 internal, 10678 local.
INFO: Build completed successfully, 11853 total actions


Finally, build the TensorFlow Python wheel.

pi@raspberrypi:~/src/tensorflow $ ./tensorflow/tools/pip_package/build_pip_package.sh /tmp/tensorflow_pkg
/home/pi/src/tensorflow
/tmp/tmp.wiZjwBgJfY/tensorflow/include /home/pi/src/tensorflow
/home/pi/src/tensorflow
Sat 26 Feb 14:27:09 KST 2022 : === Building wheel
warning: no files found matching 'README'
warning: no files found matching '*.pyd' under directory '*'
warning: no files found matching '*.pyi' under directory '*'
warning: no files found matching '*.pd' under directory '*'
warning: no files found matching '*.so.[0-9]' under directory '*'
warning: no files found matching '*.dylib' under directory '*'
warning: no files found matching '*.dll' under directory '*'
warning: no files found matching '*.lib' under directory '*'
warning: no files found matching '*.csv' under directory '*'
warning: no files found matching '*.h' under directory 'tensorflow/include/tensorflow'
warning: no files found matching '*.proto' under directory 'tensorflow/include/tensorflow'
warning: no files found matching '*' under directory 'tensorflow/include/third_party'
/usr/local/lib/python3.9/dist-packages/setuptools/command/install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
  warnings.warn(
Sat 26 Feb 14:31:58 KST 2022 : === Output wheel file is in: /tmp/tensorflow_pkg

You can see the message that the tensorflow python wheel has been created in the tmp/tensorflow_pkg directory.

pi@raspberrypi:~/src/tensorflow $ ls -al /tmp/tensorflow_pkg/
total 279968
drwxr-xr-x   2 root root      4096 Feb 26 14:31 .
drwxrwxrwt 735 root root     36864 Feb 26 14:32 ..
-rw-r--r--   1 root root 286646178 Feb 26 14:31 tensorflow-2.8.0-cp39-cp39-linux_aarch64.whl


The reason the Python version of wheel is 3.9 is because the Python version installed on the Raspberry Pi OS 64-bit Bullseye version is 3.9. If you want to make a different version of Python wheel such as 3.8, install Python 3.8 and connect the python3 symbolic link in the /usr/bin directory to python3.8.

pi@raspberrypi:~/src/tensorflow $ ls -al /usr/bin/python3
lrwxrwxrwx 1 root root 9 Apr  5  2021 /usr/bin/python3 -> python3.9


Install the Tensorflow wheel 

To install the wheel file you just built, you must first install the packages required to use TensorFlow.

$ sudo apt-get install -y libhdf5-dev libc-ares-dev libeigen3-dev gcc gfortran libgfortran5 \
                          libatlas3-base libatlas-base-dev libopenblas-dev libopenblas-base libblas-dev \
                          liblapack-dev cython3 libatlas-base-dev openmpi-bin libopenmpi-dev
$ sudo pip3 install pip --upgrade
$ sudo pip3 install keras_applications==1.0.8 --no-deps
$ sudo pip3 install keras_preprocessing==1.1.0 --no-deps
$ sudo pip3 install h5py==3.1.0 
$ sudo pip3 install pybind11
$ pip3 install -U --user six wheel mock


It's time to install the python wheel

Finally, it's time to install the Python TensorFlow package.

pi@raspberrypi:~/src/tensorflow $ pip3 install /tmp/tensorflow_pkg/tensorflow-2.8.0-cp39-cp39-linux_aarch64.whl 

......

Successfully installed absl-py-1.0.0 astunparse-1.6.3 cachetools-5.0.0 flatbuffers-20181003210633 gast-0.5.3 google-auth-2.6.0 google-auth-oauthlib-0.4.6 google-pasta-0.2.0 grpcio-1.44.0 importlib-metadata-4.11.1 keras-2.8.0 keras-preprocessing-1.1.2 libclang-13.0.0 markdown-3.3.6 opt-einsum-3.3.0 protobuf-3.19.4 pyasn1-0.4.8 pyasn1-modules-0.2.8 rsa-4.8 tensorboard-2.8.0 tensorboard-data-server-0.6.1 tensorboard-plugin-wit-1.8.1 tensorflow-2.8.0 tensorflow-io-gcs-filesystem-0.24.0 termcolor-1.1.0 tf-estimator-nightly-2.8.0.dev2021122109


Let's check if TensorFlow is installed properly. You should not test in the tensorflow source directory. Because the tensorflow directory exists in this directory, an error occurs in import tensorflow.

pi@raspberrypi:~/src/tensorflow $ cd ..
pi@raspberrypi:~/src $ python3
Python 3.9.2 (default, Feb 28 2021, 17:03:44) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow as tf
>>> tf.__version__
'2.8.0'


Wrapping up

On Github, many developers have already created and provided a Python wheel for Raspberry Pi OS 64-bit. You can download the wheel they made and use it, but it's also a good job to build a TensorFlow package yourself that matches the Python version and OS version you want.


댓글 없음:

댓글 쓰기