MinikubeでKubernetesを試す

まずは Vagrant でイメージを作成します。

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "bento/ubuntu-19.10"
  config.vm.provider "virtualbox" do |vb|
    vb.cpus = "2"
  end
  config.vm.network "private_network", ip: "192.168.33.100"

  config.vm.provision "shell", inline: <<-SHELL
    curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.9.0/bin/linux/amd64/kubectl
    chmod +x ./kubectl
    mv ./kubectl /usr/local/bin/kubectl

    curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.24.1/minikube-linux-amd64
    chmod +x minikube
    mv minikube /usr/local/bin/

    minikube version
    kubectl version

    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
    sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
    apt-get install docker-ce docker-ce-cli containerd.io -y

    ufw disable
  SHELL
end

起動します。

vagrant up
vagrant ssh

イメージ内で起動するプロセスを作ります。

git clone https://github.com/kubernetes-up-and-running/kuard.git
cd kuard
sudo make
sed -ie 's/FROM ARG_FROM/FROM alpine/' Dockerfile.kuard
sed -ie 's/ARG_FAKEVER\/ARG_ARCH/blue\/amd64/' Dockerfile.kuard
sudo docker build -t kuard-run:1 . -f Dockerfile.kuard
sudo docker run -d --name kuard  -p 8080:8080 kuard-run:1

ブラウザで http://192.168.33.100:8080/ を開いてみます。

f:id:taku-woohar:20200222211155p:plain
KUAR Demo

多分このような画面が出ると思います。

sudo docker stop kuard

で停止します。

Kubernetesを使います。

export CHANGE_MINIKUBE_NONE_USER=true
sudo -E minikube start --vm-driver=none

まず状態を確認します。

$ minikube status
minikube: Running
cluster: Running
kubectl: Correctly Configured: pointing to minikube-vm at 127.0.0.1

$ kubectl get node
NAME      STATUS    ROLES     AGE       VERSION
vagrant   Ready     <none>    15m       v1.8.0

$ kubectl get pods
No resources found.

Podを作ります。

$ kubectl run kuard --image=kuard-run:1 
deployment "kuard" created

$ kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
kuard-86d4765c69-4crbk   1/1       Running   0          7m

とりあえず一旦削除します。

kubectl delete deployments/kuard

kuard.yml を用意します。

apiVersion: v1
kind: Pod
metadata:
  name: kuard
spec:
  containers:
  - name: kuard
    image: kuard-run:1
    ports:
      - containerPort: 8080
        name: http
        protocol: TCP

Podが作成されているのを確認します。

$ kubectl get pods
NAME      READY     STATUS    RESTARTS   AGE
kuard     1/1       Running   0          1m

