外部記憶装置

脳みそ小さすぎるからメモしとく

リレー式計算機で円周率を計算する その2

丸々1ヶ月ぶりの更新です。命令セットの決定とエミュレーターの作成は進めていたのですが、ブログ更新は完全に放置していました。 早速ですが、今回は計算アルゴリズムの大まかなフロー作成です。

ライプニッツの公式へ変更

前回の記事でマチンの公式を利用すると言っていたのですが、計画を変更しライプニッツの公式を利用することにしました。 理由は以下の計算結果が出たからです。

以下の結果は前回のN(分母)を1000に変更して計算したものです。

./leibniz
Step:252
3148

./machin
Step:5
3152

以上のような結果になったわけです。 何が問題かというと、前回分母を10000に設定したのはリレー計算機を16bitで作成すると考えていたからです。

しかし、8bitでも大変なのに16bitとなるとえげつない量のリレーが必要となり計画の達成が困難になることは明白です。 「多倍長計算」なども一応決めた命令セットをもとにアセンブラで書いてみたのですが、除算の手間を考えると現実的ではありませんでした。 そのため、Nを1000に変更してもライプニッツの公式で314が計算可能であることが分かったため、データバス幅を減らすべく、ライプニッツの公式を利用することにしました。

計算アルゴリズムの大まかなフロー作成

というわけで、ライプニッツの公式を利用することになりました。前回の計算プログラムから無駄な部分を省き改良したものが以下のとおりです。

int main(){
  int result=0;
  int u=1;
  int l=1;
  int step = 1;
  while(u != 0 && l != 0){
    u = 4000/(step*2-1);
    l = 4000/(step*2+1);
    result = u - l + result;
    step += 2;
  }
return result;
}

このプログラムを実行するために必要な命令は大きく分けて、「加算」・「減算」・「乗算」・「減算」・「分岐」 の5つです。1つずつ考えていくことにします。

加算

この命令に関しては何も言う必要は無いと思います。今回の計算に関しては4000以下つまり符号なしで12bitまでの加算が出来ることが求められます。

減算

加算と同様基本的な演算です。今回はデータバス幅の関係上、符号なしの数も扱いたいので補数による減算ではなく、減算器をハード的に実装することになります・

乗算

乗算は加算とシフト、AND命令で全て実現できるのですが、プログラムはかなり長いものになります。 そのため、今回は小さな乗算器をハード実装してソフトウェアで大きな数も扱えるようにする方法でいきます。

除算

除算をハードで実装するとなるとかなり大変なので、これは最初からソフトウェアでエミュレーションすることにします。 幸いなことに多倍長計算は扱わないので比較的に簡単にできそうな気はします。

分岐

このプログラムにおいて最も重要な命令です。whileループの条件式にNon Zero判定を利用し、 除算のソフトウェアエミュレーションでは2数の大小比較の分岐命令を必要とします。 大小比較は比較器によって行うことができますが、今回はリレー数も考慮して 減算命令と正数分岐、負数分岐、0分岐命令を利用することにします。

まとめ

エミュレーターアセンブリで計算プログラムを書いてみた結果、以上のような方針で進めることにしました。 命令セットは大方完成しているのですが、さらに必要・不必要な命令がないか精査して正式に決定したあとで記事にしたいと思います。 エミュレーターも作っていたのですが、初めて作ったこともありスパゲティ状態なので0から作り直したいと思います。

リレー式計算機で円周率を計算する その1

サークルでの作業やら何やらで更新が遅れてしまいました。今回は使用する円周率計算公式の選定です。

円周率計算公式の候補

ライプニッツの公式

ライプニッツの公式(Wikipedia)

別名マータヴァ・ライプニッツ級数。円周率を求めるための公式の一つであるが、収束が非常に遅い(Wikipediaより)

1-\frac{1}{3}+\frac{1}{5}-\frac{1}{7}+\frac{1}{9}-\cdot\cdot\cdot = \frac{\pi}{4}

\sum_{n=0}^{\infty} \frac{(-1) ^ {n}}{2n+1} = \frac{\pi}{4}

マチンの公式

マチンの公式(Wikipedia)

グレゴリー級数を利用した、非常に収束の速い級数。1兆2411億桁まで計算したという記録もある。(Wikipediaより)

4\arctan\frac{1}{5} - \arctan\frac{1}{239} = \frac{\pi}{4}

