2014-04-16

JavaScript規格の正規表現リテラルの文面の疑問点

JavaScript規格、ECMA-262 Edition 5.1を読み進めていて、以下の文面が気になった。

A regular expression literal is an input element that is converted to a RegExp object (see 15.10) each time the literal is evaluated. Two regular expression literals in a program evaluate to regular expression objects that never compare as === to each other even if the two literals' contents are identical.

正規表現リテラルは、リテラルが評価されるごとに、RegExpオブジェクトに変換される入力要素である。プログラム中の二つの正規表現リテラルは、たとえ二つのリテラルの中身が同一であっても、===と比較されることのない正規表現をオブジェクトに評価される。

§7.8.5 Regular Expression Literals

つまりは、/./ === /./ はfalseになるということだ。正規表現リテラルが評価されるごとに別のオブジェクトになるということは、以下のようになる。


for ( var elem in [ true, false ] )
{
    var r = /./ ; // ひとつの正規表現リテラル 
    if ( elem )
        var a = r ;
    else
        var b = r ;
}

a === b ; // false

なるほど、確かに複数回評価されている。

しかし、文面では二つの正規表現リテラルとあるが、このプログラム中に、正規表現リテラルはひとつしかない。ひとつの正規表現リテラルが二回評価されるだけだ。と、屁理屈めいた疑問も生ずる。

筆者が規格を読むときは、文面は全て間違っているという前提で読むので、このような屁理屈のような疑問が生ずる。

ドワンゴ広告

この記事はドワンゴ勤務中にやんごとなき理由により自分の机を離れて書いた。

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

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

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

JavaScriptのコメントと改行

今回の記事は、JavaScriptのコメントの文法についての、とてつもなく些細な内容になる。

まず、「改行」の定義について

ECMAScript規格では、俗に改行と呼ばれているものは、正式には、行終端子(Line Terminator)と名づけている。行終端子は5個あり、これは4種類の文字からなる。なぜ4種類の文字で5個あるのか。ひとつは組み合わせなのだ。

行終端子を構成する4種類の文字は、\u000A(Line Feed), \u000D(Carriage Return), \u2028(Line separator), \u2029(Paragraph separator)である。

しかし、慣習的に、CRに続くLFを、ひとつの「改行」とみなすことが横行している。JavaScriptはこの慣習を追認する形で、CRLFの2文字をひとつの行終端子として認識する。

さて、本題に入ろう。JavaScriptのコメントには、一行コメントと、複数行コメントがある。

// 一行コメント

/* 複数行
コメント*/

コメントは空白文字とみなされる。

一行コメントは、//から行終端子までがコメントとなる。ただし、行終端子はコメントに含まれない。

複数行コメントの中に行終端子があった場合、複数行コメントは、行終端子とみなされる。

なぜ行終端子が残るのかというと、自動セミコロン挿入(automatic semicolon insertion)のためだ。


function f()
{
    var i = 0 ;
    i // 一行コメント
    ++ ; // エラー
}

一行コメントは、行終端子として認識されるので、自動セミコロン挿入が働く。したがって、上記のコードは、正しく文法エラーになる。

JavaScriptの自動セミコロン挿入については、このブログでも4年前に取り上げたが、当時はまだ規格の読解力が今ほどではなく、やや稚拙であるので、この機会に、規格を§7.9まで読み進めたあとで、解説しようと思う。

ドワンゴ広告

この記事は意識高い系ドワンゴ社員である筆者が、超チューニング祭のために、自発的に06:33に出社してECMA-262 Edition 5.1を読みながら書いた。

昨日は、実質七時間しか睡眠を取っていない故に「つれー」状態にある。実質七時間なのだ。

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

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

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

2014-04-15

Multipath TCPについて

Multipath TCPとは、複数の経路を扱うためのTCP拡張である。実は、以前、本の虫: MultiPath TCPのLinuxカーネル実装という記事で、その実装デモを紹介している。

従来のTCPは、IPとの分離ができない。TCPヘッダーの中には、ひとつのIPアドレスとポートがある。経路ごとにIPアドレスが割り振られるので、経路を変えるには、別のTCPコネクションを貼り直さなければならない。

しかし、複数の通信経路を持つという環境は、もはや珍しいものでも何でもなくなっている。たとえば、多くのラップトップにはEthernetとWiFiの二つの経路があるし、スマートフォンにも、WiFiと3G/4Gという複数の経路がある。特にスマートフォンの場合、経路が使えるかどうかが頻繁に切り替わる。

過去に、TCPで複数のIPアドレスを扱う拡張はいくつも出されたが、いずれも、IPアドレスを隠すという点で、非効率的である。

複数の経路を直接扱えれば、パフォーマンス的にも、冗長性的にも、利点がある。

実は、トランスポート層で、複数のIPアドレスを扱うプロトコルは、すでに設計されている。SCTPだ。

SCTPは単に複数のIPアドレスを使えるのみならず、ストリーム単位を混ぜあわせて送信し、受信側でストリーム単位に分解できたり、送信バイト数を通知して、全部受信するまで待機できたりと、従来ならアプリケーション層でやっていたことが、トランスポート層で面倒を見てくれるので、とても便利なのだ。

問題は、SCTPのその他の利点は、とてもニッチな分野でしか需要がない。古い歴史を持つTCPには様々な問題があるとはいえ、既存のTCPからの移行コストを支払ってまで置き換えるほどの利点ではない。

