DockerでRISC-V Vector拡張へ入門 (Dockerfile作成編)

# はじめに
RISC-VのVector拡張(v0.10対応)のプログラム環境の構築をDockerで行ってみました．以下のもののインストールとビルドを行ったリポジトリを作成しました.

- riscv-gnu-toolchain
- riscv-isa-sim(spike)
- riscv-pk

https://hub.docker.com/r/a163236/rvv_toolchain

イメージサイズは900MB程度に収めたので，自分で一から環境構築をするよりいいと思います．通常これらのインストールとビルドを新しく仮想環境を作成してローカル環境でやると，17GB~程度使用されるのと時間もかかるので，RISC-VのVector拡張を少し試してみたいといった人には良いのではないかと思います．

注) 本記事の内容について，私も詳しくはないので色々間違っていたらすいません．:bow_tone1:

# 概要

RISC-VではV拡張(vector extension)の仕様が固まりつつあるようで，現在のstableなバージョンはv0.10です．

https://github.com/riscv/riscv-v-spec/releases/tag/v0.10

またsifiveによるとllvmとgccでRISC-V Vector Intrinsicsをサポートする新しいAPIを作成したらしいです．

https://www.sifive.com/blog/risc-v-vector-extension-intrinsic-support

APIのGitHubはこちらです．

https://github.com/riscv/rvv-intrinsic-doc


また，RVVの組み込み関数(intrinsics)をriscv-gnu-toolchainに統合したので，ベクタ拡張の組み込み関数対応のGNUツールチェインを構築できるみたいです．RISC-Vのベクタ拡張のプログラミング環境が整いつつあるようなので，環境構築をしてDockerで皆さんに共有できれば思いました．

# インストールとビルドするもの

今回の私のDockerイメージを作成するにあたってやったことを説明します．これらのインストールとビルドは既に私のDockerイメージで行われているので，利用する際は時間の節約になるのではないかと思います．

## riscv-gnu-toolchain (rvv-intrinsic)

まずは，riscvのgccとかが入っているriscv-gnu-toolchainをインストールします．これが一番重要なものです．riscv-gnu-toolchainのブランチにはrvv-intrinsicというブランチがあり，そのブランチが先ほどsifiveのブログで言ってたものと同じものだと思うのでこのブランチをgit cloneし，ビルドをしていきます．

https://github.com/riscv/riscv-gnu-toolchain/tree/rvv-intrinsic

このインストールとビルドが結構時間がかかります．たぶんローカルでやったら一時間は少なくともかかるでしょう．(たぶん)
私のdockerイメージではインストールとビルドが終わっているので楽だと思います．

## riscv-isa-sim (spike)

riscvのシミュレータのspikeもインストールします．こちらはmasterブランチの最新のもので問題なさそうです．
こちらもriscv-gnu-toolchainと同様にインストールとビルドします．

https://github.com/riscv/riscv-isa-sim

## riscv-pk

riscv-pkは，静的にリンクされたRISC-VELFバイナリをホストできる軽量のアプリケーション実行環境です．
正直あんまり良くわかってないですが，I/Oのシステムコールが使える，というところでしょうか？これについてもインストールとビルドします．

https://github.com/riscv/riscv-pk

# Dockerfile

上で記したものをもとに，Dockerfileを作成しました．最初に試したときは，ローカルでのimageサイズが17GB以上になってしまったので，工夫をする必要がありました．

riscv関連のものは $RISCV フォルダにインストールされます．このDockerfileでは **/opt/riscv** にインストールされるので，Dockerのマルチステージビルドというものを使って，最初のステージで出てきた成果物である **/opt/riscv** フォルダだけを最終的なイメージにコピーすることで大幅にイメージサイズを縮小することができました．

https://hub.docker.com/r/a163236/rvv_toolchain

```dockerfile:Dockerfile
FROM ubuntu:latest
RUN apt-get update && apt-get upgrade -y
RUN apt-get install -y tzdata

# riscv パス
ENV RISCV=/opt/riscv
ENV PATH=$RISCV/bin:$PATH
# timezone setting
ENV TZ=Asia/Tokyo

RUN apt-get install -y git autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev

# riscv-gnu-toolchainのrvv-intrinsicブランチ
RUN git clone https://github.com/riscv/riscv-gnu-toolchain && \
  cd riscv-gnu-toolchain && \
  git checkout rvv-intrinsic && \
  ./configure --prefix=/opt/riscv && \
  make newlib -j$(nproc)

# riscv Spike
RUN apt-get install -y device-tree-compiler
RUN git clone https://github.com/riscv/riscv-isa-sim.git && \
  cd riscv-isa-sim && \
  mkdir build && \
  cd build && \
  ../configure --prefix=$RISCV && \
  make -j$(nproc) && \
  make install

# riscv procy kernel
RUN git clone https://github.com/riscv/riscv-pk && \
  cd riscv-pk && \
  mkdir build && \
  cd build && \
  ../configure --prefix=$RISCV --host=riscv64-unknown-elf && \
  make -j$(nproc) && \
  make install

# ================================================================　マルチステージビルド

FROM ubuntu:latest

RUN apt-get update && apt-get upgrade -y
RUN apt-get install -y tzdata

# 実行に最低限必要そうなパッケージ
RUN apt-get install -y gcc device-tree-compiler

# timezone setting
ENV TZ=Asia/Tokyo

# set local to jp
RUN apt-get install -y language-pack-ja && \
    update-locale LANG=ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8

# riscv パス
ENV RISCV=/opt/riscv
ENV PATH=$RISCV/bin:$PATH

# homeディレクトリへ
WORKDIR /home
# デフォルトのdash から bashへ  sourceコマンドが使えないから
SHELL ["/bin/bash", "-c"]
CMD ["/bin/bash"] 
COPY --from=0 /opt/riscv/ /opt/riscv
```

## サイズの比較

こちらが最終的なイメージサイズになります．912.23MBとなりました．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575388/c283f628-042f-2fef-5705-c888911708a9.png)

調べると，@kamiya_owlさんがriscv-gnu-toolchain(V拡張ではない)のdockerのイメージを公開していらっしゃるようでした．下が@kamiya_owl氏のサイトです．docker imageのサイズを確認してみたところ4.34 GBありました．

http://kamiya.tech/blog/riscv-gnu-toolchain-docker/

UCB(University of California, Berkeley：カリフォルニア大学バークレー校)が公開している ChipyardリポジトリのDocker image( https://hub.docker.com/r/ucbbar/chipyard-image/tags?page=1&ordering=last_updated )は1.68GBでした．こちらは色々でかいリポジトリなので比較対象には微妙ですが参考にはなるかと思います．

以上のものと比較しても，まあまあサイズを抑えられたかなと思います．ただ@kamiya_owlさんのものと違ってビルドの成果物だけをデプロイ(?)しているので，「自分でカスタム命令を実装する!」という用途にはあまり向いていないので，「ちょっとベクタ拡張を試してみたい」といった人には良いかなと思います．


# おわりに

Dockerについて分からないところも多かったですが，やってみました．
DockerとGithubを連携させた，automated buildというものもやってみたのですが，docker hubでの自動ビルドにはメモリの制限が厳しいようで，エラーになって出来ませんでした．成功した方などは教えていただければ嬉しいです．
本記事については無駄なところや，間違ったところもあると思うので何かありましたら @a163236 まで教えて頂けると幸いです。