をグレゴリー級数

\arctan x = \sum_{n=0}^{\infty} \frac{(-1)^{n}}{2n+1} x^{2n+1} = x - \frac{1}{3}x^{3} + \frac{1}{5}x^{5} - \frac{1}{7}x^{7} + \cdot\cdot\cdot

を利用することによって計算する。

実際に計算してみた

実際にテストプログラムを書き、計算してみました。固定小数点演算を前提とした計算のため、予め分子を10000倍し、項が1未満になった時点で計算を終了します。

ライプニッツの公式

プログラム

#include <stdio.h>
#define N 10000
#define MAX_STEP 200
int main(){
  int result=0;
  int step = 1;
  int u=1;
  int l=1;
  while(u >= 1 && l >= 1){
    u = (int)(N/(step*2-1));
    l = (int)(N/(step*2+1));
    result = u - l + result;
    step+=2;
    if(result*4 >= 31400 && result*4 < 31500){
      break;
    }
  }
  printf("Step:%d\n",(step+1)/2);
  printf("%d\n",result*4);
}

結果

Step:210
31400

目標値3.14を計算するまでに210ステップでした。

マチンの公式

プログラム

#include <stdio.h>
#define N 10000
#define MAX_STEP 200
int step=0;   
int test(int x){
    int a=x;
    int b=1;
    int pos=1;
    int ans;
    step++;
    ans=N/x;
    printf("Step:%d\n",step);
    int flag=1;
    while(pos>=1){
          a=a*x*x;
      b+=2;
      pos=N/(b*a);
      if(flag==0){
        ans+=pos;
            flag = 1;
      }else{
        ans-=pos;
            flag = 0;
      }
      step++;
      printf("Step:%d\n",step);
    };
    return ans;
}


int main(){
    printf("%d", 4*(4 * test(5) - test(239)));
    return 0;
}

結果

Step:5
31420

1つの項あたりの計算量がかなり異なるため一概には言えませんが、収束はかなり速いことが分かります。 計算誤差も桁数が増加した場合はマチンの公式のほうが有利であると考えられます。

まとめ

多倍長計算や乗算・除算の計算コストなどを全く考慮していないため、どちらの公式がいいとは言えませんが、桁数が増加した場合の誤差を考慮し、CPUエミュレータ作成まではマチンの公式を利用する方針とします。

(と言っても、利用する四則演算は変わらないんですけどね...)

リレー式計算機で円周率を計算する その0

リレー式計算機とは?

コンピュータ黎明期はダイオードとリレーによって構成されたコンピュータが主流でした。時代が進むに連れて素子は真空管トランジスタLSIと微細化・省電力化が進み、今のような超小型ICが実現しました。今回はあえて時代に逆行し、リレーとダイオードを利用した計算機を自作したいと思います。CPUはもちろんRAMなどにもICは一切利用しません。具体的な目標としては、第一段階としては円周率3.14の計算です。第2段階では円周率10桁の計算を目標とします。(そういえば今日は円周率の日ですね)

目的

ロマン以外の何物でもない。

方針

以下のような工程で進めていくつもりです。

  1. 円周率計算公式の選定
  2. 計算アルゴリズムの大まかなフロー作成
  3. CPUの命令セット決定
  4. 命令セットに基づいたCPUエミュレーターの作成
  5. 専用アセンブラ作成
  6. プログラム作成
  7. CPUエミュレーター上でプログラムの検証
  8. 回路設計
  9. 回路に基づいたCPUシミュレータの作成
  10. CPUシミュレータ上での回路検証
  11. 組み立て
  12. 実働テスト

今現在2.計算アルゴリズムの大まかなフロー作成まで完了しているので近いうちに記事にします。 計画としては11月にある大学の学祭に間に合うようにするつもりです。

Debian9にKimchiを導入する。その1(インストール編)

f:id:PiBVT:20180222013850j:plain

Kimchiとは

Kimchiは仮想マシンの管理をWebGUIで行うことのできる、wokのプラグインです。同じようなものとしては、WebVirtMgrやoVirtがありますが、今回はインストールイメージをネットから直接ダウンロードできたり、操作がしやすそうだったりしたのでKimchiを導入することにしました。

動作環境

KVMを始めとする仮想化環境が構築されている必要があります。インストールしていない場合はLinuxサーバーを再構築した。その5(KVM設定編) を参考にしてインストールしてください。