それに、既存のほとんどのルーターが、SCTPパケットを、単に破棄してしまう。卵と鶏の問題と同じで、SCTPの利用者がいないので、ルーターベンダーはSCTPをサポートしない。ルーターがSCTPをサポートしていないので、開発者はSCTPを使えない。

必要とされているのは、既存のTCPパケットとして流せて、既存の機器でも問題なく動く、TCPの拡張だ。それが、Multipath TCPである。

MTCPは、アプリケーションからは、従来のsocketによるTCPと同じように扱える。ただし、アプリケーションが従来のTCPと同じだと信じているものは、実はMTCPによるレイヤーを通した仮想的なもので、本物のTCPコネクションは、MTCPによって管理されている。MTCPは複数の経路をまとめて管理し、アプリケーション側には、従来のTCPのようにみせかける。

MTCPの実装には、TCPオプションを使う。しかし、これは現実的に問題になる。

今日のインターネットは、当初のインターネットとは大きく違う。経路上に、実に多数の、中間箱(middlebox)が存在する。ルーターやスイッチだけではなく、ファイヤーウォールやらNATやらロードバランサーやらDeep Packet Inspectionやらだ。多くの中間箱が、TCPパケットを書き換える。

そもそも、モダンなNICは、効率化のために、勝手にTCPパケットを分割する。この際、TCPヘッダーは、単にコピーされてしまう。そのため、MTCPがTCPヘッダー内で予約して使うデータシーケンス番号が、コピーされてしまう。

MTCPシーケンス番号のコピーは、従来のTCPシーケンス番号の範囲のマッピングにより対処した・・・つもりであった。しかし、これでも問題があった。なんと、多くのルーターが、シーケンス番号を書き換えているのだ。背景には、最初のシーケンス番号をランダムに開始しない脆弱性ある実装に対処するため、ルーター側でシーケンス番号を振り直すということが、広く行われているようなのだ。このため、マッピングを絶対的ではなく、相対的にすることで、対処した。

さらに、active FTPなど、複数のTCPコネクションを貼り、ASCIIでIPアドレスをエンコードするような特定のプロトコルに対し、中身を書き換える(すなわち長さも変わる)などの改変を行うルーターすら存在する。

Linuxカーネルに実装されたMTCPでは、チェックサムを使うことで、データの改変を検知し、従来のTCPにフォールバックする実装になっている。

研究者がインターネット上の中間箱(middlebox)について調査を行ったところ、どうやら今日のインターネットでは、TCPパケットのあらゆる部分は、中間箱により改変される可能性があるということが判明した。これは、将来のTCP拡張を設計する上で考慮に入れなければならないことである。TCPヘッダーの中身のあらゆる箇所は、改変されないという保証がないのだ。

さて、利用例であるが、Wifiと3G/4Gなどの複数の経路を持つスマートフォンやデータセンターが挙げられている。

スマートフォンは、短期間で有効、無効が切り替わる複数の経路でも、TCPコネクションを維持するために使われる。

今日、データセンターでは、複数の経路を使うことは当然になっている。ただしその実装は、複数の経路をロードバランサーなどでまとめて、ラウンドロビンで複数の経路にパケットを割り振り、あたかもひとつのMACアドレス、ひとつのIPアドレスを持つように見せかけている。これは非効率的である。また、通常の経路と、バックアップ用の待機経路を持って、冗長性を確保するという利用方法もある。MTCPならば、複数の経路がそれぞれ異なるMACアドレス、IPアドレスを持てる。直接MTCPが管理するので、パフォーマンス目的でも、冗長性目的でも、効率的に管理できる。

Multipath TCPは、従来のTCPパケットのまま経路上を流せるということと、安全のために従来のTCPへのフォールバックがある、既存のアプリケーションの対応が必要ないという点で、移行しやすい拡張だと言える。

現在、Linuxカーネルで実装されていて、FreeBSDでも実装する計画がある。

さて、流行るだろうか。理想主義者の筆者としては、むしろ抜本的な解決方法として、SCTPのような全く新しいプロトコルが主流になって欲しいのだが。

ドワンゴ広告

この記事は、たまたま、ドワンゴ社内にCOMMUNICATIONS OF THE ACM 04/2014 VOL. 57 NO.04が転がっていたので、興味を引いたMultipath TCPについての論文を読んで、勤務時間中に書いた。

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

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

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

2014-04-14

Python 2.7のサポート期間が2020年まで延長

peps: 76d43e52d978

Python 2.7のThe End Of Life時間(EOL、日没の時間)は5年間延長されて、2020年になった。この決定はPython 2.7の状態を明確にし、まだPython 3に移行出来ない利用者の懸念を取り除くものである。PEP 466も参照されたし。

この表明は、バグ修正リリースが頻繁に行われることを保証するものではないが、Python 2.7のバグ修正を行いたいボランティアの貢献を可能にし、また、今後もしばらくPython 2をサポートする必要のあるベンダーを満足させるものであろう。

Python 2.8はない。

いかにプログラミング言語にとって、下位互換性が重要化が分かる事例だ。Python 3は、下位互換性をぶち壊す変更をすべきではなかった。たとえどんなに汚かろうが、一度使われてしまった文法は、いまさら廃止することは出来ないのだ。

ドワンゴ広告

この記事は、そろそろドワンゴを退社しようとしかけたところでニュースに気がついたので、急遽、勤務中に書いた。

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

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

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

JavaとJavaScriptの違い

JavaとJavaScriptには、Unicode escape sequenceというものがある。どちらも同じ文法で、\uに続いて4文字の16進数文字を指定することで、Unicode Code Pointを指定できる。あたかも、Unicode Code Pointを記述したかのように振る舞う。

