2014-04-10

OpenSSLはサルによって書かれた

OpenSSLの脆弱性により、OpenSSLを使っているプロセスのどこかの64KBのメモリを何度もガチャ読みし放題というニュースが流れたのは、いまさら言うでもない。この騒動を発端として、OpenSSLのような超重要なソフトウェアが、実は内部的にはいかに悲惨でずさんであるかということを書いた記事が、ネット上に浮上しつつある。

OpenSSL is written by monkeys (2009) | Hacker News

Flingpoo!

OpenSSLのコードが汚すぎるというお話。

インデントだけでも相当変だ。

"OpenSSL has exploit mitigation countermeasures to make sure it's exploitable" | Hacker News

Re: FYA: http: heartbleed.com

むかし、OpenSSLのメモリ確保で、バグがあったら意図的にクラッシュさせるチェック用のコードを仕込んでおいたが、メモリ確保が何重にもレイヤー化されるにしたがって、そのチェック用のコードは何の意味もなくなってしまった。しかし、誰もそのチェク用のコードを無効にしてテストしていないので、その無駄なコードが残っているというお話。

コモンズの悲劇にも似ているが、あまりにも公共すぎるソフトウェアは、誰からも関心を払われないということか。

ドワンゴ広告

この記事は溜まっていたC++論文を解説し終えたので、息抜きにささっとドワンゴ勤務中に書いた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-04-09

2014-02 post Issaquah mailingsのレビュー: N3950-N3966

Post Issaquah論文集のレビューも、これが最後。長かった。

N3950: Defaulted comparison operators

かつて、Alexander Stepanovは、regular typeを提唱した。regular型は、自動的にコピー、代入、比較できるべきであると。

さて、C++では、コピーと代入は自動的にできるが、比較だけは自動的に出来ない。


class X
{
    int a ;
    int b ;
    int c ;
    int d ;
} ;

X a, b ;
a == b ; // ill-formed. 呼び出し可能なoperator ==は宣言されていない。
a < b ; // ill-formed. 呼び出し可能なoperator <は宣言されていない

さて、このクラスXの比較を実装してみよう。


bool operator == ( X const & l, X const & r )
{
    return 
        l.a == r.a &&
        l.b == r.b &&
        l.c == r.c &&
        l.d == r.d ;
}

bool operator < ( X const & l, X const & r )
{
    return
        l.a < r.a && l.a != r.a &&
        l.b < r.b && l.b != r.b &&
        l.c < r.c && l.c != r.c &&
        l.d < r.d && l.d != r.d ;
}

なんと言う機械的なコードだ。このようなコードは、人間が書くべきコードではない。特に比較演算子はひどい。

このような、基本クラスや非staticデータメンバーごとに比較は、自動生成できる。したがって、この論文は、C++に、デフォルトの比較演算子の定義を提案している。

過去のコードの挙動を変えないために、デフォルトの定義を使うには、明示的なdefault化を行わなければならない。


struct Thing {
    int a, b, c;
    std::string d;

    bool operator==(const Thing &) const = default;
    bool operator<(const Thing &) const = default;

    bool operator!=(const Thing &) const = default; 

    bool operator>=(const Thing &) const = default; 
    bool operator>(const Thing &) const = default; 
    bool operator<=(const Thing &) const = default;
};

すなわち、この提案されている機能は、opt-inである。opt-inであるために、既存のコードに影響を及ぼすことはない。

比較の順序は、基本クラスが書かれている順番に比較され、非staticデータメンバーが、宣言されている順番に比較される。


struct D : A, B, C
{
    int a ;
    int b ;
    int c ;
} ;

この例では、比較の順番は、A, B, C, a, b, cである。

[理解に苦しむPDF] N3951: C++ type reflection via variadic template expansion

これはどこまで本気なのか理解に苦しむ提案論文。

この論文で提案されている機能は、コンパイル時リフレクションだ。Variadic Templatesのパック展開を流用して、パック展開できる部分に、型のメンバーを展開できる機能を追加する提案となっている。

この提案は、パック展開を流用している。追加する文法は二つ。

  1. typename<T>...は、T型の名前と、T型のメンバーの識別子に展開される。0個目の展開結果にT型の名前、n個目の展開にn個目のメンバーの識別子の文字列が、UTF-8エンコードされたconst char *で展開される。
  2. typedef<T> ...は、T型のポインターと、T型のメンバーへのポインターに展開される。0個目の展開結果にTへのポインター型のnullポインター、n個目の展開にn個目のメンバーへのポインターが値として展開される。ただし、constexprメンバーは、値として展開される。
// 例
namespace ns
{

struct X
{
    int x ;
    int y ;
} ;

}

// { "ns::X", "x", "y"}と展開される
std::vector<std::string> identifiers{ typename<ns::X>... } ;

// { static_cast< ns::X * >(nullptr), &ns::x, &ns::y }と展開される
auto values = std::make_tuple( typedef<ns::X>... ) ;

新しいキーワードを必要としないし、ASTを弄くる必要もない。極めて質素な機能となっている。

利用例としては、Serializationやdelegatesやgetter/setterの生成、その他が挙げられている。

この論文では提案していないが、この機能を土台にしたサポート用のtratis(is_virtual_baseとかis_protected)などがあればよいと言及している。

また、メンバーを全部列挙するのはパフォーマンス的にも厄介なので、たとえばコンパイル時のフィルターがあれば良いともしている。つまり、typename < T requires U>という形で、Uというboolを返すconstexpr関数で、型に対するフィルターができるようにするなどという機能も議論されている。

また、文字列のエンコードはUTF-8だと明言しているのも興味深いところだ。

当初の提案では、基本クラスやネストされたクラスとその中身や、クラス定義の中のtypedefやenumとその中身まで含めたあらゆる情報を列挙しようというものだったらしいが、それはカオスになるとのことで、いまのレベルに抑えられたらしい。

N3883の壮大な提案と比べると、だいぶ現実的で最小限の質素な提案だ。ただ、これを扱うには、やたらと面倒なテンプレートメタプログラミングの技法が必要になるため、あまり

それにしても、typedef<T>...は、その質素な見た目とは裏腹に、強力すぎて難しい気がする。

ただ、筆者にとっては、N3883を見たときのような心躍るほどの衝撃はない。あれば便利な機能という程度の印象だ。

N3952: C++ Standard Core Language Active Issues

コア言語によせられて、現在議論されている問題集

N3953: C++ Standard Core Language Defect Reports and Accepted Issues

active issuesの中で、議論の結果、実際に問題であると判明した問題集と、その対応の一覧集。

N3954: C++ Standard Core Language Closed Issues

一度はactive issuesに載ったものの、議論の結果、実は問題ではなかったと判断され、取下げられた問題集の墓場。

[PDF邪魔すぎる] N3955: Group Member Specifiers

グループメンバー指定子(Group member Specifiers)の提案。

virtualとかstaticなどのメンバー指定子(member specifiers)は、しばしば連続して複数のメンバーに指定子なければならない。例えば、以下のようなコードになる。

// 冗長なコード
class foo : public bar
{
public:
    explicit foo(int);
    explicit foo(float);
    explicit foo(double);

protected:
    virtual T f() const override ;
    virtual U g() const override ;
    virtual V h() const override ;
    virtual W i() const override ;

private :
    static constexpr int X = 123 ;
    static constexpr float Y = 42.0f ;
    static constexpr double Z = 123.0 ;
} ;

ここでいう、explicitとかvirtualなどは、極めて冗長である。これをひとつにまとめられないか。

N3955提案では、アクセス指定子にメンバー指定子を記述する文法を新たに追加することで、メンバー指定子をグループ化することができる。

// N3955提案
class foo : public bar
{
public explicit :
    foo(int) ;
    foo(float) ;
    foo(double) ;

protected virtual const override :
    T f() ;
    U g() ;
    V h() ;
    W i() ;

private static constexpr :
    int X = 123 ;
    float Y = 42.0f ;
    double Z = 123.0 ;
} ;

これはどうだろうか。筆者には、机上の空論のように見える。教科書に載せるような短いサンプルコードはともかく、現実のコード(コメントやCプリプロセッサーなども含む)は、よりわかりにくくなってしまうような気がするのだが。

どうやら、文法上、指定子なら何でも指定できるようで、以下のようなコードさえ通ってしまう。

// N3955提案
struct X
{
public typedef :
    int int_type ;
    float float_type ;
    double double_type ;
} ;

文法上、以下のコードも通るはずだ。


struct X
{
public int :
    x = 0 ;
    y = 0 ;
    z = 0 ;
} ;

たしかに、冗長性は改善されるものの、うっかり間違いを増やすような気がするのだが。

[とても見づらいPDF] N3956: ISO/IEC CD 14882, C++ 2014 Responses to National Body Comments

NBコメントへの返答。特に目新しい回答はないようだ。

N3957: C++ Standard Evolution Active Issues List

Evolution、つまり、C++に提案されている新機能の文面案に対して議論されている問題集

N3958: C++ Standard Evolution Completed Issues List

上記の問題集にかつて載っていた問題で、対応が完了した問題集。

N3959: C++ Standard Evolution Closed Issues List

議論の結果、実は問題ではなかったとか、重複であったと判断された問題集。

[うんざりするほどPDF] N3960: Working Draft, Technical Specification for C++ Extensions for Parallelism

C++に並列実行を付け加えるTS(Technical Specification)のドラフト。<algorithm>に実行ポリシーを指定して、並列実行やベクトル実行を行える機能を定義している。

規格ではなくてTSなので、これを叩き台に、いずれはC++に取り入れられる合意が得られるような設計になる、かもしれない。

[不適切なtitle要素のHTML] N3961: A proposal to add shared_mutex (untimed)

N3891にあるように、現行のshared_mutexは、TimeLockable requirement(try_lock_for/try_lock_until)も満たすので、実は、shared_timed_mutexと命名されるべきである。そのように改名して、そして、TimeLockableではないuntimed shared mutexを、shared_mutexとして追加する提案。

TimeLockable要件を満たさないことにより、実装により効率的な実装をさせる余地を提供する。

つまりは、従来のshared_mutexを、shared_timed_mutex(try_lock_for/try_lock_untilをサポート)に改名した後釜に、新しいshared_mutex(try_lock_for/try_lock_untilをサポートしない)を提供する提案だ。

N3962: File System TS Editor's Report

Filesystem TSのドラフト編集者の報告書。前回の文面からの変更点が記載されている。

[中身もフォーマットも気に食わないPDF] N3963: Centralized Defensive-Programming Support for Narrow Contracts (Revision 4)

防衛的プログラミングを支援すると称するCプリプロセッサーマクロによるASSERTの変種の提案。

筆者はCプリプロセッサーマクロを使ういかなる提案にも反対の立場である。Cプリプロセッサーはいずれdeprecated扱いされなければならないのだ。

[二つ続けて悲惨なPDF] N3964: Library Foundations for Asynchronous Operations, Revision 1

N3896の改訂版。futureは力不足だ。コールバックこそが最もパフォーマンスがよいことを示し、その上で、futureモデルとコールバックモデルを両方サポートできる設計が必要だと主張している論文。

N3965: Proposal for Unbounded-Precision Integer Types

上限を定めない制度の整数型の提案。いわゆるBigIntの系譜だ。提案は、integerという演算子オーバーロードを駆使して、整数のように振る舞うクラスを提案している。

この手のライブラリは、何度も議論に上がるのだが、どうもなかなか議論が進まない。やはり、万人を満足させる多倍長整数演算ライブラリの設計は難しいのではないだろうか。

もちろん、そのようなC++用のライブラリは、すでに独立した実装が多数ある。しかし、任意の精度の整数演算ができる機能は、モダンなプログラミング言語には標準で備わっている機能なので、C++でも標準化されて欲しいところだ。

N3966: Fixes for optional objects

Issaquah会議で指摘された、optionalの文面上の問題を修正する提案。

今週が始まってから、まだ一度もドワンゴ社内でカタンをしていないので、ドワンゴ勤務中に論文レビューがはかどってしまった。なんということだ。

とりあえずたまっているC++論文の解説は片付いたので、今月末まで、付け焼刃的にECMA-262 Edition 5.1でも読もうかと思う。

ドワンゴ広告

この記事は、ドワンゴ社内でボードゲームをしていない暇に書かれた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

Dell Vostro 1500を手に入れた

休日に買い物に出かけたら、近所の公園でフリーマーケットを行っていた。ほう、これは面白い。なにか掘り出し物があるだろうか。

大方はガラクタであったが、ひとつだけ目に止まったものがあった。何やら、ホコリまみれの汚れたラップトップが無造作に投げ置かれている。

「これはいくらだ?」
「二千円」

二千円? ラップトップが二千円? それは魅力的だ。動けばの話だが。

ラップトップにはACアダプターもついている。ただし、周りの骨董品と同じように投げ置かれていて、表面は泥のようなホコリにまみれている。

ラップトップを開いてみると、内蔵キーボードのキートップがいくつか欠けていた。

「これは動くのか?」
「ノーチェックや」
「それは博打だな」
「ワシもこれ、千円で友達から買うたんや。ワシなら二千円で売れるで」

ここで動作確認が出来ないし、詳細なスペックを調べる方法もない。ラップトップにはられているシールには、Windows XPと、Core2Duoがあった。Core2Duoか。二千円か。

結局、他のものと合わせて買うということで、更に安く買った。

さて、妖怪ハウスに持ち帰って検証を行うと、どうやら動作はするようだ。

ただし、色々と壊れていた。

まず、内臓キーボード全体が、なにか粘着質の液体でもぶちまけたのか、固まって動かなくなっている。バッテリーは死んでいる。

また、それ以外の不満としては、Ethernetが100BASE-Tであることだ。

通常の用途に耐える状態ではないが、動くことは動くので、妖怪ネットワーク内の遊べるサーバーとして使うのが適切だろう。

2014-04-08

cpの速度を計測する方法

ふと、cpの速度を調べてみたくなった。いや、具体的には、ファイルシステムからの読み込みと書き出しの速度だ。

すでにそのようなソフトウェアがないのか調べた結果、pv(Pipe Viewer)が使えそうだ。

apt-get install pv
pv source-file destination-file

なるほど、便利だ。そして表示も直感的でわかりやすい。

pvはパイプの中間に挟んで、速度を計測するのに使うのが本来の使い方だ。

コマンド | pv | コマンド

2014-04-07

2014-02-post-Issaquah-mailingsのレビュー: N3940-N3949

N3940: Draft Filesystem Technical Specification

ファイルやディレクトリの操作を行う標準ライブラリ、FilesystemのTS(Technical Specification)のドラフト

N3941: Filesystem Study Group (SG3) Active Issues List

現在、標準化委員会で議論されている、Filesystemの文面に対する問題集

N3942: Filesystem Study Group (SG3) Closed Issues List

かつてFilesystem active issuesリストに載っていたが、解決されたか、対応するコンセンサスが得られないと判断されたため閉じられた問題集。

N3943: Filesystem Study Group (SG3) Defect Report List

かつてFilesystem active issuesリストに載っていたが、実は問題ではなかったと判断された問題集。

3947: URI - Proposed Wording (Revision 4)

URIを処理するための標準ライブラリの文面案。URIをパースしたり、構築したりといったライブラリである。これは規格ではなくて、TSである。

N3948: Feature-testing for C++ Technical Specifications

C++のTS用の、機能テスト用の標準マクロライブラリ。

理想では、あるC++実装は、C++03, C++11, C++14を、完全に規格準拠にサポートしているか、していないかの二択であるべきである。しかし現実では、C++コンパイラーは、個々の機能を独立して実験的に実装を進めている。また、ドラフト時の挙動と、正式な規格の挙動が異なることもある。

そして、現実では、複数のコンパイラーや、複数のバージョンのコンパイラー間で移植性のあるコードを書かなければならないことがよくある。その場合に、遺憾ながら多用されているのが、Cプリプロセッサーだ。

// よく使われているパターン

// コンパイラーに合わせてマクロを定義しておく

#if HAS_FEATURE_X
// 機能Xを使った実装
#else
// 機能Xを使わない実装
#endif

この論文は、そのような機能テスト用の標準のマクロの、TSに提案されている機能用のものを提案している

必要悪だろうか。いやしかし・・・

[せっかくいい気分でレビューしていたのをぶち壊すPDF] N3949: Scoped Resource - Generic RAII Wrapper for the Standard Library

汎用RAII(Resource Acquisition is Initialization)ラッパーライブラリの提案の改定論文。

指定したリソースを指定したデリーターに実引数として渡して実行する、unique_resource_t(実際に使用する際には、unique_resource関数テンプレートを利用する)、スコープを抜けた時にデリーターを実行してくれる、scoped_guard_t(とscoped_guard関数テンプレート)がある。

