読者です 読者をやめる 読者になる 読者になる

kubo39's blog

ただの雑記です。

re-visit kNN and operf/LDC

以前書いたものはシングルスレッド版のRust/OCamlよりも遅かった。これをprofilingしてみる。

  • スペック
$ lscpu                                                [kubo39:knn][git:master]
Architecture:          x86_64
CPU 操作モード:   32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                4
On-line CPU(s) list:   0-3
コアあたりのスレッド数:2
ソケットあたりのコア数:2
Socket(s):             1
NUMA ノード数:     1
ベンダー ID:       GenuineIntel
CPU ファミリー:   6
モデル:             69
Model name:            Intel(R) Core(TM) i5-4200U CPU @ 1.60GHz
...
  • dmdのバージョン
$ dmd --version                                        [kubo39:knn][git:master]
DMD64 D Compiler v2.073.1

コードを2.073.1でも動くように修正。

import std.algorithm;
import std.array;
import std.conv;
import std.range;
import std.stdio;
import std.string;
import std.typecons;
import std.parallelism;

struct LabelPixel
{
    int label;
    int[] pixels;
}

auto slurpFile(string filename)
{
    int count;

    auto lp = File(filename)
        .byLine
        .dropOne
        .tee!(a => count++)
        .map!chomp
        .map!(a => a.to!string.split(","))
        .map!(a => LabelPixel(a[0].to!int, a[1..$].to!(int[])) )
        .array;
    return tuple(lp, count);
}

int distanceSqrt(const ref int[] x, const ref int[] y) pure
{
    return reduce!((a, b) => a + (b[0] - b[1]) * (b[0] - b[1]))(0, x.zip(y));
}

int classify(const ref LabelPixel[] training, const ref int[] pixels) pure
{
    int smallest = int.max;
    int result = void;

    foreach (t; training)
    {
        int tmp = distanceSqrt(t.pixels, pixels);
        if (tmp < smallest)
        {
            smallest = tmp;
            result = t.label;
        }
    }
    return result;
}

void main()
{
    const trainingSet = "trainingsample.csv".slurpFile;
    const validationSample = "validationsample.csv".slurpFile;

    int count(const LabelPixel data) pure
    {
        int num;
        if (classify(trainingSet[0], data.pixels) == data.label)
            num++;
        return num;
    }

    immutable num = taskPool.reduce!"a + b"(
        std.algorithm.map!(count)(validationSample[0]).array);

    writefln("Percentage correct: %f percent",
             num.to!double / validationSample[1].to!double * 100.0);
}

timeコマンドで測ってみる。

  • 最適化なし
$ time ./knn                                           [kubo39:knn][git:master]
Percentage correct: 94.400000 percent
./knn  110.16s user 0.03s system 99% cpu 1:50.33 total

うーん、遅い。

  • 最適化あり
$ time ./knn                                           [kubo39:knn][git:master]
Percentage correct: 94.400000 percent
./knn  90.50s user 0.06s system 99% cpu 1:30.59 total

少し早くなったけどぜんぜん遅い。

Rustを見直し。

Rustのシングルスレッド版を再度測ってみる。

$ rustc --version                                      [kubo39:knn][git:master]
rustc 1.17.0-nightly (306035c21 2017-02-18)

少々手直しが必要。

use std::io::{BufRead, BufReader};
use std::fs::File;
use std::path::Path;
use std::str::FromStr;

struct LabelPixel {
    label: i32,
    pixels: Vec<i32>
}

fn slurp_file(file: &Path) -> Vec<LabelPixel> {
    BufReader::new(File::open(file).unwrap())
        .lines()
        .skip(1)
        .map(|line| {
            let line = line.unwrap();
            let mut iter = line.trim()
                .split(',')
                .map(|x| i32::from_str(x).unwrap());

            LabelPixel {
                label: iter.next().unwrap(),
                pixels: iter.collect()
            }
        })
        .collect()
}

fn distance_sqr(x: &[i32], y: &[i32]) -> i32 {
    // run through the two vectors, summing up the squares of the differences
    x.iter()
        .zip(y.iter())
        .fold(0, |s, (&a, &b)| s + (a - b) * (a - b))
}

fn classify(training: &[LabelPixel], pixels: &[i32]) -> i32 {
    training
        .iter()
        // find element of `training` with the smallest distance_sqr to `pixel`
        .min_by_key(|p| distance_sqr(p.pixels.as_slice(), pixels)).unwrap()
        .label
}