ところで、JavaとJavaScriptは、このUnicodeエスケープシーケンスの使い方が異なる。例えば、行終端文字\u000Aを、以下のように書く。

// これは\u000Aコメント

これは、JavaScriptで解釈すると、以下のようになる。

// これは\u000Aコメント

以下は、Javaによる解釈である。

// これは
コメント

Javaでは、Unicodeエスケープシーケンスが、実際に行終端文字として扱われてしまう。したがって、行終端文字以降が一行コメントからはみ出してしまう。

これは、文字列リテラルの中でもそうである。

"これは\u000A文字列リテラル" ;

というコードは、Javaでは

"これは
文字列リテラル" ;

と解釈される。Javaの文字列リテラルは、途中に改行文字を記述してはならないので、これはエラーとなる。Javaで文字列リテラルの中に、リテラルの値として改行文字を入れたい場合は、\nなどと書かなければならない。

Javaは謎すぎる。ますますJavaはクソであるという認識を新たにした。

というわけで、ECMA-262 Edition 5.1を読んでいるが、まず、文法記法の丁寧な定義が書いてある。これはとても親切だ。ただし、丁寧な定義と引き換えに、いろいろと文法記法が複雑になっている。これは、JavaScriptのデファクトスタンダードな文法を、後から追認する形で規格化したので、どうしてもこのような複雑な記法にならざるを得ないのだろう。例えば、改行が意味を持つ文脈など。

次はLexical Conventionsだ。

ドワンゴ広告

この記事は超チューニング祭のために勤務中にECMA-262 Edition 5.1を読んでいて興味深かったので書いた。

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

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

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

超チューニング祭

超チューニング祭が告知された。

公式サイトから引用すると、

超チューニング祭開催のお知らせ

ニコニコ超会議3内で開催予定のチューニングイベント!
ニコニコ動画のスマートフォンサイトをHTML/CSS/JavaScriptでフロントエンドチューニングしよう!
(表示速度のみの判定ではありません!ユーザー投票あり!)

ニコニコ動画史上最速の座を賭けた白熱の2日間・・・
豪華賞品と名誉は誰の手に!?

超チューニング祭

とのことだ。超会議3の企画のひとつで、参加には、以下のイベント支援Webサイトから登録する必要がある。

超チューニング祭 - connpass

また、公式サイトによれば、

参加スターエンジニア

君はドワンゴの精鋭達に勝つことができるか!?

  • 戀塚昭彦 @koizuka / 世界で最初のニコ厨
  • 江添亮 @EzoeRyou / C++標準化委員会エキスパートメンバー
  • 山田将輝 @masarakki / Ruby界隈で著名なエンジニア
  • 水島宏太 @kmizu / 日本Scalaユーザーズグループ 代表

超チューニング祭

となっている。はて、江添亮とはどこかで見た名前だ。どこだっただろうか。

この疑問はさておき、この他称ドワンゴの精鋭達は、重大な問題を抱えている。誰もフロントエンドエンジニアではないということだ。そして、いずれも強いこだわりをもっているということだ。

筆者が思うに、@masarakkiは、Opalを、@kmizuScala.jsを、@koizukaemscriptenを、それぞれ使うのではなかろうか。@EzoeRyouは、どうせ規格でも読むのだろう。

ところで、超会議3で、筆者がこの超チューニング祭に割り当てられるというのは、つい先週、本人に伝えられたばかりだ。それも、この公式サイトに書いてあるより少ない情報量が伝えられただけだ(何かハッカソン的なもの、フロントエンドのパフォーマンス改善的な何か、HTMLとかJavaScriptあたり? パフォーマンスをテストするらしい、テスト環境の不備をついて高パフォーマンスに見せかけられないものだろうか云々)

幸い、C++WG論文も片付いたし、次の論文集の発行は6月になる見込みなので、月末までHTML5やCSSやECMA-262 Edition 5.1を読むことにしよう。これまでも断片的には読んでいたが、C++の規格ほど本気で読んだことはない。月末までには到底読みきれないだろうが、とりあえずECMAScriptの規格を読むことにする。

ドワンゴ広告

この記事は14:24に出社したら、出社にさかのぼること30分ほど前に超チューニング祭の告知Tweetが出ていたので、急遽、勤務中に書いた。

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

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

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

2014-04-13

GCC 4.9リリース

GCC, the GNU Compiler Collection - GNU Project - Free Software Foundation (FSF)

GCC 4.9がリリースされた。少なくとも、公式Webサイトのトップページからは、リリースされたことになっている。ただし、なぜかリンクをたどると

GCC 4.9 Release Series — Changes, New Features, and Fixes - GNU Project - Free Software Foundation (FSF)

GCC 4.9がリリースされた。興味深い変更点を上げると。

大昔の、もはや保守もテストもされていないようなプラットフォームのサポートがobsolete扱いになった。もし、活発な活動が行われない場合、次のリリースでは取り除かれるそうだ。特に、Solaris 9が挙げられている。

Clangにある、AddressSanitizerが、ARM向けにも提供されるようになった。また、ClangにもあるUndefinedBehaviorSanitizerが、GCC 4.9にも実装された。これは、規格上の未定義動作を、実行時に検出して実行時エラーにしてくれるものである。

LTOが改良されたらしい。

Inter-procedural optimizationが改良された。これにより、virtual関数呼び出しをしなくてもいい文脈がよりよく判定できるようになったようだ。

プロファイルによる最適化にも改良があったようだ。