// 例
int main()
{
    {
        auto ur = std::unique_resource( new int, []( auto ptr ) { delete ptr ; } ) ;
    }

    {
        auto ur = std::scope_guard( []{ std::cout << u8"抜けたよ" << '\n' ;}
    }
}

unique_ptrは、ポインター用に特化していて、deleteをするデリーターがデフォルトで動く。unique_resourceは、もっと汎用的な設計になっている。

前回の提案からの変更点としては、unique_resource_checkが加わったところだ。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。ところで、ドワンゴには4月からScalaエヴァンジェリストがいる。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-02-post-Issaquah mailingsのレビュー:N3930-N3939

2014-02-post-Issaquah mailingが公開されているので、レビューを続ける。

[title要素が残念すぎる] N3930: C++ Standard Library Immediate Issues

標準ライブラリに持ち上がっている問題の修正案。

特に興味深いものを紹介すると。

2112. User-defined classes that cannot be derived from

あるクラスからの派生を禁止する機能は、finalとしてC++11に入った。

// finalの例
class underivable final { } ;

// ill-formed
class try_derive : underivable { } ;

実は、C++03でも、クラスからの派生を禁止させる方法はあるにはあったが、あまりにもトリッキー過ぎて、それほど一般的に使われていない。

More C++ Idioms/Final Class - Wikibooks, open books for an open world

finalがC++に入ったことで、ユーザー定義型は、簡単に派生を禁止できるようになった。そこで、ひとつ重大な問題が持ち上がった。標準ライブラリに渡す型は、派生禁止を認めるのかどうか、である。

C++の標準ライブラリは、テンプレートを用いて、ユーザーが定義した型を受け取る。標準ライブラリに渡す型には、規程によりいくつかの要件がある。

また、C++には、EBCO(Empty Base Class Optimization)という技法がある。C++では規格上、空のクラスから派生したクラスは、空のクラス分のストレージを無視することが許されている。

// EBCOの例
struct empty { } ;

// EBCOが許されている
struct is_a : empty
{ char c ; } ;

// EBCOの働く余地はない
struct has_a
{
    char c ;
    empty a ;
} ;


上記のコードで、is_aは、empty分のストレージを割り当てるなくてもよいことが、規格上認められている。空の基本クラスに、わざわざ無駄なストレージを割り当てる必要がないということは、、容量効率をよくできる。

このEBCOは、モダンなC++実装では広く使われているし、モダンなSTL実装でも、活用されている。たとえば、unique_ptrを考える。

// EBCOを使わないunique_ptr
template <class T, class D = default_delete<T> >
class unique_ptr
{
    // デリーターをメンバーとして持つ
    deleter_type deleter ;

public :
    deleter_type & get_deleter() noexcept
    {
        // メンバーを返す
        return deleter ;
    }

// 略
} ;

この実装は、deleterが空のクラスであった場合、容量的に非効率である。EBCOを使うと、以下のように書ける。

// EBCOを使うunique_ptr
template <class T, class D = default_delete<T> >
class unique_ptr : D // デリーターから派生する
{
public :
    deleter_type & get_deleter() noexcept
    {
        // 自分はデリーターから派生している
        return *this ;
    }
} ;

このように、自分自身がテンプレート仮引数として与えられるデリーターから派生することで、デリーターが空クラスであった場合にも、容量効率が良くなる。

問題は、C++11で派生を禁止できる機能が入ったことにより、ユーザー定義のデリーターは、finalである可能性がある。これは、EBCOを使っているSTL実装で問題になる。

// EBCOが使えないデリーター
class custom_deleter final
{
    template < typename Pointer >
    void operator () ( Pointer ) cosnt
    {
        // 実装
    }
} ;

// 実装上の問題でill-formedになってしまう
std::unique_ptr< int, custom_deleter > p ;

この問題が指摘された2011年11月30日当時、主要なSTL実装は、EBCOを多用していたので、派生不可能なクラスをテンプレート実引数として渡すと、軒並みコンパイルエラーになってしまった。

また、std::tupleの実装も、派生による主流な実装方法では、動かない。

ではいったいどうするのか。STLに渡す型はfinalであってはならないという要件を追加するのか。しかし、そのような要件を追加してしまうことは、明らかに邪道である。C++的ではない。finalな型も認めなければならない。

この問題は、ある型がfinalであるかどうかを判定できるメタ関数、is_finalがあれば解決する。たとえば、以下のように書ける。

// is_finalがある場合

// EBCO実装
template < typename D, typename = void >
class deleter_holder : public D
{
public :
    D & get_deleter() noexcept
    {
        return *this ;
    }

// コンストラクターなど
} ;

// 非EBCO実装
template < typename D >
class deleter_holder< D, std::enable_if_t< is_final<D> >
{
    D d ;
public :
    D & get_deleter() noexcept
    {
        return d ;
    }

// コンストラクターなど
}

template < typename T, typename D = std::default_deleter >
class unique_ptr : public deleter_holder< D >
{

} ;

このように、簡単なメタプログラミングで対応できる。is_finalのようなコンパイラーマジックが標準化されない場合、ライブラリー実装の移植性がなくなるので、is_finalのようなメタ関数を標準化すべきである

論文の修正案も、is_finalを規格に付け加えるものとなっている。

2132. std::function ambiguity

以下のコードは、オーバーロード解決が曖昧となる。

// オーバーロード解決が曖昧となる例
#include <functional>

void f(std::function<void()>) {}
void f(std::function<void(int)>) {}

int main() {
  f([]{});
  f([](int){});
}

fの呼び出しが曖昧な理由は、std::functionの変換関数が、どのようなstd::functionの特殊化であっても、同一だからである。この問題を解決するには、std::functionの変換関数に与えられた実引数の型が、実際にstd::functionのテンプレート実引数の引数に対して呼び出し可能であるかどうかを調べ、もし呼び出し可能ではない場合、SFINAEなどの技法を使い、候補関数に現れないというメタプログラミングが必要になる。

これを実装するにあたり、呼び出し可能かどうかを調べるには、result_ofだけで十分なのだが、意図を明確にするために、is_callableというメタ関数があったほうがいいのではないかという議論もされたようだ。

最終的には、is_callableは追加しないという方向に向かっている。

2263. Comparing iterators and allocator pointers with different const-character

core issue 179という、大昔の問題が、掘り返されている。

問題は、iterator とconst_iteratorは比較可能であるべきだが、保証する文面が見当たらない。また、pointerとconst_pointerも比較可能であるべきだが、やはり文面による保証が見当たらない、というもの。

コレに対する文面の追加。

その他、些細な文面上の誤りの修正が多い。

N3931: Filesystem Study Group (SG3) Issues Resolved Directly In Issquah

Filesystemのドラフトの文面の小粒な修正集。重箱の隅をつつくような文面の訂正が多い。

例えば、現行文面では、ファイル名の長さは、実装依存(implementation dependent)となっているが、規格ではそのような用語の意味を定義していない。規格で定義している用語には、実装定義(implementation defined)とオペレーティングシステム依存(operating system dependent)がある。ファイル名の長さは、明らかにOS依存であるので、OS依存という用語を使うようにする。などなど。

N3932: Variable Templates For Type Traits (Revision 1)

N3854で提案された、従来の、値を返すtraitsに対する、変数テンプレートのラッパーの、文面案。

たとえば、

constexpr bool b = std::is_same<T, U>::value ;

というコードは、この提案を使えば、

constexpr bool b = std::is_same_v<T, U> ;

と書くことができる。スコープ解決演算子を使う必要がないので、簡潔に書くことができる。命名法則は、従来のtraitsに、_vを追加した名前になる。

実装はとても簡単で、以下の通り。

// N3932の実装例
template < typename T, typename U >
constexpr bool is_same_v = is_same<T, U>::value ;

すでに、型を返すtraitsに対する同様のラッパーは、エイリアステンプレートを使ったものが、C++14に追加されている。

using pointer_type = std::add_pointer<T>::type ;

というコードが、

using pointer_type = std::add_pointer_t<T> ;

このように書ける。コレも、スコープ解決演算子を使う手間を省ける。

この実装も、機械的に簡単だ。

// 実装例
template < typename T >
using add_pointer_t = add_pointer<T>::type ;

N3933, N3934, N3935

[デブいPDF] N3936: Working Draft, Standard for Programming Language C++

現在の最新のC++ドラフト。

本物のC++プログラマーならば、常に最新のドラフトを参照しながらコードを書くはずである。

[もひとつデブいPDF] N3937: Programming Languages — C++

内容はN3936とほぼ同じだが。ISO規格として発行する際の体裁が整えられているドラフト。いよいよC++14発行の日が近い。何事もなければ、今年末に発行される。

N3938: Editor's Report

ドラフト編集者の報告書。前回のドラフトN3797からの変更点を記載している。今回は、git logがついている。

ちなみに、C++ドラフトは、現在GitHubで、ソースコード(tex)が公開されている。

cplusplus/draft

簡単な誤字脱字の修正程度ならば、pull requestも受け付けている。

N3939: Extending make_shared to Support Arrays, Revision 2

std::shared_ptrをネイティブに配列に対応させる提案論文の改訂版。わざわざカスタムデリーターを指定子なくても、shared_ptr<T[]>を認識して、自動的にdelete[]を使ってくれるようになる。

前回のN3870からの変更点は、単一のT &&を受け取るmake_sharedが、議論の結果、取り除かれた。

ドワンゴ広告

この記事は恒例のドワンゴ勤務中に書かれた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-04-04

Rの興隆が科学にオープンソースをもたらす

How The Rise Of The "R" Computer Language Is Bringing Open Source To Science ⚙ Co.Labs ⚙ code + community

予算削減と科学ソフトウェアコストの上昇のおかげで、オープン科学信者は、科学界にオープンソースを持ち込むことに成功しつつある。あまり知られていない言語、Rも貢献している。

Rとは自由な、オープンソースの統計解析ソフトウェアである。MATLABのような民間に所有されている数値計算ソフトウェアや、SASのような統計ツールは、歴史的に、研究所には必要なツールであった。Microsoft Officeがオフィスに必要なように。しかし、ソフトウェアの爆発的なコスト上昇と、研究費の削減により、科学者はRを使いはじめるようになった。

現在、日々増えつつある多数の研究社がR開発コミュニティに参加し、新しいライブラリを作り、Rを統計解析から科学記事やデータをパースしてオンライン上に提供し始めている。これにより、我々が科学を行う方法を変えることができるのだ。

科学界におけるRの由来

今日、科学者はオープンソースソフトウェアを使ってデータを解析している。R言語はこの流行を支援するデファクトツールとなっている。科学業界における統計解析ツールであったことによる。

「私がRを使い始めたのは、2005年に博士課程をやっているときだった。当時は、Rはまだ見慣れぬ言語で、我々がRを統計に使っていることを知っている人すら少なかった」と、科学者のためのRパッケージを開発するrOpenSciプロジェクトのコア開発チームのメンバーであるTed Hart博士は言う。

「私の知る限り、当時の人はたいていSASを使っていた。SASは巨大な、古い、プログラミング言語で、Fortranみたいなものだ。一行づつ解析するとかそのへんの」と博士は言った。

Hartが2011年にポスドクを始めた時、研究をしていたラボはRしか使っていなかった。「Rは進化生物学者のDolph Schluterに教わった。私が院生だった頃と違い、そこの院生は皆使っていた。その部署でRを使っていないのは、私ぐらいなものだった。私はRが広がっていくのを実感した」とHart。

科学出版社、PLoSのArticle-Level Metricsのテクニカルリードを務めるMartin Fennerも同意見だ。「Rはそこらかしこで使われている。みんなRを学んで、何らかの統計に使っている」とFennerは言う。

Rの他の利点としては、金がかからないということと、SASやMATLABみたいな巨大なソフトウェアパッケージのライセンスを取得するのに必要な事務作業が必要ないということだ。

「私は政府機関で働いているが、MATLABは使えそうにない。MATLABの利用料を正当化するための長い文書を書かなければならない。そこで「君、このツールを無料で使えるんだろ。なんでMATLABを使いたいのさ?」と言われるわけだ」とHart。

新しいRのプロジェクト

HartのrOpenSciチームはRを統計解析の外に広げるための門出である。「今まさに動き始めたのだ」とHartは言う。

大海原に漕ぎだす変革は、科学データのデジタルフォーマットの必要性のためだ。Hartと開発チームは、研究者が研究を標準化されたフォーマットで共有、保存しやすいようにするパッケージ群を作った。共有可能な研究が増えるほど、科学はより発展するであろうという考えだ。これがオープン科学運動の基本原理なのだ。

NatureやScientific Data出版のような大手の科学出版社は、研究者に研究データを指定のメタデータフォーマットで提出するように要求している。他の科学組織も、科学データを様々なWeb上の標準的なフォーマットで実績ある場所に上げるよう推奨している。

rOpenSciのRパッケージは、科学コミュニティのデータ標準に合うようにデータを加工するのに役立つ。

EMLというパッケージがある。これは基本的に、Rを使えば、EMLと呼ばれるものから、適切なXMLメタデータをRから出力できるようにする。これはEcological Metadata Languageの略で、Matt JonesとNational Center for Ecological Analysis and Synthesis at the UC Santa Barbaraの人間に酔って開発されたものだ。」とHartは言った。

rOpenSciプロジェクトは、rOpenGovのようなRベンチャーの立ち上げのきっかけにもなった。rOpenSci開発チームが公共ソースのデータをいじりはじめたところ、米国政府の公開情報へのアクセスと社会科学問題に注力するための、新しいプロジェクトの立ち上げにつながったのだ。rOpenGovプロジェクトは、Sunlight Foundationの提供するAPIを活用している。

rOpenHealthグループは、rOpenSciのrpubmedパッケージを管理している。これは、アメリカ国立衛生研究所のPubMedデータベースにアクセスするためのものだ。このプロジェkツオは、公共の健康とヘルスケア業界の研究データにアクセスしやすくすることを目的としている。

ネイティブWebアプリケーション用のR

Web上のある大量のオープンデータは、Rの興隆のおかげだとHartは指摘する。「大勢の人が、多くのパッケージを書いて、Web上のデータを、XMLとかJSONのようなフォーマットに変換している」とHartは言う。

Hartはカリフォルニア大学のDuncan Temple Langと、RStudioの科学者長を務めるHadley Wickhamの名を挙げた。Wickhamは、rOpenSciがWebからデータを落としてくるのに使う、httrパッケージを開発した。

その他の大きなR貢献者としては、マギル大学のRamnath Vaidyanathanがいる。rCharts, rMaps - Interactive Maps from R, Slidifyを開発した。

「rChartsは、データをJavaScriptでWeb上に上げることのできるパッケージだ。rMapsは似たようなものだがLeaflet.jsのようなオープンマッピングフォーマットを使い、JavaScriptによるマッピング視覚化やライブラリを提供する。つまり、データをRでとってきて、これらのネイティブなフォーマットに変換してくれるので、JavaScriptを習得する必要はないわけだ」とhartは言う。

VaidyanathanのSlidifyは、GitHubやDropboxやRPubsで共有されているR Markdownをスライドプレゼンにしてくれる。Markdownとは、プレインテキストをWebで読めるようにするためのマークアップ言語のことだ。

「[Markdown]はとても興味深い。というのも、コードと、何らかの定義の間の境界は、とても曖昧だからだ。どれもひとつのドキュメントになってしまう。Pythonの連中も似たようなことをしている」とFennerは言う。

「たとえば、私はPLoS生物記事を数カ月前に、記事の例として書いた。データが5つほどあるだけ。データは全部Rで処理されていて、記事の中にRコードが含まれている。これを実行したら結果が得られる。結果のデータが得られる」とFennerは言う。

さらに、rOpenSciチームはオンライングラフツールのplotlyと協力している。「我々はplotlyのWeb用のRインターフェースを開発している。これも、RのデータをWebでプロットする方法の一つとなる」

APIによるデータの簡単な取得

オープンアクセス科学出版社のPLoSは最近、記事のテキストとメタデータを検索するためのpublic APIを公開した。関心を持ったR開発者が、このAPIを使い、有益なアプリケーションで研究コミュニティにおける論文の影響力を解析してくれることを願っている。

「腰を落ち着けて、何百万件もの記事を様々な方法で解析したいのであれば、Rはおそらくいい選択だろう。特に、腰を落ち着けるのが夕方で、プログラミングのために数週間を費やしたくない場合は」とFenner。

FennerがPLoS APIを使うときは、何百もの数値が並ぶ結果を出力するより、Rを使って視覚化を行う方を好む。「Rは視覚化のために使っている。私は統計解析には興味がないんだ」とFennerは言った。

「RはAPIから簡単にデータを引っ張ってきて、適切なフォーマットにするために揉んでくれるので、とてもよい」とFennerは付け加えた。

RをAPIに使う強みは、パッケージの豊富さにある。たとえ、他の言語が、専用のライブラリなしに行えたとしてもだ。「Rubyの方が、RよりWebネイティブ系の言語なので、APIを扱うのは、多少やりやすくはあるのだが、Rも使える」とHartは言う。

「つまり、Rが使えるのは、労力を費やしてパッケージを書いているからだ。例えば、httrパッケージがAPIからデータを取得するのを簡単にしているように」とHartは付け加えた。

アカデミアから飛び出すこと

rOpenSciは、生物学データを扱うパッケージを作ることに注力しているが、開発チームは他の分野にも進出しようとしている。「私らは生態学全般を扱う学者みたいなものだからね。それが専門なんだ。だから他の分野に進出しようとしているわけさ」とHartが言った。Sloan財団はrOpenSciに、様々なカンファレンスや大学で宣伝する許可を与えた。

「生物情報科学コミュニティには多くの派閥がある。[Bioconductor]はRのための生物情報科学のための巨大なアドオン集みたいなものだ。これも、アカデミックな研究と民間業界の接点のひとつだろう」と、HartはRの生物科学における広がりを挙げた。

HartはRovolution Analyticsという会社名を挙げた。これはRをビジネス用のデータ解析用に販売している会社だ。「ほら、いわゆるビッグデータとかデータアナリティクスとかデータサイエンスとかいう言葉を使いたくない連中もいるだろ。その手のことが流行したため、Rはビジネス界でさらに浮き上がるだろう。それは、すでに機会学習や統計アルゴリズム用のパッケージが豊富に用意されているという理由からさ」とHartは言った。

未来のR

さらに多くの種類のデータや、さらに多くのWebフレンドリーなフォーマットを出力できるようにパッケージを整えることが、R開発の推進力になる。

「Webネイティブなプロジェクトの境界を押し破るのが見てみたいね。より能力のある開発者を惹きつけるに連れ、パッケージ開発もさらに一般的になるだろう」とHart。

科学研究の検索可能性を上げるのは、始まりに過ぎない。「これが成果を発揮し始めるまで、あと僅かに数年程度だ。これから多くのことが起こるぞ」とFenner。

Hartはより強固なドキュメントや多数のパッケージを保守する必要性を感じている、「科学業界について歯に衣着せずいわせてもらえば、生態学研究に使われているアルゴリズムのいくつかは、やっつけ仕事だ」とHart。

「より注目を集めるにつれ、特に、ビジネス業界で注目を集めるにつれ、より多くの、本物のプログラマーをひきつけるだろう。ほら、Rはコミュニティからひょっこりでてきたものだろ。多くのパッケージは科学者によって書かれていて、科学者はプログラマーではない。私は他のことにフルタイムの時間をとられていて、プログラミングは余暇にやっているんだよ」とHart。

その日まで、Hartと残りのrOpenSciチームは、言語を科学界に普及させる予定だ。月末にhackathonをホストして、RStudioの科学長のような一流のR開発者を招待するのだ。

言語の浮沈にかかわらず、Rの科学サークルにおける立場は強固たるものだ。コミュニティは支援的だ。「Rを使うスレッショルドはとても低い。Rは最高に簡単な言語というわけではないが、すべてが無料で提供されている。質問できるコミュニティがある。利用にあたって障害はない」とFenner。

この翻訳では、文脈から判断して、freeを無料と訳した。彼ら、オープンソース(笑)の連中は自由の価値を理解していないようだ。

Rというプログラミング言語は、研究者の間では広く使われている。

筆者の見解では、Rは統計解析とか、データをグラフ化するなどの、特定の分野には優れているが、汎用のプログラミング言語としては、あまりいいものではない。なぜそのような言語が、汎用に使われているのか。

結局、研究者はプログラマーではないし、プログラマーではないものが、とりあえず動くソフトウェアを書くとなると、ライブラリが充実していて、難しいことを考えずに書ける、COBOLとかVBとかHSPとかJavaのような言語になるのだろう。ないよりマシだろうか。

ドワンゴ広告

この記事はC++とは関係がないがドワンゴ勤務中に書かれた。ドワンゴ社内でRが使われているかどうか、筆者は知らない。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-04-03

Linus様がSystemdにぶちきれる

systemdは、/proc/cmdlineをパースして、もし、その中に"debug"という文字列を発見した場合、大量の冗長なデバッグメッセージをdmsegに出力する。これは様々な問題を引き起こす。まず、"debug"というあまりに一般的すぎる文字列に勝手に反応してしまうことがひとつ。dmseg、すなわちカーネルのリングバッファーをsystemdの冗長なデバッグメッセージだけで溢れ返させてしまうことがひとつ。そして、なぜかLinuxカーネルのブートに失敗してしまうことがひとつ。

Bug 76935 – Do not parse "debug" command line parameter

カーネルコマンドラインに"debug"を与えると、systemdによりパースされる。適当なassertに引っかかると、こんな風にぶっ放される。

[  150.308000] systemd-journald[1559]: Assertion 'dual_timestamp_is_set(&e->timestamp)' failed at src/libsystemd/sd-event/sd-event.c:2191, function sd_event_get_now_monotonic(). Ignoring.
[  150.308000] systemd-journald[1559]: Assertion 'dual_timestamp_is_set(&e->timestamp)' failed at src/libsystemd/sd-event/sd-event.c:2191, function sd_event_get_now_monotonic(). Ignoring.

dmsegがあふれかえり、ログインすらできなくなる。ブートさせるためには、リブートしてコマンドラインから"debug"を取り除かなければならない。だがしかし!、俺はsystemdに邪魔されることなく、"debug"を与えてカーネルデバッグメッセージをみたいんだよ。

systemdがやるべきなのは、"debug"をパースするんじゃなくて、何らかの名前空間を使うべきなんだ。たとえば、"systemd.debug"とかさ。"debug"はカーネルコマンドラインパラメーターであって、systemdのためじゃない。

これに対し、Kay Sieversは、以下のように答えている。

これは仕様だ。何かがぶっ壊れたときは、"debug"はすでに必要以上に大量のメッセージを出力するだろう。

一般的な言葉である"debug"は、基本OSツールからも読み込まれている。

俺は同意しない。一般名詞は一般名詞だ。最初に使った奴に権利が発生するものじゃない。

この問題に対し、Linuxカーネル側で対応すべく、Steven Rostedtによって、/proc/cmdlineから"debug"を隠すパッチがMLに投下された。

LKML: Steven Rostedt: [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline

Date Wed, 2 Apr 2014 14:42:19 -0400
From Steven Rostedt <>
Subject [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline

どうやら、特定のユーザースペースのinitプログラムを利用しているシステムは、カーネルコマンドラインに"debug"という文字列があるとブートしないようである。何が起こっているかというと、このユーザースペースのツールはカーネルコマンドラインをパースし、もし"debug"なる文字列を発見したならば、システムがブートしないほど大量のメッセージを吐き出すためである。これにより、カーネルに対する"debug"というオプションが役に立たなくなるものである。

このバグは同ツールの開発者に報告されたるも、

https://bugs.freedesktop.org/show_bug.cgi?id=76935

返答は:

「一般名詞は一般名詞だ。最初に使った奴に権利が発生するものじゃない」

すなわち、「カーネル」のコマンドラインにある"debug"なる宣言は、カーネルが最初に使ったからという理由で、カーネルが所有しているものではないのだという。彼らは自分のバグの修正を拒んでいる。

さて、吾輩の返答は、我々はカーネルコマンドラインを所有しているのであるからして、我々がそう望むのであれば、ユーザーから見せないことも可能であるということだ。すなわち、このパッチを提案する。このパッチは、"debug"を/proc/cmdlineから隠すものであり、その結果、ツールがパースして、その結果、カーネルのデバッグに支障をきたす懸念を取り除くものである。

訳注:この後に続くパッチは、ユーザースペースに見せるカーネルコマンドライン、すなわち/proc/cmdline用の文字列から、"debug"という文字列を検索して、全て取り除く内容のコードである。

さて、Linus Torvaldsの返信

LKML: Linus Torvalds: Re: [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline

Date Wed, 2 Apr 2014 11:57:41 -0700
Subject Re: [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline
From Linus Torvalds <>

その「奴ら」というのは、Kay Sieversのことだろう。

Kay、テメーの書いたコードの問題をテメーで直さねーから、カーネルで対応しなきゃならねーのには、もういい加減うんざりだぜ。

Greg、言っておくが、俺はこの毎度おなじみの問題が治るまで、Kayのコードはゼッテーにカーネルにマージしねぇ。

この手の問題は、もう何年も何年も起きてて、よくなる気配がねぇ。お前、kdbusパッチのことを言ってたから、お前にも関係あることだぜ。お前のせいでもあるんだから、きっちりやれ。ディストリビューションが必要だと感じたら、奴らの方でマージさせろ。で、ディストロがこの手の開発者と十分に戯れた後で、実際安定しているとわかったなら、俺らもマージしてやるかもしれんな。

だがな。俺は、バグやregressionを気にかけず、他のプロジェクトの連中に、自分のプロジェクトを修正させるようなメンテナー由来の門をマージしたいとは思わん。なぜかというと、俺は自分で問題を修正しないし、自分で修正すべき問題だとも認めない奴らのパッチを受けとりたくねーからだ。

Kay、もう一度言っておく。オメーのせいだ。オメーが直せ。「俺の好きなようにやる。俺の尻拭いは他人がやれ」的なクソを持ち込むな。

Linus

その次に投稿した、Andrew Mortonの発言も、なかなか笑える。

LKML: Andrew Morton: Re: [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline

Date Wed, 2 Apr 2014 12:04:40 -0700
From Andrew Morton <>
Subject Re: [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline

日付を確認したが、どうやら発言は4月1日に行われていたらしいな。

--- a/fs/read_write.c~a
+++ a/fs/read_write.c
@@ -513,6 +513,8 @@ SYSCALL_DEFINE3(read, unsigned int, fd,
  struct fd f = fdget_pos(fd);
  ssize_t ret = -EBADF;
 
+ BUG_ON(!strcmp(current->comm, "systemd"));
+
  if (f.file) {
   loff_t pos = file_pos_read(f.file);
   ret = vfs_read(f.file, buf, count, &pos);

上記のLinuxカーネルに対するパッチは、まずsystemdが実行されているかどうかを検出して、もし実行されていた場合は、BUG_ONマクロにtrueを与えるものである。BUG_ONマクロにtrueが与えられると、BUGマクロの中身が実行される。BUGマクロの中身は、直ちにカーネルパニックを起こすものである。すなわち、systemdが実行されていた場合は、かならずカーネルパニックとなるパッチとなっている。

このパッチは、複数のカーネル開発者から賛同を得ているようだ。Thomas Gleixnerは、「strncmp(current->comm, "systemd", 7)にしてくれない? systemd-xxx的なものも全部補足したいからさ」と改善案を出している。

ところで、Linusによれば、ユーザースペースから/proc/cmdlineをパースするのは、特に問題はない。そもそも、/proc/cmdlineはそのためにある。ただし、あまりにもやりすぎて、dmsegをスパムで埋め尽くすのは問題である、とのことである。

LKML: Linus Torvalds: Re: [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline

ドワンゴ広告

この記事はC++とは関係がないがドワンゴ勤務中に書かれた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-04-01

MSVC++コンパイラーの中に入っているWebブラウザー

You Got Your Web Browser in my Compiler! | Random ASCII

筆者は最近、MicrosoftのVC++コンパイラーがmshtml.dll、すなわちInternet Explorerを読み込むことを発見した。/analyzeオプション(静的コード解析を指示)を使うとコンパイラーがこの挙動を示す。筆者はコンパイラーアーキテクチャの専門家ではないが、インターネットエクスプローラーを読み込むコンパイラーというのはいかにも奇妙だ。

これは単なる気持ちの問題ではないのだ。筆者の環境で静的解析を並列コンパイルすると、コンピューターが数分間も反応が悪くなる。どうやらmshtmlウインドウが、その原因らしいのだ。

いつも通り、筆者はxperf/ETWを使って原因を探った。

本当に問題なのか?

筆者は問題を探すために何日もの時間を浪費したりはしない。問題が私を見つけたのだ。この場合、筆者は新しいコードベースに/analyzeを使おうとしていた。

(/analyzeの利用方法について学びたい場合は、Two Years (and Thousands of Bugs) of Static Analysisを参照されたし)

筆者は並列コンパイルと、並列プロジェクトビルドを有効にしている。どちらの並列ビルドオプションも、デフォルトでプロセッサーの数だけの並列数設定になっているため、プロセッサーの数 * プロセッサーの数だけの数のコンパイラーが実行されることになり、私の環境では、144個の並列コンパイルが走ることになる。筆者は高速なSSDと32GBのRAMを有しているため、多少は遅くなるものの、メルトダウンを引き起こすほどではないと考えている。実際、通常のコンパイルでは、ちょっと遅いかな程度のものだ。ところが、/analyzeでコンパイルすると、筆者のコンピューターは30分ほど反応がなくなるのだ! マウスクリックが処理されるのに、10秒もかかり、タスクマネージャーがウインドウをアップデートするのもまれにしか行われなくなる。これは筆者が並列/analyzeビルドを行うたびに発生する。筆者はこの問題をVS2010で発見していたが、VS2013を使うまで、この問題を真剣に調査することはなかった。

ハング解析

筆者のコンピューターでは、ETWトレーシングを24時間週7日走らせている。データーは300MBのリングバッファに記録されていて、Win+Aを押した時に、いつでもトレースが記録されるようにしてある。これは、ゲーム中にトレースの記録を取りやすいようにするためだが、デスクトップがろっくされたが、トレースだけは取りたい場合にも、都合がいい。Microsoftのwpruiにも、Ctrl+Win+Cというグローバルショートカットで、似たようなものがある。トレースを記録した後、筆者はなんとかビルドをキャンセルさせて、デスクトップのコントロールを取り戻した。そして、トレースを解析して、何が起こっているのかを確かめた。

(wpruiでトレースを記録する方法については、Xperf Basics: Recording a Trace (the easy way)を参照されたし)

「なぜ俺のコンピューターは何重もの並列コンパイル中に反応が悪くなるのか」という質問は、答えにくい種類の質問だ。あまりにも範囲が広すぎる。数十個のコンパイラーがCPU時間を奪い合っているというのは、どのスレッドもCPU時間に飢えている状態になるわけだ。検証には、もっと狭い質問が必要だ。

WPAには、UIハングの検証に役立つグラフがある。Windowsは各アプリケーションがメッセージを確認していない時間を把握していて、もし、アプリケーションがメッセージを確認していない時間が「長すぎる」場合、ETWイベントが発行される。適切なところ(Microsoft-Windows-Win32k)からデータを記録していれば、これらのイベントがトレースに入り、UIディレイグラフがSystem Activity areaに表示される。通常、このグラフは空であるが、筆者の反応しないシステムのトレースは、棒グラフの海となり、何十ものMsgCheckディレイイベントが、システムのあらゆるプロセスから発せされていた。これがその一部だ。

[訳注:画像]

興味深いことに、3/4ほどのハングしたプログラムは、cl.exeのインスタンスだ。Windowsはコンパイラーがメッセージポンプを実行していないと報告している。この事実は、ただちに、「なぜコンパイラーにメッセージポンプがあるのか!」という疑問を生じさせる。

この疑問は、ひとまず無視しよう。その背景事情を考えるのだ。

次のステップは、ハングしたアプリケーションをひとつ選び、なぜメッセージを処理できていないのかという原因を探ることだ。筆者はdwm.exe(Desktop Window Manager)を選択した。なぜならば、これは高優先度で実行されているからだ。このプロセスはシステムがオーバーロードした時もスムーズに動くべきであるので、何か悪いことが起こっているのは明らかである。

UIディレイイベントには、メッセージポンプに失敗しているスレッドのプロセスIDとスレッドID、メッセージが処理されていない時間といった情報が含まれている。これにより、ようやくまともな疑問を構築することができる。

なぜ、プロセスdwm.exe(4336)のスレッド19,308は、トレース開始から84847.551566180秒時点で、2.668秒もメッセージを処理できていないのか?

このしっかりとした疑問があれば、この疑問に答えることができる。

このまともな疑問の存在は重要である。なぜならば、適当にwait analysisをしても、多くのスレッドが何秒も実行されずに待っていることが判明するだけだからだ。wait analysisをするときは、アイドルスレッドは問題ではないという認識を持つことが重要である。コンピューター上のほとんどのスレッドは、たいていの時間はアイドルであるべきなのだ。問題なのは、反応していないスレッドだ。メッセージポンプを行うべきなのに行っていないスレッドだ。だからこそ、UIディレイイベントはとても重要なのだ。反応していないスレッドを抽出してくれる。

(wait chainをたどる方法については、Xperf Wait Analysis–Finding Idle Timeを参照されたし)

反応の遅いdwmスレッドは、ExAcquireResourceExclusiveLiteを、何度も待っていた。時として、何百ミリ秒も待っている。ここで解説されている、ReadyingProcessなどのカラムにより、誰がdwmスレッドを準備可能な状態にするのがが判明する。誰がロックをリリースして、dwmスレッドを実行させるのかが判明する。筆者はこのチェインを手動でしばらく追っていたが、数百回ものコンテキストスイッチの後には、いい加減に飽きた。

そこで、筆者はwpaexporterを使って、関心のある範囲のコンテキストスイッチをすべてエクスポートした。そして、結果をフィルターしてNewThreadStackの中のExAcquireResourceExclusiveLiteのある行だけ得て、Excelでコンテキストスイッチの時間差を計算した。これはlock chainのアタリをつけるためと、誰がロックを長い間握っているか調べるための、手っ取り早くて小汚い方法である。これらのロック所有は、通常はとてもすばやいものである。大方は、1ミリ秒以下である。しかし、大多数が、長い間ロックを握っていた。大方は、16ミリ秒か32ミリ秒だ。観測によれば、15ミリ秒以上もロック所有しているスレッドは全体の3%だというのに、この遅いロック所有は、全体の75%の時間を使っている。

コンテキストスイッチのデータをより詳細にみると、どうやら、遅いロック所有の原因は、スレッドがロックを所有しているのに、CPU時間が割り当てられていないからであるように思われた。そのため、ロックは、OSの次のスケジューリング期間になってCPU時間を割り当てられるまで、未使用のままだ。もしくは、ひょっとしたら、スレッドがロックを所有した後に、タイムスライスを失っているのか。どちらとも言えない。とにかく、これは優先順位の逆転のように思われる。もしくは、単にビジーなシステムで毎秒数千回もロックしたら必ず起こる現象なのだろうか。

訳注:優先順位の高いスレッドがロックの解放を待っているが、そのロックを開放するのは、優先順位の低いスレッドであり、優先順位の低いスレッドにはCPU時間がなかなか割り当てられずに、ロックの解放に無駄に時間のかかる現象。

ExAcquireResourceExclusiveLiteの呼び出しはすべて、SetWindowsPos, CreateWindowExなどの関数から生じているようだ。明らかに、奪い合っているリソースは、ウインドウシステムの重要な部分であるようだ。

lock chainの筆頭に存在するスレッドは、VC++コンパイラーの一部である。CreateWindowExWから呼ばれている。CreateWindowExWとは、コンパイラーにとっては奇妙だ。それから、CreateWindowExWはmshtmlから呼ばれているが、これはさらに解せない。実際、65%のウインドウシステムのロックへのトラフィックは、VC++コンパイラー由来で、ほとんどがmshtml.dllからだ。

つまり、/analyzeを実行すると、コンパイラーは多数のCPU時間をコード解析に費やすと同時に、ウインドウも開く(実際には二つひらく。COM目的にもうひとつ)というわけだ。コンパイラーを多数走らせると、多数のウインドウが開かれて、GPUに負荷がかかる。狂気お墨付き。

コンパイラーのインスタンスは、Visual StudioとかOutlookといった通常のウインドウ付きプロセスより、すこし低い優先順位で実行される。そして、この低優先度と高CPU時間要求と、ウインドウシステムのロックの多用は、問題の根本的理由のようだ。優先順位の逆転を引き起こすのだ。

技術的に、筆者はmshtmlと、ウインドウを開くといったことが、ハングの原因であるかどうかはわからない。筆者が分かるのは、ハングは/analyzeでコンパイルした時のみ起こること、/analyzeコンパイルはmshtml.dllをロードすること、mshtml.dllがwait chainに現れることである。相関と因果はちがうが、だいぶ怪しい

xkcd: Correlation

男「いままで、相関関係があると、因果関係があると思っていたんだ」

男「統計学の授業を取ったら、そうは思わなくなった」

女「授業は役に立った様子ね」
男「うーん、たぶんね」

もし、Microsoftがmshtml.dllをコンパイラーから取り除いたのならば、筆者は喜んで再びテストをして再報告する所存である。

でも、なんで?

ソースコードにアクセスできない以上、筆者には何が起こっているのか明らかではない。だが、これだけは分かる。コンパイラーを/analyzeで実行すると、コンパイラーはmspft120.dllをロードする。/analyzeのDLLだ。そして、mspft120はmsxml6.dllをロードして、XML設定ファイルを読み込む。そして、msxml6はurlmon.dllをロードして、ストリームを開く、そして最後に、urlmonはmshtml.dllをロードする。そして、mshtml.dllはウインドウを作成する。なぜならば、mshtml.dllはそうなっているからだ。

読み込まれてるXMLファイルは、

  • res://C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\mspft120.dll/213
  • res://mspft120.dll/300

この一連の処理は、ある場合においては当然のことであることは確かだ。ただしこの場合においてではない。思うに、だれもmshtml.dllがロードされていることに気がついていないのではないか。もしくは、問題が発覚するほど大規模な並列コンパイルを誰も実行したことがないのか。

訳注:原文ではMSVCがmshtml.dllを読み込むことを検証する方法が書かれているが省略

対処法

Microsoftが、自社のコンパイラーがWebブラウザーを読み込む問題を修正するまでは、大規模な並列ビルドを行う際にこの問題は避けられないようだ。筆者の知る唯一の解決法は、並列数を下げることだ。最大の並列プロジェクトビルドを小さな値に設定することで、ハングの度合いを、まだマシなレベルに抑えられる。

思うに、CPUコアが少なければ、問題を抑えられるのではないだろうか。自動的に過剰な設定が減るわけだから。しかし、筆者は多大な並列性がほしいのだ。やれやれ。

Microsoftにグローバルなコンパイラースケジューラーがあれば、このCPU多使用は回避できたであろうに。

追記

筆者に対して、なぜに段階の並列プロジェクトビルドをやめることで問題解決にはならないのかという質問が寄せられた。その理由は、もちろん、コンパイラーがWebブラウザーを開くなどということは、依然として馬鹿げているからだ。もうひとつの理由は、12並列並行プロジェクトビルドは、12スレッドCPUのデフォルトだからだ。デフォルトの挙動はもっとマシであるべきだ。

対処法が理想ではない最後の理由は、理想のビルド速度を得るためには、2並列並行プロジェクトビルド以上が必要な場合があるからだ。筆者が先週、並列コンパイルのブログ記事で示したように、並列コンパイルはデフォルトで無効になっている。たとえ有効にしても、多くのプロジェクトは、かなりの時間を直列ビルドに使っている。そのため、並列コンパイルと並列プロジェクトビルドを組み合せることが適切なのだ。

特に、我々はほとんどのプロジェクトでプリコンパイルドヘッダーを使っている。VC++はプロジェクトのビルドに際して、プリコンパイルドヘッダーをまずビルドする。プリコンパイルドヘッダーが用意できるまで何もコンパイルしない。そのため、プロジェクトビルドこそが、すべてのプロジェクトのフルビルドを開始時から並列できる方法なのだ。

VC++/msbuildが、144個ものコンパイルを並列実行するのを止めるために、グローバルスケジューラーを持っていないのは残念である。グローバルなコンパイラースケジューラーこそが、プロジェクト外部、内部で、過剰にならずに完全な並列化を達成するための方法であるのに。

それから、並列プロジェクトビルドはグローバル設定であるので、設定値を下げると、いくつかのソリューションが余計に遅くビルドされる。

ドワンゴ広告

この記事は自宅とドワンゴ勤務中の両方で書かれた。MSVCが本物のC++コンパイラーかどうかは議論の分かれるところである。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

Quake IIIを走らせる完全に自由な新規のRaspberry Pi用のGPUドライバーが公開

Quake III bounty: we have a winner! | Raspberry Pi

今年のはじめ、Broadcomは、VideoCore IV graphics coreのGPUドライバーの仕様とGPUドライバーのソースコードを公開した。このGPUはBCM21553に搭載されているものであり、すなわち、Raspberry PiのGPUである。

Android for All: Broadcom Gives Developers Keys to the VideoCore® Kingdom | Broadcom Connected

これにより、Raspberry PiのGPUスタックが自由になった。また、完全に独立した自由なGPUドライバーを作成するための情報が出揃った。

これを記念して、Quake IIIをRaspberry Piの新規のGPUドライバー上で最初に動作させたものに、1万ドルの賞金がかけられた。

この賞金を見事勝ち取ったのが、Simon Hallである。

リンク先では、実際にこの新ドライバー上でQuake IIIを動かすための手順が説明されている。

説明されている手順では、Raspberry Pi上でLinuxカーネルのコンパイルを行っているので、「コンパイルは12時間ほどかかるので、このためにPiをオーバークロックしておくと便利だ」などと書かれている。

この手順書に対し、Hacker Newsでは、

Quake III bounty: we have a winner | Hacker News

「あの、クロスコンパイラーというものがありましてですね」とコメントが付き、そこから、「GCCのクロスコンパイルがいかに大変か」や、「いや、Raspberry Pi用のクロスコンパイルはドキュメントが相当に整備されているので、まだ楽だ」などといったコメントがついている。

2014-03-31

2014-02-post-Issaquahのレビュー: N3920-N3929

前回同様、2014-02-post-Issaquahを引き続きレビューしていく。今回は、N3920からN3929までだ。N3966まであるので、すこし先が見えてきた。

N3920: Extending shared_ptr to Support Arrays, Revision 2

shared_ptrで配列を直接にサポートする拡張案。

現在、shared_ptrで配列へのポインターを扱うには、カスタムデリーターを書いて指定する必要があった。そんな面倒なことをしなくても、shared_ptr<T[]>やshared_ptr<T[N]>を認識して、デリーターを適切に選択してくれるように変更する提案だ。

前回のN3869からの変更点は、特筆すべきでもない細かな文面変更にとどまるようだ。

N3921: string_view: a non-owning reference to a string, revision 7

文字列を、実装の詳細を隠匿して、通過的に扱うためのライブラリ、string_viewの提案の文面案。

文字列を表現する方法として一般的なのが、charなどの文字型の配列と、文字数のペアである。文字列クラスというのは、標準ライブラリにもあるし、また標準ライブラリが目的に合わない場合は、自作されるこのような文字列の実装の詳細を隠して、文字列にアクセスできるラッパークラスが、string_viewだ。

string_viewは、std::basic_stringとほぼ互換のあるメンバーを備えていて、basic_stringのように扱うことができる。

前回の論文からの変更点は、それほど特筆すべきものはない。興味のある読者は、直接論文を読んでもらいたい。

N3922: New Rules for auto deduction from braced-init-list

N3912の提案のための規格の文面案。

[江添フレンドリーとは真逆の存在であるPDF] N3923: A SFINAE-Friendly std::iterator_traits, v3

[PDF注意] N3909によるstd::iterator_traitsをSFINAEフレンドリーにする提案の規格文面案。

[PDFの利用も非推奨扱いにするべき] N3924: Discouraging rand() in C++14, v2

C++11で、新しい乱数ライブラリが導入されたことにより、既存のC時代から受け継いだrand, srand, RAND_MAXと、std::random_shuffleの使用を非推奨扱いにする提案の文面案。

C++11では、より優れた乱数生成と乱数分布のためのライブラリが追加されたので、従来の使いづらく誤用されやすい劣ったrand, srand, RAND_MAXは、規格で使用を推奨しない強いNOTE(注記)を追記する。

std::random_shuffleは、randに依存するオーバーロードがある。また、この関数に独自の乱数生成器を渡す際にも、そのインターフェースが極めて使いづらい。C++11では、新しく設計が洗練されたstd::shuffleが追加されたので、std::random_shuffleもdeprecated扱いにする。

論文では、文面案も示している。

[PDFは採取する必要がない] N3925: A sample Proposal, v4

値の集合の中から、ランダムで標本を採取するアルゴリズム、std::sampleの提案。値がいくつあるかわからなくても正しく採取できる。

もともと、SGI STLにsample, sample_nとして存在したアルゴリズム。提案では、別の名前に分けずに、オーバーロードで切り分ける設計になっている。

そのリファレンス実装も論文に書かれているが、50行程度なので、ここに貼れるほど短い。

// リファレンス実装
template< class PopIter, class SampleIter, class Size, class URNG >
SampleIter
sample( PopIter first, PopIter last
      , SampleIter out
      , Size n, URNG&& g
)
{
    using pop_t = typename iterator_traits<PopIter>::iterator_category;
    using samp_t = typename iterator_traits<SampleIter>::iterator_category;

    return __sample( first, last, pop_t{}
                   , out, samp_t{}
                   , n, forward<URNG>(g)
                   );
}

template< class PopIter, class SampleIter, class Size, class URNG >
SampleIter
__sample( PopIter first, PopIter last, input_iterator_tag
        , SampleIter out, random_access_iterator_tag
        , Size n, URNG&& g
)
{
    using dist_t = uniform_int_distribution<Size>;
    using param_t = typename dist_t::param_type;
    dist_t d{};

    Size sample_sz{0};
    while( first != last && sample_sz != n )
        out[sample_sz++] = *first++;

    for( Size pop_sz{sample_sz}; first != last; ++first, ++pop_sz ) {
        param_t const p{0, pop_sz};
        Size const k{ d(g, p) };
        if( k < n ) out[k] = *first;
    }
    return out + sample_sz;
}


template< class PopIter, class SampleIter, class Size, class URNG >
SampleIter
__sample( PopIter first, PopIter last, forward_iterator_tag
        , SampleIter out, output_iterator_tag
        , Size n, URNG&& g
)
{
    using dist_t = uniform_int_distribution<Size>;
    using param_t = typename dist_t::param_type;
    dist_t d{};

    Size unsampled_sz = distance(first, last);
    for( n = min(n, unsampled_sz); n != 0; ++first ) {
        param_t const p{0, --unsampled_sz } ;
        if( d(g, p) < n ) { *out++ = *first; --n;}
    }

    return out;
}

前回の論文からの変更に、特筆すべきものはないようだ。

[PDFはdefect] N3926: LWG Issue 2168 is NAD

Library issue 2168はNAD(Not A Defect、問題ではない)と結論する論文。

26.5.8.22 p1では、uniform_real_distributionは、\(a \leq x < b\) の範囲に分布する乱数を生成するとある。

26.5.8.22 p2では、uniform_real_distribution( RealType a = 0.0, RealType b = 1.0 ) ;とあり、\( a \leq b \) かつ \(b - a \leq \verb=numerix_limits<RealType>::max()=\) でなければならないとしている。

この文面では、aとbの差が表現可能ではない場合(最もわかりやすい例はa == b)では、26.5.8.22を満たせないではないか。なぜ半開区間なのか。

まず、この文面はもともと\(a < x < b\)だった。しかし、プログラマーというものは、 統計学者や数学者と違い、閉区間ではなく、半開区間を好むものであるので、\(a \leq x < b\)に修正された。issue 2168はこの背景をしらずに追加されたというのがまず一点。

\(a \neq b\)である理由は、\(1 / (b - a)\)を計算する必要があるためである。したがって、\(a \neq b\)である引数を与えるのは、利用者側の責任であるとのことだ。

ただし、\(a \neq b\)が要求されるのは、operator ()を呼び出した時だ。uniform_real_distributionのオブジェクトを\(a = b\)の条件で初期化しても、問題はない。

N3927: Definition of Lock-Free

C++ Standard Library Active Issues 2075を解決するための文面案。

Library issue 2075は、規格の以下の文面を問題としている。

1.10 [intro.multithread] p2

Implementations should ensure that all unblocked threads eventually make progress.

C++の実装は、ブロックされていないスレッドは、いずれ実行が進むことを保証したほうがよい。

ちょっとまて。これを文字通り解釈して保証しようとすると、大変なことになるぞ。アトミック操作にロックフリー程度の保証では実現できないぞ。アトミック操作は、一部のスレッドの実行が進むことを保証するだけだからだ。

そもそも、実行が進む(make progress)とはどういう意味だ。「ブロックされていないスレッド」には、現在ロックされているスレッドは含まれないのか(そうであれば、アトミック操作がロックフリーであるだけで十分なはずだが)

29.4 [atomics.lockfree] p2で、ロックフリー(Lock-free)という用語が使われているが、ロックフリーなる用語の定義がないぞ。そして、議論の結果、どうやらC++規格の文面で使われているロックフリーという用語は、一般的なロックフリーとは意味が異なるものであるぞ。

この問題を解決するために、「ロックフリー」という言葉を定義することにした。文面案は以下の通り

Executions of atomic functions that are either defined to be lock-free (29.7 [atomics.flag]) or indicated as lock-free (29.4 [atomics.lockfree]) are lock-free executions.

ロックフリーと規定されている、もしくはロックフリーであると示唆されているアトミック関数の実行はロックフリー実行である。

  • If there is only one unblocked thread, a lock-free execution in that thread shall complete. [Note: Concurrently executing threads may prevent progress of a lock-free execution. For example, this situation can occur with load-locked store-conditional implementations. This property is sometimes called obstruction-free. —end note]
  • When one or more lock-free executions run concurrently, at least one should complete. [Note: It is difficult for some implementations to provide absolute guarantees to this effect, since repeated and particularly inopportune interference from other threads may prevent forward progress, e.g. by repeatedly stealing a cache line for unrelated purposes between load-locked and store-conditional instructions. Implementations should ensure that such effects cannot indefinitely delay progress under expected operating conditions, and that such anomalies can therefore safely be ignored by programmers. This property is sometimes called lock-free outside this International Standard. —end note]
  • ブロックされていないスレッドがひとつだけ存在する場合、そのスレッド内におけるロックフリー実行は完了しなければならない。[注:平行に実行されているスレッドはロックフリー実行を妨げるかもしれない。たとえば、load-locked store-conditionalな実装をしている場合におこる。このような特徴を、時に、obstruction-freeと言う。注終わり]
  • ひとつかそれ以上のロックフリー実行が平行に実行する場合、少なくとも、ひとつは完了するべきである。[注:一部の実装では、この効果を完全に保証するのは難しい。というのも、他のスレッドからの連続して特に間の悪い干渉が、実行の進展を妨げるかもしれないからである。例えば、load-lockedとstore-conditional命令の間で、キャッシュラインを奪い合う場合。実装は、通常の実行の条件下において、このような効果が、永久に実行の進展を妨げないように保証すべきである。それにより、余りの異常な条件は、プログラマーは安全に無視できる。このような特徴を、時に、この国際規格の範疇の外では、ロックフリーと呼んでいる。注終わり]

[PDFを省略したい] M3928: Extending static_assert, v2

static_assertの2つ目の文字列を省略できるようにする提案。

// N3928提案
static_assert( true )

[PDFで論文を公開すべきではない] N3929: Concepts Lite Specification

Concept LiteのTSドラフト

軽量コンセプトについては、TSが正式に出たときに、詳細な解説記事を書きたい。

TSなので、たたき台に過ぎないのだが。

ドワンゴ広告

この記事はドワンゴ勤務中に鳩サブレーを食べながら書かれた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

LenovoのThinkpad X60を手に入れた

LenovoのThinkpad X60を格安で手に入れた。

基本的なスペックとしては、CPUがIntel Core Duoで、メモリがDDR2の1.5GB、GPUはIntel Media Accelerator 950、HDDはSATA接続で、容量は80GB。ディスプレイのサイズは12.1インチで、解像度は1024x768。1Gb Ethernetはあるものの、USB 2.0ポートしかない。

スペックは今からみれば使い物にならないほど低いが、何しろ格安で入手できたので、おもちゃにちょうどいい。さて、どう料理してくれようか。

まず、メモリーとストレージ容量が低いという問題がある。しかし、わざわざ金を払って、いまさら2GBのDDR2を二枚購入したり、1TBの2.5インチHDDや128GBのSSDを購入して換装するのは、なにか違う気がする。これはこのまま活用すべきであろう。

まず、Ubuntu 13.10 64bit版をインストールしようとしたが、なぜかインストーラーが動かない。おそらく、メモリ不足のために、OOM Killerが仕事をしてしまっているのではないかと思う。32bit版ならインストールできた。

ところで話は変わるが、同居人に、英語を学びたい意欲を示している者がいる。自ら学ぶ意欲を示した者には、環境を与えてやらなければならない。私が多数の人間の善意によって支援を受けてここまでやってきたので、その恩は、次の世代を育てることで返さなければならない。

色々と考えた挙句、NHKのラジオ英語講座を受けさせるのがいいだろうと判断した。本人は、中学程度の英語なら理解していると主張しているが、実際にみてみると、be動詞や時制すらできていないので、やはり基礎からやり直す必要があると判断した。

基礎英語1のテキストとともに、私が英語を学び始めた時にぜひとも読みたかった本、 ビッグ・ファット・キャットの世界一簡単な英語の本を与えた。この本はとても良い本であるが、残念ながらこの本が出版されたときには、筆者はすでに英語をある程度理解してしまったあとであったので、この本は筆者のためには、それほど役に立たなかった。しかし、この本は良い本であることには変わりない。

それから、神保町を回って、捨て値で売られていた研究社の英和、和英辞書、そしてLONGMAN英英辞書を買ってきた。

幸いこの同居人は、洋楽が好きなので、最低限の英語に触れる環境にあった。また、中学高校と、公教育の授業では真面目に学んでいたので、完全に英語を知らないわけでもない。そして、まだ若い。まだ希望はあるだろう。

さて、この同居人は、コンピューターを持っていなかったので、このUbuntuをインストールしたX60を与えてみた。何の環境構築もしていないので、日本語すら入力できない。UIも英語だ。英語と自由ソフトウェアを学ぶにはいい環境だろう。

残念ながら、この同居人は、コンピューターには興味を示さなかったので、X60は回収した。何かを学ぶには、その学ぶべき対象に興味を持つ必要がある。コンピューターに興味を示さない以上、コンピューターからは学べないだろう。強制的に教えても身につかない。同居人は、コンピューター以外のものから英語に触れる必要があるだろう。

さて、そんなわけで、X60が手元にある。とりあえずは来客が手軽にWeb閲覧をする共用端末としてもいいのだが、なにか活用してみたい。

あるいは、手頃なNASとして扱おうか。ラップトップは電力消費が低く、また実質UPSが組み込まれているようなもので、家庭用のお手軽自作NAS用としては優れているのではないか。ただし、内臓のHDDは80GBしかないし、2.5インチだ。USB接続のHDDをつけようにも、USB 2.0という問題がある。どうせ自作するならば、秋葉原で叩き売られている中古PC(1Gb EthernetかつSATAポートが数個はあるやつ)を買ってきたほうがいいのかも知れない。

もちろん、専用のNAS製品のほうが手間がかからないし、パフォーマンスも安定しているだろう。しかし、手間がかからないということは、面白くもないということだ。工夫のしどころがない。

さて、実際に秋葉原に行って、色々と探してみたが、どうも、思ったような中古コンピューターが思ったような値段で見つからない。1万円を切るような値段で売っているコンピューターは、残念ながら私の希望する最低のスペック要件を満たせない(SATA、1000BASE-Tの有無など)

さて、どうするか。こんなことならば、実家から引っ越すときに、コンピューターを持ってくればよかったと後悔している。

とりあえず、X60にSATA-USB変換器を取り付けて、即席にNASを作ってみた。お手軽だったのでSMBを使ってみたが、どうにも不安定だ。私は不自由な二大OSであるWindowsとAppleを一切使わないし、いまはGNU/Linuxしか使っていないのだから、NFSの方がいいだろうか。

2014-03-30

ギークハウス新宿二丁目

最近東京に出てきた筆者は、自らシェアハウスにすみ、またシェアハウス巡りをしている。今回は、ギークハウス新宿二丁目に伺った。

当日は、たまたまギークハウス新宿に飲みによばれたのであった。仕事帰りに向かったのだが、筆者はたまたま、妖怪ハウスに必要なゴミ箱を六箱も抱えていたため、上腕を疲労させながら新宿まで向かった。ギークハウス新宿で飲んでいたところ、場の流れで、ギークハウス新宿二丁目に向かうことになった。

ギークハウス新宿二丁目は、名前通りに、新宿二丁目に存在する。新宿二丁目というのは、ゲイバーが立ち並ぶところであるらしい。

新宿二丁目 - Wikipedia

実際に現地を観察した所、たしかにゲイバーが多かった。

ギークハウス新宿二丁目は、ゲイバーも入っている雑居ビルの上の階に存在した。どうやら、エレベーターが設置されていない雑居ビルの上層階というのは、客が入りづらく、なかなか借り手がいないらしい。そのため、上層階が住居となることは、よくあることなのだそうだ。

さて、ギークハウス新宿二丁目の住人が言うには、私はきわめてもったいない生き方をしているという。せっかく東京に出てきて、機会に恵まれているのに、その機会を存分に活用していないという。

例えばブログだ。私のブログは、広い読者層を獲得する内容ではない。もっと広く浅く書けば、読者が増える。すなわち、私の支持者が増える。私の支持者が増えるということは、それだけ私は強い影響力を行使することができ、様々なことがやりやすくなるであろうということだ。

なるほど、確かに支持者が増え、影響力が高まれば、都合の良いこともあるだろう。しかし、そのために払う犠牲が多すぎる。

まず、広く浅く、一般受けする文章を書く力を向上させると、狭く深く書く能力が失われる。その結果、私はC++の規格の理解をおざなりにして、かわりに、猫画像に適当なキャプションをつけて公開するとか、2chのレスを自作自演してまとめるとか、本の読書感想文を投稿するなどの、よくあるアクセス数だけは稼げるブログのひとつに成り下がってしまうだろう。

広く浅く書く能力だけを鍛えると、いざ、影響力を行使できる状況になったところで、その影響力を行使すべき能力が失われてしまう。

そもそも、影響力とは何なのか。私に盲目的に従う信者の数を言うのか。それはもはや宗教である。私は人間の無謬を信じていない。私は私の周りをイエスマンで固めたいとは思わない。

なおも住人の話は続く。私は妖怪ハウスに住むべきではないという。私は、シェアハウスを運営すべきなのだという。シェアハウスを運営し、利益を上げ、その利益でプログラマーが格安で住めるシェアハウスを提供すべきなのだという。ギークハウス新宿、ギークハウス新宿二丁目、ギークハウス秋葉原の管理人のようになるべきなのだという。そうすれば、自分の才能に気がついていない、誰かからの後押しを必要としているプログラマーの才能を開花させることができるのだという。

たしかに、シェアハウスの運営は興味深い。しかし、今はまだその時ではない。私の理想は吉田寮だが、あの雰囲気を作り出すのは難しい。私がシェアハウスを立ち上げ、運営し、管理し、利益を上げる(あるいは損失をひきうける)ということは、管理者である私に不平等な権力差が発生する。自己主張をしない人間であれば、穏健的な独裁者となることも可能であろうが、私は自己主張をする。したがって、私の管理するシェアハウスは、吉田寮とはならないであろう。

それに、周りにプログラマーが多くいる環境は好ましいが、それだけでは本物のプログラマーにはなれない。本物のプログラマーとなるためには、遅くとも志学までには、プログラミングの価値を理解し、学ぶ意欲を示さなければならない。

私は、プログラミングというのは、直接物理的に対面して教えられることは少ないのではないかと思う。確かに、個々の知識を教えることはできる。しかし、やはりプログラミングの学習というのは、大部分は独学しなければならない。その独学の役に立つのが、文章だ。文章は、いつでも好きなときに読むことができる。

かつまた、ギークハウス新宿二丁目や秋葉原の住環境と家賃は、妖怪ハウスに比べて見劣りするように感じられる。これは、シェアハウスで利益を上げなければならないためである。シェアハウスを住人の自治とし、シェアハウス自体で利益を上げなければ、家賃は安く、一人では到底住めないような広い部屋に住める。

また、この住人の職歴も、私の価値観と反する。この住人は、まずSI屋に雇用されていた。設計に何年もかけ、関係者同士の調整に駆けまわるような仕事だったという。私の価値観では、このようなプロジェクトは極めて非効率的である。これは、住人も認めていた。

この住人が次に就いたのは、転職エージェントだという。転職エージェント・・・これがクセモノだ。

そもそも、エージェント(代理人)というのは、ふさわしい言葉なのだろうか。転職には、雇用者と被雇用者がいるが、いったい、転職エージェントはどちらの代理人なのだろうか。代理人は、一方の代理人であるべきであり、両方の代理人となるべきではない。しかし、どうも日本の転職エージェントは、両方の代理人として振舞っている雰囲気がある。

そもそも、転職エージェントはなぜ必要なのか。この住人が語るところによれば、それは私の価値観に真っ向から反する内容であった。

人を雇いたい企業がいる。希望する人材の条件がある。当然だ。人を雇うのであるから、有能な人材を求めているはずだ。ところが、この条件というのがクセモノだ。

企業が転職エージェントに開示する条件とは、例えば、「32歳以下の人が欲しい」、「男のみ欲しい」、「女のみ欲しい」といった、公にできない条件である。ことによっては、法律に抵触する条件である。こういった公に出来ない、ことによっては違法な条件を転職エージェントに伝える。転職エージェントはその条件を満たす人間のみに企業を紹介する、マッチングを行う。

これは、本質的には何も変わらない。もし、条件が違法であれば、間にプロキシーを一枚かませたところで、違法であることに変わりはない。条件を提示した時点で違法であるからだ。結局、転職エージェントとは、犯罪の片棒を担ぐ仕事であったのか。

そもそも、違法な条件で求人する企業である。すでに法を犯したものに、その余りの法を順守することが望めるだろうか。そのような企業は、たいてい他の法律(例えば労働基準法など)も破っているだろう。そのような企業で働くのは危険である。

かつまた、その企業は、雇用者を能力ではなく、年齢や性別で選別している企業である。すなわち、自分の同僚も同様にして、能力ではなく、単なる年齢や性別のみで選別されて雇用されているに違いない。したがって、同僚は無能である可能性が高い。この点からも、そのような目的で転職エージェントを使う企業で働くのは危険である。

また、住人は言う。転職エージェントは非雇用者にとっても有益である。なぜならば、レジュメを書くにあたって、大抵の人間は、自分を効果的にアピールすることができない。自分の本来の能力を、規程の枚数の紙面で宣伝できない。そのために、プロの指導が必要なのだ。云々

これも、私にはよくわからない。そもそも、プログラマーの能力が、そんなに簡単に紙切れ一枚の上に宣伝できるだろうか。ことプログラミングにおいては、学歴フィルターはそれほど役に立たないし、資格などというものも役に立たない。たとえ、素晴らしい研究をしたものにのみ学位が与えられるだとか、能力を正しく検定して認められる資格があったにせよ、それはその当時のことである。この移り変わりの激しいソフトウェア業界で、5年前、10年前の学位や資格が、状況の変わった今、どれほど役に立つものか。経験年数も、目安にはならない。たとえ無能を5年続けても、経験5年である。

そのようなファンシーなレジュメを追い求めると、手書きの履歴書を評価するような馬鹿げた風潮が流行る。手書きの履歴書を評価項目に加えていいのは、筆耕業者ぐらいなものだ。

こうして、議論は一切の歩み寄りをせず、平行線のまま終わった。

2014-03-28

なんでGCCはa*a*a*a*a*a を (a*a*a)*(a*a*a) に最適化できないの?っと

c - Why doesn't GCC optimize a*a*a*a*a*a to (a*a*a)*(a*a*a)? - Stack Overflow

俺は科学技術計算の数値計算の最適化をしてたんだけどさ。GCCはpow(a, 2)a*aにしてくれるんだな。うん。で、pow(a, 6)は最適化されずに、ライブラリ関数であるpowを呼んじゃうんだ。パフォーマンス的に最悪。(Intel C++ Compilerはpow(a,6)のライブラリ関数呼び出しを消し去ってくれるんだけどな)

どうもよくわからんのが、pow(a, 6)a*a*a*a*a*aで置き換えて、GCC 4.5.1をオプション"-O3 -lm -funroll-loops -msse4"で使ったら、mulsd命令を5個使う。

movapd  %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm14, %xmm13

だが、(a*a*a)*(a*a*a)と書いたら、出力は、

movapd  %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm13, %xmm13

これは、乗算命令が3個になっている。iccもGCCとほぼ同じだ。

なんでコンパイラーはこれを最適化できないんだ?

答え:浮動小数点数演算では、結果が変わってしまうおそれがあるから。

それは、浮動小数点数は結合法則を満たさないからだ。浮動小数点乗算のオペランドの囲み方により、結果の数値精度に影響を及ぼすからだ。

その結果、ほとんどのコンパイラーは、浮動小数点数演算のリオーダリングに対して極めて保守的なのだ。答えが変わらないと確信できるときや、数値精度を気にしない場合にしか最適化できない。たとえば、GCCの-ffast-mathだ。

c - Why doesn't GCC optimize a*a*a*a*a*a to (a*a*a)*(a*a*a)? - Stack Overflow

GCCに-ffast-mathオプションを指定すると、浮動小数点数演算の誤差を気にしないとコンパイラーに伝えたことになる。このオプションを指定すると、GCCは浮動小数点数の演算に対して、大胆な最適化ができるようになる。もちろん、演算精度に注意しなければならない。

What Every Computer Scientist Should Know About Floating-Point Arithmetic(すべてのコンピューター科学者が浮動小数点数演算について知っておくべきこと)

ドワンゴ広告

この記事はC++とは直接関係がないが、ドワンゴ勤務中に書かれた。

ドワンゴはIEEE 754フォーマットを忘れたくても忘れられない本物のプログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-03-27

2014-02-post-Issaquahのレビュー: N3910-N3919

引き続き、2014-02-post-Issaquahの論文集を解説していく。

N3910: What can signal handlers do? (CWG 1441)

シグナルハンドラーの中で、アトミック変数を使えるように文面を変更した所、うっかりと、volatileでもatomicでもない変数が使えないように解釈できる分綿と鳴ってしまった。この文面を修正するにあたって、そもそも、既存の文面を厳密に解釈した所、色々と本来意図しない制限があることが判明した。その制限を緩和する提案。

この文面変更は、もう少し継続した議論が必要だということで、C++14には入らない。

シグナルハンドラーはロックフリーなアトミック操作を行うことができる。

[PDFにする必要が感じられないPDF] N3911: TransformationTrait Alias void_t

エイリアステンプレート、void_tの提案

void_tのリファレンス実装は以下の通り。

// N3911提案のvoid_tのリファレンス実装
template < typename ... >
using void_t = void ;

これだけである。「ハァ? なんだそりゃ」と読者が思うのも無理はない。しかし、これだけなのだ。

なんでこんな単純極まりないものを、標準ライブラリに入れなければならないのか。それは、この一件単純すぎるエイリアステンプレートが、テンプレートメタプログラミングでとても重宝するからだ。

たとえば、ある型が、ネストされた型名typeを持つかどうか調べる、メタ関数を書いてみよう。

// has_typeの実装
template < typename ... >
using void_t = void ;

template < typename, typename = void >
struct has_type
    : std::false_type { } ;

template < typename T >
struct has_type< T, void_t< typename T::type > >
    : std::true_type { } ;

void_tは、任意個の型を受取、かならずvoidを返すので、とても使いやすい。いくらでも型を突っ込むことができる。そして、突っ込んだ型がすべてwell-formedならば、void_t自体もwell-formedになる。ひとつでもill-formedな型がまじっていれば、void_t自体もill-formedとなる。これはつまり、SFINAEのために悪用可能である。

さて、実はこの単純極まりないvoid_tエイリアステンプレートではあるが、ひとつ問題が持ち上がっている。なんと、GCCとClangの間で、実装上の差異があるのだという。なぜそんな自体に陥ったかというと、規格の文面の問題である。なんと、エイリアステンプレートの未使用のテンプレート実引数の扱いをどうするか、規格上、まったく規定していなかったのだという。

この問題は、core issue 1558で把握されていて、現在の議論による解決案は、未使用のテンプレート実引数であっても、SFINAEで考慮されるようになる方向で、変更されるように調整が進んでいる。したがって、この論文の利用方法に合致する。

論文では、当面のworkaroundとして、未使用のテンプレート実引数を出さない、以下のようなマヌケな実装を提示している。

// 当面のマヌケなworkaround
template< class... > struct voider { using type = void; };
template< class... T0toN > using void_t = typename voider<T0toN...>::type;

N3912: Auto and braced-init-lists, continued

これは小さいが下位互換性をぶち壊す提案。

C++11では、braced-init-listをauto指定子でうけると、型はinitializer_listになる。

// C++11のコード
auto x{ 0 } ;       // std::initializer_list<int>
auto x{ 0, 1 } ;    // std::initializer_list<int>
auto x = { 0 } ;    // std::initializer_list<int>
auto x = { 0, 1 } ; // std::initializer_list<int>

新しいlambdaキャプチャーの文法である、init-captureは、autoと同じ方法で型推定を行うので、これは問題になる。

// C++11の型推定ルールを使ったinit-capture
[ x{0} ] (){} ;         // std::initializer_list<int>
[ x{0, 1} ] (){} ;      // std::initializer_list<int>
[ x = {0} ] (){} ;      // std::initializer_list<int>
[ x = {0, 1} ] (){} ;   // std::initializer_list<int>

これはさすがに問題がある。

このため、N3912は、なんと直接初期化の場合、initializer_listとはならない変更を提案している。

// N3912提案
auto x{ 0 } ;       // int
auto x{ 0, 1 } ;    // ill-formed
auto x = { 0 } ;    // std::initializer_list<int>
auto x = { 0, 1 } ; // std::initializer_list<int>

同様に、init-captureも以下のようになる

// N3912提案のinit-capture
[ x{0} ] (){} ;         // int
[ x{0, 1} ] (){} ;      // ill-formed
[ x = {0} ] (){} ;      // std::initializer_list<int>
[ x = {0, 1} ] (){} ;   // std::initializer_list<int>

これは、もちろん下位互換性をぶち壊す。しかし、Issaquah会議での投票により、この変更は好ましいとされた。

この変更が、この最終段階で、C++14に入るかどうかは、未定である。ひょっとしたら入るかもしれないし、次に持ち越されるかも知れない。

これは興味深い変更だ。下位互換性をぶち壊すという点がとても興味深い。

これはもともと、シカゴ会議のときにフィンランドのNBコメントとして出ていて、その時には却下されているが、今回、init-captureという新たな問題が持ち上がったことにより、問題が再認識され、議論が再開された。

[古典的に悲惨なPDF] N3913: Greatest Common Divisor and Least Common Multiple, v2

最大公約数と最小公倍数を計算する関数テンプレート、gcdとlcmを<numeric>に追加する提案。

前回の論文、[PDF注意] N3845では、<cstdlib>に提案されていたが、議論の結果、合意が得られずに、ヘッダーが変更された。

N3914: Additional Core Language Issue Resolutions for Issaquah

コア言語のちょっとした文面上の解釈揺れなどを修正する提案。

N3915: apply() call a function with arguments from a tuple (V3)

tupleの全要素を関数オブジェクトの実引数に渡してくれるヘルパー関数テンプレート、applyの提案。

前回の論文、[PDF注意] N3829からは、ほとんど変更はない。

[PDFという多様性はいらない] N3916: Polymorphic Memory Resources - r2

この提案論文は、アロケーターに実行時ポリモーフィズムを実現するための、Polymorphic Memory Resourcesの提案である。

従来のC++のSTLでは、アロケーターは、テンプレート実引数で指定する。たとえば、独自実装のアロケーターを使いたい場合、以下のように書く。

// アロケーターを指定する例
#include <memory>
#include <string>

// 独自実装のアロケーター
class super_fast_allocator ; 
class awesome_allocator ;


int main()
{
    std::basic_string< char, std::char_traits<char>, super_fast_allocator > s1 ;    
    std::basic_string< char, std::char_traits<char>, awesome_allocator > s2 ;
}

なるほど、これは動く。しかし、色々と問題がある。まず、s1とs2は、別の型になってしまう。s1とs2の違いは、その生のストレージがどのように確保されるかという違いだけで、その他は同じであるはずだ。それにも関わらず、型が異なってしまう。

それに、このコードは、コンパイル時にアロケーターを指定子なければならない。しかし、多くの現実のプログラムは、実行時にメモリ確保の戦略を変えたいはずだし、メモリ確保の戦略を変えるためだけに、わざわざコンパイルし直すことはない。

この問題は、古典的なオブジェクト指向で解決できる。すなわち、抽象基本クラスを指定して、そこから派生して具体的な実装をし、基本クラスへのポインターを経由して、virtual関数を呼び出すのだ。問題は、そのためのアロケーターの基本クラスを、標準ライブラリは定狂していない。そのため、これを実現しようとすると、利用者がそれぞれ独自に基本クラスを定義しなければならなくなる。他人の書いたコードを混在させるのが難しくなる。

そもそも、メモリ確保の戦略をコンパイル時に決定できない状況で、わざわざアロケーターをテンプレート化する意味があるだろうか。コンパイル時に指定する必要のないもの、コンパイル時に汎用化できないものを、テンプレートにする意義は薄い。

このため、N3916は、実行時ポリモーフィズムを実現するためのクラス、memory_resourceと、それを従来のアロケーターにするためのラッパークラス、polymorphic_allocatorを提供している。さらに、それ以上にも色々と提供している。

注意:以下の解説は、まだ提案段階の論文、N3916を元に解説している。この提案のあらゆる内容は変わる可能性がある。

std::pmr名前空間

Polymorphic Memory Resourceのライブラリは、std::pmr名前空間スコープに配置される。pmr名前空間は、仮の名前で、いずれバイク小屋議論を巻き起こすであろう。

memory_resource

memory_resourceとは、抽象基本クラスで、バイト単位の生のストレージの確保、解放をするためのクラスである。このクラスには、allocate, deallocate, is_equalというメンバー関数があり、それぞれdo_allocate, do_deallocate, do_is_equalというpure virtual functionを呼び出す。

// memory_resourceの実装例
namespace std { namespace pmr {

class memory_resource
{
private :
    static constexpr std::size_t max_align = alignof(maxalign_t) ;

public :

    virtual ~memory_resource() { }
    void * allocate( size_t bytes, size_t alignment = max_align )
    { return do_allocate( bytes, alignment ) ; }
    void  deallocate( void * p, size_t bytes, size_t alignment = max_align )
    { do_deallocate( p, bytes, alignment ) ; }

    bool is_equal( const memory_resource & other ) const noexcept
    { do_is_equal( other ) ; }

protected :

    virtual void * do_allocate( size_t bytes, size_t alignment ) = 0 ;
    virtual void do_deallocate( void * p, size_t, bytes, size_t alignment ) = 0 ;
    virtual bool do_is_equal( const memory_resource & other ) const noexcept = 0 ;
} ;

} }

独自のメモリ確保を実装する際には、このmemory_resourceから派生して、do_xxxをオーバーライドする。

// 独自のストレージ確保クラスを実装するひな形
class super_fast_mr
    : memory_resource
{
protected :
    virtual void * do_allocate( std::size_t bytes, std::size_t alignment )
    {
        // サイズが少なくともbytes、でアライメント要求がalignmentを満たすストレージを確保して、そのストレージへのポインターを返す
    }

    virtual void * do_deallocate( void * p, std::size_t, bytes, std::size_t alignment )
    {
        // ストレージを解放
    }

    virtual bool do_is_equal ( const memory_resource & other ) const noexcept
    {
        // *thisとotherを比較
    }
} ;

polymorphic_allocator<T>

polymorphic_allocatorは、memory_resourceをラップして、std::allocatorと同等のインターフェースを提供するクラステンプレートである。std::allocatorのかわりに、共通の基本クラスとして使うことができる。

// 例
class custom_resource : std::pmr::memory_resource
{ /* 実装 */ } ;

int main()
{
    custom_resource cr ;
    using vec = std::vector< int, std::pmr::polymorphic_allocator<int> > ;
    vec v( std::pmr::polymorphic_allocator<int>( &cr ) ) ;
}

ただし、いちいちアロケーターを指定するのは面倒だ。そのため、標準ライブラリで、エイリアステンプレートが用意されている。

// エイリアステンプレートが提供される
namespace std { namespace pmr {

template < typename T >
using vector = std::vecotr< T, polymorphic_allocator<T> > ;

// ... その他のコンテナー
} }

resource_adaptor<Alloc>

resource_adaptorは、従来のアロケーターをmemory_resourceのインターフェースに合わせるラッパークラステンプレートだ。

// 従来のアロケーター
class custom_allocator { /* ... */ }

int main()
{
    using custom_resource = resource_adaptor< custom_allocator > ;
}

その他

new_delete_resource関数は、allocateやdeallocateがグローバルなoperator new, operator deleteを呼び出すmemory resourceへのポインターを返す。

null_memory_resourceは、allocateが必ず失敗してbad_alloc例外を投げるmemory resourceへのポインターを返す。このポインターは、memory resourceの集合の最後に番兵として配置するのに使うことができる。また、テストのために使うこともできる。

get_default_resourceは、プログラムでデフォルトのmemory resourceへのポインターを返す。set_default_resourceは、デフォルトのmemory resourceへのポインターをセットする。

標準のmemory resource

論文では、二種類(細かく分けて三種類)の標準で提供されるmemory resource実装を提案している。

synchronized_pool_resource/unsyncronized_pool_resource

この二つのクラスは、確保したストレージを所有していて、デストラクターで一括して開放する。つまり、確保したストレージ片を個別に開放しなくても、このオブジェクトの破棄とともに、一括解放されるのだ。

// synchronized_pool_resourceの例
int main()
{
    {
        synchronized_pool_resource spr ;
        spr.allocate( 100 ) ;
        spr.allocate( 100 ) ;
        spr.allocate( 100 ) ;
    } // 一括解放される

}

deallocateしなくても、synchronized_pool_resourceが破棄されるときに、そのオブジェクトから確保したメモリは、すべて解放される。

unsynchronized_pool_resourceは、マルチスレッドから同時にアクセスして動くことが保証されていない。そのため、実装に酔っては、スレッド間の同期処理を省くなどして、より効率的な実装とすることを許している。

実装例としては、メモリをチャンクと呼ばれる一定サイズごとに区切って、別々のチャンクごとの専用ヒープから確保するような方法が考えられる。

pool_optionsで、色々と設定もできるようになっている。

monotonic_buffer_resource

これはかなり特殊なメモリ確保戦略を取る。このクラスのdeallocateメンバー関数は、何もしない。このクラスを用いて確保したメモリーを、個別に解放することはできない。確保したストレージは、クラスのオブジェクトに所有され、オブジェクトが破棄されるときに、一括して破棄される。

このmemory resourceは、すぐに一括して破棄する小さなオブジェクト群のためのストレージを高速に確保するのに向いている。

また、polymorphic memory resourceは、これまでstd::functionやstd::promiseが、実装上必要になっていた、アロケーターのtype erasureの実装を、標準化するという意味合いもある。polymorphic memory resourceが採択されれば、std::functionやstd::promiseは、polymorhpic memory resourceを使うと規定されるようになる。

N3918: Core Issue 1299: Temporary objects vs temporary expressions

temporary object(一時オブジェクト)という用語があり、temporary expression(一時式)という用語もある。ところで、exception object(例外オブジェクト)は、もはやtemporaryとは何の関係もない。しかし、現行規格の文面上、関係のあるようになってしまっている。このために、文面を修正して、明確に分離する提案。

[C++論文フォーマットとしてPDFはサポートしなくてよい] N3919: Transactional Memory Support for C++

[PDF注意] N3859の改訂版。どうもあまり違いが見られないようだが。

Transactional Memoryの詳しい解説については、本の虫: 2014-01-pre-Issaquah mailingの簡易レビュー Part 1を参照。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-03-25

2014-02-post-Issaquahのレビュー: N3900-3909

2014-02-post-Issaquah mailingsが公開された。

最新のドラフトは、N3936となった。

[一発目から気分の悪いPDF] N3900: WG21 2014-01-31 Telecon Minutes

2014年1月31日に行われた電話会議の議事録。

[二発目にも気分を害するPDF] N3901: Minutes (February 2014) WG21 Meeting No. 57 N3902: Minutes (February 2014) PL22.16 Meeting No. 62

2014年2月15日に、米国ワシントン州Issaquahで開かれた国際会議の議事録。

N3903: C++ FCD Comment Status

FCDに対するNBコメントへの返答一覧。

スイス(・∀・)< C++14はバグ修正リリースとマイナー新機能のはずだろ。標準規格の品質を下げる新機能を全部外せ。互換性をぶち壊す変更をいれんな。

(´・ω・`)< すまんかった。std::dynarrayとstd::optionalはドラフトから外すわ。

ああ、ああああ。std::optionalが消えてしまう。なんということだ。スイスのせいで・・・スイスのせいで・・・

一方、std::dynarrayは、スタックからネストされた確保という概念に、もう少し議論が必要なので、外すのは妥当である。

このように、国家を代表するNBコメントは、とても強い力を持っている。日本のC++WG JPがNBコメントを送れる状況ではないのは、残念でならない。

イギリスからのNBコメントである、「u8"À"はu8"\u00c8"となり、これをUTF-8エンコードすると、char[3]が、{ 0xc3, 0x80, 0 }と初期化されることになる。しかし、charは0x80を表現可能であると保証されていない」というコメントに対しては、UTF-8のオブジェクト表現は、それぞれUTF-8エンコードのコードユニットの値をもち、0から255までの値は、charとunsigned charで、相互に変換可能な表現方法が存在するという規程が設けられることになった。

最初からUTF-8文字型として、char8_tを規定していればよかったのに。

1759を参照。

また、C++14では、連続したメモリ確保を、一括したメモリ確保に変えることを、実装に許す制限緩和が入った。問題は、そのような制限緩和を行った結果、従来は小さなメモリーリークだったコードが、大きなメモリーリークに変化してしまう可能性がある。

// 大きなメモリーリークになってしまう例
class P {
  int x;
};
class Q {
public:
   Q(){ throw 42; }
private:
   int x[LARGE_NUMBER];
};
{
   P* p1 = new P();
   Q* q1 = new Q(); // bang :-(
   // don't get here
   delete q1;
   delete p1;
}

このコードは、bangの時点で、例外が投げられる。C++11までのように、すべてのnew式で、独立してメモリ確保がされるのであれば、Qで確保されたメモリは、オブジェクトの構築中に例外が投げられたことにより解放されるはずである。しかし、もしPとQのメモリ確保がまとめられるのであれば、Qを構築する部分のメモリもPと一緒に確保されてくっついているので、そのままリークしてしまう。

もちろん、このコードは、もともと間違いであるが、小さなメモリーリークを大きなメモリーリークにしてしまう変更はいかがなものか。そのため、そのような場合に対応するために、何やら変な条件が付け加えられた。

1786を参照。

[title要素のないHTML] N3905: Extending std::search to use Additional Searching Algorithms (Version 4)

現在、STLのアルゴリズムには、std::searchがある。しかし、検索アルゴリズムというのは、ひとつではない。特殊な文脈では、もっと効率的にうごく検索アルゴリズムがある。たとえば、Boyer-Mooreが有名だ。

一般に、これらの検索アルゴリズムは、検索を行う前に、検索準備のためのパターン構築処理を行う。この前処理にはコストがかかるが、検索をかける現実のデータには、たいてい偏ったパターンが存在するので、うまくはまれば検索を高速ができる可能性があり、前処理のコストを考えても、通常の愚直な検索にくらべてお釣りがくることもあるのである。

この論文では、このような検索アルゴリズムを、汎用的にサポートするために、std::searchに新しいオーバーロードを追加することを提案している。新しいオーバーロードされたsearchは、Search Objectという追加の実引数を取る。これは、検索に使われる前処理された結果生成される、何らかのオブジェクトだ。検索する際には、そのオブジェクトを使って検索を行う。

論文では、デフォルトの追加検索アルゴリズムとして、Boyer-Mooreと、その改良版であるBoyer-Moore-Horspool(オリジナルよりメモリ使用量が低いが、worst-caseパフォーマンスでオリジナルに劣る)を追加する提案をしている。

// N3905提案の例

// 従来の検索
auto iter = std::search( corpus_first, corpus_last, pattern_first, pattern_last ) ;

// 従来のコードの新しいインターフェース版
auto iter = std::search( corpus_first, corpus_last, std::make_default_searcher( pattern_first, pattern_last ) ) ;

// Boyer-Mooreによる検索
auto iter = std::search( corpus_first, corpus_last, std::make_boyer_moore_searcher( pattern_first, pattern_last ) ) ;

Boyer-MooreとBoyer-Moore-Horspoolは、比較関数とハッシュ関数の両方を必要とする。

論文筆者によるリファレンス実装が、GitHubに上がっている。

mclow/search-library

[PDF警告] N3906: ISO/IEC PDTS 18822, File System, National Body Comments

Filesystemライブラリに対するNBコメント集。回答は次の会議の後以降になるだろう。

N3908: C++ Extensions for Library Fundamentals, Working Draft

標準ライブラリのTS(Technical Specification)のドラフト。TSは正式な規格とは分離される。C++に対する実験的な拡張案を、すこし正式に提案する程度の位置づけという感じだ。これはC++標準規格とは別物で、実際にC++の正式な規格に入るわけではない。

[江添フレンドリーではないPDF] N3909: A SFINAE-Friendly std::iterator_traits, v2

iterator_traitsをSFINAEフレンドリーにする提案。

SFINAEフレンドリーの解説については、本の虫: 2014-01-pre-Issaquah mailingの簡易レビュー Part 1を参照。

ドワンゴ広告

近況:社内IRCで、":q!"、と誤爆した人がいたが、幸い宗教戦争には発展しなかった。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-03-24

ドワンゴの女子マネという過酷な訓練

ドワンゴ現在、ドワンゴでは「女子マネ弁当」という企画が復活している。

過去の女子マネ弁当の様子については、すでに社外にも相当の情報が出回っているので、例えば以下のような情報を参考にしてもらいたい。

【第1回】ドワンゴ大改革の鍵は、インフラと女子マネージャー。|川上量生の胸のうち|川上量生|cakes(ケイクス) ドワンゴ「助けて! エンジニアが朝出社しないの!」→ 女子マネージャーが弁当を手渡してくれる「女子マネ弁当」システム導入で生活習慣改善へ - ねとらぼ

今回は、その女子マネ弁当の実情に迫る、社内からのレポートをお届けする。

女子マネ弁当の概要とは以下の通りである。

  • 3月17日から、4月25日までの一ヶ月間、午前10時30分までに出社すると、以下の特典がある
  • 午前10時30分から、エンジ色のジャージを来た女子マネ人員(なぜか若い女性のみで構成されている男女比率の偏った集団)が、エンジニアのいるフロアにやってきてラジオ体操をする
  • ラジオ体操をしたのならば、女子マネにスタンプを押してもらう
  • 当日のスタンプの押された用紙を持っていれば、午前11時45分から午後1時15分までの間に、社内カフェテリア(通称リフレ)で、またもや女子マネから、無料の弁当をもらえるし、社内タリーズで当日に限り700円分の買い物が無料でできる。

さて、その実態はどうか。

  • 午前10時頃、女子マネ人員は、エンジニアが極限の集中力を発揮して仕事をしている神聖なフロアにやってきて、ペチャラクチャラとやかましくたわいもない私語をしている。集中力が乱されることこの上ない。このため、本当に集中して仕事をしたいエンジニアは、自分のデスクを捨てて別のフロアに避難している。
  • 午前10時20分頃、手際悪くラジオ体操の音楽をスピーカーから流すテストが行われる(なんどか失敗する)
  • 午前10時30分、ラジオ体操が始まる。女子マネはド素人丸出しのへにゃへにゃな動きでラジオ体操の見本展示をする。
  • 体操後、一人ひとりスタンプカードを持って並び、女子マネに当日のスタンプを押してもらう。これは極めて効率が悪く、時間のかかる作業である。
  • 午前11時頃、ようやく悪夢が去り、エンジニアのフロアは静寂を取り戻す。
  • 午前11時45分から、無料の弁当を求めてドワンゴ社員が殺到するため、リフレが混雑する。このために、昼飯を食べながらリフレでカタンをするという極めて重要な昼の恒例行事が行えない。

謎だ。なぜこんなクソな企画が平然と行われているのか。なぜエンジニアは不満の声を挙げないのか。なぜこんな肥溜めのようなクソに耐えているのか。

どうやら、ドワンゴのエンジニアにとっては、無料の食事はとてつもないほど魅力的らしい。そのために、このようなクソの嵐にも耐えているようだ。

曰く、「無料の食事は素晴らしい」、曰く、「運動不足だけどきっかけがないと運動できない。皆で一斉に行うラジオ体操があれば参加したい」、曰く、「どうせ朝出てこないので関係ない」

しかし、筆者は未だに、エンジニアから、「女子マネは必要だ」という意見を聞いたことがない。体操の見本展示は、体操のプロが行うべきであって、単に若い女であるからという理由だけで集められたド素人に任せる仕事ではない。男女雇用機会均等法の観点からも怪しい。エンジニアが女子マネに反対しない理由は、女子マネ企画に付随する副産物が素晴らしいのであって、女子マネはエンジニアからは望まれていないのだ。

いったいこれは何なのだ。ムチとアメを両方与えているようなものだ。そのアメがあまりにも甘美なために、あえてムチに耐えているだけだ。

だいたい、この上から与えられる娯楽というのは、まったくエンジニアの精神にそぐわない。もし、本物のエンジニアが娯楽が欲しいと思ったら、自分で娯楽を作り出すべきなのだ。上から与えられる娯楽を享受しているだけでは、本物のエンジニアたりえない。

しかし、ここで筆者はあることに気がついた。女子マネが存在しても、別に開発効率は落ちていない様子である。

考えてみれば、午前10時というのは、ドワンゴ感覚で言えば、社外ならば午前5時頃に匹敵する早朝だ。そんな時間に出勤できるエンジニアはまれである。ドワンゴでは、朝といえば午後1時か2時、昼といえば、午後5時か6時ごろなのだ。もし、ドワンゴ社員が、午前10時に社内にいたということは、彼は昨日の夜から社内にいたと考えるべきである。

さらに、筆者がC++WG論文をレビューする速度も、女子マネが始まってから上がっている。なぜならば、リフレが混雑して昼ボドゲができないために、論文を読む時間が増えるのだ。

そうか。そうだったのか。女子マネという一件クソな企画は、エンジニアの効率を上げるための企画だったのだ。エンジニアに規律をもたらす企画だったのだ。

なるほど、それで合点が行くことがたくさんある。いままで、ドワンゴ社内で、なぜこんなにクソなのか理解に苦しむ部分が、多数あったのだ。

たとえば、ドワンゴ社員に支給される作業用のPCは、基本的に、メモリをたったの8GBしか積んでいないクソみたいなスペックのラップトップ一台である。このラップトップは非力すぎて、いまどき仮想環境を一個立ち上げるのにも不満を感じるほどである。これは、そのような非力なコンピューター上でも快適に動作するソフトウェアは、他の環境でも快適に動作するだろうという訓練の一環だったのだ。

支給されるディスプレイは、FULL HDですらない低解像度のディスプレイで、粗悪なパネルを使っていると見えて視野角が非常に狭く、画面全体が小便でガラスを作ったのかと思われるほど黄色い色合いのクソみたいなディスプレイである。いまどき、IPSパネルのディスプレイなど安いはずであるが、あえてこのような尿パネルのディスプレイを使っているのは、画面全体を適当に眺めるのではなく、一字一字、顔面を肉薄させて、しっかりと確認をさせるための訓練であろう。

社内ではEXCEL方眼紙が飛び交っている。これは、エンジニアに一般ピーポーの感覚を植え付けるためであろう。

社内システムのうち、建て替え経費精算システムは、不自由なWindows上で動作する32bit版IE6/7/8でしか動作しない。その理由は、ブラウザーから直接印刷をするために忌まわしきActiveXを使っているからだ。もちろん、そんな超古代の化石のような環境を手元で用意できるわけがない。そのため、リモートデスクトップ接続できる、大昔のIEが動く環境を特別に用意して、建て替え経費精算システムを使う際には、その環境にログインして、そこから行うようになっている。これは、不正な経費申請を防ぐために、わざと使いづらくしているのであろう。

社内には汚らしいニコチン中毒者のために、ガラス張りの大きな喫煙所が設置されている。これは、動物園で檻の中に入ったサルを見学するのと同じものに違いない。麻薬は人をダメにする反面教師としてである。

昔の社屋にはあった昼寝部屋は、今の歌舞伎座タワーに移転してからはなくなった。いまでは、身長160cmの筆者ですらはみ出してしまう、極めて寝心地の悪い狭いソファーがたったの3個、置いてあるだけである。広い喫煙所に比べて、なんと貧相なことか。これは、昼寝ばかりしていないで仕事をしろということだろう。

机も狭くなった。昔は120cmぐらいの奥行きがあり、広さは足元にPCケースが2,3台はおけるほどであり、しかもL字型であったと聞いているが、いまではそっけない机がひとつあるだけだ。これも、空間を効率良く使えという訓練のためだろう。

規律と、貧弱な環境に耐えて作業をさせたいのならば、なぜ裁量労働制を採用しているのか。なぜ昼寝をしている人間を叱らないのか。その理由は、上からの押し付けでは人は変わらないためである。自らその価値に気づかねばならない。徐々にその価値に気づかせる措置が、この一見クソに見える現状なのだろう。

この女子マネ弁当に隠された真の意図に気がついた筆者は、今日は大真面目にラジオ体操を行った。みずから皆の前に立ち、ラジオ体操の見本展示を行った。これから毎日、積極的にラジオ体操に参加することとしよう。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

ドワンゴは、わざと集中力を乱される環境でも、非力なコンピューター環境でも、集中して仕事ができる本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-03-22

SPAMは意外とうまい

妖怪ハウスにSPAMが送られてきたので、ゴーヤチャンプルとSPAM MUSUBI(SPAMを挟んだ海苔巻き)を料理した。

うまい。これはうまい。SPAMがすでに塩分が多いということで、塩を使わなかったのだが、この塩味がちょうどいい。

なんと、筆者は今まで、SPAMの価値をバカにしていた。はるかに多い目方の肉が、より安く変えるこの日本で、SPAMというのは無用の長物だと思っていた。あんなものは味のわからないイギリス人とアメリカ人の食べ物だとばかり思っていた。しかし、この塩味は米とよく合う。

そしてゴーヤだ。筆者は今までゴーヤを食べたことは一度もなかった。ゴーヤというのは、見るからに固そうで、どう料理していいかわからず、買うのを避けてきた。今回、ゴーヤチャンプルを作るために買ったのだが、これがうまい。苦くてうまい。薄切りにして炒めると実にうまい。

そして、SPAMとチーズとアボガドを挟んだ海苔巻きも、実にうまかった。

しかも、SPAM缶はまだ7缶も残っている。SPAM缶は保存が聞く。

スパム、スパム、スパム ラブリースパーム! ワンダフルスパーム! ラブリースパーム! ワンダフルスパーム!

spamが送られてきた

最近の怒涛のようなAmazon.co.jp: 江添亮: 江添のほしい物リスト経由の贈り物もようやく止まり、平穏な暮らしを享受していた今日このごろに、静けさを破って突如やってきたお届け物がひとつ。品名をみると、「減塩スパムランチョミート」と書かれている。

はて、スパム・・・スパム、スパム、ラブリースパーム! ワンダフルスパーム! ラブリースパーム! ワンダフルスパーム!

いかん、バイキングになりかけてしまった。気を取り直して改めてよく観察すると、なんと、沖縄県から送られてきている。本格的だ。

妖怪ハウスには天然のスパムフィルターが常備されており、たまに郵便物が届かないことがある。実際、アマゾンの欲しい物リストで購入済みになっているものが何点か、まだ届いていない。それが、届いていればいいブログのネタになったであろう商品だけに、実に惜しいのだ。

逆に、妖怪ハウス宛ではないのに届いてしまうこともよくある、住所が違っているのに届けられることも珍しくないので、その都度連絡して引き取りに来てもらっている。どうも野方の郵便局や配達業者は、誤配が多い気がする。前に裁判所からの書類が届かなかった例があったそうで、極めて危険なものを感じる。

それはさておき、天然のスパムフィルターを通過してやってきたこのスパム、いったいどう料理してくれようか。

スパムのことは、すぐに記事を書こうと思っていたのだが、あいにくと体調を崩してしまい、今週の後半はブログを書けなかった。病の床に臥せっている時に、もうひとつの小包が届いた。みると、またスパムらしい。

なかには、減塩スパムとガーリックスパムの缶が入っていた。

そして、何やら直方体の箱がひとつ。SPAM™ "MUSUBI"と書いてある。どうやらこれは、スパム・ムスビなる料理を作るための器具らしい。開けてみると、透明なプラスチックの容器と、小型のSPAM缶が入っていた。またSPAMか。

箱の裏側には、"How to make SPAM™ Musubi" と写真付きのスパム・ムスビ作成方法の解説が載っていた。スパム・ムスビとはかっこいいが、単にスパムを挟んだ四角形の海苔巻きだ。なぜスパム・ノリマキという名前ではないのだろうか。

スパム、スパム、スパム、スパム・・・

シャッタープ!

さて、スパムの料理方法だが、このスパム・ムスビという名前の海苔巻きの他には、どうしようか。同居人によれば、ゴーヤ・チャンプルをおすすめされた。ゴーヤを買ってきて料理することとしよう。妖怪ハウスに来た折には、スパムを振る舞うことができるようになったわけだ。

実に、必要に迫られたために、筆者の料理の腕前がめきめき上がりつつある。5kgのスパゲティを手に入れたので、この際にホワイトソースとトマトソースの作り方を会得した。今日明日中に、ミートソースの作り方も会得する予定だ。

さて、またもや本の虫著者の大勝利であります。ブログ著者の戦略はいつも同じ。ブログでネット乞食をしてまんまと物をせしめる。せしめたものはネタとしてためておいて、ブログに駄文を書く。ブログを書いたならば、妖怪ハウスでスパム美味しくスパム料理してスパム食べスパム、スパム、スパム、ラブリースパーム! ワンダフルスパーム!

2014-03-21

妖怪ハウスの電源事情

妖怪ハウスは今、電源問題をかかえている。ブレーカーが落ちるという問題だ。

妖怪ハウスは5LDKの住居で、どうやら区画ごとに20Aのブレーカーが設置されているようだ。

妖怪ハウスのリビングは、住人の集まる共用スペースとなっている。ここには妖怪ハウスの住人が憩うための電化製品が満載されていて、かなりの電力を消費する。

まず、照明が電力を食う。調光機能付きの電球ソケットなので、レフランプか、調光機能に対応した一個5千円以上するとてつもなく高いLEDしか取り付けられない。現在、90Wのレフランプを6個取り付けている。

そして、冬の時期はコタツが設置されている。

もちろん、大型のテレビもあるし、飲み物や食べ物を保管するための冷蔵庫も設置されている。

もちろん、住人はそれぞれにコンピューターを持ち寄って作業する。

そして、レンジまである。このレンジが曲者で、ブレーカーを落とす最後の引き金を引くのは、たいていこのレンジだ。人が集まって電力消費が高くなったところで、誰かがものを温めようとレンジを使い、ブレーカーが落ちるというのがよくあるパターンだ。とりあえず、このレンジは一時的に撤去した。

クーラーも備え付けのものが壁に埋め込まれているのだが、この電源のブレーカーは、ひょっとしたら独立しているのかもしれない。

とにかく、クーラーを無視しても、リビングは電力を消費するのだ。20Aを超えることは、さほど難しくはない。

昨日も、リビングのブレーカーを落としてしまった。原因は分かっている。照明とコタツとホットプレートを使用中に、レンジまで使おうとしたのだ。

ブレーカーが落ちたのならば、戻せばいい。そして、電気が使い過ぎなことが判明するので、後から気をつければいい。そうすれば電気代も安くすむはずである。妖怪ハウス全体の契約アンペアはもっと高いし、ブレーカーが細かく分けられているのであれば、他の場所には影響は及ばない。何が悪いのか。

妖怪ネットワークである。

妖怪ネットワーク、すなわち筆者の構築した妖怪ハウスのネットワーク環境を支えるネットワーク機器は、配線の都合上、リビングに設置されている。つまり、リビングで停電が起きると、全部まとめても消費電力はたったの数十ワットほどのネットワーク機器が、根こそぎ停止してしまう。妖怪ネットワークが死んでしまうのみならず、ネットワーク機器にもよろしくない。

短期的には、他の停電が起こりそうのない、独立したブレーカーの配電された場所から電源を引っ張ってくるworkaroundが考えられる。

問題は、リビングから直接つながっている隣の和室も、ブレーカーの配電としては同じになっているらしく、リビングの停電の巻き添えを食ってしまうのだ。

思うに、キッチンなら停電は少ないはずだ。キッチンには、照明の他には、壁に埋め込まれた電気式のレンジ兼オーブンと、電気ケトルや炊飯器がある程度だ。消費電力の高い機器はあるものの、20Aのブレーカーが落ちるほどの電力消費の集中はしないはずだ。ネットワーク機器にはキッチンから電力を供給しよう。

ネットワーク機器というのは、全部まとめても数十ワット程度なのだから、長期的にはUPSを導入するべきだろう。やれやれ、また出費が大きい。ただ、UPSは一度使ってみたかった機器なので、この機械に触ってみるのもいいだろう。

2014-03-18

みずほ銀行の信じられない契約軽視姿勢

仕事のため、みずほ銀行の個人の口座を作る必要があったのだが、その銀行口座を解説する手続きで、対応にあたった行員が、極めて信じられないほどに契約というものを軽視していた。

みずほ銀行に口座を開く手続きのために、書類に必要な事項を記載し、署名捺印となった。行員は捺印の二箇所を私に指示した。一箇所は単に捺印するだけであったが(法的にも、印鑑は署名の代わりに補助的に用いることができるだけの極東の奇妙な風習である)、もう一箇所には、「私は規約に同意しました」的な文面があった。

はて、これはなんだろう。

私「すみません、これはなんですか」
行員「そこに押してください」
私「いえ、この規約ですが、これはどこにあるのですか」
行員「それでしたら裏にあります」

なるほど、裏にかかれていた。その規約を確認すると、みずほ銀行は私の個人情報を、市場調査などの統計解析のために使うことができるし、ダイレクトメールを送りつけるためにも使うことができると書かれていた。

私「市場調査のための統計解析に私の個人情報を使うのですか?」
行員「はい。それは市場調査のために使う可能性があるということです」
私「ダイレクトメールを送るために私の個人情報を使うのですか?」
行員「いえ、それは、クレジットカード会社が宣伝のためにダイレクトメールを送る可能性があるということです」
私「しかし、この文面によれば、クレジットカード会社に限るようには読めませんが」
行員「えーと、ちょっとすみません」
(行員、規約の文面を確認する)
行員「そのようですね」

何だこの素人ぶりは? 可能性? なぜ人に契約するよう指示する文面について理解していないのだ。

さらに確認すると、その他の規約については、別のもの(文書名を失念)を参照している。なるほど、するとその参照されている[文書名]の規約にも同意したことになるわけだ。

私「この[文書名]はどこで閲覧できますか?」
行員「それは契約後に自宅に送る資料に含まれています」
私「今確認できないのですか?」
行員「あとで自宅に送ります」
私「あなたは、今ここで私が確認できない契約への同意を私に求めているのですか?」
行員「あとで手元に資料が届いて、確認した後に解約できます」

いったい何なんだ。この契約の軽さは。みずほ銀行というのはこんなにも契約を軽んじている銀行なのか。

私「そもそも、あなたははんこを押すことを私に指示する前に、この規約を私に読ませるべきだったのではないですか」
行員「そうでした。すみません」

行員は何の感情も示さずに、慌てず騒がず、プロフェッショナルに謝罪した。まるで機械のような即答ぶりだった。不思議だ。ここは本来、大慌てするべきところではないのか。この行員は、契約締結にあたって、私に契約内容を一切説明しなかったのだ。そのような契約の有効性は疑わしいものだ。

仕事で必要なので、私は仕方なくみずほ銀行の口座を作った。しかし、みずほ銀行のこの契約に対する軽さはなんなのだろう。みずほ銀行員は契約の文面を契約予定者に確認させずに、契約予定者に署名捺印を指示した。これは単に行員個人の問題ではなく、みずほ銀行全体の問題のように思われる。

そういうわけで、今や私の個人情報は、みずほ銀行が市場調査などの統計解析のために使うことができるし、私の自宅にダイレクトメールを送るためにも使えることになったわけだ。私が住所を公開しているからといって、SPAM(SPAM缶ならば歓迎だが)を送りつけていいことにはならない。しかし、みずほ銀行は契約により、私にSPAMを送り放題ということだ。

2014-01-pre-Issaquah-mailingのレビュー:N3890-N3899

N3890: Container<Incomplete Type>

一部のコンテナーのvalue_typeに、不完全型(Incomplete type)を許すよう、制限を緩和する提案。

この提案により、以下のようなパターンが合法になる。

// 再帰的なクラス宣言
struct Foo
{
    std::deque<Foo> deq ; 
} ;

クラスは、クラス定義の閉じカッコ、'}'を持って、完全型になる。したがって、クラス定義の中では、クラス名はまだ不完全型なのだ。クラス定義の中でテンプレート実引数にクラス名を渡すと、当然不完全型になる。

ここで、std::dequeの実装が、sizeof(value_type)のような記述をしていた場合、ill-formedとなる。

std::dequeの実装で、sizeof(value_type)のような、value_typeが不完全型であるとill-formedとなるような記述を避けることは可能である。しかし、現行のC++標準規格は、value_typeに不完全型を許していないので、上記のコードがC++98/11/14で通るかどうかは、実装依存である。

有名どころのC++実装で言えば、libstdc++のdequeは不完全型に対応しているが、libc++と、Microsoftの不自由なC++コンパイラーに付属のSTLは、ill-formedとなる。どちらの実装も、この点においては規格準拠である。

しかし、C++98時代から、このような再帰的なクラス定義のパターンを使いたいという需要は相当にあったlibstdc++の多くのコンテナーが、不完全型に対応しているのは、そのためである。

N3890提案は、多くのコンテナーを不完全型に対応させることを提案している。std::arrayのような特殊なコンテナーは対応できないが、set/mapやunordered_set/unordered_mapまで対応するという。

さて、既存のC++実装を、不完全型に対応させるのは、技術的に難しくはない。技術的な困難はないものの、現実的な困難はある。

  • LLVMのSTL実装であるlibc++は、対応可能である。ただし、std::dequeのABI互換性が壊れてしまう
  • GCCのSTL実装であるlibstdc++は、対応可能である。ただし、std::dequeのABI互換性が壊れてしまう
  • 不自由なソフトウェアであるMSVCのSTL実装は、デバック可視化機能のために、コンパイル時定数を維持したい部分がかなりある。このため、std::dequeのようなクラスの対応は予定していない。std::listやstd::forward_listの対応には興味を示している。

また、コンテナーにユーザー定義のstd::lessやstd::hashを与える場合は、その型も不完全型をサポートしていなければ、コンテナーは不完全型対応にはならない。対応しなければ、コンテナーが不完全型に対応しないだけなので、既存のコードが壊れることはない。

libc++のコンテナーを不完全型に対応させた実験的実装が、GitHubで公開されている。

lichray/libcxx at container_incomplete

それにしても、一昔前は、C++の実験的実装といえばGCCだったのに、いまではすっかりLLVMにお株を奪われている。LLVMのコードは読みやすく、ハックしやすいからであるが、このままではGCCの牙城が危うい。

[title要素と論文のタイトルが異なる悪く書かれたHTML] N3891: A proposal to rename shared_mutex to shared_timed_mutex

現行規格では、shared_mutexはtimed mutex(TimeLockable要件を満たす、すわなち、try_lock_for/try_lock_untilを提供している)かつ、shared mutex(同一の、例えばスレッドなどの実行媒体から、複数回ロックできる)である。

とすれば、shared_mutexは、実際には、shared_timed_mutexとしたほうがいいのではないか。そうすることによって、timed mutexの要件は満たさないが、shared mutexとしての要件は満たすクラスを効率的に実装できる自由度を、C++実装に与えることになる。

そういうわけで、現行のshared_mutexを、shared_timed_mutexに変更する提案。

N3892: C++ Ostream Buffers

現行規格では、ストリームに対する出力操作は、競合を引き起こさないことが規定されている。しかし、其の出力がどうなるかについては規定されていない。したがって、複数の実行媒体(execution agent)からストリームに出力した場合の結果がどうなるかは、規定されていない。

このため、C++利用者は、独自の方法で同期を取らなければならない。独立したソースコードは独立した同期方法を取るため、複数のソースコードを混在させることが難しい。そのため、ストリーム出力に対する同期方法は標準化されるべきである。

ストリームの同期方法は、過去にも何度か提案された。

N3535: C++ Stream Mutexesは、ストリームに対するmutexを標準化しようという提案だった。2013年春の会議で、本格的なmutexではなく、バッファーに対する同期であるべきだとする合意がなされた。

それを受けて、N3678: C++ Stream Guardsでは、ストリームに対するバッチ処理という概念のライブラリが提案された。バッチ処理は、mutexでもバッファーでも、あるいは其の両方を組み合わせても実装できる。会議では、単にバッファーを扱うだけにしては、複雑で問題が多すぎると指摘された。

なかなか決まらないので、後発の提案、N3665: Uninterleaved String Output Streamingでは、単に複数の実行媒体から出力操作されても、混ざらずに出力されることが規格上保証された最小バッファー長を規定しようという提案がなされた。これも否決された。

そこで、今回の論文だが、バッファーに対する操作を明示的に行えるライブラリの提案となっている。以下のように使う。

// N3892提案の例
#include 
#include 

int main()
{


{// ブロックスコープ
  std::ostream_buffer bout(std::cout) ;
  bout << "Hello, " << "World!" << std::endl;
}// ここで出力される。

}

std::ostream_bufferは、自動変数として使う。出力をバッファーし、破棄されるタイミングで、混ざらずに一気に出力される。

N3893: C++ Standard Library Active Issues List (Revision R86)
N3893: C++ Standard Library Defect Report List (Revision R86)
C++ Standard Library Closed Issues List (Revision R86)

標準ライブラリに指摘されている既知の問題点集。

[今回最後の不快なPDF] N3896: LIBRARY FOUNDATIONS FOR ASYNCHRONOUS OPERATIONS

この論文は、futureのthenによって指定する継続は、コールバックで指定する継続に比べてパフォーマンスが悪いと指摘する

futureは、処理を発行してfutureオブジェクトが返されたあとに、thenで継続をセットなければならない。thenで継続をセットする前に発行した処理が完了した場合、まず同期が発生してfutureの状態が変更され、しかし継続はセットされていないのでそのままで、そのあとにthenで継続がセットされて、この際にも同期が発生する。

コールバックは、処理を発行する際に、同時に継続もセットするので、無駄な同期が発生しない。

なぜ同期の発生回数にこだわるかというと、一回同期するのに、論文著者によれば、論文筆者の環境では、mutexやアトミック操作による同期は10-15ナノ秒かかる。また、std::futureによってブロックされていたスレッドにコンテキストスイッチして、ブロックから目覚めるのに、3マイクロ秒かかるとしている。

一方、64バイトのUDPパケットをあるホストのユーザースペースのアプリケーションから、別のホストのユーザースペースのアプリケーションまで、10GbEネットワークで送るのにかかる時間は、2マイクロ秒である。

論文筆者は、マイクロ秒単位のパフォーマンスの差が問題になる金融取引などの仕事をしているらしく、パフォーマンスの低いfutureではお話にならないとバッサリ切り捨てている。

しかし、futureもfutureで、利用価値はある。いや、世の中の並列実行は、futureとコールバックだけではない。resumable functionやcoroutineと呼ばれている、函数の栃生で実行を中断、再会できるようなものや、さらにはファイバーなどと呼ばれている、通常のスレッドより軽い協調的なマルチタスクによる実行単位など、様々な方法がある。もちろん、ユーザーが独自実装した方法も使いたい。

論文は、Boost 1.54のAsioを引き合いに出して、多様性があり、拡張性もあるasyncのインターフェースと実装方法を紹介している。

N3897: Auto-type members

non-static data memberの宣言の型指定子にauto指定子を使えるようにする議論のまとめ論文。これは提案ではない。

もし、議論されている内容が提案されて可決されたのならば、以下のようなコードが書けるようになる。

// N3897議論が提案されて可決された場合に書けるようになるコード
struct Foo
{
    auto a = 0 ; // int
    auto b = 0.0 ; // double
    auto * c = this ; // Foo *
    auto d = c ; // Foo *
    auto & e = *this ; // Foo &
} ;

さて、このようなコードを書きたいだろうか。筆者にはよくわからない。論文では、Faisal Valiが実験的な実装を行ったそうだ。

このような機能を追加するには、様々な懸念が噴出しているので、これが提案されるかどうかはわからない。

コンパイラー屋も含む、多くのC++標準化委員が懸念を示している機能なので、なにか説得力のある利用方法を示すとか、現場の利用者からネツレツに使いたいという意見でも上がらない限りは、この機能はこのままお蔵入になるだろう。

もし、具体的な活用方法や、ぜひとも実務で使いたい、コレがなくては不便でならぬ。C++を使うかどうかはこの機能の有無にかかっているという強い意思があるのならば、筆者まで知らせてもらいたい。

N3898 HASHING AND FINGERPRINTING

これは提案ではなく、ハッシュ関数の設計と実装の紹介としての論文のようだ。

ユーザー定義型のハッシュ値を簡単に計算できるようにするために、char, bool, longなどの基本型を複数突っ込めば、ハッシュ値を計算してくれるライブラリの設計と実行を紹介している。

N3899: Nested Allocation

歴史的に、C++の実装では、automatic storageというものは、一般にスタックとよばれる確保済みのメモリ領域から確保している。スタックは環境によって様々ではあるが、かなり強い制限がある。しかし、スタックからメモリを確保するのは高速である。

C++では、allocaなどの例外的な関数を除き、スタックから直接確保するための方法を提供してこなかった。

C99はvariable length arrayを追加した。C++でも、似たような機能をruntime sized arrayとして提案中だ。

また、C++では、non staticデータメンバーにruntime sized arrayを認める提案もしている。この場合、クラスはautomatic storage上に確保しなければならない。しかし、これはクラスのオブジェクトはどのストレージにも構築できるいう、C++の利点が損なわれてしまう。これは極めて例外的な提案だ。

また、現在提案中のstd::dynarrayは、automatic storageに確保できる文脈では確保し、そうでない文脈ではヒープに切り替えるといった、柔軟な対応が可能なライブラリだ。しかし、これはいつスタック上に確保されるのかということが、規格ではなく、実装の都合で決まってしまう。およそ、スタックに確保されることを気にするC++ユーザーは、絶対にスタックに確保されるという保証が欲しいはずだ。

さらに、これらの提案のすべてに、再構築という大問題が立ちはだかる。以下のような問題だ。

// 再構築
void f( std::dynarray<int> & r )
{
    r~dynarray<int>() ; // デストラクターの明示的呼び出し
    new(r) dynarray<int>(2) ; // 再構築。いいのか?
}

int main()
{
    std::dynarray<int> a(1) ; // 構築
    f( a ) ; // リファレンス渡し
}

これはいったいどうなるのだろうか。このようなコードは認められなければならない。しかし、これを認める場合、オブジェクトの寿命がネストしてしまう。

論文では、まずそもそも根本的に、オブジェクトの寿命のネストをサポートするための規格が必要であると主張している。

結び

とにかく、これで2014-01-Pre-Issaquah論文集をレビューし終えた。筆者がドワンゴに入社して二ヶ月近くたつが、C++WG論文をいつもより丁寧にレビューするぐらいしかしていない。ドワンゴ社内は、現場のC++利用者の意見が聞ける環境なので、提案の問題点の発見に役立つ。

また筆者も、社内でC++に提案されている新機能について、論文をレビューしながら社内IRCでチャットという形で解説しているが、この提案というのは、仮に採択されるにしても、正式にドラフト規格に、取り入れられて、C++コンパイラーで実装されて、現場で使えるようになるまで、まず10年はかかる機能ばかりだ。今すぐに役立つ知識ではない。

そして、2014-02-Post-Issaquah論文集もあるので、もうしばらくはこの状態が続く。たまっているC++WG論文をレビューし終えたら、他のC++啓蒙活動も始めようと思う。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

「C++11は十分に枯れて現場で使えてしまうので、もう飽きた。C++11をバリバリに書きつつ、10年後に現場で使えるようになるかもしれないC++17の新機能の話がしたい」という君。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0