Kimchiをインストールする

Debian9の場合、CentOSUbuntu Serverに比べ、パッケージの依存性の問題で手順が煩雑になっています。

パッケージをダウンロードする

公式から必要なパッケージをダウンロードします。

$ wget https://github.com/kimchi-project/kimchi/releases/download/2.5.0/wok-2.5.0-0.noarch.deb
$ wget http://kimchi-project.github.io/gingerbase/downloads/latest/ginger-base.noarch.deb
$ wget https://github.com/kimchi-project/kimchi/releases/download/2.5.0/kimchi-2.5.0-0.noarch.deb

この記事を書いている時点では2.5.0が最新版ですが、各自の状況に合わせて書き換えてください。

依存性問題を解決する

kimchiに必要なパッケージの一つに

libvirt-bin

がありますが、Debian9ではパッケージが分割されて

libvirt-daemon-system
libvirt-dev
libvirt-clients

に分割されています。普通にインストールするとlibvirt-binの依存性が解決できないのでエラーとなりインストールできません。今回はパッケージの一部を書き換えてインストールできるようにします。

まず、作業用のディレクトリを作成します。

$ mkdir tmp
$ cd tmp

次に、パッケージを展開します。

$ ar p ../kimchi-2.5.0-0.noarch.deb control.tar.gz | tar -xz

展開したファイルの中に

control.in
control

があり、これが必要なパッケージを指定しています。この2つのファイルを適当なエディタで開き、

libvirt-bin,

libvirt-daemon-system,
libvirt-dev,
libvirt-clients,

に書き換えます。保存後、パッケージをまとめます。

cp ../kimchi-2.5.0-0.noarch.deb ../kimchi-2.5.0-0~4deb9.noarch.deb
tar czf control.tar.gz *[!z]
ar r ../kimchi-2.5.0-0~4deb9.noarch.deb control.tar.gz

以上でパッケージの書き換えは終了です。

パッケージのインストール

ようやくパッケージをインストールできるようになったので、導入していきます。

$ sudo apt-get install nginx-full
$ sudo dpkg -i wok-2.5.0-0.noarch.deb 
$ sudo apt-get install -f
$ sudo dpkg -i ginger-base.noarch.deb
$ sudo apt-get install -f
$ sudo dpkg -i kimchi-2.5.0-0~4deb9.noarch.deb
$ sudo apt-get install -f

これでインストール自体は終了です。一応再起動しておきます。

$ sudo reboot

今回はここで終了です。次回は、UFWの設定とバグパッチの適用を行います。

参考文献

I got WOK & KIMCHI working on Debian 9 – Here’s how I did it

Linuxサーバーを再構築した。その5(KVM設定編)

f:id:PiBVT:20180213221038j:plain

KVMとは

KVMとはKernel-based Virtual MachineでLinuxカーネルに組み込まれた仮想化基盤ことです。要は便利な仮想化ソフトウェアという感じです。今回はサーバー上で複数のマシンを稼働させるために利用します。

KVMをインストール

KVM本体と関連パッケージをすべて一括でインストールします。

$ sudo apt install qemu-kvm libvirt0 virt-manager bridge-utils

インストール後再起動します。

$ sudo reboot

ユーザーをlibvirtグループに追加し、仮想マシンの作成等の操作がroot権限なしでできるようにします。

$ sudo gpasswd libvirt -a hoge

ネットワークの設定

ゲストOSの通信は以下の2つの方式によって経由されます。

NAT方式

ブリッジ方式

NAT方式はホストのファイアーウォールを介することになるので、セキュリティ的には便利なのですが、ゲストの対外通信が面倒なことになります。ブリッジ方式はその正反対で、ゲストの通信はファイアーウォールを全く介さないので、物理マシンとほぼ同じように扱うことができます。

ブリッジ方式で通信するためのブリッジを作成します。

/etc/network/interfaces

をroot権限で開きます。 第一回で設定した固定IP設定を変更し、以下のようにします。

auto enp0s25
iface enp0s25 inet manual

iface br0 inet static
  address 192.168.100.100
  network 192.168.100.0
  netmask 255.255.255.0
  broadcast 192.168.100.255
  gateway 192.168.100.1
  dns-nameservers 192.168.100.1 8.8.8.8
  bridge_ports enp0s25
  bridge_stp off
auto br0