-fdiagnostics-colorオプションが追加され、Clangにもある、コンパイラーの出力する警告とエラーのメッセージに色を付ける機能が実装された。

C++に目を向けると、C++14の新機能が実装されつつある。C++14の新機能はまだ実験段階で、、-std=c++1yオプションを与えることで、有効にできる。

GCC 4.9では、通常の関数の戻り値の型推定機能が実装された。

// 戻り値の型はint
auto f(){ return 0 ; }

もちろん、decltype(auto)も実装された。

// decltype(auto)の例
int & f() ;

auto x = f() ; // int
decltype(auto) y = f() ; // int &

規格上、autoとdecltype(auto)は、ともにplaceholder typeと呼ばれている。autoは、初期化子から関数呼び出しのtemplate argument deductionのルールを使って、型を推定する。そのため、上記の例では、xの型はintになる。

一方、関数の戻り値の型推定に伴って追加された新しいplaceholder typeであるdecltype(auto)は、あたかも初期化子の式をdecltype( 式 )の中にいれたかのように振る舞う。つまり、この場合はdecltype(f())と同じように振る舞う。したがって、yの型はint &になる。

GCC 4.9では、lambda capture initializerが実装された。

// lambda capture initializerの例
auto f = [ x = 42 ](){ } ;

これにより、ムーブコンストラクターを呼び出すコピーキャプチャもできるようになった。

GCC 4.9では、C++14に提案されているruntime sized arrayをサポートするようになった。この結果、実行時サイズ配列がラムダでキャプチャーできるようになった。

// 例
void f( std::size_t size )
{
    int a[size] ;
    [&a](){} ;
}

GCC 4.9は、deprecated attributeをサポートした。deprecated attributeに記述できる文字列リテラルは、コンパイラーの警告メッセージに含まれる実装となっている。

// deprecated attributeの例
[[ deprecated ]] void foo() ;


[[ deprecated("bar(int) is deprecated. Use bar(bool) instead.") ]] void bar( int use_super_fast_algorithm ) ;
void bar( bool use_super_fast_algorithm ) ;

int main()
{
    foo() ;
    bar( 1 ) ;
}

GCC 4.9では、数値区切り(digit separator)をサポートした。

// digit separatorの例
int i = 123456789 ;
int j = 123'456'789 ;
int k = 0x10'000 ;

// 区切りは1文字以上なら何文字でもよい
int l = 1'22'333'4444'55555 ;

GCC 4.9では、ジェネリックラムダ、あるいはポリモーフィックラムダと呼ばれているC++14提案を実装した

// generic lambda
int main()
{
    auto f = []( auto x ) { } ;
    f( 0 ) ;
    f( 0.0 ) ;
    f( "hello" ) ;
}

その他、libstdc++も、C++11の標準ライブラリをサポートしつつあるようだ。

OpenBSDが2014年度の寄付金目標額に到達したため、文字通り腐敗したサーバーインフラを再構築できるようになった

OpenBSDが電気代を払えないほどの資金難に陥っていることはすでに報告した。その後、寄付が集まり、OpenBSDは持ちこたえた。さて、今回、OpenBSDの寄付金額が、今年の目標に達したそうだ。

'OpenBSD Foundation 2014 Fundraising Campaign.' - MARC

List:       openbsd-misc
Subject:    OpenBSD Foundation 2014 Fundraising Campaign.
From:       Bob Beck <beck () openbsdfoundation ! org>
Date:       2014-04-10 16:23:41
Message-ID: 20140410162340.GA15909 () hogfat ! obtuse ! com

OpenBSD財団は、2014年度の寄付金が、目標額である15万ドルに達したことを報告する。

我々は大小の貢献者に感謝する。我々は資金調達努力を、今年度と来年度に渡り、継続する。

今年の資金調達の成功により、本財団はOpenBSDプロジェクトが陥ってた問題を緩和することができるようになった。財団は電気代のような、プロジェクトのインフラに資金を回す責任を果たすことができる。

本財団は、プロジェクトのサーバーインフラを再構築する作業に着手できるようになった。このインフラには、文字通り腐敗しているものも含む。

2014年のハッカソンは開催可能となり、OpenBSDと関連プロジェクトに改良をもたらすこの重要なイベントを継続することがデキるようになった。

我々は財団に継続的に寄付している貢献者に感謝する。寄付は予算と計画をより効率的に行うことに使われる。

財団は今後も財務状況改善と、プロジェクトのサポートに向けて努力する。寄付を継続してくれ!

「文字通り腐敗しているサーバーインフラ」というのが気になる文面だ。

しかし、15万ドルというのは、有能なプログラマーを一人雇うのに必要な程度の金額である。OpenSSHのような超重要なソフトウェアも開発しているプロジェクトに有能なプログラマー一人分の給料ほども資金が集まらず、電気代すら払えない状況になっていたというのは、コモンズの悲劇に似ている現象だろうか。

2014-04-12

妖怪ネットワーク改善案

妖怪ハウス内のネットワーク、すなわち妖怪ネットワークの改善作業は続いている。

さて、まともなスイッチングハブとルーターを導入したことで、妖怪ネットワークはだいぶマシになった。しかし、まだ妖怪ネットワークのパフォーマンスには、不満がある。厳密に計測したわけではないが、京都に住んでいたときよりも、パフォーマンスが劣っているように感じられる。何十個ものブックマークしたURLをタブで開いて閲覧するのが遅すぎる。