$ kubectl describe  pods kuard
Name:         kuard
Namespace:    default
Node:         vagrant/10.0.2.15
Start Time:   Sat, 22 Feb 2020 13:19:44 +0000
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"kuard","namespace":"default"},"spec":{"containers":[{"image":"kuard-run:1","name":...
Status:       Running
IP:           172.17.0.4
Containers:
  kuard:
    Container ID:   docker://7b17419be3b56fb76e3539a0702782b9a7749252b214d859143064a7eb2aa1ab
    Image:          kuard-run:1
    Image ID:       docker://sha256:d4081f1dfbe6f426cd1ac49dbb16b2f073e5d18af7022e03fa2c674b77b7f7f4
    Port:           8080/TCP
    State:          Running
      Started:      Sat, 22 Feb 2020 13:19:45 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-hkpw5 (ro)
Conditions:
  Type           Status
  Initialized    True 
  Ready          True 
  PodScheduled   True 
Volumes:
  default-token-hkpw5:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-hkpw5
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     <none>
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              1m    default-scheduler  Successfully assigned kuard to vagrant
  Normal  SuccessfulMountVolume  1m    kubelet, vagrant   MountVolume.SetUp succeeded for volume "default-token-hkpw5"
  Normal  Pulled                 1m    kubelet, vagrant   Container image "kuard-run:1" already present on machine
  Normal  Created                1m    kubelet, vagrant   Created container
  Normal  Started                1m    kubelet, vagrant   Started container


$ kubectl logs kuard
2020/02/22 13:19:45 Starting kuard version: v0.10.0-blue

Podを削除します。

$ kubectl delete pods/kuard
pod "kuard" deleted

以上です。

Selenium RemoteWebDriver を試してみる

クライアントPCの上で仮想環境を構築し、その上でSeleniumを動かします。 まずはVagrant仮想マシンを作成します。

# -*- mode: ruby -*-

Vagrant.configure("2") do |config|
  config.vm.box = "bento/ubuntu-19.10"

  config.vm.network "private_network", ip: "192.168.33.10"

  config.vm.provision "shell", inline: <<-SHELL
    apt-get update -y
    apt update -y
    apt install fonts-ipafont fonts-ipaexfont default-jdk unzip -y

    # Install Google Chrome
    wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
    echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' | tee /etc/apt/sources.list.d/google-chrome.list

    apt update -y
    apt install google-chrome-stable -y
    
    # Install Selenium Environment
    mkdir /home/vagrant/selenium
    cd /home/vagrant/selenium
    wget https://chromedriver.storage.googleapis.com/80.0.3987.16/chromedriver_linux64.zip
    unzip chromedriver_linux64.zip
    wget https://selenium-release.storage.googleapis.com/3.141/selenium-server-standalone-3.141.59.jar
  SHELL
end
vagrant up

仮想環境内でHubとNodeの2つのプロセスを立ち上げます。HubとNodeは1:Nの関係になるようです。

Hub

$ cd selenium/
$ DISPLAY=:99.0 java -Dwebdriver.gecko.driver=geckodriver -jar selenium-server-standalone-3.141.59.jar  -role hub

Node

$ DISPLAY=:99.0 java -Dwebdriver.gecko.driver=geckodriver -jar selenium-server-standalone-3.141.59.jar -role node -hub http://localhost:4444

http://192.168.33.10:4444/grid/console をブラウザで開くと現在の状況が確認できます。

Seleniumのコードを用意します。

import org.junit.After
import org.junit.Before
import org.junit.Test
import org.openqa.selenium.OutputType
import org.openqa.selenium.TakesScreenshot
import org.openqa.selenium.WebDriver
import org.openqa.selenium.chrome.ChromeOptions
import org.openqa.selenium.remote.RemoteWebDriver
import java.io.File
import java.net.URL

class RemoteTest {
  var driver: WebDriver? = null
  @Before
  fun setup() {
//    val option = FirefoxOptions() // 今は使えない
    val option = ChromeOptions()
    option.setHeadless(true);
    driver = RemoteWebDriver(URL("http://192.168.33.10:4444/wd/hub"), option)
  }
  @Test
  fun test1() {
    driver!!.get("https://www.yahoo.co.jp/");

    val ss = (driver as TakesScreenshot).getScreenshotAs(OutputType.FILE)
    ss.renameTo(File("./yahoo_top.png"))
  }
  @After
  fun dispose() {
    if (driver != null) {
      driver!!.quit();
    }
  }
}

実行するとホスト側のルートディレクトリにスクリーンショットが保存されます。

f:id:taku-woohar:20200208154440p:plain
実行結果

問題なく実行できました。

過去JJUG CCCの発表資料一覧

個人的にまとまってくれてた方が見返しやすいので作成

Intel DL boostを使おうとした続き

先日の記事ですが、問題解決できました。

#include <immintrin.h>
#include <stdio.h>

int main()
{
    int8_t __attribute__((aligned(64)))   op1_int8[64];
    int8_t __attribute__((aligned(64)))    op2_int8[64];
    int    __attribute__((aligned(64)))   op3_int[16];
    int    __attribute__((aligned(64)))   presult[16];

    int16_t __attribute__((aligned(64)))   op4_int16[32];
    int16_t __attribute__((aligned(64)))   op5_int16[32];

    __m512i  v1_int8;
    __m512i  v2_int8;
    __m512i  v3_int;
    __m512i  v4_int16;
    __m512i  v5_int16;

    for (int i = 0;i < 64;i++) {
        op1_int8[i] = i;
        op2_int8[i] = i;
    }
    for (int i = 0;i < 16;i++) {
        op3_int[i] = 0;
    }
    for (int i = 0;i < 32;i++) {
        op4_int16[i] = i;
        op5_int16[i] = i;
    }

    v1_int8 = _mm512_load_si512(&op1_int8);
    v2_int8 =_mm512_load_si512(&op2_int8);
    v3_int = _mm512_load_si512(&op3_int);
    v4_int16 = _mm512_load_si512(&op4_int16);
    v5_int16 = _mm512_load_si512(&op5_int16);


    printf("vpdpbusds\n");

    __m512i result = _mm512_dpbusds_epi32(v3_int, v1_int8, v2_int8);
    _mm512_store_si512(presult, result);

    for (int i = 0; i < 16; i++) {
        int val = presult[i];
        printf("%d = %d\n", i, val);
    }

    printf("vpmaddwd + vpaddd\n");
    result = _mm512_madd_epi16(v4_int16, v5_int16);
    result = _mm512_add_epi32(result, v3_int);
    _mm512_store_si512(presult, result);
    for (int i = 0; i < 16; i++) {
        int val = presult[i];
        printf("%d = %d\n", i, val);
    }


    return 0;
}

実行結果

vpdpbusds
0 = 14
1 = 126
2 = 366
3 = 734
4 = 1230
5 = 1854
6 = 2606
7 = 3486
8 = 4494
9 = 5630
10 = 6894
11 = 8286
12 = 9806
13 = 11454
14 = 13230
15 = 15134
vpmaddwd + vpaddd
0 = 1
1 = 13
2 = 41
3 = 85
4 = 145
5 = 221
6 = 313
7 = 421
8 = 545
9 = 685
10 = 841
11 = 1013
12 = 1201
13 = 1405
14 = 1625
15 = 1861

なんか vpmaddwd + vpaddd の使い方間違っている気がしますが、気にしない方針で

Intel DL boostを使おうとしたけど

EC2 c5.12xlarge インスタンスでは使えるはずと思って試しました。 Intelのサイトを参考に

sudo apt install gcc-8 clang-8
#include <immintrin.h>
#include <stdio.h>

int main()
{
    int8_t __attribute__((aligned(64)))   op1_int8[64];
    int8_t __attribute__((aligned(64)))    op2_int8[64];
    int    __attribute__((aligned(64)))   op3_int[16];
    int16_t __attribute__((aligned(64)))   op4_int16[32];

    __m512i  v1_int8;
    __m512i  v2_int8;
    __m512i  v3_int;
    __m512i  v4_int16;

    printf("size of int8_t is %zu\n", sizeof(int8_t));
    printf("size of int is %zu\n", sizeof(int));
    printf("size of int16_t is %zu\n", sizeof(int16_t));

    for (int i = 0;i < 64;i++) {
        op1_int8[i] = i;
        op2_int8[i] = i;
    }
    for (int i = 0;i < 16;i++) {
        v3_int[i] = 0;
    }
    for (int i = 0;i < 32;i++) {
        v4_int16[i] = 0;
    }

    v1_int8 =_mm512_load_si512(&op1_int8);
    v2_int8 =_mm512_load_si512(&op2_int8);
    v3_int =_mm512_load_si512(&op3_int);
    v4_int16 =_mm512_load_si512(&op4_int16);

    __m512i result = _mm512_dpbusds_epi32(v3_int, v1_int8, v2_int8);
    int* presult = (int*) &result;

    for (int i = 0; i < 16; i++) {
        printf("%d = %d\n", i, presult[i]);
    }

    return 0;
}

gccコンパイル

gcc-8 -mavx512f -march=icelake-server  main.c -o main

実行結果が以下の通り

size of int8_t is 1
size of int is 4
size of int16_t is 2
0 = 15
1 = 126
2 = 1135245462
3 = 33463
4 = 1135244750
5 = 34583
6 = 2607
7 = 3486
8 = 1135208014
9 = 38359
10 = 1133029965
11 = 41015
12 = 1135254878
13 = 44183
14 = 13230
15 = 15134

明らかに計算結果が違っています。 原因調査中・・・

AVX-512 Vector Neural Network Instructions (VNNI) - x86 - WikiChip

「線形代数の基礎」をJavaで実装してみる2

線形代数の基礎」はこちらのページです。 https://tutorials.chainer.org/ja/05_Basics_of_Linear_Algebra.html

スカラ値の乗算

ベクトル

    public Vector multiply(float scalar) {
        float[] scalars = new float[this.scalars.length];
        for (int i = 0;i < this.scalars.length;i++) {
            scalars[i] = this.scalars[i] * scalar;
        }
        return new Vector(scalars);
    }

行列

    public Matrix multiply(float scalar) {
        float[][] o2scalars = new float[this.o2scalars.length][this.o2scalars[0].length];

        for (int i = 0;i < this.o2scalars.length;i++) {
            for (int j = 0;j < this.o2scalars[i].length;j++) {
                o2scalars[i][j] = this.o2scalars[i][j] * scalar;
            }
        }
        return new Matrix(o2scalars);
    }

各要素にスカラ値を掛けます。

Vector v1 = new Vector(new float[] {1, 2, 3});
Vector v2 = v1.multiply(10);
System.out.println(v2);

Matrix m1 = new Matrix(new float[][] {
        {1, 2, 3},
        {4, 5, 6},
});
Matrix m2 = m1.multiply(10);
System.out.println(m2);

実行結果

[10.0, 20.0, 30.0]
2 x 3
| 10.0| 20.0| 30.0|
| 40.0| 50.0| 60.0|

次はベクトルの内積です

    public float innerProduct(Vector object) {
        if (this.isVertical || !object.isVertical) {
            throw new RuntimeException("vertical error");
        }

        float sum = 0;
        for (int i = 0;i < scalars.length;i++) {
            sum += scalars[i] * object.scalars[i];
        }

        return sum;
    }

内積は横ベクトルと縦ベクトルの積の場合可能です。

        Vector v10 = new Vector(new float[] {1, 2, 3}, false);
        Vector v11 = new Vector(new float[] {4, 5, 6}, true);
        float result = v10.innerProduct(v11);
        System.out.println(result);

実行結果

32.0

こちらが行列積になります。

    public Matrix matrixMultiplication(Matrix object) {
        final float[][] our = o2scalars;
        float[][] newScalars = new float[our.length][our[0].length];
        for (int i = 0;i < our.length;i++) {
            for (int j = 0;j < our[0].length;j++) {

                float sum = 0;
                for (int k = 0;k < our.length;k++) {
                    sum += our[i][k] * object.o2scalars[k][j];
                }
                newScalars[i][j] = sum;
            }
        }

        return new Matrix(newScalars);
    }
        Matrix m10 = new Matrix(new float[][] {
                {1, 2},
                {3, 4},
        });
        Matrix m11 = new Matrix(new float[][] {
                {5, 6},
                {7, 8},
        });
        System.out.println(m10.matrixMultiplication(m11));

結果

2 x 2
| 19.0| 22.0|
| 43.0| 50.0|

積算の実装については以上です。

「線形代数の基礎」をJavaで実装してみる

線形代数の基礎」はこちらのページです。 https://tutorials.chainer.org/ja/05_Basics_of_Linear_Algebra.html

テンソル

public class Tensor {
    protected final int order;
    public Tensor(int order) {
        this.order = order;
    }
}
public class LinearAlgebraTest {
    public static void main(String[] args) {
        Tensor o1 = new Tensor(1); // 1階のテンソル
        Tensor o2 = new Tensor(2); // 2階のテンソル
    }
}

order は N階のテンソルを表します。 Java的にはN次元の配列ということになります。

ベクトル

ベクトルクラスを定義します。

public class Vector extends Tensor {
    private final float[] scalars;
    public Vector(float[] scalars) {
        super(1); // ベクトルは1階のテンソル
        this.scalars = scalars;
    }
}

ベクトルはテンソルを継承して、order は 1 固定です。

加算を実装します。

Vectorに以下を追加

    public Vector add(Vector object) {
        float[] scalars = new float[this.scalars.length];
        for (int i = 0;i < this.scalars.length;i++) {
            scalars[i] = this.scalars[i] + object.scalars[i];
        }
        return new Vector(scalars);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        if (scalars.length > 0) {
            sb.append(scalars[0]);
            for (int i = 1;i < scalars.length;i++) {
                sb.append(", ").append(scalars[i]);
            }
        }
        sb.append("]");
        return sb.toString();
    }

呼び出し

        Vector v1 = new Vector(new float[]{1, 2, 3});
        Vector v2 = new Vector(new float[]{4, 5, 6});

        System.out.println(v1);
        System.out.println(v2);

        Vector v3 = v1.add(v2);
        System.out.println(v3);

実行結果

[1.0, 2.0, 3.0]
[4.0, 5.0, 6.0]
[5.0, 7.0, 9.0]

行列

こんな感じの実装にしてみます。

public class Matrix extends Tensor {
    private final float[][] o2scalars;
    public Matrix(float[][] o2scalars) {
        super(2); // 行列は2階のテンソル
        this.o2scalars = o2scalars;
    }
}

加算を実装してみます。

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(o2scalars.length).append(" x ").append(o2scalars[0].length).append("\n");
        for (int i = 0;i < o2scalars.length;i++) {
            sb.append("|");
            for (int j = 0;j < o2scalars[i].length;j++) {
                sb.append(String.format("% 5.1f|", o2scalars[i][j]));
            }
            sb.append("\n");
        }
        return sb.toString();
    }

    public Matrix add(Matrix object) {
        float[][] o2scalars = new float[this.o2scalars.length][this.o2scalars[0].length];

        for (int i = 0;i < this.o2scalars.length;i++) {
            for (int j = 0;j < this.o2scalars[i].length;j++) {
                o2scalars[i][j] = this.o2scalars[i][j] + object.o2scalars[i][j];
            }
        }
        return new Matrix(o2scalars);
    }
        Matrix m1 = new Matrix(new float[][] {
                {1,2,3},
                {4,5,6},
        });
        Matrix m2 = new Matrix(new float[][] {
                {7,8,9},
                {10,11,12},
        });
        System.out.println(m1);
        System.out.println(m2);

        Matrix m3 = m1.add(m2);
        System.out.println(m3);

実行結果です。

2 x 3
|  1.0|  2.0|  3.0|
|  4.0|  5.0|  6.0|

2 x 3
|  7.0|  8.0|  9.0|
| 10.0| 11.0| 12.0|

2 x 3
|  8.0| 10.0| 12.0|
| 14.0| 16.0| 18.0|

次回は行列の積を実装してみたいと思います。