Kokkosのビルド・インストール（備忘録）

### Kokkosのビルド・インストール

Kokkos[^1]のビルド・インストールは、ドキュメントを参考にCMakeで行うことができます。以下の手順でUbuntuにインストールしました。

- Documentation

https://kokkos.org/kokkos-core-wiki/building.html

- GitHub
 
https://github.com/kokkos/kokkos


まずはKokkosのソースコードをダウンロードします。
今回は```<tag>```を```4.3.01```としました。

```console
$ git clone --depth 1 --branch <tag> https://github.com/kokkos/kokkos.git
```

ビルドではCPUでSerial、GPUでCUDAを有効にして構築しました。

```bash
# CUDAのパスを通す
$ export PATH=$PATH:/usr/local/cuda/bin
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64

# Kokkosのビルド・インストール
$ cmake -B <build directory> -S </path/to/kokkos> \
  -DCMAKE_INSTALL_PREFIX=<install prefix> \
  -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++ \
  -DKokkos_ENABLE_SERIAL=ON -DKokkos_ENABLE_CUDA=ON \ # 今回はSERIALとCUDAを有効
  -DKokkos_ARCH_TURING75=ON # ここはGPUのArchを設定
$ cmake --build <build directory>
$ cmake --install <build directory>
```

### サンプルコードのビルド・実行

Kokkosを構築できたので、Hello Worldを動かしてみます。

- https://github.com/kokkos/kokkos/tree/develop/example/tutorial/01_hello_world

Kokkosのソースコードに付いているExampleです。
SerialとCUDAのそれぞれで動かすために、Makefileを編集する必要があります。ビルドするための適当なディレクトリ```<workdir>```にMakefileをコピーして編集します。

```bash
$ cd <workdir>
$ cp </path/to/kokkos>/example/tutorial/01_hello_world/Makefile .
```

今回の環境に合わせて以下のように編集しました。

- Makefile(diff)

```diff
-KOKKOS_PATH = ../../..
+KOKKOS_PATH = </path/to/kokkos>
KOKKOS_SRC_PATH = ${KOKKOS_PATH}
SRC = $(wildcard ${KOKKOS_SRC_PATH}/example/tutorial/01_hello_world/*.cpp)
vpath %.cpp $(sort $(dir $(SRC)))

default: build
	echo "Start Build"

ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
CXX = ${KOKKOS_PATH}/bin/nvcc_wrapper
CXXFLAGS = -O3
LINK = ${CXX}
LDFLAGS = 
EXE = 01_hello_world.cuda
-KOKKOS_DEVICES = "Cuda,OpenMP"
-KOKKOS_ARCH = "SNB,Kepler35"
+KOKKOS_DEVICES = "Cuda"
+KOKKOS_ARCH = "Turing75"
else
CXX = g++
CXXFLAGS = -O3
LINK = ${CXX}
LDFLAGS =  
EXE = 01_hello_world.host
-KOKKOS_DEVICES = "OpenMP"
-KOKKOS_ARCH = "SNB"
+KOKKOS_DEVICES = "Serial"
+KOKKOS_ARCH = "Native"
endif

DEPFLAGS = -M

OBJ = $(notdir $(SRC:.cpp=.o))
LIB =

include $(KOKKOS_PATH)/Makefile.kokkos

build: $(EXE)

test: $(EXE)
	./$(EXE)

$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)

clean: kokkos-clean 
	rm -f *.o *.cuda *.host

# Compilation rules

%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $< -o $(notdir $@)

```

このMakefileではデフォルトはg++で```KOKKOS_DEVICES=Cuda```を指定するとnvccでビルドされます。また、bcコマンドを入れないと動かないことがあります。

```bash
$ sudo apt install bc
```

まずはSerialで実行してみます。

```bash
# CPU Serial
$ make build
:
$ ./01_hello_world.host 
Hello World on Kokkos execution space N6Kokkos6SerialE
Hello from i = 0
Hello from i = 1
Hello from i = 2
Hello from i = 3
Hello from i = 4
Hello from i = 5
Hello from i = 6
Hello from i = 7
Hello from i = 8
Hello from i = 9
Hello from i = 10
Hello from i = 11
Hello from i = 12
Hello from i = 13
Hello from i = 14
```

次にCUDAで実行してみます。

```bash
# Cuda
$ PATH=$PATH:/usr/local/cuda/bin LD_LIBRARY_PATH=$LD_LIBRARY_PATH=/usr/local/cuda/lib64 KOKKOS_DEVICES=Cuda make build
:
$ ./01_hello_world.cuda 
Hello World on Kokkos execution space N6Kokkos4CudaE
Hello from i = 0
Hello from i = 1
Hello from i = 2
Hello from i = 3
Hello from i = 4
Hello from i = 5
Hello from i = 6
Hello from i = 7
Hello from i = 8
Hello from i = 9
Hello from i = 10
Hello from i = 11
Hello from i = 12
Hello from i = 13
Hello from i = 14
```

execution spaceが変わっているので実行デバイスが切り替わっているようです。
Kokkosについては引き続き勉強していきたいと思います。

[^1]:https://github.com/kokkos/kokkos