これはなぜだろうと考えたが、ふと、DNS lookupが遅いのではないかと考えた。帯域的には、何の問題もないはずである。ルーターの性能も十分である。実際、Webサイトのダウンロードは十分に早い。ダウンロードまでがなぜかもたつく。

調べてみようと、digを使ったところ、なぜか動かない。動かない理由は、DNSキャッシュサーバーとして動作しているYAMAHAのRTX810は、EDNSをサポートしていないからであった。digコマンドに+noednsオプションを指定した所、digは動いた。

しかし、RTX810越しにDNS lookupをしたのでは、正しく計測できない。digコマンドは、@に続けてサーバーを指定することで、直接サーバーに対してDNS lookupを飛ばしてくれる。さっそく、ISPが通知しているDNSサーバーについて調べてみた。すると、奇妙な特徴が判明した。

私のよく閲覧するWebサイトのドメイン名を引くのに、400msはかかる。あるドメイン名に対して、DNS lookupをしてから数秒間は、8msほどでlookup可能なのだが、数秒を過ぎると、また400msかかる。これは、京都に住んでいたときのISPの提供するDNSサーバーに比べて、あまりにも遅すぎる。

RTX810のキャッシュに載っている限りは、1msでDNS lookup可能だが、大本がこんなに遅くてはどうしようもない。

とりあえず試験的に、Googleの提供するPublic DNSである、8.8.8.8と8.8.4.4をRTX810に設定してみた。これにより、利用者側での設定変更の必要はない。Googleの提供する公開DNSサーバーで、普段閲覧するWebサイトのドメイン名を引いてみたところ、どのドメイン名でも、38ms程度の、非常に安定した時間がかかることが判明した。ほとんどのドメイン名のDNS lookupに400msかかる、ISPの提供するDNSサーバーよりは相当に優れているといえる。

妖怪ネットワークのもうひとつの問題は、WiFiだ。今は、BUFFALOに変えて、NECの無線LANルーターを使っているが、これも複数人で接続すると、とたんに不安定になる。やはり、業務用のしっかりした無線LAN APを使うべきだろうか。問題は、そのような業務用機器は、値段も高いということだ。

私は基本的に無線は使わないので、今すぐに解決しなければならない問題ではないが、長期的には解決したいところだ。

2014-04-11

なぜTheo de RaadtはIETFに激怒しているのか

本の虫: OpenBSD、怒りのコミットで、OpenBSDのTheo de RaadtがIETFに対して激怒している。

src/lib/libssl/ssl/Makefile - view - 1.29

SegglemannのRFC520 heatbeatを無効化。

あのまともなプロトコルひとつ制定できないIETFの無能集団が、超重要なプロトコルで64Kの穴をこしらえるとか、マジであきれてものも言えねーわ。奴らはマジこの問題を本気で検証すべきだろ。なんでこんなことをしでかしたのか。こんな事態を承認した責任ある連中を全員、意思決定プロセスから取り除く必要がある。IETF、てめーは信用なんねぇ。

なぜTheo de Raadtは、OpenSSLではなく、IETFに対して激怒しているのか。IETFというのは、インターネット上の規格制定の団体である。今回、世上を騒がせているHeartbeat問題は、Heartbeatの実装のうちのひとつ、OpenSSLのバグのために引き起こされている問題である。設計上の問題ではない。なぜTheo de RaadtはOpenSSLを放置して、IETFを問題にするのか。これはいったいどういうことだ? ひょっとしてTheo de Raadtはバカなのか?

もちろん、Theo de Raadtはバカではない。もとより、あのTheo de Raadtである。どんなに人格的に彼が嫌いな人であろうと、Theo de Raadtの能力は認めざるを得ない。彼は問題の核心を指摘しているのだ。

Heartbeatと呼ばれているこの機能は、具体的には、RFC 6520 - Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS) Heartbeat Extension(TLS/DTLS Heartbeat拡張)のことである。このTLSに対する拡張は、TLSにkeep-aliveの機能をもたらすものである。

ではなぜTCP keep-aliveではだめなのか。たいていのOSでTCP keep-alive間隔があまりに長時間に設定されているためか。それなら必要であると感じるものだけがOSの設定を変えれば良い話だ。なぜわざわざ同等機能の規格を重複して作るのか。そもそも、大多数の一般人にとって必要なのは、もっと上のアプリケーション層でのKeep-alive実装ではないのか。

このHeartbeatという機能は、基本的に誰からも必要とされておらず、事実、さっくりと無効にしても誰も困らない機能である。だからOpenBSDでもさっくりと無効にした。なぜそんな誰からも必要とされていない無用の機能を規格化するのか。規格化された以上、規格準拠のソフトウェアは実装しなければならない。新しく実装した機能には不具合が含まれる可能性が高い。誰からも使われない機能は、不具合が発見されにくい。無駄な機能を規格化するとは、いったいIETFは何をしているのか。

Hacker Newsでは、この背景事情を解説するコメントが投稿されている。

There are smart people working in the TLS WG, but there are also people there th... | Hacker News

TLS WGには頭のいい奴らもいるが、同時に、このインターネットの最高に重要な暗号通信を制定する資格のない奴らも多くいる。

さらに、ワーキンググループは、新機能に対してイエスと答える傾向が高い。否定論者こそ必要とされているのに。Heartbeat機能はこの問題の明らかな例だ。リファレンス実装がやっつけ仕事すぎるからだ。