ファイアーウォールにブリッジ経由の通信をスルーする設定を追加しておきます。

/etc/default/ufw

をroot権限で開きます。

DEFAULT_FORWARD_POLICY="DROP" を DEFAULT_FORWARD_POLICY="ACCEPT" に変更

以上で設定は終了です。最後に再起動して完了です。

今回で再構築は終了です。今までCUIベースで仮想マシンを管理していたのですが、結構大変なのでWebGUIで管理できるようにしたりするつもりです。他にもNextCloudというプライベートクラウドも気になるので使ってみたいです。

参考文献

Debian 9: 仮想化のKVMをインストールする Debian 9: bridgeインターフェースの設定 UbuntuでKVMを構築して、ファイアーウォール(ufw)を有効化する

Linuxサーバーを再構築した。その4(Samba設定編)

f:id:PiBVT:20180212234250j:plain

Sambaとは

SambaはSMBプロトコルのファイルサーバーでWindowsUnix間でのファイル共有を可能にするソフトウェアです。

今回は個人用にファイルサーバーを立てるので、複数人での共有については配慮してません。

Sambaをインストールする。

サーバーにSSHして

$ sudo apt install samba

次に基本的な設定を行います。

/etc/samba/smb.conf

をroot権限で開き、

;    interfaces = 127.0.0.0/8 eth0 を interfaces 127.0.0.0/8 192.168.100.0/24
;    bind interfaces only = yes を bind interfaces only = yes

とすることで、アクセス可能な範囲をLAN内に限定することができます。

共有ディレクトリの設定

サーバーのホームディレクトリで

mkdir share
chmod 770 share

と、共有対象のディレクトリshareを作成します。

次に、共有設定をするために再び

/etc/samba/smb.conf

をroot権限で開き、ファイルの最後に

[Share]
    path = /home/hoge/share
    writable = yes
    create mode = 0770
    directory mode = 0770
    guest ok = no
    valid users = hoge

を追記します。

path は共有対象のディレクトリのフルパス

writableは書き込み許可

create mode,directory mode はアクセス権限の設定

guest ok はゲストの接続

valid usersはアクセス可能なユーザー名

となっています。 今回はインストール時に登録したユーザーhogeのみがアクセス可能となるようにしています。

そして、アクセス時専用のパスワードを設定します。

sudo smbpasswd -a hoge
New SMB password:(新規にパスワードを設定する)
Retype new SMB password:(上と同じものを入力)

とすることで登録ができます。 最後にSambaサービスを再起動し、ファイアーウォールに通信許可を追加します。

sudo systemctl restart smbd
sudo ufw allow samba

以上でサーバー側の設定は終了です。

Windowsから接続する

ファイルエクスプローラーを開き、上部のアドレス欄に

\\192.168.100.100\Share

と入力すると、ユーザー名とパスワード入力画面が出てくるので、ユーザー名hogeと登録したパスワードを入力することでアクセスできます。

以上でファイルサーバーの構築は終了です。複数人で異なるアクセス権限の設定等も可能ですが、当人は使う機会が無いので今回はしません。

次回はKVMのインストールと設定を行い、サーバー再構築を終了します。

参考文献

Debian 9 Stretch : Samba : アクセス権付の共有フォルダ作成 : Server World

Linuxサーバーを再構築した。その3(UFW設定編)

f:id:PiBVT:20180211160126p:plain

UFWとは

UFWとはUncomplicated Firewallの略でLinuxにおけるファイアーウォールの一つです。 今回のサーバーは外に公開することになるのでセキュリティを高めるために導入しておきます。

UFWをインストールする

UFWのインストール・設定はDebian 9: UFWでファイアウォール制御 を参考にしました

サーバーにログイン後

$ sudo apt install ufw
$ sudo systemctl start ufw
$ sudo ufw enable
$ sudo ufw logging on

UFWの有効化、ログ取得と、自動起動の設定が完了します。

UFWを設定する

今はSSHだけできればいいので、前回SSH用に設定した18500番ポートでの通信を許可します。

$ sudo ufw allow 18500/tcp

以上で、外部からの18500番ポートに対する通信以外はすべて遮断されます。

Webサーバーなどを立てた場合はその都度、UFWの設定に追加していくことになります。

次回はSambaのインストールと設定を行います。

参考文献

Uncomplicated Firewall Debian 9: UFWでファイアウォール制御