fn main() {
    let training_set = slurp_file(&Path::new("trainingsample.csv"));
    let validation_sample = slurp_file(&Path::new("validationsample.csv"));

    let num_correct = validation_sample.iter()
        .filter(|x| {
            classify(training_set.as_slice(), x.pixels.as_slice()) == x.label
        })
        .count();

    println!("Percentage correct: {}%",
             num_correct as f64 / validation_sample.len() as f64 * 100.0);
}

releaseビルド。めちゃくちゃ早い。。

$ cargo build --release                              [kubo39:knnrs][git:master]
   Compiling knnrs v0.1.0 (file:///home/kubo39/dev/dlang/knn/knnrs)
    Finished release [optimized] target(s) in 2.6 secs
$ time ./target/release/knnrs                        [kubo39:knnrs][git:master]
Percentage correct: 94.39999999999999%
./target/release/knnrs  1.21s user 0.01s system 99% cpu 1.217 total

D言語に戻る。

計測しやすいようにシングルスレッド版からはじめる。

import std.algorithm;
import std.array;
import std.conv;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

struct LabelPixel
{
    int label;
    int[] pixels;
}

auto slurpFile(string filename)
{
    int count;

    auto lp = File(filename)
        .byLine
        .dropOne
        .tee!(a => count++)
        .map!chomp
        .map!(a => a.to!string.split(","))
        .map!(a => LabelPixel(a[0].to!int, a[1..$].to!(int[])) )
        .array;
    return tuple(lp, count);
}

int distanceSqrt(const ref int[] x, const ref int[] y) pure
{
    return reduce!((a, b) => a + (b[0] - b[1]) * (b[0] - b[1]))(0, x.zip(y));
}

int classify(const ref LabelPixel[] training, const ref int[] pixels) pure
{
    int smallest = int.max;
    int result = void;

    foreach (t; training)
    {
        int tmp = distanceSqrt(t.pixels, pixels);
        if (tmp < smallest)
        {
            smallest = tmp;
            result = t.label;
        }
    }
    return result;
}

void main()
{
    const trainingSet = "trainingsample.csv".slurpFile;
    const validationSample = "validationsample.csv".slurpFile;

    int count(const LabelPixel data) pure
    {
        int num;
        if (classify(trainingSet[0], data.pixels) == data.label)
            num++;
        return num;
    }

    immutable num = reduce!"a + b"(
        std.algorithm.map!(count)(validationSample[0]).array);

    writefln("Percentage correct: %f percent",
             num.to!double / validationSample[1].to!double * 100.0);
}

シングルスレッド版のほうが早い。といってもあまり変わらないが。

$ dmd -O knn.d                                         [kubo39:knn][git:master]
$ time ./knn                                           [kubo39:knn][git:master]
Percentage correct: 94.400000 percent
./knn  88.90s user 0.02s system 99% cpu 1:28.94 total

dmdだとだめそう。ldc2は理論値性能が出る?

http://leonardo-m.livejournal.com/111598.html

$ ldc2 -version | head -2
LDC - the LLVM D compiler (1.0.0):
  based on DMD v2.071.2 and LLVM 3.8.1

最適化つきで計測。DMDよりぜんぜん速いけどRustより遅い。

$ ldc2 -O knn.d
$ time ./knn
Percentage correct: 94.400000 percent
./knn  10.76s user 0.02s system 99% cpu 10.794 total

operf

operfはdwarf情報を使うので-gつけてビルド。

$ ldc2 -O -g knn.d
$ sudo operf ./knn
operf: Profiler started
Percentage correct: 94.400000 percent

Profiling done.

opannotate --source をみると、distanceSqrt関数が14%を占めていることがわかる。

$ opannotate --source
[ ... ]
/* 
 * Total samples for file : "/home/kubo39/dev/dlang/knn/knn.d"
 * 
 *  45735 15.2286
 */


               :import std.algorithm;
               :import std.array;
               :import std.conv;
               :import std.range;
               :import std.stdio;
               :import std.string;
               :import std.typecons;
               :
               :struct LabelPixel
               :{
               :    int label;
               :    int[] pixels;
               :}
               :
               :auto slurpFile(string filename)
               :{
               :    int count;
               :
               :    auto lp = File(filename)
               :        .byLine
               :        .dropOne
               :        .tee!(a => count++)
               :        .map!chomp
               :        .map!(a => a.to!string.split(","))
               :        .map!(a => LabelPixel(a[0].to!int, a[1..$].to!(int[])) )
               :        .array;
               :    return tuple(lp, count);
               :}
               :
               :int distanceSqrt(const ref int[] x, const ref int[] y) pure
               :{
 45028 14.9931 :    return reduce!((a, b) => a + (b[0] - b[1]) * (b[0] - b[1]))(0, x.zip(y)); /* _D3knn12distanceSqrtFNaKxAiKxAiZi total: 165424 55.0818 */
               :}
               :
               :int classify(const ref LabelPixel[] training, const ref int[] pixels) pure
               :{
               :    int smallest = int.max;
               :    int result = void;
               :
   523  0.1741 :    foreach (t; training)
               :    {
    33  0.0110 :        int tmp = distanceSqrt(t.pixels, pixels);
    50  0.0166 :        if (tmp < smallest)
               :        {
               :            smallest = tmp;
               :            result = t.label;
               :        }
               :    }
               :    return result;
               :}
               :
               :void main()
               :{
               :    const trainingSet = "trainingsample.csv".slurpFile; /* _Dmain total:    711  0.2367 */
               :    const validationSample = "validationsample.csv".slurpFile;
               :
               :    int count(const LabelPixel data) pure
               :    {
               :        int num;
   101  0.0336 :        if (classify(trainingSet[0], data.pixels) == data.label)
               :            num++;
               :        return num;
               :    }
               :
               :    immutable num = reduce!"a + b"(
               :        std.algorithm.map!(count)(validationSample[0]).array);
               :
               :    writefln("Percentage correct: %f percent",
               :             num.to!double / validationSample[1].to!double * 100.0);
               :}

distanceSqrtの実装を変えてみる。

...
int distanceSqrt(const ref int[] x, const ref int[] y) pure
{
    int total;
    foreach (i, a; x)
        total += (a - y[i]) ^^ 2;
    return total;
}
...

4倍以上早くなった。

$ ldc2 -O knn.d
$ time ./knn
Percentage correct: 94.400000 percent
./knn  2.45s user 0.01s system 99% cpu 2.463 total

その他シングルスレッド版では無駄な処理を省いてみる。

import std.algorithm;
import std.array;
import std.conv;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

struct LabelPixel
{
    int label;
    int[] pixels;
}

auto slurpFile(string filename)
{
    int count;

    return File(filename)
        .byLine
        .dropOne
        .map!chomp
        .map!(a => a.to!string.split(","))
        .map!(a => LabelPixel(a[0].to!int, a[1..$].to!(int[])) )
        .array;
}

int distanceSqrt(const ref int[] x, const ref int[] y) pure
{
    int total;
    foreach (i, a; x)
        total += (a - y[i]) ^^ 2;
    return total;
}

int classify(const ref LabelPixel[] training, const ref int[] pixels) pure
{
    int smallest = int.max;
    int result = void;

    foreach (t; training)
    {
        int tmp = distanceSqrt(t.pixels, pixels);
        if (tmp < smallest)
        {
            smallest = tmp;
            result = t.label;
        }
    }
    return result;
}

void main()
{
    const trainingSet = "trainingsample.csv".slurpFile;
    const validationSample = "validationsample.csv".slurpFile;

    immutable num = validationSample
        .filter!(a => classify(trainingSet, a.pixels) == a.label)
        .count;

    writefln("Percentage correct: %f percent",
             num.to!double / validationSample.length.to!double * 100.0);
}

うーむ、誤差程度。というか少し遅くなってる。

$ ldc2 -O knn.d
$ time ./knn
Percentage correct: 94.400000 percent
./knn  2.52s user 0.00s system 99% cpu 2.528 total

もう一度operfをかけてみる。72%が二乗の処理らしい。

...
               :int distanceSqrt(const ref int[] x, const ref int[] y) pure
               :{
               :    int total;
  8513 13.5856 :    foreach (i, a; x)
 45571 72.7251 :        total += (a - y[i]) ^^ 2;
               :    return total;
               :}
...

operf –assemblyもしてみたがあまりわからなかった。

sub -> imul -> add -> inc の場所で60%以上喰ってるらしいが。。

000000000001a580 <_D3std9algorithm9iteration62__T12FilterResultS213knn4mainFZ9__lambda1TAxS3knn10LabelPixelZ12FilterResult8popFrontMFNaZv>: /* _D3std9algorithm9iteration62__T12FilterResultS213knn4mainFZ9__lambda1TAxS3knn10LabelPixelZ12FilterResult8popFrontMFNaZv total:  54369 86.7655 */
...
  4071  6.4968 :   1a600:   cmp    %rsi,%rbx
    21  0.0335 :   1a603:   jae    1a649 <_D3std9algorithm9iteration62__T12FilterResultS213knn4mainFZ9__lambda1TAxS3knn10LabelPixelZ12FilterResult8popFrontMFNaZv+0xc9>
  3182  5.0780 :   1a605:   mov    (%rcx,%rbx,4),%r8d
 14565 23.2438 :   1a609:   sub    (%rdx,%rbx,4),%r8d
  6849 10.9301 :   1a60d:   imul   %r8d,%r8d
 10065 16.0624 :   1a611:   add    %r8d,%ebp
  9923 15.8358 :   1a614:   inc    %rbx
  5268  8.4070 :   1a617:   cmp    %rax,%rbx
    35  0.0559 :   1a61a:   jb     1a600 <_D3std9algorithm9iteration62__T12FilterResultS213knn4mainFZ9__lambda1TAxS3knn10LabelPixelZ12FilterResult8popFrontMFNaZv+0x80>
...

そもそもなんでRustこんなはやいのか。

objdumpでみてみる。なるほど、SIMDでループをベクトル化してるのか。releaseビルドぱない。

    // run through the two vectors, summing up the squares of the differences
    x.iter()
        .zip(y.iter())
        .fold(0, |s, (&a, &b)| s + (a - b) * (a - b))
    8b80:       f3 0f 6f 0c b7          movdqu (%rdi,%rsi,4),%xmm1
    8b85:       f3 0f 6f 14 b2          movdqu (%rdx,%rsi,4),%xmm2
    8b8a:       66 0f fa ca             psubd  %xmm2,%xmm1
    8b8e:       66 0f 70 d1 f5          pshufd $0xf5,%xmm1,%xmm2
    8b93:       66 0f f4 c9             pmuludq %xmm1,%xmm1
    8b97:       66 0f 70 c9 e8          pshufd $0xe8,%xmm1,%xmm1
    8b9c:       66 0f f4 d2             pmuludq %xmm2,%xmm2
    8ba0:       66 0f 70 d2 e8          pshufd $0xe8,%xmm2,%xmm2
    8ba5:       66 0f 62 ca             punpckldq %xmm2,%xmm1
    8ba9:       66 0f fe c8             paddd  %xmm0,%xmm1
    8bad:       f3 0f 6f 44 b7 10       movdqu 0x10(%rdi,%rsi,4),%xmm0
    8bb3:       f3 0f 6f 54 b2 10       movdqu 0x10(%rdx,%rsi,4),%xmm2
    8bb9:       66 0f fa c2             psubd  %xmm2,%xmm0
    8bbd:       66 0f 70 d0 f5          pshufd $0xf5,%xmm0,%xmm2
    8bc2:       66 0f f4 c0             pmuludq %xmm0,%xmm0
    8bc6:       66 0f 70 c0 e8          pshufd $0xe8,%xmm0,%xmm0
    8bcb:       66 0f f4 d2             pmuludq %xmm2,%xmm2
    8bcf:       66 0f 70 d2 e8          pshufd $0xe8,%xmm2,%xmm2

多摩動物公園に行った

多摩動物公園に行った。

サーバル

お目当てのサーバルキャット。耳はけっこう個体差があるようだ。 あまり人間は好きでないのだろうか、やや人から離れた場所をうろついていた。

ライオン

運良くめちゃくちゃ吼えてるとこに遭遇した。ライオンの咆哮はめちゃくちゃ迫力がある。 目の前で喧嘩もはじまっておしっこちびった。勝てる気がしない。 それでも大半の時間はゆったり過ごしているようだ。

トラ

多摩動物公園で飼育されているのはアムールトラであった。こいつはクマとかも餌にする。つまり勝てない。 トラは室内飼育用の檻と観察用の柵から観ることができた。ボール遊びをしている姿は、やっぱりネコの仲間なのだなあという風情であった。

チーター

ぐるぐる動き回っていた。他の大型肉食獣と比較すると小型だろうが、それでも思っていたより大きくて勝てそうな気はしなかった。 人間には興味があるらしいのか、こちらの様子は常に伺っていた。

ユキヒョウ

チーターよりはひとまわり大きい。まあ勝てないな。結構サービスをしてくれて、目の前で吊るされた丸太に飛びついたりしていた。 ヒョウはちょうど先日テレビで都市との共存というテーマで題材になっていた。ムンバイでは都市部に出没し、家畜を襲うらしい。 近くに「手を出すとかじるよ!」という看板があったけどかじるだけですむのかな?

オオカミ

遠吠えを聞きつけて急行すると、タイリクオオカミがいた。オオカミは4匹の1チームでブースをぐるぐる回っていた。群れるのは卑怯なので勝てない。 何度か目があったので、そこそこ人間に興味はあるようだ。思っていた以上に犬、というかんじだった。 室内飼育のほうでは激しい爪とぎをしていたり、重低音なうなり声をあげていた。一匹でも勝てそうにない。 やはりオオカミなのだな。はじめてみたけど。

ワシ

ワシはけっこう多様な種類がいた。とにかく見た目がかっこいいしワシに生まれた時点で勝ちでしょ。

フクロウ

昼でも活動しているようだった。猛禽類だけあってけっこう大きい。

タスマニアデビル

かなり活発に動いており、可愛らしい見た目もあいまってとても人気があるようだ。実際活動している動物をみるのは飽きない。 タスマニアデビルは顔に腫瘍ができる病気で絶滅しかけているらしい。動物はいろいろな理由で絶滅の危機に瀕している。

カンガルー

やる気がなかった。ブースには糞がたくさんあった。

アフリカゾウ

とにかくでかい。象は賢い動物のようで、検査?のときも自ら進んで脚をあげて協力していた。

インドゾウ

糞を鼻でつかんで人間を攻撃しようとしていた。

キリン

わりと穏やかな生物なのか、実際に触っている人もいた。

クロサイ

なかなか迫力があった。鎧のような皮膚をしている。皮が余っていて垂れ下がっているのだが、あれはいったいなんなのだろうか。 どうでもいいが子どものころ「かんちがい」という絵本が好きだったのだが、あれはサイの親子が出てくる絵本だった。

松江周辺のうまい店

ずいぶん戻っていないが、青春時代の記憶を頼りにまとめた。

  • おおはかや - 鰻のお店。アクセスは悪いけどめちゃくちゃ美味しい。
  • 海鮮問屋博多 - ちょっと場末の香りがする、海鮮系の料理のお店。郷土料理のかにまま、鯛ままがおいしい。
  • きがるそば - 松江でおいしいそばと言えばここ。おすすめはやっぱり割子そば。
  • かつふじ - 松江でとんかつはここがいいだろう。かつももちろん豚汁もかなりおすすめできる。
  • カフェ ブラン - 洋食。隠れ家的なところにある。若鶏の香草パン粉焼きマスタード風味を食べただけだが、他のメニュー全般的に高評価。
  • CAFFE VITA - 全国バリスタ選手権優勝経験者の店。カフェオレボウルで飲むカフェオレが絶品。ちなみにこの店のオーナーの兄も安来に店をかまえており、こちらは世界バリスタ選手権で準優勝した腕前の持ち主。
  • 珈琲館 - ケーキと喫茶店の店。「ウィーンの森」は私が知る限り最高のチョコレートケーキ。
  • リビドー - 松江はケーキも名店が多いが、ただひとつおすすめするとしたらここだろうか。種類も多く食べ比べるのも一興。

この他、ケーキや喫茶店は隠れた名店揃いだ。また境港まで出れば新鮮な魚介類にもありつける。

各OSにおけるRustのインストール方法

たまーに聞かれるので。うろ覚えで書いているので違ってたら直すのでこっそり教えてください。

Linux/macOS/FreeBSD/Windows

rustup使いましょう。macOSでもhomebrew使うよりrustup使ったほうがいいと思います。.bashenvなり.zshenvなりに export PATH="$HOME/.cargo/bin:$PATH" を追記してください。

NetBSD

rustupで入れられるように見えたんですが、つい最近試した時rustupで入りませんでした。packagesにバイナリがあるのですが1.9.0とけっこう古いです。stable/nightly新しいものを使いたければ自前でビルドするほかなさそう?

OpenBSD

こちらはそもそもrustupでサポート対象にされているものではなく、packagesにバイナリもおかれていません。portsのlang/rustに1.10が置かれているので多少古くてもよいならこれをビルドするのが一番楽でしょう。新しいのがほしければこちらも依存を調べてビルドするしかなさそうです。

DragonflyBSD

こちらもrustupは対応していませんが、意外にもpackagesに1.14.0と現時点で最新のstableのバイナリが置かれているので人権があります。

DMD on FreeBSD

だいたいこの記事のとおりなんだけど、細々と補足をしておく。

まず選定したFreeBSDのboxの話。最初はfreebsd/FreeBSD-11.0-STABLEのboxを試していたのだけど、これは毎度VMが突然シャットダウンしてしまって使い物にならなかったためにfreebsd/FreeBSD-11.0-RELEASE-p1を使うことになった。ログも一応目を通したが原因はさっぱり不明。これはけっこう時間を喰ってしまった。

いったんFreeBSDを入れてしまうと案外楽に環境構築はできた。記事中のbash/gcc/curlもpkgでバイナリで手軽にインストールできた他、gitやzshemacs-nox11もあっさりバイナリインストールして既存のLinux環境とだいたい同じような環境を構築できた。まったく同じというわけにはいかずGNU toolとBSD toolにはオプションの差異があるが(lsやnmなど)、そこはmanを見ながら地道に解決していくしかない。

portsのセットアップもNetBSDOpenBSDに比べるとずっと簡単で、だいたいここの通りにやれば解決する。というかOpenBSDportsのmakeがX11に依存してるのおかしいでしょ、X11がなんか壊れたのでportsが機能しなくなってしまったんだよなあ。

D言語環境の構築は公式の提供しているバイナリインストーラを使ったのは元記事に追記しているとおりportsのlang/dmd2がやや古いバージョンであったため。ていうか最新のportsにはまだlang/dmd1が入ってる。最新版のdmd-2.073.0に比べ2017年1月27日時点でのlang/dmd2は2.071.1であった。バイナリインストーラは引数にldcgdcも受け付けられるので他のコンパイラFreeBSDで簡単に動かせるかもしれない。

ところでこの公式インストーラで入るdub、libphobos2.072.2.soに動的リンクしているため、さらにdmd-2.072.2をダウンロードしてdmd-2.073.0より先にactivateするようにして運用している。これはバグなんだろうか。

D言語環境を構築したので https://github.com/kubo39/syscall-d とか https://github.com/kubo39/tiny-d-demo といったプログラムを試しにFreeBSD上でも動くように修正してみた。このあたりはわりと簡単に動かせる状態にできた。

環境構築まわり

どういうツール使ってるかなどまとめておくと移行のときよさそう?

最近使ってるツールだらだらあげていく。

Tool

  • emacs
  • git
  • zsh
  • tree
  • gcc
  • nasm
  • anyenv (pyenv/rbenv/denv)
  • rustup
  • rg
  • binutils (gdb/readelf/objdump/file/nm/etc..)
  • strace
  • ltrace
  • valgrind
  • perf
  • rr
  • wrk
  • firejail

OS setup (ubuntu)

sudo apt install build-essential tree curl valgrind nasm -y
env LANGUAGE=C LC_MESSAGES=C xdg-user-dirs-gtk-update

これから試してみるつもり系

  • tig
  • pv
  • powertop

FreeBSDとNetBSDとOpenBSDをVirtualBox on OSXでいろいろ触る

ここのところ仕事そっちのけでやっています。

FreeBSD 11-STABLE

vagrant init freebsd/FreeBSD-11.0-RELEASEしてvagrant upすると作れる。

デフォルトのシェルはcshだったかな。pkg installでだいたい入るので便利。rustupも使えるしcargo installでripgrepも入る。sys-info crateがFreeBSD対応してなくてparallel crateが動かなかったりはする。dmdは現時点で最新版の2.073.0を入れてみたがlibstdc++.soが見つからないとかで動かなかった。これはgccが入っていないからである。

ただしOSXVirtualBoxFreeBSDを動かしていると突然VMが死ぬのが難点。

NetBSD 7.0

こちらもvagrantでいける。

デフォルトのシェルはbash。PKG_PATHの指定してpkg_addで入れる。デフォルトで入ってるcurlが古くてgitが入らなかったのでpkg_add -u curlしてからpkg_add gitした。rustupがなんかcurlの警告で動かず、rust 1.11がパッケージに入ってるとあったがなんかうまいこといかなかった。

vagrant# PKG_PATH="ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/x86_64/7.0/All"
vagrant# export PKG_PATH
vagrant# pkg_add rust-1.11.0nb1
pkg_add: Can't process ftp://ftp.NetBSD.org:21/pub/pkgsrc/packages/NetBSD/x86_64/7.0/All/rust-1*: File unavailable (e.g., file busy)
pkg_add: no pkg found for 'rust-1.11.0nb1', sorry.
pkg_add: 1 package addition failed
vagrant# pkg_add ftp://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/lang/rust
pkg_add: no pkg found for 'ftp://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/lang/rust', sorry.
pkg_add: 1 package addition failed
vagrant# ^D-bash-4.3$
-bash-4.3$ sudo -i pkg_info
Terminal type is xterm-256color.
We recommend that you create a non-root account and use su(1) for root access.
pkg_install-20150901nb1 Package management and administration tools for pkgsrc
libarchive-3.1.2nb2 Library to read/create different archive formats
pkgin-0.9.4nb1      Apt / yum like tool for managing pkgsrc binary packages
libidn-1.32         Internationalized Domain Names command line tool
bash-4.3.039        The GNU Bourne Again Shell
sudo-1.8.15nb1      Allow others to run commands as root
wget-1.17.1nb1      Retrieve files from the 'net via HTTP and FTP
curl-7.47.1nb1      Client that groks URLs
digest-20160304     Message digest wrapper utility
perl-5.24.0         Practical Extraction and Report Language
libatomic_ops-7.4.4 Multi-platform library of atomic operations by Hans Boehm
boehm-gc-7.6.0nb2   Garbage collection and memory leak detection for C and C++
w3m-0.5.3.0.20161120 Multilingualized version of a pager/text-based browser w3m
-bash-4.3$ su
Password:
vagrant# pkg_add git
pkg_add: no pkg found for 'git', sorry.
pkg_add: 1 package addition failed
vagrant# export PKG_PATH="ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/x86_64/7.0/All"
vagrant# pkg_add git
pkg_add: A different version of curl-7.52.1 is already installed: curl-7.47.1nb1
pkg_add: Can't install dependency curl>=7.50.3nb1
pkg_add: Can't install dependency git-base>=2.11.0
pkg_add: 1 package addition failed
vagrant# ^D-bash-4.3$
-bash-4.3$ su
Password:
vagrant# echo $PKG_PATH

vagrant# export PKG_PATH="ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/x86_64/7.0/All"
vagrant# pkg_add zsh
zsh-5.3: adding /usr/pkg/bin/zsh to /etc/shells
zsh-5.3: registering info file /usr/pkg/info/zsh.info
vagrant# ^D-bash-4.3$ chsh -s $(which zsh)
-bash-4.3$ su
vagrant# pkg_add -u curl
vagrant# curl --version
curl 7.52.1 (x86_64--netbsd) libcurl/7.52.1 OpenSSL/1.0.1p zlib/1.2.3
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP UnixSockets HTTPS-proxy
vagrant# pkg_add git
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/description to /usr/pkg/share/git-core/templates/description
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/applypatch-msg.sample to /usr/pkg/share/git-core/templates/hooks/applypatch-msg.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/commit-msg.sample to /usr/pkg/share/git-core/templates/hooks/commit-msg.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/post-update.sample to /usr/pkg/share/git-core/templates/hooks/post-update.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/pre-applypatch.sample to /usr/pkg/share/git-core/templates/hooks/pre-applypatch.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/pre-commit.sample to /usr/pkg/share/git-core/templates/hooks/pre-commit.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/pre-rebase.sample to /usr/pkg/share/git-core/templates/hooks/pre-rebase.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/prepare-commit-msg.sample to /usr/pkg/share/git-core/templates/hooks/prepare-commit-msg.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/update.sample to /usr/pkg/share/git-core/templates/hooks/update.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/info/exclude to /usr/pkg/share/git-core/templates/info/exclude
===========================================================================
$NetBSD: MESSAGE,v 1.3 2016/05/26 15:41:06 khorben Exp $

NOTE:   Pristine templates are located in:
        /usr/pkg/share/examples/git/templates.

To use the git-cvsimport repository conversion from CVS, install git-cvs.

To use the git-svn interface to Subversion, install git-svn.

===========================================================================

OpenBSD 6.0

こちらもvagrantでいける。

デフォルトのシェルはksh。なんかわりとあっさりpkgまわりがいってしまったので拍子抜け。オレオレdotfilesもzshでうまいこと動くし。 なんとrustもパッケージがあったが1.9というかなり古いバージョンだったので残念。

D言語はそもそもPhobosOpenBSD対応してないので

# export PKG_PATH=http://ftp.jaist.ac.jp/pub/OpenBSD/$(uname -r)/packages/$(uname -p)/
# pkg_add curl
quirks-2.241 signed on 2016-07-26T16:56:10Z
curl-7.49.0:nghttp2-1.12.0: ok
curl-7.49.0:libiconv-1.14p3: ok
curl-7.49.0:gettext-0.19.7: ok
curl-7.49.0:libidn-1.32p1: ok
curl-7.49.0: ok
# pkg_add rust
quirks-2.241 signed on 2016-07-26T16:56:10Z
rust-1.9.0:gcc-libs-4.9.3p9: ok
rust-1.9.0: ok
# rustc --version
rustc 1.9.0
# pkg_add cargo
quirks-2.241 signed on 2016-07-26T16:56:10Z
cargo-0.10.0:libssh2-1.7.0: ok
cargo-0.10.0: ok
# pkg_info
cargo-0.10.0        package manager for Rust language
curl-7.49.0         get files from FTP, Gopher, HTTP or HTTPS servers
gcc-libs-4.9.3p9    GNU compiler collection: support libs
gettext-0.19.7      GNU gettext runtime libraries and programs
libiconv-1.14p3     character set conversion library
libidn-1.32p1       internationalized string handling
libssh2-1.7.0       library implementing the SSH2 protocol
nghttp2-1.12.0      library for HTTP/2
quirks-2.241        exceptions to pkg_add rules
rsync-3.1.2p0       mirroring/synchronization over low bandwidth links
rust-1.9.0          compiler for Rust Language
sudo-1.8.17.1       execute a command as another user
# pkg_add emacs
quirks-2.241 signed on 2016-07-26T16:56:10Z
Ambiguous: choose package for emacs
a       0: <None>
        1: emacs-21.4p36
        2: emacs-21.4p36-no_x11
        3: emacs-24.5p5-gtk2
        4: emacs-24.5p5-gtk3
        5: emacs-24.5p5-no_x11
Your choice: 5
emacs-24.5p5-no_x11:libffi-3.2.1p2: ok
emacs-24.5p5-no_x11:libtasn1-4.8: ok
emacs-24.5p5-no_x11:p11-kit-0.23.2p0: ok
emacs-24.5p5-no_x11:gmp-5.0.2p3: ok
emacs-24.5p5-no_x11:libnettle-3.2: ok
emacs-24.5p5-no_x11:gnutls-3.4.14: ok
emacs-24.5p5-no_x11:xz-5.2.2p0: ok
emacs-24.5p5-no_x11:libxml-2.9.3: ok
emacs-24.5p5-no_x11: ok
Look in /usr/local/share/doc/pkg-readmes for extra documentation.
# pkg_add zsh
quirks-2.241 signed on 2016-07-26T16:56:10Z
zsh-5.2p3:pcre-8.38p0: ok
zsh-5.2p3: ok
# pkg_add git
quirks-2.241 signed on 2016-07-26T16:56:10Z
git-2.9.0:p5-Error-0.17024: ok
git-2.9.0:cvsps-2.1p0: ok
git-2.9.0: ok
The following new rcscripts were installed: /etc/rc.d/gitdaemon
See rcctl(8) for details.
Look in /usr/local/share/doc/pkg-readmes for extra documentation.

~~ dotfiles入れて.zshenvとか適用 ~~

$ sudo -i pkg_info                                                                                                            [openbsd60:rust]
cargo-0.10.0        package manager for Rust language
curl-7.49.0         get files from FTP, Gopher, HTTP or HTTPS servers
cvsps-2.1p0         generate patchsets from CVS repositories
emacs-24.5p5-no_x11 GNU editor: extensible, customizable, self-documenting
gcc-libs-4.9.3p9    GNU compiler collection: support libs
gettext-0.19.7      GNU gettext runtime libraries and programs
git-2.9.0           GIT - Tree History Storage Tool
gmp-5.0.2p3         library for arbitrary precision arithmetic
gnutls-3.4.14       GNU Transport Layer Security library
libffi-3.2.1p2      Foreign Function Interface
libiconv-1.14p3     character set conversion library
libidn-1.32p1       internationalized string handling
libnettle-3.2       cryptographic library
libssh2-1.7.0       library implementing the SSH2 protocol
libtasn1-4.8        Abstract Syntax Notation One structure parser library
libxml-2.9.3        XML parsing library
nghttp2-1.12.0      library for HTTP/2
p11-kit-0.23.2p0    library for loading and enumurating of PKCS#11 modules
p5-Error-0.17024    error/exception handling in an OO-ish way
pcre-8.38p0         perl-compatible regular expression library
quirks-2.241        exceptions to pkg_add rules
rsync-3.1.2p0       mirroring/synchronization over low bandwidth links
rust-1.9.0          compiler for Rust Language
sudo-1.8.17.1       execute a command as another user
xz-5.2.2p0          LZMA compression and decompression tools
zsh-5.2p3           Z shell, Bourne shell-compatible