そもそも、TCP TLS heartbeatを無効にしたという事自体に、もっと非難の声が上がるべきなのだ。誰も必要としていないし、だれも作ってくれと頼んでいない機能なのだ。なんで最初からデフォルトで無効になっていないのだ? デフォルトで有効であることに、いったいどんな意思決定がなされたのだ?

I have read all the TLS WG discussions I can find on this RFC. The picture that... | Hacker News

俺はRFCで探せる限りのTLS WGを全部読んでいるが、これはワーキンググループ事態の根本的な失敗だ。

俺の知る限り、「これ必要ないだろ」という主張をしたのは、たったの一人だ(GnuTLSの主要開発者のNikos Mavrogiannopoulos)。彼はこの機能が必要だという理由を提出しろと三度も要請した[0][1]。返事は二件、どちらも同一人物からの返答だ。これ以降、議論は一切ない。つまり、彼の反対意見は解決されたか、これ以上の議論は非建設的だと判断されたかのどちらかだ。いったいどちらなのか、非常に気になるところだ。GnuTLSではheartbeatが無効にされている。つまり、Nikosはこの機能に未だに価値を見出していないということだな。

しかし、このドキュメント[訳注: RFC6520か?]は、今ここで名前を挙げて辱めることはしないが、多くのセキュリティ専門家が関わっているのだ。彼らは皆、反対意見を出さずに、検証し、コメントを出し、ドキュメントを編集したのだ。

思うに、このワーキンググループの性質として、ある機能が欲しい勢力は、その機能が、ひょっとしたら、悪く実装されて脆弱性をもたらし、無関係の被害を被るような、大多数の勢力より、強い影響力を持つようだ。どうも逆NIMBYな状況だな。ソフトウェアコミュニティは、ぽこぽこ生まれるすべての新しいTLS提案に反対するだけの暇はないが、ボクの考えた最強の機能の標準化を押し通そうとする勢力には暇があるわけだ。

[0] : IETF - TLS - tsv-dir review of draft-ietf-tls-dtls-heartbeat-01

[1] : IETF - TLS - Working group last call for draft-ietf-tls-dtls-heartbeat-02

標準化のためのワーキンググループというのは、不思議な場所だ。標準化のための権力を持っていながら、提案されている規格に対する詳細な知識や理解を持たないものが大勢いる。これには仕方のない部分もある。あらゆる分野の専門家たることはできない。Theo de Raadtのような例外的存在を別にすれば、専門家たろうとすれば、専門範囲は狭く深くなる。したがって、自分の専門分野以外は素人同然というのは、不思議なことではない。

問題は、それでもワーキンググループのメンバーである以上、様々な提案の採決に意見表明しなければならない。自分の専門ではない分野は、自然と肯定に回ってしまう傾向がある。

否定論者は必要である。ワーキンググループのメンバーにすら、提案された新機能の必要性を説得できなければ、いったいどうやって世界中の利用者に価値を説得できるというのか。

ドワンゴ広告

この記事は、前の記事とは違い、ドワンゴ勤務中に書かれた。前の記事は自宅で書き、この記事は15時頃(ドワンゴ定義ではそろそろ昼飯時、部署によってはまだ朝)出社して書いた。どうやら勤務中でもやることは変わっていないようだ。

今夜は社内でボードゲームをする予定であるので、なおさら変わっていない。最近、To Court The Kingというとても面白いゲームにハマっている。

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

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

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

OpenBSD、怒りのコミット

OpenSSLのheatbeatバグの対応のため、OpenBSDはOpenSSLのheatbeatを無効にするコミットをした。ただし・・・

src/lib/libssl/ssl/Makefile - view - 1.29

SegglemannのRFC520 heatbeatを無効化。

あのまともなプロトコルひとつ制定できないIETFの無能集団が、超重要なプロトコルで64Kの穴をこしらえるとか、マジであきれてものも言えねーわ。奴らはマジこの問題を本気で検証すべきだろ。なんでこんなことをしでかしたのか。こんな事態を承認した責任ある連中を全員、意思決定プロセスから取り除く必要がある。IETF、てめーは信用なんねぇ。

このコミットは、Makefileの中で、OpenSSLでheatbeatを無効にするマクロを定義するよう、コンパイラーオプションを指定するものだ。ただし、無効にするマクロは、OPENSSL_NO_HEARTBEATSなのに、このコミットで定義されているマクロは、OPENSSL_NO_HEARTBEATだ。なんと、typoをしている。これでは何の意味もない。

すなわち、このパッチは、実際にheatbeatが無効化されているかの確認を一切せずしてコミットされたものである。

はて、このコミットメッセージの論法で行くと、OpenBSDはこのパッチを書いた者と、このパッチをレビューして承認した者を、OpenBSDの意思決定プロセスから取り除くべきだろうか。

ちなみに、この問題は2時間後に発見されて、続くコミットで直されている。

src/lib/libssl/ssl/Makefile - view - 1.30

やっべ、typoだ。Matthias Schelerが発見。

このお話の教訓としては、人は誰でも間違いを犯すということだ。

2014-04-10

余は如何にしてDを書くにいたりしか

How I Came to Write D | Dr Dobb's

Dr. Dobbsの記事で、Walter Bright(C++とDプログラマーでウォルたんの名前を知らないものはモグリである)が、なぜDを書くに至ったのかを書いている。

余は如何にしてDを書くにいたりしか

Walter Bright著

Walter Brightが、世界で最も使われている言語20位までに入る言語を書くに至った道は、興味と・・・侮辱。

私は小さい頃から、ものが如何にして動き、設計されているかを調べるのが好きだった(Tom Swiftの本は大好きだ)。小さい頃の将来の夢は、列車とか水上機の設計だった。私の専門は機械工学だった。ただ、機械工学は、何を作るにも多額の費用がかかり、それに私自身の製作スキルの低さという点で、不満だった。

一方、プログラミングでは、私はコンピューターにアクセスさえできれば、何の費用もかからずに、最高に複雑な機械をつくり上げることが出来た。多くのプログラマーと同じく、私はゲームを書くことから始めた。ゲームを書くことの魅力は、神のごとくなれることに似ている。自分のルールに従う世界を作るのだ。私はEMPIREというゲームを作り、コンピューターが敵軍に対して以下にうまく立ち振る舞うかということに、多大な時間をつぎ込んだ。今日ですら、私はいまだに、改良方法に思いを巡らせている。

問題は、コンピュターの戦略のためには、途方もないほどの計算力が必要になる。そのため、私はコンパイラーが如何にしてコードを最適化するかということに興味を持った。コンパイラーというのは、ソースをマシンコードに変換する、何やら魔法のようなデバイスに思えたのだ。この魔術は如何にして動いているのか。これは、BYTEマガジンがTiny Pascalのソースコードを出版するまでは、大宇宙における最大の謎であった。私はTiny Pascalプログラムのすべての行を消化し、一度理解するや、私は秘密の部屋へのパスワードを与えられたが心地になったのであった。

数年して、80年台のはじめ頃、私はMS-DOS用のソフトウェアを開発するプログラミング部署に属していた。我々は、Cを使った。なぜならば、PCで動く高級言語というのは、Cしかなかったからだ。他の言語実装は、信じられないほど悲惨だった。Cコンパイラーすらひどかったが、少なくとも、利用可能な程度ではあった。そのCコンパイラーの生成するコードは悲惨で、最適化などというものは存在しなかった。私は、自分ならばもっとマシなCコンパイラーを書けるという確信があった。

私がこの確信を同僚に伝えた所、同僚は、近所のCグルと同僚とで、昼食を同席することを提案した。このCグルは、実装方法についていくつか助言ができるという。食事の席で、友人は私の野望をグルに伝えた。そのグルの屈辱的な物言いは、未だに私の脳裏に刻みつけられている。「オメー、自分でCコンパイラー作るとか、何様のつもりだよ?」

私はこのグルに感謝しなければなるまい。というのも、このグルに見せつけてやりたいという思いは、強力なモチベーションとなったのだから。私は直ちにCコンパイラー、Datalight Cの実装にとりかかった。私の最適化の興味を反映して、このCコンパイラーは、PC向けで初めてデータフロー最適化を備えたコンパイラーとなった。この概念は、当時としては新しすぎたので、コンピューターマガジンのベンチマークでは、ひと騒動を起こした。なぜならば、オプティマイザーは、ベンチマークが何もしていないと判断し、デッドコードをすべて切り捨ててしまったからだ。編集者は、私のコンパイラーは壊れているか、ズルをしていると決め付けたため、Datalight Cのレビュー結果は悪くなってしまった。(これは、もちろん私を非常に怒らせたが、残念ながら、反論を掲載するのに便利なインターネットというものは、当時は存在しなかった)

Datalight Cは後に、Zortech Cとして復活した。この時になると、PC用のCコンパイラーは他にも多数あった(当時、30ぐらいは数えていたと思う)。私が差別化のための材料を探したところ、本屋でBjarne StroustrupのC++本を見つけた。当時の私は、「ヘン、キーワードいくつか追加して、数ヶ月ぐらいで、俺のコンパイラーはC++コンパイラーだぜ」と考えていた。このプログラミング世紀における見くびった発言であるだろう。もし、当時の私が、自分が何に突っ込んでいくかを知っていれば、当時の私は、周りの人が言う「絶対出来ない」という言葉を信じてしまっただろう。

ともかく、1980年台の後半というのは、多くの人が、Cの後継言語を開発していた時代だった。

当時のusenetで、そのような後継言語を目指すプロジェクトのひとつが、Dと呼ばれていたこともある。様々な理由で、これにはZortechが当時の最も有名なプラットフォーム向けの格安のC++コンパイラーとなっていたことも理由の一つであろうが、C++は他の言語を打ち破って、1990年代のプログラミングにおける独占言語になった。私はブームに乗って躍進した。

同時期(1990年代)に、私はネイティブコードを生成するJavaコンパイラーや、JavaScriptコンパイラー/インタープリターも書いた。この製品は成功しなかった。ここで書いておくが、私は、他人が必要だと私に言ってよこしたものを開発するより、私が必要とするものを開発する方が、相当に気分が良くなる種類の人間である。

たとえば、ある日、私はプログラマーの友人とジョギングをしていて、その友人に言われたことには、「ほら、この世界が切実に必要としているのは、ネイティブコードを吐くJavaコンパイラーだぜ。お前は造幣局になれるぜ。俺はJavaを使っているんだが、マジで必要なんだ」と。私は偶然にも、自分はすでにそういうものを書いてあるので、今すぐ使うことができるぞと言ってやった。もちろん、彼は使いはしなかった。

私がEmpireゲームを発明したのは、この私が遊びたかったゲームであったからだ。私がCコンパイラーを開発したのは、この私が、Empireを開発するのにマシなコンパイラーが必要だったからだ(あと他のプロジェクトも)。JavaやJavaScriptコンパイラーは、他人のアイディアだ。ただ、Dの誕生につながる話ではある。

15年以上もコンパイラーに携わっていて、言語の改良案のひとつやふたつも思いつかない者などいない。私は多くの言語の改良を、CとC++コンパイラーで試したが、全て失敗してしまった。誰も言語拡張には興味を示さない。皆、標準規格準拠の言語を求めている。当然のことだ。残念ながら、改良案が標準化委員会で採択されるには、とても難しい長年の政治活動が必要であった。実に私の忍耐力では耐えられない作業である。

1999年、私は引退を決め込んで、六週間も気が狂うぐらいテレビを見続けた。

そろそろ現実に戻らなければならない。既存の言語の問題について泣き言を言うのはもうたくさんだ。私は道具をパワーアップさせるべきだと決断した。このような問題について考えるたびに、私の脳裏には、ドワーフのギムリの言葉が浮かぶ。「死は確実にして業は成り難し。何を迷う?」。そうだ。少なくとも、手に利剣をひらめかして、栄光ある戦いに赴かねばならぬ。

そして、Dが始まった。単独で道路整備をしていくプロジェクトだ。私は自分でコンパイラーを書いたことがない言語でプログラミングするのでは満足できない性質であった(自分でも奇妙な性質だと思う)。私は様々な言語を実装した十分な経験があるので、私にはDを動かすことが可能であるという自信があった。また、すでに既存のC++コンパイラーという環境があったため、多大な利点も得ていた。

数年後、Dが初めてSlashdotにあらわれて、利用者と貢献者を急速に惹きつけていった。どうやら、私は、言語に求める機能という点で、変人というわけではなかったようだ。Dは理想に向かって、全世界の貢献者と共に、急激に成長していった。数カ月前に開かれたDconf2013まで、我々はお互いの顔すら知らなかったのだ(これはインターネット革命の偉大なる点である。他人の性別や年齢や風貌や人種や宗教や言語や文化や障害や境遇などを一切知らずして、協調作業が可能なのだ。実に純粋な実力主義社会である。意見と、貢献と、宣伝力だけがモノをいうのだ)

今日び、Dはインターネットなしでは存在し得なかった。インターネットの他に、切実な理想家が協力できる場所などどこにあろうか? githubやbugzillaのような協調作業ツールの興隆はDの開発にあたって重要であった(もちろん、オープンソースモデルもだ!)

しかし、私自信も、学ばねばならぬことがあった。厳しい方法で

  1. 私の単独作業を好む性質。多くの仕事で、私の仕事に対する評価というのは、たいてい次のような意見を含んでいた。「ウォルター君は他人と協調作業することを学ぶ必要あり」と。すべてを自分の支配下に置きたいという私の思いは、一度はDコミュニティを崩壊させかけたので、私は変わらなければならなかった。
  2. 私は全員がボランティアであるプロジェクトを管理する方法を学ばなければならなかった。私が誰にも金を払っていない以上、私は誰にも何かをさせることができないわけだ。私は他の方法を見つける必要があった。私は、性格テストでは「オタク」に限りなく近く分類されるので、他人のモチベーションを上げるなどというのは、私の得意分野ではない。これは面白い問題である。
  3. Dフォーラムでは、新しい言語機能の提案が毎日行われる。私は実に多く「ノー」と言わねばならない。これは実に難しいことで、特に提案者にとっては聞くのも難しいことだ。
  4. 管理というのは難しいそごとで、私には適任ではない。私もZortechやその他の強調する仕事では、うまくやれていなかった。私は(賢明なことに)、管理職に昇進されなかった。しかし、Dにおいては、避けることは出来ない。私は管理のやり方を学ばなければならず、十分にうまくやらねばならなかった。私には良き管理者になるべきモチベーションがあった。なぜならば、私はDに成功して欲しかったからだ。
  5. 私の友人はよく知るように、私は議論好きである。私はインターネット上の多くの炎上した議論に参加している。しかし、Dにおいては、私はそういうことができない。炎上した議論では、たとえどんなに間違っていようとも、誰も自分の意見を変えようとしないからだ(´・ω・`)。私の議論の経験は、面白い利点になっている。私には、議論がいつ、非建設的な論争になるかわかるので、頭を冷やさせることができるのだ。

    私は未だに、「シールドを張れ! 消滅光線が来るぞ!」的な行動をしたい衝動と戦わなければならない。もちろん、Dフォーラムの皆が同意するように、これはまだ発展途上なのだ。Dはこれまでも、これからも、素晴らしい実験であり続ける。多くの他の言語から最高のアイディアを拝借し、多くの、多くの世界中の貢献者による多大な貢献の集大成であり、参加者皆が、胸を張って誇れることなのだ。

結果として、私には宝物が出来た。Dでプログラミングするのは最高だ。Dは私が常に欲していた言語なのだ。私は否定論者や、Debbie Downer(米国の生放送コメディ番組Saturday Night Liveの登場人物、常にネガティブなことを言って場をしらけさせる役回り)や、そしてもちろん、借りを作っている大昔の無名のCグルの意見を聞かなくて、本当に良かったと思う。

で、君は独自の言語を書きたいんだって? そうだなぁ、「死は確実にして業は成り難し。何を迷う?」

ウォルたんはBjarne Stroustrupとパフェを食いながらC++のとある機能の実装方法について話し合って、即座に理解したなど、C++界隈でも逸話が多い。これを読むと、自尊心の高い気難し屋という印象を受ける。某連続的な人のコメントが待たれる。

ドワンゴ広告

この記事はC++とはちょっと関係があり興味深いと思ったので、ドワンゴ勤務中に紹介記事を書いてみた。

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

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

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

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