Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

2013-11-30

100kbpsで閲覧できるWebサイト、できないWebサイト

今、私が常時使えるネット回線は、DTIの提供する格安のSIMカードを利用したLTE経由のものだ。利用料金は月々490円+ユニバーサルサービス料3円となっている。

とてつもなく格安だが、極端な制限がある。帯域が100kbps、今は実験的に150kbpsに制限されているということだ。転送量制限はないのだが、この帯域は、2013年にはなかなかに厳しい。

私は、まだ56Kbpsのアナログモデムの頃からインターネットを利用しているが、もはや最低でも数Mbpsは当たり前になったこの時代に、100kbpsは、結構難しいところもある。使えるかどうかは、Webサイトにより異なる。

今、風邪をひいて体調が悪く、外に出れないのを幸いに、この低帯域でできることを試してみることにした。

まず、まともに閲覧できないWebサイトだ。

例えば、GMailのような、巨大なJavaScriptでできたプログラムで、常にサーバーと通信しているようなWebサービスは、かなり使いづらい。GMailのWeb UIには遅いネットワーク版もあるが、これでも100kbpsでは使いにくい。

結局、問題は帯域なのだ。あらゆる通信は100kbpsの帯域を通らなければならないのが問題なのだ。これら、数百キロバイトから数メガバイトもあるような巨大なJavaScriptプログラムをダウンロードするだけで時間がかかる。また、それだけではなく、そのJavaScriptプログラムは、さらにサーバーと通信を行う。

単に時間がかかるというだけではない。詳しい理由はわからないが、通常のGMailはたいてい、いくら待っても使えない。何度かリロードしてようやく使えるようになる。思うに、HTTPやHTTPSプロトコルを使い、複数のファイルを同時にダウンロードしようと試み、それがすべて狭い100kbpsのネットワークを通過しなければならないため、どのファイルもダウンロードが完了せずに延々とちびちび読み込み続けているのではないかと思う。通常のGMailは極端な低帯域は考慮していないようで、そういう場合に、いくら待ち続けようとも、延々と読み込み中の画面を表示し続ける。何度かリロードすると使えるようになるというのは、あるいはファイルの一部がキャッシュされてダウンロードしなくても済むため、並行ダウンロードが減少し、GMailのJavaScriptプログラムでも動く程度の時間でダウンロードできるようになるのではないか。あるいは、あまりに時間がかかりすぎるため、JavaScriptプログラムかブラウザーのどちらかがダウンロードを諦めたのか。

はたまたあるいは、これらのサイトがHTTPSプロトコルを使っているからなのかもしれない。あまりに低帯域でHTTPSプロトコルを使うとこういう問題に出くわすのかも知れない。

ひとたびGMailの巨大なJavaScriptプログラムが動きさえすれば、あとは快適に使えるのだが。

TwitterのWebサイト上のUIも、同じ問題を抱えている。Twitterのページを読み込む際に、他にも、別のページやファイルなどのダウンロードが発生している場合、たとえ別のページやファイルのダウンロードが終わって、帯域が空いても、読み込み中のまま一向に進まないことがある。

Googleの検索も、同じ問題を抱えている。

YouTubeは、動画の再生はともかく、極小のサムネイルの表示まで遅い。

では、まともに閲覧できるWebサイトは何か。

基本的に、テキストを主体とし、JavaScriptで高度で頻繁な通信を行っていないようなページは、問題なく表示できる。Hacker Newsも問題ない。[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッも問題ない。

意外なところでは、pixiv.netが快適に閲覧できるということだ。サムネイルの表示も十分に速い。もちろん、100kbpsなので、個々の画像をダウンロードして表示するのにはそれなりに時間がかるが、このサムネイル画像の速さは大したものだ。また、pixivはHTTPSを使っていないことも影響しているのかも知れない。しかし、それをいえばYouTubeだってHTTPSではないのは同じだ。しかも、pixiv以上に小さいサムネイル画像の表示が遅い。

あるいは、YouTubeを閲覧する利用者のネットワークは、そもそもそれなりに広い帯域が必要であろうから、手描き画像に特化したpixivほど低帯域ユーザーの需要がないのかも知れぬ。需要がなければ供給もない。Yahooが既存の広告媒体よりは安いが、ネット広告としては高すぎるのに、無知な広告主によって払われる多額の広告料にあぐらをかいて技術革新を怠り、Googleに追いぬかれたように、需要は重要である。

はて・・・低帯域ユーザーでも変わらず需要があるものとなると・・・

深い技術的好奇心の念に駆られた筆者は、あくまで知的探究心のために、xvideos.comを閲覧した。

Lo and behold!

すると見よ! わずか100kbpsの低帯域だというのに、YouTubeよりはるかに大きな、しかも大量のサムネイル画像が一瞬にして表示され、マウスカーソルを当てるとコマ送りまでするではないか。

筆者は慄然とした。今にして始めて芸道の深淵を覗き得た心地であった。

誠に残念ながら、OSから上は自由なソフトウェアのみで構成された筆者のコンピューター環境にはFlash Playerがなく、したがって、100kbpsのネットワーク越しに動画を再生できるかという肝心の主要機能に関しては、技術上非常に興味はあるものの、遺憾ながら検証できなかった。ただ、おそらくうまくやるのではないかと思う。

無論、これは今に始まった話ではない。エロサイトの動画プレイヤーの方が、YouTubeよりよっぽど優れているというのは、昔から言われていたことだ。

本の虫: なぜエロサイトの動画プレイヤーはYouTubeより高機能なのか

このようなエロサイトは、厳しい競争にさらされている。収益をあげるためには、できるだけ多くの閲覧者を得る必要がある。広告収入を得るにしても、課金収入を得るにしても、とにかく大量の閲覧者を集めなければならない。そのためには、低帯域ユーザーが閲覧できないということは、取り逃すことのできない機会損失なのだろう。それにしても・・・

論語に言う、いまだに色を好むが如きものを見ざるとはこのことか。

追記:pixiv.netとxvideos.comが快適な件について、少し事情が異なった。

ご注意事項|ServersMan SIM LTE:【dream.jp】

DTIの格安SIMカードを経由してHTTPプロトコルによりダウンロードされる、画像フォーマットのうち、JPG, GIF, PNGは、DTI側で自動的に劣化圧縮される。

xvideos.comで確認したときは、まあ、エロサイトだしこんなものかと思っていたのだが、さすがに引越し前まで毎日見ていたpixivは気がついた。

何のことはない。HTTPSプロトコルが遅いと感じていたのは、中間で乗っ取りできないからだったのだ。pixivやxvideosが快適に閲覧できたのは、画像を劣化圧縮していたからなのだ。

というわけで、この記事は当初の面白い記述から遠ざかってしまった。この記事を書くときは、「やはりエロ需要の力は偉大だ」という、あからさまに面白い結果になったと早合点して、そのように面白おかしく書いたのだが、現実はそれほど面白くはなかった。残念。

2013-11-29

Clangで-std=c++1yがいまだに使いにくい事情

ClangがC++14の機能完全に到達したことはすでに述べた。これはつまり、最新版のClangで、-std=c++1yを指定すると、現在のC++のドラフト規格の、動く実装が手に入るということだ。

これは素晴らしいことだ。

しかし、いざ実際にUbuntu 13.10でClangのSVN HEADを自前ビルドして使ってみようとすると、以下のようなエラーが表示される。

/usr/include/c++/v1/cstdio:156:9: error: no member named 'gets' in the global namespace

ヘッダーファイルを一切includeしなくても、このエラーは表示されてしまう。

この事情は・・・結構複雑なのだ。

C++14では、Cの標準ライブラリは、C11のものに合わせられた。C11の標準ライブラリでは、とうとうあの忌まわしき太古の呪いである、getsを廃止した。廃止である。非推奨ではない。C11では、もはやgetsは存在しないのだ。

したがって、C11やC++14モードでコンパイルするには、このgetsを#ifdefで囲むなどして、取り除く対応をしなければならない。

しかし、現行の多くのGNU/Linuxの安定版ディストロが使っているglibcのバージョンは、まだこの変更に対応していない。

それもそのはずで、C11のgets廃止に対応したglibcを使うには、GCC 4.9が必要なのだ。GCC 4.9は、まだ開発途中で安定リリースされていない。そんなGCCをデフォルトで出荷するGNU/Linuxディストロなどあるはずがない。

GNU/Linuxにおいては、libcのような基本的なライブラリと、C++コンパイラーは密接に関係していて、単にコンパイラーだけを自前ビルドして使うわけにはいかないのだ。

したがって、もし自前ビルドするとなると、ClangとGCC一式を完全に自前ビルドした上で、ライブラリへのパスを自前ビルドのglibcに通すなどしなければならない。おっと、C++標準ライブラリも、libc++を使いたいし、ABIライブラリも悩ましい。これらのコンパイラーとライブラリを正しく配置して正しくパスを通すのは、とても面倒なのだ。

やればできるだろうが、こんな面倒なことはやりたくない。私はおとなしく、GCC 4.9が安定リリースされて、GNU/Linuxディストロで、ソフトウェアがプロの手によってパッケージ化されるのを待つことにする。

とはいっても、とりあえずC++14の新機能を試してみたいものだ。実は、そんなあなたにうってつけのSaaSSがある。

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

melponさん、ありがとよ。

なんと、Vim用のプラグインまである。

rhysd/wandbox-vim

Linda_ppさん、ありがとよ。

参考:

Bug 13566 – Glibc should define gets for C++11

Bug 51785 – gets not anymore declared

2013-11-28

12月18日に東京に行きそうな予定

どうやら、12月18日に東京に行く機会がありそうだ。

今回は、表立った発表ではないが、魔導書の記事執筆依頼、数年ぶりにC++の歴史をまともに調べた。といっても、大方はD&EやHOPL2, HOPL3を読み返しただけなのだが。HOPL-3以降の歴史は、現在進行形で私も追っているし、まだ現在のことなので、Stroustrupがまとめるほどではない。ただ、いずれStroustrupの視点でまとめたHOPL-4がでれば、読みたいとは思う。

また、今となっては死んだEC++についても、いい機会なので、最初から最後まで関わっていた人物から、改めて話を聞いた。

その結果は、まだスライド資料として執筆中だが、とりあえず資料だけでも、12月中に公開しておこうと思う。

今のところの予定としては、とりあえず18日は卓球ハウスに泊めてもらい、18日か19日に、誰かと食事にでも行ければと考えている。

CとC++の違い: Basic Concepts編

京都C++勉強会の宣伝のために、CとC++の違いを、少しづつ解説することにした。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

C++はCの完全互換ではない。Cのあまり良くない部分は、変更して改良した。ここでは、そのような変更点のうち、互換性に特に問題のあるものを取り上げる。

tentative definitionの有無

C言語には、tentative definitionという機能があった。以下のようなコードが合法になる。

int i ;
int i ; // well-formed in C, ill-formed in C++

C++にはOne Definition Ruleがあるので、このようなコードは違法である。

C言語に存在するtentative definition機能は、定義の後で初期化できるという機能を提供している。

struct X { X * next ; } ;

X a ; // 定義
X b = { &a } ;
X a = { &b } ; // 初期化

C++では、基本型とユーザー定義型で別々の初期化ルールを設けるのを防ぐために、tentative definition機能はCから受け継がなかった。

structにはスコープがある

C++では、structは構造体ではなくクラスであり、新たなスコープを作る。Cではstructは、単なる構造体であり、その名前探索の挙動が異なる。

ただし、通常はこの差を気にする必要はない。

ファイルスコープ内で、const修飾され、extern指定されていない変数は、C++では内部リンケージとなる。Cでは、外部リンケージとなる。

// file1

// Cでは外部リンケージ
// C++では内部リンケージ
const int x = 0 ;
// file2

// Cではfile1のxを指す
// C++は違う
extern const int x ;

C++では、constオブジェクトは、コンパイル時定数となることもあるので、初期化子が必須なこともあるので、このような変更がなされた。

C++では、main関数を再帰的に呼び出すことはできず、アドレスを取得することもできない。

C++では、main関数は特別なものとして認識され、呼び出すことはおろか、アドレスを得ることさえできない。Cでは、そのような制限はない。

C++でこのような制約がある背景事情としては、mainは特別な扱いであるべきで、その実装方法に関して、C++の実装に、通常のような関数として扱えるような制約を持たせたくないというものがあるそうだ。

Cで書かれたmain関数を再帰呼び出ししたりアドレスを得たりするコードを移植する際には、単にmain関数から呼び出される別名で同じ仮引数の関数を作ればいい。そもそも、main関数を再起呼び出ししたりアドレスを得たりするような実用的なコードは、あまり存在しないだろう。

C++にはCompatible type(互換型)が存在しない

Cには、互換型というものが存在する。例えば、タグ名以外はすべて同一の構造体などが該当する。C++は強い静的型付けを持っているので、そのような互換型は存在しない。

Cでは、そのような型非安全なコードは多いのではないかと思う。

明日も、宣伝のために標準型変換の変更点を解説する。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

2013-11-27

CとC++の違い:字句編

京都C++勉強会の宣伝のために、CとC++の違いを、少しづつ解説することにした。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

C++はCの完全互換ではない。Cのあまり良くない部分は、変更して改良した。ここでは、そのような変更点のうち、互換性に特に問題のあるものを取り上げる。

今回は、字句編だ。

新しいキーワード

C++では、新しいキーワードが追加されている。C++で追加されたキーワードを名前に使っているようなCコードは、問題になる。

文字リテラルの型がintからcharに変更

Cでは、'a'の型は、intだった。これは、オーバーロード解決で問題になる。

// 実装依存の整数が出力される
std::cout << 'a' ;

C++では、文字リテラルの型をcharに変えた。

これにより壊れる可能性のあるコードとしては、sizeof('x')のようなコードが想定されている。しかし、そのようなコードはあまり多くないだろう。

文字列リテラルの型がconstになった。

Cでは、文字列リテラルの型はconstではなかった。C++ではconstだったが、C++03までは、文字列リテラルに限り暗黙にconstを消し去ることを認めていた。C++11では、そのような標準変換もなくなったので、以下のようなコードはエラーとなる。

// エラー
char * ptr = "hello" ;

このようなコードは、そもそも適切ではない。文字列リテラルの指し示すストレージを書き換えた結果は未定義だからだ。案外まだ、このような不適切なコードは残っているのではないだろうか。

明日も、宣伝のためにBasic Conceptsの変更点を解説する。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

2013-11-26

ラップトップ用のインナーケースを買った

新しい15.6インチのラップトップを譲り受けたことはすでに述べた。このラップトップのパフォーマンスは申し分ないが、少々大きい。大きいのはいいのだが、最近はラップトップを持ち運んで、家の外で作業をすることが多い。その持ち運びがやや不便だ。

私は、昔使っていた13か14インチのラップトップ用のカバンを持っている。このカバンは、ラップトップを固定するためのポケットが付いているのみならず、背負うこともできれば手持ちのとっても縦横二箇所についているし、肩から下げる取り外し可能なヒモも付いているという、結構多機能なカバンなのだ。ただし、だいぶ傷んできて、背負いヒモの縫い目も危なげにみえるし、15.6インチのラップトップがポケットに入らない。ポケットに入れずに直接入れると、他にいくらも入らないし、他にもACアダプターやマウスやキーボードなどが直接あたって危なげだ。

私は、安いが高機能なリュックを持っている。腰で固定するヒモがあるし、外側から引っ張って中身を固定するためのヒモも四カ所についているリュックだ。このリュックは悪くないが、ラップトップを固定するためのポケットがついていない。このリュックに、他の荷物とともにラップトップを入れるのは怖い。

しかし、毎日ラップトップを持ち運ぶという事情もあるので、やはりなにか一つ、ラップトップ用のカバンを買わなければならないだろう。背負いヒモもついているものがよい。

大型の家電量販店に行って、色々とみてみたが、どうもいいものがない。カバンには背負いヒモがついていない。ラップトップ用のポケットがあるリュックもたくさん売っているのだが、どれもリュックとしては甚だ貧弱なのだ。しかも、値段も1,2万円する。質が低すぎて、値段に見合っていない。一体これはどういうことだろう。

色々と考えた結果、ラップトップ用のインナーケースを買うことにした。インナーケースはどんなに高いものでもせいぜい数千円なので、たとえ失敗しても数万円のカバンやリュックよりはましだ。インナーケースならば、カバンやリュックは別に高品質なものを使えばよい。

どのくらい頼れるのかはわからないが、撥水加工された表面で、適度に硬くて四隅も丈夫で、面はクッションになっているものを買った。

コンパイル時zip関数の書き方、並びに京都C++勉強会の案内

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

さて、昨日は、コンパイル時zip関数を書いた。ただし、コードだけで解説が欠けていた。今日は、解説をしようと思う。

zip

本の虫: 久しぶりにメタプログラミングらしいメタプログラミングをした

以下のような関数

template<std::size_t N, typename... T>
auto zip(const std::array<T, N>&... containers)
    -> std::array < std::tuple < T ... > , N >

が、以下のように動く。

std::array<int, 5> a = {1, 2, 3, 4, 5}; std::array<char, 5> b = {'a', 'b', 'c', 'd', 'e'}; zip<5>(a, b); // -> std::array<std::tuple<int, char>, 5> : (1, 'a'); (2, 'b'); ...; (5, 'e') std::array<int, 4> c = {1, 2, 3, 4}; zip<4>(a, c) // -> compile time error std::vector<int> d = {1, 2, 3, 4, 5} zip<5>(a, d) // -> complie time error

これ自体は、実行時関数ならば、以下のように書ける。

template < std::size_t N, typename ... Types >
auto zip_runtime( std::array< Types, N > const & ... containers )
    -> std::array< std::tuple< Types... >, N >
{
    std::array< std::tuple< Types... >, N > result ;

    for ( std::size_t i = 0 ; i != N ; ++i )
    {
        result[i] = std::make_tuple( containers[i] ... ) ;
    }

    return result ;
}

と、このように簡単なコードなのだが、これはconstexpr関数にできない。無駄なループがある。このようなコードは、リスト初期化を使えば、以下のように書ける。

std::array< std::tuple< Types... >, N >{
    { std::make_tuple( containers_0[0], containers_1[0]) },
    { std::make_tuple( containers_0[1], containers_1[1]) },
// ...
} ;

こういう形に落としこんでしまえば、最初から初期化としてarrayを構築できるし、constexpr関数にできる。

containersは、パック展開でいくらでも展開できるが、添字をどうにかしたい。これにはInteger Sequenceと呼ばれているテクニックを用いることができる。原理はN3493で解説されていて、C++14の標準ライブラリに入るのだが、残念ながら、C++11で実装しなければならないので、これを実装しなければならない。この論文と実装例は、すでに簡易レビューで紹介している。

本の虫: C++ 2013-01 mailingの簡易レビュー

template< std::size_t ... >
struct index_seq { } ;

template < std::size_t N, typename T >
struct make_index_seq_impl ;

template < std::size_t N, std::size_t ... I  >
struct make_index_seq_impl< N, index_seq< I ... > >
{
    using type = typename make_index_seq_impl< N-1, index_seq< N-1, I... > >::type ;
} ;

template < std::size_t ... I  > 
struct make_index_seq_impl< 0, index_seq< I ... > >
{
    using type = index_seq< I... > ;
} ;

template< std::size_t N >
using make_index_seq = typename make_index_seq_impl< N , index_seq< > >::type ;

これは、単にNを指定すると、0,1,2,3... Nまで整数型の非型テンプレートパラメーターパックを生成するための、簡単なメタ関数だ。この実装は簡易的なもので、テンプレートの再帰深度が線形に増えていくが、今回は特に問題としない。

ここまではいい。ではさっそく、これを使ってリスト初期化に展開されるコードを書こう。

template < std::size_t N, std::size_t ... I, typename ... Types >
constexpr auto zip_aux( index_seq< I ... >, std::array< Types, N > const & ... containers )
    -> std::array< std::tuple< Types... >, N >
{
    return std::array< std::tuple< Types ... >, N >{ { 
        // エラー
        std::make_tuple<I>( containers[I]... )...
    } } ;
} 

template < std::size_t N, typename ... Types >
constexpr auto zip( std::array< Types, N > const & ... containers )
    -> std::array< std::tuple< Types... >, N >
{
    return zip_aux( make_index_seq< N >(), containers ... ) ;
}

残念ながら、これエラーになる、なぜなら、パラメーターパックが2つもあって、その数も同じではないからだ。そのため、パック展開に失敗する

C++ Templates Metaprogrammingに書いてあるように、問題があるときは、もう一段階の参照を挟んでやるとよい。ここでは、パック展開されたコンテナーをパラメーターパクで、添字を非パラメーターパックで受け取ってtupleを返す関数を追加する。

template < std::size_t I, std::size_t N, typename ... Types >
constexpr auto make_unpacked_tuple( std::array< Types, N > const & ... containers )
    -> std::tuple< Types ... >
{
    return std::make_tuple( containers[I]... ) ;
}

このもう一段階の参照を使えば、以下のように書ける。

template < std::size_t N, std::size_t ... I, typename ... Types >
constexpr auto zip_aux( index_seq< I ... >, std::array< Types, N > const & ... containers )
    -> std::array< std::tuple< Types... >, N >
{
    return std::array< std::tuple< Types ... >, N >{ { make_unpacked_tuple<I>( containers... )... } } ;
} 

template < std::size_t N, typename ... Types >
constexpr auto zip( std::array< Types, N > const & ... containers )
    -> std::array< std::tuple< Types... >, N >
{
    return zip_aux( make_index_seq< N >(), containers ... ) ;
}

このように書けば、constexpr関数にできるzip関数の出来上がりだ。わざわざループで代入しなくても、構築時のリスト初期化で済ますことができる。

さて、冒頭でも書いたように、江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能や、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

2013-11-25

久しぶりにメタプログラミングらしいメタプログラミングをした

zip

これをみて、早速実装を始めたが、残念ながらボレロ村上さんに抜かれてしまった。

ボレロ村上の実装

ボレロ村上さんのコードを参考にしたわけではないが、書き終わってから見ると、同じになっていた。

江添の実装

#include <iostream>
#include <array>
#include <tuple>
#include <cstddef>


template< std::size_t ... >
struct index_seq { } ;

template < std::size_t N, typename T >
struct make_index_seq_impl ;

template < std::size_t N, std::size_t ... I  >
struct make_index_seq_impl< N, index_seq< I ... > >
{
    using type = typename make_index_seq_impl< N-1, index_seq< N-1, I... > >::type ;
} ;


template < std::size_t ... I  > 
struct make_index_seq_impl< 0, index_seq< I ... > >
{
    using type = index_seq< I... > ;
} ;

template< std::size_t N >
using make_index_seq = typename make_index_seq_impl< N , index_seq< > >::type ;

template < std::size_t I, std::size_t N, typename ... Types >
constexpr auto make_unpacked_tuple( std::array< Types, N > const & ... containers )
    -> std::tuple< Types ... >
{
    return std::make_tuple( containers[I]... ) ;
}

template < std::size_t N, std::size_t ... I, typename ... Types >
constexpr auto zip_aux( index_seq< I ... >, std::array< Types, N > const & ... containers )
    -> std::array< std::tuple< Types... >, N >
{
    return std::array< std::tuple< Types ... >, N >{ { make_unpacked_tuple<I>( containers... )... } } ;
} 

template < std::size_t N, typename ... Types >
constexpr auto zip( std::array< Types, N > const & ... containers )
    -> std::array< std::tuple< Types... >, N >
{
    return zip_aux( make_index_seq< N >(), containers ... ) ;
}

int main()
{
    constexpr std::array<int, 5>  a = { { 1, 2, 3, 4, 5 } };
    constexpr std::array<char, 5> b = { { 'a', 'b', 'c', 'd', 'e' } };

    auto c = zip<5>(a, b) ;


    for ( auto const & i : c )
    {
        std::cout << std::get<0>(i) << " , " << std::get<1>(i) << '\n' ;
    }
}

なお、ここで使っているindex_seqは、今、標準ライブラリに提案されている。

本の虫: C++ 2013-01 mailingの簡易レビュー

ちなみに、これはコンパイル時実行にこだわっているからこうなるのであって、実行時実行なら、普通に以下のように書ける。

zip.cpp

Ubuntu 14.04でもMir/XMirの採用はなし

[Phoronix] Ubuntu 14.04 LTS Won't Be Powered By Mir

[Phoronix] Canonical Commits To Mir For Ubuntu 14.10

まだMir/XMirは十分な完成度ではないとして、LTSリリースとなるUbuntu 14.04では、デフォルトで採用とはならないようだ。

吉田物語

願わくはこれを語りて非寮生を戦慄せしめよ

今日は昼前に吉田寮にやってきて、探索を行った。目的は、この場所の現状の記録と、話の収集である。

吉田寮は外から見ると、まるで廃墟同然だが、中からみても、やはり廃墟同然だ。ただし、そこには紛れもなく人間が生息している。

庭には、様々な動物が、食用として飼われている。私が確認した限りでは、ニワトリとヤギとウサギとエミューがいる。ネコもいるのだが、これはさすがに食用ではないだろう。

ここでは、あらゆるものが乱雑に放置されている。盗まれることもあるらしいが、果たしてどれが私物で、どれが捨てられているのか、そのへんは明確ではない。

ここでは、食べ物には所有の概念がないらしく、食べ物を放置していると、しょっちゅう食べられる。私の取材し得たO氏からは、炊飯器にご飯を炊いておき、いざ食べようとフタを開けたら、すでに誰かに食べられて空っぽだった事例を収集した。

ただし、ここで私が収集し、これから私が物語る話を読めば、むしろ食べてくれたほうがいくらかありがたいことを知るであろう。

決して開けてはならぬ封印されし炊飯器のこと

まだ遠からぬ昔、吉田寮入り口付近に、炊飯器が放置されていたそうだ。いつから放置されていたのか、正確に知るものはいない。数カ月かもしれないし、数年かもしれない。とにかく、長い間放置されてきたことに疑いはない炊飯器だ。問題なのは、その炊飯器には、どうやら中身が入っているらしいというのが、住人の間の暗黙の了解であった。

かくして、その炊飯器は、決して開けてはならぬ禁断の炊飯器として、長らく封印されてきた。まるで、魔封波を受けたナメック星人が封じられているとでも言わんばかりに、避けられてきた。

しかし、いつまでもかの封印されたる炊飯器を入り口に置いておくわけにはいかぬ。いずれは開けねばならぬこととて、とうとう、開封の儀を執り行う次第に決まった。

皆が万全の体制(無論、逃走の用意である)で見守るなか、決して開けてはならぬ炊飯器が開かれた。彼らは一体、何を見たのであろうか。

残念ながら、私がこの話を収集した某氏は、この続きをはぐらかして語ろうとしない。単に固まったご飯が入っていたという者もあり、黒いものが入っていたという者もあり、液状の何かが入っていたという者もあり、虫がたくさん湧いていたという者もあり、その詳細は判然としない。

2013-11-24

純粋仮想関数は定義を持てる

GitHubで公開しているC++参考書に、以下のようなpull requestが送られてきた。

Pure virtual function by daisukekoba · Pull Request #153 · EzoeRyou/cpp-book

純粋virtual関数は、宣言を分ければ、定義も持てるそうだ。実際にまともなC++コンパイラーでコンパイルしてみると、たしかにその通りだ。

どうやら、私の規格の文面の解釈が間違っていたらしい。

C++の規格に曰く、

10.4 paragraph 2

A function declaration cannot provide both a pure-specifier and a definition.

ひとつの関数宣言はpure指定子と定義の両方を提供することができない。

これを読むと、以下のコードがエラーになることがわかる。

struct S
{
// エラー、pure-specifierと定義を両方持つ
    virtual void f() = 0 { }
} ;

しかし、私は「ひとつの」という部分を見落としていた。つまり、複数の関数宣言を使えば、両方とも持てるのだ。

struct S
{
// pure-specifier
    virtual void f() = 0 ;
} ;

// 定義
void S::f() { } 

規格の文面を正しく解釈すると、このコードは正しいはずで、実際に、既存のC++コンパイラーはこのコードを通す。

これをなぜかと考えると、abstract classでも、デストラクターは定義したいという利用例がある。

class Base
{
    int * ptr ;
public :
    Base() : ptr( new int(0) ) { }

// コピーとムーブの特別なメンバーの宣言など

    virtual ~Base() = 0 ;
} ;

Base::~Base()
{
    delete ptr ;
}

class Derived : public Base
{
    virtual ~Derived() { }
} ;

なるほど、もちろん、このように書きたい。すると、pure virtual functionかつ定義をもつというデストラクターは、至極当然のように思われる。デストラクターに許されているのだから、一貫性を保つために、普通の非staticメンバー関数でも、当然許されるべきだ。

しかし、このことについて色々と試していた結果、以下のようなコードが書き上がってしまった。

struct Base
{
    virtual void f() = 0 ;
    virtual ~Base() = 0 ;
} ;

void Base::f() { }

Base::~Base()
{
// Derivedはすでに破棄されている
// デストラクター呼び出しは警告、実行時abort、ともになし。

// GCC, Clang、ともにコンパイル時警告
// GCCでは問題なく実行可能
// Clangでは実行時に純粋仮想関数呼び出しエラーで意図的にabort
    f() ; // Base::fを呼ぶ
}

struct Derived : Base
{
    virtual void f() { }
    virtual ~Derived() { }
} ;

int main()
{
    Derived d ;
}

なんと、GCCとClangでは挙動が違っているではないか。しかも、GCCでは問題なく実行できるのに対し、Clangでは実行時エラーとしてabortするという、実行時にまで影響を呼ぼす差異だ。これはどちらかのコンパイラーが間違っているのではないか。しかし、どちらの挙動が正しいのか。

私の当初の間違った考えでは、デストラクターも純粋仮想関数かつ定義をもつのに、警告も実行時abortもないため、どうも一貫性にかける。これは、コンパイラーがおかしいのではないか、とくに、Clangがおかしいのではないかと考えた。

久しぶりに、よくよく考えてもわからない問題だったので、私よりもっとできる人に聞いてみた。つまり、C++WGのMLにメールを投げた。すると、私の考えは全く持って見当違いだったことが明らかになった。

12.7で規定されているように、ポリモーフィックなオブジェクトの構築時、破棄時は、あたかもそのオブジェクトが最終的なオーバーライダーであるかのように振る舞う。Baseのデストラクター内で呼ばれている未修飾名fが、Base::fを呼ぶのはそのためだ。しかし問題は、未修飾名で呼び出すので仮想関数呼び出しになるということだ。仮想関数呼び出しで純粋仮想関数が呼び出された場合、挙動は未定義である。たとえ定義があろうとも、Base::fは純粋仮想関数であることに変わりはない。純粋仮想関数である以上、仮想関数呼び出しで呼び出された場合、挙動は未定義となる。未定義である以上、何が起きても文句は言えない。

そのため、この場合にBase::fを呼び出したい場合は、修飾名で呼び出して、仮想関数呼び出しを避けなければならない。

Base::~Base()
{
    Base::f() ; // OK
}

しかし、デストラクターはどうなのだ。なぜデストラクターにはコンパイル時警告も実行時エラーもないのだ。それはなぜかというと、デストラクター呼び出しは、たとえ仮想関数であっても、派生クラスから明示的に基本クラスのデストラクターが呼び出されたかのように振る舞うのだ。だから、仮想関数呼び出しではない。仮想関数呼び出しではない以上、問題はない。

したがって、GCCとClangの挙動は、どちらとも正しい。規格上未定義なのだから、何が起きても文句は言えない。ただし、GCCはコンパイル時に警告を出しているので、かろうじて問題がわかる程度だが、Clangは実行時にabortを出しているので、とても親切である。だからといって、GCCが規格違反の実装というわけではない。

ああ、まだまだ未熟だ。

2013-11-23

伝説のゲームプログラマー、John Carmack様がid Softwareから離脱

id Software founder John Carmack resigns | Polygon

Id Software founder John Carmack resigns | Hacker News

ビデオゲームに3D FPSというジャンルを作り上げた伝説のゲームプログラマー、John Carmack様が、id Sfotwareをお離れになられるそうだ。

Daikatanaとかいうクソゲーを作ったRomero様に続いて、Carmack様もidから去り、一つの時代が終わったのを感じる。

もはや、まともなFPSゲームは二度と作られないだろう。リアルタイムレンダリングの3DCGによるゲーム、特にFPSゲームはあまりにも大衆化してしまった。これからのシューターは、無線による遅延を気にしないほどの大味な作りになり、三人称視点になり、カバーやQTEだらけで、しかも何もしなくてもNPCが勝手に進めてくれる、そんな屁みたいなゲームに成り下がるだろう。

John Carmack様の離脱は寂しいが、もはやリアルタイム3DCG描画には、彼のような天才は必要ないのだ。3Dゲームエンジンなども、もはや一人の天才の手によって書かれるものではなくなっている。残念だが、それほど大衆化してしまったのだ。

聞けば、John Carmack様は最近、ゲームよりも、ヘッドギアなどの大掛かりな装置を使った拡張現実に興味を示されているご様子で、そのような研究開発している会社、Oculus VRでフルタイムで働くために、idを離れるのだそうだ。

拡張現実は、いまだに一般大衆が使えるほど安価な装置やソフトウェアがない。拡張現実がまともに一般人が楽しめるレベルにまで進化するのかどうかは、浅学近眼の筆者にはわからないが、Carmack様のあふれる才能を発揮して挑戦する場としては、ふさわしいのではないかと思う。才能あるものは、常に未知の分野を開墾するべきなのだ。すでに耕されて、安定した石高の田畑にとどまり、あたら才能を埋もれさせるのはあまりにももったいない。

2013-11-22

プログラミングを学ぶ環境について

昨日、今日と吉田寮にいて、数人集まって、それぞれ自分勝手にコードを書いていたわけだが、思うに、このような環境はプログラミングの学習環境としてかなりいいのではないかと思う。

結局、プログラミングというのは、講師が前の黒板に90分間板書したものを読んで学べるものではないのだ。自分で調べて、コードを書いて、動かして学ばなければならないのだ。

ただし、「自分で調べて」というのが、大抵の場合、非効率的になる。例えば、テンプレートメタプログラミングに詳しくないものが、CRTPのようなテクニックを必要とする場面に出くわしたり、ある型がPODであるかどうかを調べる方法(std::is_pod)について、自力で調べるとすると、無駄に時間がかかる。まずどこを調べればいいのかわからない。ドキュメントがどこにあるのかもわからない。

しかし、CRTPやstd::is_podのようなものは、理解しているものが教えれば、5分、10分で原理を教えられるようなものだし、ドキュメントがどこにあるのか指し示すのも一瞬ですむ。こういう時、複数人が、めいめい自分勝手に作業をしていて、たまに相談できるような環境があればいい。

ただ、そのような学習環境は、お互いのためにはなるが、金にはならないという問題がある。難しいものだ。

また、小規模なら、吉田寮でも勉強会を開けそうだが・・・あまりに汚らしい場所なので人を選ぶ。

江添とボレロ村上の京都C++勉強会、開催の告知と参加者募集のお知らせ

参加申し込み:江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

江添とボレロ村上の京都C++勉強会

江添とボレロ村上の京都C++勉強会

概要

12月16日に、京都にある、はてな京都本社で、C++の勉強会を開催します。参加申し込みは上下のATNDリンク先から行えます。

基礎情報

内容C++の勉強会
開催日2013年12月16日
時間19:00~22:00
場所〒604-0835 京都府 京都市中京区高宮町206 御池ビル8F (1階にセブンイレブンが入っているビルです)
会場名 セミナールーム(エレベーターを8階で下りてまっすぐ廊下を進んだ先が入り口です)
発表者江添亮ボレロ村上
参加枠40人
参加費無料

入場方法

御池ビル8階には、西側の玄関から入り、廊下をまっすぐ進むと見えるエレベーター1つで上がれます。

開場の時間帯(19:00~19:30)には、正面玄関はシャッターが閉まっている可能性が高いので、ご注意下さい。

また、西側の入口も19:40には施錠されるため、それ以降に入場される場合は、ドアの右側に備え付けのインターホンで「801」を押して呼び出して下さい。

セミナールームへは、エレベーターを8階で下りて、まっすぐ廊下を進んだ先にあるドアから入れます。

時間割

時間 内容 発表者
19:00-19:30 開場
19:30-20:20 C++14の新機能 江添亮
20:20-20:30 質疑応答 江添亮
20:30-20:40 休憩
20:40-21:30 すごいconstexprたのしくレイトレ! ボレロ村上
21:30-21:40 質疑応答 ボレロ村上

発表内容

タイトル:C++14の新機能

発表者:江添亮

内容:C++14のコア言語の新機能をすべて解説

スライド資料

タイトル:すごいconstexprたのしくレイトレ!

発表者:ボレロ村上

内容:constexprでのレイトレーシングの実装を通じて、ライブラリ設計や数学演算実装などの実践的テクニックから言語トリビアまでをたのしく学ぼうという主旨

その他

当日、Ustreamによる配信があります。

http://ustream.tv/channel/hatenatech

質問があれば、boostcpp@gmail.comまで

参加申し込み:江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

追記:申し込みキャンセルできるように設定

追記2:もし、今回の開催が平日の夜のために参加できないが、ぜひとも参加したい人が十分にいれば、来年にもどこかで開くかもしれない。

吉田寮に泊まることになった

ふとした縁で、京大の吉田寮に呼ばれた。吉田寮というのは、名前だけはしっていたが、まさか実際に行くことになるとは思わなかった。そしてこの記事は、吉田寮の中で書いている。

吉田寮に行くにあたって、事前に画像を検索すると、出るわ出るわ、何十年も前からタイムスリップしてきたような画像が出てくる。まさか、今もこの佇まいを残しているのだろうか。

今回呼ばれたのは、ある京大生が、C++勉強会の部屋として、京大の教室を借りられると連絡してきたことがきっかけだ。勉強会の詳細は、明日ATNDで公開するが、今回は、はてなのセミナールームで行うことになった。だが、京大の教室というのはかなりの人数が入るので、来年に勉強会を開く際には、使えるだろう。

それはさておき、今は吉田寮だ。吉田寮は、実際、画像の通りの佇まいを残していた。今にも倒れそうなほどボロボロだ。壁は穴だらけ、落書きだらけ、廊下にも部屋に物があふれ、おまけにドアには鍵がかかってない。

今日は一日、C++やプログラミング言語について語り合った。C++にはあまり詳しくない人も多いのに、C++14やC++17で提案されている新機能が、口頭で言うだけで通じるというのは、なかなか興味深い。

吉田寮は汚いが、私はとても気に入った。とても気に入ったので、200円払って一泊することにした。しかしこの、勝手に泊まってもあまり誰も問題にしなさそうな雰囲気はどうだろう。折田先生の精神は未だに残っているのだろうか。

吉田寮で興味深いのは、京大に関係ない人間もいるということだ。ニートとかフリーターとか、吉田寮が楽しくてわざわざ大阪から京大の近所に引っ越してきた人がいる。混沌とし過ぎていて現実感がない。

もっと解せないのは、女もいるということだ。一体、こんな汚い男だらけの環境に、どうやって女が生活していけるのか疑問だが、まあ、意外と犯罪は少ないそうだし、環境さえ気に入れば、いいところなのだろう。

最高に解せないのは、時期によっては子供までいるのだそうだ。まあ、暇人は常にいるし、子供には面白い遊び場だろう。

とても面白い場所だ。これを機会にちょくちょく遊びに来よう。

2013-11-20

引っ越し最終日

今日は引っ越しの最終日だ。部屋は不要品ごと売り渡すことになっているので、今日は最終の確認をしなければならない。もう、必要なものは全て運びだしたはずだが、念の為だ。

とりあえず、今日までは引っ越しで忙しいが、明日以降はだいぶ落ち着けるはずだ。

もったいなくも捨てなければならないこともある。例えば、高校の時の数学の教科書は、何かの役に立つかと思って今まで持っていたが、結局一度も開くことはなかった。必要ならば、後でいくらでも手に入るし、名残惜しいが、この際処分してしまうことにしよう。

新しい環境は意外と快適だ。まず場所が賑やかなので、歩いていける範囲で何でも揃う。

さしあたっては、ネット環境をどうするかということだ。今、100kbpsの回線が常時あるし、より帯域が必要ならば、無料や少額で利用できるWiFiがあるので、特に問題はない。落ち着いたら、WiMAXの契約を考えてみようと思う。C++の参考書が、数十人に売れたので、とりあえずWiMAXをしばらく契約することはできる。

もし、C++を詳細に解説した参考書が見つからなくて困っている者がいれば、私の自由なC++参考書が役に立つだろう。

Gumroadで購入:C++11参考書:C++11の文法と機能

本の虫: C++参考書の販売:C++11の文法と機能

GitHub: EzoeRyou/cpp-book

GitHubからzipでダウンロード

GitHub Pagesでの閲覧:C++11の文法と機能

本の虫: C++11参考書の公開:C++11の文法と機能

2013-11-19

(仮)京都で行うC++勉強会について現時点で決まっていること

かねてから計画と準備をしていた、京都で行うC++勉強会の正式な告知と募集は、今週末に行う予定だが、現時点で決まっていることを公開しておく。

場所は、はてなの好意で、はてな京都本社のセミナールームを使わせてもらえることになった。

まさか江添がC++だけで伝わるとは、思えばC++の規格に絞って深く学び始めてから、もう10年はたつ。

今回は、場所が確保できたので、参加料の徴収は考えていない。

日時は、2013年12月16日、時間は19:00頃から受付して、19:30から発表、22:00までには終了を予定している。終了時間はまだ確定していない。

発表者は、私とボレロ村上さん。私の発表は、C++14のコア言語の新機能すべて、ボレロ村上さんはまだ詳細が決まっていないが、constexprについて発表するそうだ。constexprの解説か、あるいはコンパイル時レイトレーシングか。

時間の都合上、発表は、大きな発表2つに絞ることにした。

勉強会には、終わった後の懇親会もつきものだが、今回は終了時間が遅いので、特にあらかじめ表立って計画することは考えていない。終わった後に、夜遅くだが一緒に食事でも行きたい人がいるかどうか。

実は、京大の教室が借りられるかもしれないという話もあったが、今回は、はてなのセミナールームで行うことにした。京大の教室は広いので、もし借りられて、人数が集まるならば魅力的だ。来年に検討してみたい。

2013-11-18

ひざ上時代の到来

というわけで、しばらくはこの貰い物のラップトップで作業する。ひざ上時代の到来だ。

ラップトップとはいえ、パフォーマンス的には文句のつけようがない。

さようならデスクトップ、こんにちはラップトップ

6年間もの長きに渡り、直しつつ使っていたこの思い出深いデスクトップともお別れだ。思えばいろいろあった。CPUファンと電源は壊れたので交換したし、GPUは3枚も交換しているし、HDDもOSを変える際に変えた。

ただ、IntelのQ6600や、DDR2の4GBのメモリは、さすがに時代に遅れてきた。

幸い、この思い出深いデスクトップを破棄することだけは免れたが、次に使う日は、いつになるのか分からない。新しく引っ越す場所は、仮の家で、数ヶ月でまた引っ越す予定だからだ。使えたとしても、そろそろ時代に合わなくなってきている。

残念ながら、私が高校生の一夏バイトをして買った、始めて私が所有したコンピューターは、HDD以外は破棄することになる。もう6年使っていないし、そのHDDもIDEだし、そもそも動くかどうかもわからないが、HDDだけは何が入っているかわからない。6年前とはいえ、ログインcookieも残っているし、個人情報のかたまりである。たしかパスワードも平文で保存していたような気もする。捨てるにしても破壊して捨てなければならない。

とはいえ、今は時期が悪い。いや、ことコンピューターを購入するにあたっては、いつだって時期が悪いのだが、特に今は時期が悪い。そろそろDDR4が市場に出回る頃で、できればそれを待ってから買いたいものだ。また、その時までに、経済上の問題を解決しなければならない。

これから代わりに使うのは、このAcerのラップトップ。だいぶ増設されていて、もてあますぐらいのパフォーマンスになっている。6年前から使っている思い出深いデスクトップよりパフォーマンスが高い。

インターネットは、とりあえず100bpsのDTIの格安SIMのカードによるLTEがあるが、これは来年の半ば辺りまでの借り物だし、C++の参考書の売上で、数年ぐらいは無線インターネット接続を契約できるぐらいにはなったし、引っ越しが落ち着いたら、無線によるインターネット接続の契約を考えなければならない。

最近は喫茶店や行政によるWiFiも発達してきたので、早いインターネット回線が欲しい場合も、さしあたって苦労はしないが、やはり常時使えて、数Mbpsの帯域のあるインターネット接続がほしい。

今考えているのは、WiMAXだ。WiMAX2+も、値段としては変わらないのだが、残念ながら端末がクソすぎて使い物にならない。無駄にでかい上に、タッチパネルやらファイルサーバーやら無駄な機能がゴテゴテとついていて、そのためにバッテリー駆動時間も短いし、それでいて肝心の無線通信の感度が最悪と来ている。2年縛りも難点だ。そのため、旧来のWiMAXを考えている。

WiMAX端末は、クレードル付きのURoad-Aeroがいいのではないかと思う。クレードルを装着すれば有線LANも使えるそうだし、わざわざ無線を二重に使うことに違和感を覚える私としては、精神的にも楽だ。

さて、電源を落とすか。このデスクトップを動かせば、引越し作業はほぼ終わりだ。あとはラップトップの仕事だ。

技術屋にMac使いが多い理由ってなに?

技術屋にMac使いが多い理由ってなに? : IT速報

答え:お手軽なUNIX互換環境だから。

今、個人が使うデスクトップやラップトップ用のOSとして、実用的なものに、GNU/Linux, Windows, Mac OS Xがある。読者の中には、FreeBSDも十分に実用的だと主張する者もいるかもしれないが、少数派だろう。

もちろん、サーバーや組込み用途には、その用途に合わせて別のOSが使われている。しかし、プログラマー個人が使うコンピューター用のOSは、圧倒的にMac OS Xである。これはとても残念なことだ。なぜならば、Macは不自由なソフトウェアで、しかもその動作するコンピューターまで、技術的な理由がなく制限されているからだ。

UNIX互換環境を必要とする理由としては、既存のPOSIX互換環境向けに書かれた有用なツールがとても多く、プログラマーはなんとしてもそのツールを使いたいのだ。

GNU/Linux向けに書かれたソフトウェアを、Macに移植するのは、Windowsに移植するよりはるかに簡単である。これは、Macが、やや独自な方向もありながらも、基本的にはネイティブでPOSIX互換であるからだ。WindowsはネイティブでPOSIX互換ではないので、ソフトウェア移植は、Windows用のAPIを使って書きなおすか、あるいはWindows上にPOSIX互換環境を構築しなければならない。たとえばCygwinだ。ユーザースペースで実装されたこの手の互換レイヤーは、あまり効率が良くない。

では、なぜ自由なGNU/Linuxではなく、不自由なMacなのか。それは、Macは簡単に使えるからだ。

GNU/Linuxは、どのディストロも何かしらの問題を抱えている。世の中に出回っているコンピューター(もちろんハードウェアにも不具合がある)を全て完璧にサポートするのは難しい。Macは動作するコンピューターが限定されているので、サポートしやすい。

たとえば、以下は筆者が、現在Ubuntu 13.10で悩まされている問題である。

  • USBマウスが勝手に省電力状態になり復帰しなくなる。

    USBの抜き差しで解決。(何かのデーモンを再起動してソフトウェア的に解決する方法がないものか)

  • サスペンドからの復帰時に、GUIのネットワーク接続が機能しなくなる。

    Upstartを使ってnetwork-managerデーモンを再起動することにより解決できる

    sudo restart network-manager
    
  • GUIからのシャットダウンやリブートができなくなる

    古き良きshutdownコマンドは動く

    sudo shutdown -h now
    
  • iBusが動かなくなる

    iBusデーモンを再起動する

    ibus-daemon -drx
    

他にも今は修正されたが、CLIツールの利用を余儀なくされたり、手動での設定ファイルの変更が必要な、ちょっとした問題がたくさんあった。

私のこれまでにUbuntuで出くわした問題と解決方法は、いずれも簡単なコマンドや手動での設定ファイル書き換えで対処可能なものであり、ちょっと調べれば、既に問題に出くわした人により、解決方法がそのまま書かれている場合も多いので、さほど苦労していない。もちろん技術者なら皆できる。しかし、できるからといってやりたいわけではない。我々はコンピューターを使いたいのであって、管理したいのではないのだ。

xkcd: Cautionary

Linux: 実際にあった話:第一週

もしもし、あたしあたし、いとこだけど。新しいパソコン手に入れたんだけどさ、Windowsとか入れたくないのよ。Linuxとかいうやつのインストール手伝ってくれない?

いいよ

第二週

XORGが壊れたって。XORGって何? どうすればいいの
「manページ教えるよ」

第六週

autoconfigがうまくいかないんでUbuntuからDebianに変えることにする
「えっ」
Gentooにするかも
「やばい」

第十二週

「最近電話に出ないけど」

寝らんない。カーネル、コンパイル、しなきゃ。

「手遅れか」

親に告ぐ:誰か他人に教わる前に、子供にLinuxを教えるべきである。

これが、初心者にも使いやすいと言われているUbuntuの現状である。あるいは、私のような初心者が使うUbuntuがクソで、他のディストロはまともなのかもしれない。しかし、上級者様の使うArchやGentooといったディストロは、ローリングリリースを採用しており、単なるアップデートで、ブート不可能なほど深刻に壊れやすい。しかし、ローリングリリースは壊れやすいとからかうと、Arch上級者様は皆、まるで申し合わせたかのように言う。

「何? 壊れる? まさか? ちゃんと公式から発行される変更情報や注意点を確認していれば、壊れるなどということはない。よしんばブート不可能なほど壊れたにせよだ。復旧用のArchを入れたUSBドライブからブートしてchrootとしてpackman -Syuすればたいてい直る。問題ない。設定ファイルもプレインテキストで書かれていて、とても簡単だ。恐れることなど何もない。むしろUbuntuのようなどうやって直していいのかわからない複雑なシステムの方が怖いわ」と。

結局、ArchやGentooをインストールして、GUIのデスクトップ環境が利用可能なほどに設定できる上級者様なのだから、システムが壊れるということは問題ではないのだ。問題は、壊れた時に簡単に直せないことなのだ。

その点、Macにはそのような問題はない。もちろん、問題は発生するにせよ、GNU/Linuxほど頻繁ではないし、GNU/Linuxほどのつまらない問題に悩まされることはない。

Macが使われているのは、手軽なUNIX互換環境だからだ。GNU/Linuxのディストロで、つまらない問題に時間を潰したくないのでMacを選ぶのだ。それ以上の理由はない。もし、GNU/Linuxのディストロが十分に安定して、つまらない問題に悩まされることがなければ、彼らは別にGNU/Linuxでも問題ない種類の人間なのだ。

できるからといってやりたいわけではない。

追記:私はMacを使っていないし、今後も使うつもりはない。私がMacを使うとしたら、それは私が所有せず、また支配下にもないコンピューターを、一時的に借りて使う時だけだ。私はGNU/Linuxで満足している。私は特にGUIのソフトウェアに自由であること以外のこだわりはない。GUIのソフトウェアは、煩わしい設定をせずに簡単に使えるのならばそれでいいのだ。だから私は、今はUbuntuのUnityを使っている。単にデフォルトで設定されていて、極端に使いづらいというわけでもないので、これでいい。GNU/Linuxは、前述の通り、つまらない問題にも悩まされるが、いずれも簡単に解決、あるいはworkaround可能な問題であり、私はそのために不自由なソフトウェアを使うつもりはない。

2013-11-17

京都市での勉強会用の部屋の確保の難しさ

京都市で勉強会に使える部屋を確保するというのは、かなり難しいことが判明した。

今流行りの勉強会には、プロジェクターとマイクと電源とWiFiが必要だ。プロジェクターは資料投影に、マイクは、部屋広い場合に声を届かせるために必要になる。その性質上、多くの参加者はラップトップを使いたいだろうから、電源も必要になる。WiFiでインターネット接続が提供されていればさらによい。また、参加料を低く押さえるために、利用料が安くなければならない。

そういう場所は、意外と少ない。部屋自体はあるのだが、その他の点で、ほとんどの施設が候補から外れる。

公的な施設で、会議室を格安か無料で貸し出しているところもあるが、そういうところは、営利目的での利用を禁止している。実際にそのような施設に出向いて聞いてみたところ、施設の利用料を賄うために参加者から必要な額の参加料を徴収するのはかまわないが、企業の宣伝や求人といったものすら、営利に引っかかるらしい。これではとても勉強会には使えない。

そうした難しい条件を満たしたのが、ベーコン研究所アンテナカフェ丸太町だ。どちらも十分に安い値段で、プロジェクター、電源、WiFiを提供している。ただし、アンテナカフェ丸太町は、名前通り丸太町のだいぶ中央のわかりにくい場所にある。ベーコンラボは京都駅の近くにあるのでわかりやすい。そして2つとも部屋が狭く、実質20人ぐらいしか入らないという問題を抱えている。

東京ならば、勉強会に理解があり、部屋を貸してくれる企業が結構いるのだろうが、京都では少ない。

今週中には部屋を確保したいと色々と悩んでいたのだが、ひょっとしたら思わぬ盲点があった。決まればそこに、決まらなければベーコンラボになるだろう。

追記:さらにもうひとつでかい候補が見つかった。まだ決まっていないが、こちらも面白そうだ。

connpassの利用規約が理解不可能で笑える

12月21日に京都でC++勉強会を行うために、その告知と参加者管理のためのSaaSS(Service as a Software Substitute)を探している。connpass.comは、最近、ドワンゴの勉強会告知にも使われていたので、まずこれを検証してみる。

connpassはTwitterやFacebookからもメールアドレスが別必要ながらも、サインアップできるようだ。最近は、TwitterやFacebookが、メールアドレスの代わりに使われているように感じる。まあ、公開して問題ないようなやりとりならば、Twitterの方が手軽で便利なのだということだろう。

さて、サインアップ前に、connpassの利用規約を読んでみるが、以下のような文面が目についた。私は弁護士ではないが、とても気になる点だ。

第9条【本規約の有効性】

本規約の規定または、その一部が法令・判決等に基づいて無効と判断された場合でも、本規約は有効とします。

はて・・・そもそも、その契約は有効なのだろうか。その契約が無効だと判断された場合、当然効力がないわけだから、無効となる。その場合、無効な契約なのだから、相手がいくら有効性を主張しようとも、無効であることに変わりはない。

さらに、以下の文面を考えると、

第1条【本規約の範囲および変更】

2. 当社は、いつでも任意の理由により、利用者に事前に通知することなく、本規約を変更、追加、及び削除をすることができるものとします。

connpassは、いつでも契約を変更して、
「当社は、いつでも任意の時点で、利用者の臓器を摘出して利用できる権利を有するものとします」とか、
「当社は。いつでも任意の時点で、利用者を殺害する許諾を得たものとします。当社は同殺害による責任を負いません」
などといった文面を追加できる。このような文面は法令や判決に違反するだろうが、先の第9条と合わせれば、有効であると考えられる。

しかし、たとえ有効だったからといって、何だというのだ。たとえ、殺される本人の許諾を得ていたとしても、それは刑法202条が規定するように、違法である。契約が有効だとしても、殺人は違法である。契約がどうあれ、罪に問われる。なぜならば、殺人者は、国家と契約して、特別な殺人の許可を得たわけではないからだ。契約したのは殺された被害者である。

一部の法律違反は、被害者との契約の有無やその有効性に関わらず、発生する。そのため、たとえ契約が法令と判決に反して有効であったとしても、意味がないと思うのだが、私は法律が専門ではないゆえに理解に苦しむ。

誰か法律家が、トンデモ利用規約集みたいなものを作っていないだろうか。

2013-11-16

15日の様子

朝、めるぽん邸にて起床、犬の熱烈な挨拶を受ける。

その後、興味深げに猫が近寄ってきたが、こちらから近づこうとすると、逃げてしまうというサイクルをずっと繰り返していた。犬はすぐに駆け寄ってくるのだが、猫は気まぐれで食えないものだ。

今日は、昼から、ドワンゴの勉強会の後の懇親会として呼ばれていて、ドワンゴ技術者と世間話をした。面白い話も聞いたが、どこまで本気なのか、食事の席の話のはずみなのか。

その後、江添亮を囲む会に参加した。色々と熱弁を振るった挙句、結局、新幹線は逃してしまった。新幹線の切符はあらかじめ買っておいたが、新幹線の自由席の切符は、二日間有効なので、明日帰る。

ところで、帰り際に誰かから、押し付けられるように小さな紙袋を渡された。一体何なのか。それはさておくとして、今日の宿を決めなければならない。まためるぽん邸の厄介になるかと思っていたら、矢口さんの申し出で、卓球ハウスというところに泊まることにした。

卓球ハウスというのは、5人で住んでいるシェアハウスで、都内に一軒家だという。行くと、なるほど、確かに一軒家だ。それも、かなり広い。

しかしなぜ卓球ハウスなのか。それは、卓球台があるからだ。地下室に卓球台が設置してあり、いつでも卓球ができる。実際に卓球をしたが、確かに面白い。

そして、今これを書いているのだが、ひとつ言及して置かなければならないことがある。江添を囲む会からの帰り際に押し付けられた小さな紙袋だ。中を見てみると、なんとクッキーだった。はて・・・なぜクッキーなのだろうか。その謎は後ほど考えるとして、今は地下室だ。

卓球ハウスの地下室は、なかなか面白い。面白く入り組んだ小部屋がいくつもあり、好奇心をくすぐられる。こういうところに住むと、夏暑く冬寒いと最悪だが、面白そうだ。

さて、クッキーについてだが、なにかやたらと手の混んでそうなクッキーだ。工場やポータルでもってきたようなクッキーではない。しかし、なぜクッキーなのか。クッキー・・・まさか・・・クッキークリッカー?

とにかく、今これを書きながらクッキーを食べている。クッキーにはチーズが塗られている。

そして今、男7人が一部屋に集まって、皆ラップトップを操作しながら日常会話をしている。部屋に設置されたディスプレイからは常にアニメが流れているが、あまり真剣に見ているものはいない、BGMと化している。

2013-11-15

江添亮を囲む会の告知

2013年15日の夕方から、筆者、江添亮を囲んで飲み食いする集会がある。具体的な募集方法に悩んでいたが、(あんちべ! 俺がS式だ) (AntiBayesian)さんが参加希望者の取りまとめや場所の予約などの幹事を引き受けてくれることになった。参加希望者は、Twitter上で@AntiBayesianまでmentionを飛ばされたし。

私は昼に少し用事があるので、このブログに参加希望のコメントを書いても、反応できません。

ドワンゴのC++勉強会で発表した

歌舞伎座.tech#2でC++14について発表した。

今回、ドワンゴ側から、交通費ぐらいは出すから、C++11かC++14について話してくれと言われた。正直、C++14が出てくるとは思わなかった。まさか、日本の企業にそんな気概のあるところが残っていようとは期待していなかった。ともかく、C++14について話してくれと言われたので、C++14に新しく追加されるコア言語機能をすべて解説することにした。

当日使ったスライドは、GitHubにあげてある。

EzoeRyou/kabukiza-tech2-slide

また、GitHub Pagesも有効にしてあるので、Web上で閲覧できる。

http://ezoeryou.github.io/kabukiza-tech2-slide/index.html

当日はそれなりに盛り上がったようだ。

私は普段酒は飲まないのだが、今日、たまたまビールがあるので飲んでみたら、なぜだか非常にうまく感じた。不思議だ。味覚が変化したのだろうか。考えてみれば、最近ますます肉より野菜を好むようになっているし、加齢による味覚の変化だろうか。まあ、あんな明るい雰囲気の中、350ml缶を3缶ぐらい飲んだところで全然酔えないが。

さて、それはともかく、私は明日も東京にいる。一応、予定では明日の夜、京都行きの新幹線があるうちに帰るつもりだが、明日の夕方から夜にかけては、ひょっとしたら酒を飲むかもしれないので、その場の雰囲気でもう一泊東京逗留になるかもしれない。まあ、どうしても15日に帰らなければならないわけでもなし。

それから、やはり対面してC++を教育することにも、意義があるのかもしれぬ。今日の私の発表は、だいぶ拙かったが、これを鍛えるには、ただ回数をこなすしかない。やはりかねてからの計画通り、勉強会を自分で主催する必要がある。

2013-11-14

夜行バスで東京にやってきた

というわけで、歌舞伎座.tech#2 - connpassに参加するために、久しぶりに東京にやってきた。とりあえず行きは夜行バスだ。

夜行バスというのは、まあ私が便宜上使っている言葉で、今では制度上、新高速乗合バスという名前になっている。

それまで、ツアーバスという形で、夜間に高速道路を使って、各地を移動するバスが、安価な交通手段として、貧乏人にもてはやされてきた。私はツアーバスにはとてもとても詳しい。どのくらい詳しいかというと、関越自動車道高速バス居眠り運転事故を起こしたツアーバス、ハーヴェストライナーに毎年何度も乗っていたほど詳しい。

ハーヴェストライナーというのは、乗客を管理する会社と、バスを管理する会社が分かれていた。しかもその別れ具合というのは、乗客を管理する会社が、その時の状況に応じて、開いているバス会社にバスについては委託する形をとっていた。おそらく、これが問題だったのだろうと思う。というのも、ハーヴェストライナーの使っていたバスは、およそ夜行バスとは言いがたいシロモノだったのだ。

およそ夜行バスというものは、程度の差こそあれ、最低限の品質は保っているものだ。夜、乗客が寝ている間に高速を走るのだ。当然、遮光カーテンを取り付けているべきだし、また座席はかなり傾斜させることができ、限界まで傾斜させても、後ろの乗客の迷惑にならないようになっているべきなのだ。

まずハーヴェストライナーは安かった。おそらく、当時数十種類あった似たようなツアーバスの中でも、相当に安かったはずだ。その安さには理由がある。バスの品質が一定しないことだった。もちろん安いのだから、座席独立トイレ付きではなく、中央を通路に開けた二列、二列の座席だが、そのバス自体が、夜行バスを想定したバスのときもあったが、夜行バスには向いていないこともあったのだ。つまり、遮光カーテンすらなく、座席の傾斜も貧弱で、倒しすぎると後ろの人間の迷惑になるような作りのバスだ。

そういう夜行バス向きではないバスの場合、運転手からして、明らかに場違いだった。どうも、ガテン系というかなんというか、長距離トラックの運転手のような、明らかに接客態度の図太い運転手だったのだ。

つまりあのバスの品質の安定しなかった理由というのは、その時々で、てんでバラバラに適当に開いているバス会社に委託していたのだろう。その委託先のバス会社は・・・夜行バス向けではないこともあったということだ。

まあ、今となっては、いい笑いの種でしかない。幸い、状況がどんどん悪化していって、日本語すら不自由な運転手をろくに睡眠も取らせずに運転させるような末期の時には、私は運良く東京に行く用事もなくなっていたので、使わなかったのだ。

ところで、今回使った夜行バスは、あの悪名高いハーヴェストライナーより料金が安かったので、どんな悲惨な目に合うか楽しみにしていたのだが、あの事件の後、色々と制度も発達したのか、至って普通の常識的な夜行バスだった。貧乏なため怖いもの見たさであえて選んだのに、拍子抜けだ。

とにかく、朝の6時前に新宿についた。それから山手線にのって神田駅まで行き、安いチェーン店で朝食を認めたあと、神保町に向かうつもりだったのだが、うっかり東側に向かって歩き出してしまったので、まったく目的地につかず、ウロウロと見慣れない土地をさまよった。

しばらくして間違いに気がつき、引き返して、ようやく神保町にたどり着いた。あいにくと、まだ足に馴染んでいない新しい目の靴を履いていたので、足の指が妙に痛む。マメはできていないと思うのだが・・・。思うに、JRではなく、地下鉄を使えば、もっと神保町に近い駅があるのではないかと思うのだが、東京の電車は迷路のようでよくわからない。

どっちにしろ、神保町の古本屋が開き始める10時頃まで待たなければならないのだから、まあ、損ではない。笑い種がひとつ増えるだけだ。

もっと事前に計画と下調べをしておけばいいという人もいるかもしれない。しかし、私は事前に予定を組んで、その予定通りにそつなく物事をこなすのが嫌いなのだ。あらかじめわかりきっていることを淡々と行って何が楽しいのか。なにか致命的な問題がない以上、多少の不便さによる損は、不便を上回る予測不可能な面白さによる得が上回るため、許容できるのだ。

せっかく神保町に来たのに、あまり興味深い本はなかった。いや、あるにはあるのだが、高すぎて手が出ない。それに全集なのでかさばる。今は引っ越しでゴタゴタしているので、金がどうにかなり、宅配で送ったとしても、保管しておく場所がない。

100円で投げ売られていた面白そうな本を二冊だけ買った。やれやれ、今回はあまり収穫がなかったな。私は、捨て値で投げ売られているゴミ本の山から宝を見つけるのが好きなのだ。聞けば、ついこの間、神保町でも大規模な古本まつりが行われていたというではないか。惜しいことだ。まあ、私は同じ時期に、百万遍智恩寺の古本まつりに参加していた。百万遍智恩寺の古本まつりでは、初日の朝に、法要と数珠回しが行われる。もちろん、数珠回しには子供がいなければならない。毎回、どこかからか幼稚園児がやってきては参列し、数珠回しをしていく。興味深いことだ。京都に来てから、地蔵盆や数珠回しのような文化がまだ残っていることに驚いた。もっとも、その地蔵盆も、子供の数が足りないために、かつてほどの面白さはないのだが。

さて、今は公園のベンチに座り、貰い物のもったいないほど増設されたラップトップと、モバイルWiFiルーターで、試みにブログの記事を書いている。案外かけるものだ。やはり、このラップトップの性能が悪くないことと、15.6インチは、持ち運びには難があるが、膝において使うには悪くない大きさであるためだろう。

さて、記事を書き終えたが、まだ15時だ。歌舞伎座タワーで開かれるドワンゴ主催の勉強会まで、あと3時間ほどは潰さなければならない。

2013-11-13

14日、15日に東京に行く

ドワンゴが主催するC++の勉強会、歌舞伎座.tech#2で発表するので、14日に東京に行く。勉強会が夜なので、日帰りできず、都合上15日も東京にいる。

私は予定を立てて、予定に従って行動するのを面白くないと思う種類の人間なので、特に予定はない。今のところ決まっているのは、

  • 14日の早朝に東京着
  • 多分どこかで朝飯と昼飯と晩飯を食べる。晩飯は勉強会が中途半端な時間なので終わってから食べるかも。
  • 日中、数時間は神保町に行って、古本を漁る
  • どこかに宿泊。
  • 15日に新幹線で帰る。あるいは16日かも

私は予定通りに動くことが嫌いなので、帰りは予め予約の必要のない新幹線を使う。

後は予定がない。14日の勉強会は、せっかくネット上で知っている顔ぶれとリアルで対面するのだから、どこかで集まって食事でもと思うのだが、勉強会が終わるのは22時というだいぶ遅い時間なので、やや都合が悪い。

どうせ一泊はしなければならないのだから、あるいは15日の夕方から夜にかけて、誰かと食事ができないだろうかとも思うが、

東京から京都に行く新幹線は、20時頃まであるようだ。だから15日は丸々滞在できる。まあ、とくに帰るのが16日になっても、大した問題はないのだが。

今回、私はラップトップとモバイルWiFiルーターを持っていくので、どこでもネットに接続できるという便利な環境で東京をうろつける。

C++参考書に、著作権が発生するほどのpull requestを受け入れた

Auto anchor by tzik · Pull Request #139 · EzoeRyou/cpp-book

私は今まで、GitHubで公開しているC++参考書には、誤字脱字のpull requestならばすぐに受け入れてきた。なぜならば、単純な誤字脱字、句読点の修正、ふりがなの追加などには、著作権は発生しないからだ。

著作権が発生するほどに複雑な修正は、受け入れずに自分で修正してきた。

今回、少し悩んだが、始めて、著作権が発生するほどのpull requestを受け入れることにした。41行ほどのJavaScriptコードだ。

内容は、JavaScriptを使って、スクロールイベントが発生するたびに、スクロールしている場所のidを指すように、ブラウザーのアドレスバーの文字列を書き換えるものだ。

これにより、今見ている場所のリンクが、常にブラウザーのアドレスバーに表示されることになる。

アイディアさえ与えられていれば実装は簡単だし、自分でも書けるが、私はC++ほどJavaScriptとDOMには詳しくないので、多分自分で書くと何時間もかかるだろう。それに既にコードを読んでしまったわけだし、元のコードの影響がなかったかどうかを証明するのが難しい。何よりもせっかく書かれて動くものがあるのだから、受け入れることにした。

まあ、JavaScriptのコードなので、私が想定していることには、問題にはならないだろう。

想定というのは、本書の紙媒体での出版だ。いま、本書を紙媒体で出版する方法を探している。結果はいまだにはかばかしくないが、もし実現できそうな場合に、本書の全著作権を自分で有していない場合、困ったことになる。

というのは、紙媒体の出版社は、依然として自由の価値に目覚めていないところが多く、あるいはGFDLを拒むかもしれない。GFDLで出版するということは、本の印刷に使った組版のデジタルデータ(tex, AdobeのInDesignなどのフォーマットのファイル)が、GFDLでいう通過ドキュメントとなるので、当然、そのような通過ドキュメントを、その時点で主要なコンピューターネットワーク(インターネットなど)で公開しなければならない。思うに、多くの既存の不自由を好む紙書籍出版社は、組版のデジタルデータを公開したがらないのではないか。そういう不自由人は、たとえ金を払ってでも、求めて不自由を得たがるものだ。

私に自力で組版、印刷、流通を行うだけの技術も資本もない以上、紙書籍を出すとなれば、そのような作業は、既存の紙書籍出版社にやらせなければならない。そして、おそらく自由の価値を理解しない旧態依然の出版社は、たとえ無料で出版させてやると言ったとしても、組版のデジタルデータを公開することを拒むだろう。

私は、もはやプログラミングの参考書として紙媒体は死んだ媒体だと考えているのだが、いまだに紙媒体を好む旧時代の人間がいる以上、紙媒体でも提供されていることが望ましい。たとえそれが不自由なものにせよ、存在しないよりはマシであろう。

そのため、私は現状のGFDLで公開している電子媒体のC++参考書と衝突しない限り、紙媒体に限り、どうしても必要であれば、極めて苦渋の判断にはなるが、明示的な契約をもって、多少の不自由を認めるかもしれない。不自由なプログラミングの参考書は悪であるが、もたらす善の方が大きいだろうと思うからだ。紙書籍の存在を店頭で確認することにより、GFDLでライセンスされた自由なプログラミングの参考書があることを知る人もいるだろう。この2013年においても、まだインターネットは万能ではないのだ。

その時に、著作権が発生するほどのGFDLのパッチを受け入れた場合、私一人の著作権では不自由にできなくなる。

幸い、これはJavaScriptなので、取り除くのは簡単だ。そもそも、紙媒体に対して実行できるJavaScriptは、未だ発明されていないので、とりあえずこの件に関しては問題はない。

私は以前にも言ったように、このC++参考書に関しては、これ以上大幅な内容の変更はしないことにしている。というのも、来年には文面の不具合を多く修正したC++14がでてくるし、またその3年後には、またもやメジャーアップデートであるC++17が控えている。もし書くとすれば、今の文章を手直しして対応するよりも、新しく書き直したほうがいい。

また、今のC++参考書に、実質コンパイラー作成者しか気にしないような些細なC++14の修正を反映させるよりは、もっと簡単なC++の短い記事とか、入門書でも書いたほうが、おそらく日本のC++プログラマーのためになると思う。

それに、今のC++の参考書のマークアップは、甚だ稚拙なので、一から設計したいというのもある。たとえば、highlight.jsを導入できるようにしたいし、またC++の標準ライブラリには、数式が必要なものもあるので、MathJaxのようなライブラリも取り入れたい。

とにかく、何とかして紙書籍の出版社を探さなければならない。できれば自由の意義を理解し、GFDLでの出版に同意する出版社がいい。

2013-11-12

C99の複素数ライブラリがクソすぎる。

C99では、複素数ライブラリが採用された。たとえば3.0 + 4.0iの複素数を書きたい場合、GNU拡張では、以下のように書く。

#include <complex.h>

double _Complex x = 3.0 + 4.0i ;

complex.hをincludeすれば使えるようになる。見た目はそのまんまだ。

これはGNU拡張であって、C99の規格による正式な書き方は以下の通りだ。

float _Complex x = 3.0 + 4.0 * _Complex_I ;

_Complex_Iは、"0+1i"を意味する虚数単位定数であり、にかければ任意の虚部を表現できる。あとは実部を足せばいい。

どうやら、C標準化委員会は、まともな名前を考えつかなかったらしい。まあ、大方のきれいな名前は、既存のソースコードと衝突してしまうから、アンダースコアに大文字で始まる予約語を使うしかないのだろう。

ただし、_Complex_Iのような汚い名前を書かせるのはどうかと思ったらしく、C標準化委員会のバカどもは、とんでもないマクロを標準で定義してしまった。

// complex.hのincludeによって宣言されるマクロ
#define I _Complex_I

// ユーザーのコード
3.0 + 4.0*I ; // OK

一文字マクロだと? 標準規格で?

アホかあいつらは。

最悪なことに、C++11はC99の標準ライブラリを取り込んでいるので、C++11でも、なんとcomplex.hをincludeすると、この恐ろしい一文字マクロまで宣言されてしまう。つまり、C++にもこの問題がやってくる。

ちなみに、このマクロはユーザー側でundefしても問題ないらしい。最初から入れるなボケ。

Complex Numbers - The GNU C Library

さすがに反省したらしく、C11では、この恐ろしい一文字マクロはoptional扱いになっているようだ。

ただ、GCCとClangではどういうわけか、独自拡張を許す-std=gnu++11ではなく、厳格に規格準拠にする-std=c++11すると、complex.hは使えるのだが、この一文字マクロだけは宣言されていない。不思議なこともあるものだ。

Jenkinsの開発者、間違えて一ヶ月前のローカルレポジトリをgit push --forceしてしまう

Jenkin developers accidentally do "git push --force" to over 150 repos on github | Hacker News

Jenkinsの開発者、Luca Milanesioによって、Jenkinsの多くのgitレポジトリに対してpushが行われた。不思議なことに、pushをしたというのに変更点はほとんどみられない。一体ルカは何をやったのだ。

Dominik Bartholdi

やあみんな、とくにルカ。

昨日、GitHub上のJenkinsの多くのレポジトリ(50以上)に、なにか変なことが起こった。

どうやら、Luca Mmilanesioが、何の変更もないのに、たくさんのたくさんのレポジトリにpushしたらしいのだ。少なくとも、俺には変更がみえない。

https://github.com/organizations/jenkinsciから、昨日をみると、多くのレポジトリに多くのpushが行われている。

俺はなにか勘違いをしているのかな?

どうも俺が思うに、これは誰か、GitとGitHubの仕組みを理解していない奴が、間違えてすべてのレポジトリにpushしたんじゃないのか。なにか壊れてないか確認したほうがいいのでは?

敬具など Domi

strange pushes on GitHub - Google Groups

Luca Milanesioは、どうやら一ヶ月ぐらい前のローカルレポジトリから、GitHubのリモートレポジトリに対して、git push --forceしてしまったらしい。

Luca Milanesio

やあ、みんな

昨晩、以下のJenkins-CIプラグインに、間違えて"forced push"を引き起こしてしまった。

謝罪

俺がforced pushできる権限を持ってるとは思わなかったんだ。本当にすまない。

この操作によって、すべてのブランチが約一ヶ月前に巻き戻ってしまった。歴史は消えずにGitHubのサーバーに残っているが、すでにデタッチされたブランチにある。

解決法

GitHubに頼んで、これらのレポジトリに対して"reflog"してもらった結果を送ってもらい、俺のforced pushの前の状態にまでブランチを戻す。

あるいは、各レポジトリの所有者が、"forced push"してブランチを正しい位置まで戻す。

(これをやるなら、二重にやるのを防ぐため、メーリング・リストに書いてからやってくれ)

strange pushes on GitHub - Google Groups

通常、gitはローカルがリモートの子孫でない限り、pushを拒否する。つまり、ローカルがリモートからpullしてコミットするまでの間に、リモートに変更が生じた場合は、pushを拒否する。通常は、ローカルがリモートから一度pullして、あるいは必要に応じて手動でマージしてから、pushする。

git push --forceは、このpushの拒否を無効にし、リモートを強制的にローカルに合わせる。つまり、リモートレポジトリはローカルレポジトリと同じ状態になるのであって、リモートに対するローカルに落とした以降の別のコミットはすべてなかったことになり、歴史が改変される。

gitは、間違えてgit push --forceしてしまった場合でも、普通は簡単に元に戻すことができる。なぜならば、歴史は改変されたものの、消えてはいないからだ。reflogでpush --forceの直前のハッシュ値を確認して、branch -fで、そのハッシュ値の状態に戻せばいい。

問題は、これはgitレポジトリを直接に操作できる場合である。GitHubのリモートレポジトリに対して、ユーザーはその操作ができない。GitHubのサポートにreflogを実行してもらうよう頼むなどと言っているのは、そのためだ。

Luca Milanesio

悲惨だな(´・ω・`)・・・ force pushは危険だ。特に、gitサーバーをコントロールできない場合は。

普通、force pushを直すのは簡単なんだけど:

  1. git reflogして、forced pushの前のSHA-1を確認
  2. git branch -f <name> <sha-1>

ただし、サーバーにあるgitレポジトリをコントロールできない場合、force pushを禁止する必要がある。あるいはみんなGHエンタープライズを買うか。

GitHubの運営が1.と2.をしてくれればいいんだが(^_^;)

Luca.

strange pushes on GitHub - Google Groups

幸い、GitHubの運営は、push --forceする直前のレポジトリのハッシュ値のリストを抽出して送ってくれたらしい。また、push --force直前の状態をrecoveryというブランチ名で作ってくれたらしい。

まあ、何しろJenkinsという著名なソフトウェアのレポジトリでもあるし、GitHubの対応は早かったようだ。

議論は、やはりコントロールできないリモートのサーバー上のgitレポジトリに依存する場合に、全員に全レポジトリのpush --forceの権限が与えられるべきではないという方向に進んでいるようだ。

モバイルWiFiルーター

好意で、DTIの月490円のSIMカードを刺したモバイルWiFiルーターをしばらくの間借りられることになった。

私はコンピューターとネットワークが一体となった携帯電話が好きではなく、したがって無関心だったのだが、なかなか今は面白いことになっている。

SIMカードというのは、固有のID番号が記録されたICカードである。これを携帯電話の無線局との通信機能を持った機器につければ、携帯電話のネットワークを使うことができる。

多くの邪悪な制限のある機器は、このSIMカードを、自社のものしか使えないように、SIMロックをかけている。最近はようやく、わずかに自由の価値に目覚めた人たちが、通信機器とIDの固定はおかしいと気づき始めたとみえて、どのSIMカードでも使うことができる通信機器も、ようやく増えてきた。

そうなってくると、世の中は携帯電話のインフラを借りて、独自のSIMカードを発行するところが現れ始めた。この競争により、最近は、手軽に持ち運べる大きさの無線通信機器によるインターネット接続の値段が、急激に下がっている。

さて、携帯電話の無線局と通信してインターネットにつなぐことはできるが、コンピューターとの接続はどうすればいいのか。それには、USBもあれば、そういう接続を必要とするのが大抵ラップトップであることをみこして、PCカードのものもある。私はラップトップ限定のPCカードというものは好きではないのだが。

興味深いことに、コンピューターとの接続も、無線で行う機器がある。いわゆるモバイルWiFiルーターと呼ばれるものだ。携帯電話の基地局と無線で通信、コンピューターとも無線(WiFi)で通信。なんとまあ、無線だらけであることよ。

私は古い人間なので、無線をあまり信頼していない。無線は帯域が狭く、遅延が多く、常に大声でどなって自分の居場所を知らせながら歩くようなもので、あまり好きではない。そのため、私は今でも、コードのかさばりを忌々しく思いながら、マウスもキーボードも、すべて有線のものを使っている。

ともかく、こういう用途には、無線というのは便利だ。ラップトップを外に持ち運んで使うことを考えれば、有線接続は邪魔になる。

さて、近年のSIMフリーの風潮を受けて、競争が激化し、価格が大いに下がっている。中でも極端なのはDTIの提供するサービスだ。これは文字通りSIMカードだけを月490円で契約する。あとはSIMフリーなモバイルWiFiルーターにさして使えばいい。もちろん、月490円という安すぎる価格には理由がある。帯域が100kbps(あるいは約12KB/s)ほどに制限されているのだ。

ServersMan SIM LTE 100:【dream.jp】

さて、実際に使ってみたところ、なるほど、確かにインターネットが使える。これは便利だ。

昼間に試してみると、何故か絶望的に遅かった。パケットロスこそないものの、絶望的に遅いので、速度計測は諦めてしまった。

深夜に試してみると、快適だった。なにか混み具合があるのだろうか。

肝心の通信の質であるが、まあ、確かに計測してみても、100kbps前後しかでない。

夜になって快適になってきたので、色々と試したが、これはすごく便利だ。

私の親は、プログラマーではなかったが、早くから仕事でもコンピューターを使っていた。親父はまだMS-DOSの時代から使っていたはずだ。その頃、私はまだ幼稚園児かそこらだったので、あまり記憶にない。確か親父はだいぶ後になってからの昔物語に、「MS-DOSでは、「今どこのディレクトリにいる?」というのがよくある質者だった」、「当時、20MBのHDDが始めて会社にやってきてな。みんなすごいすごいと言ってたものさ。あんな小さなものにフロッピーが20枚分も入るんだもんな。抜き差しする手間がいらないと驚いてたものさ」

親父はちょくちょく、職場からコンピューターを一式持ち帰って、家でも作業をしていた。私もまだ幼稚園の頃、触った記憶がある。一体どんなコンピューターだったか、正確には覚えていない。確かディスプレイとの一体型で、キーボードとマウスがあり、画面表示は白黒だが、GUIを備えていたように思う。オモチャのようなペイントソフトが特徴的で、画面全体を消すには、爆弾のエフェクトがでた記憶がある。仕事で使うコンピューターなので、おそらくはOSに標準でついていたペイントソフトウェアではないかと思うのだが、一体どんなコンピューターでどんなOSだったのか、思い出せない。

それから、確か1996年か1997年に、親が富士通のFMVを買ったはずだ。OSはWindows 95で、ディスクにはOSR2とUSBが書いてあったと思う。とすると、1997年にリリースされたUSB Supplement to OSR2だろうか。

Windows 95 - Wikipedia, the free encyclopedia

実は、The Windows 95などというものはなかった。Windows 95には実に多くのバージョンがあった。NECの独自規格のPC-98対応版は有名だが、1995年にリリースされたWindows 95は、まだUSBをサポートしていなかった。もちろん、USBの最初の正式な規格が制定されたのが、1996年なので、無理もない話だ。

私の記憶では、CPUはMMX Pentiumのクロック周波数は166MHzぐらいだったはずで、メモリが32MBで、1.6GBのHDDを積んでいたはずだ。当時、56Kbpsのアナログモデムでインターネットに接続していた。また、後になって、64KbpsのISDNも契約した。

コンピューターを買った次の年、1998年に、メモリを64MB積んだコンピューターが発売されはじめ、親父は、「やっぱりメモリが64MBもあると動作が快適なんだって」と言っていたのを記憶している。

そのコンピューターも壊れて、しばらくはコンピューターともインターネットとも無縁の生活を送っていた。私はコンピューターが壊れた後の中学生頃になって、ようやくコンピューターとプログラミングに興味がわいた。とはいってもコンピューターがないので、当時は参考書を読みながら脳内でソースコードを解釈していた。

そして、高校一年生の一夏を費やしてバイトして、初めてのコンピューターとインターネット接続を得るわけだが・・・いきなりADSLの8Mbpsだった。あとは、今とさほど変わらないコンピューター環境だ。まだマルチコアの時代ではなかったし、コンピューターの性能は一年ごとに2倍になっていったが、それほど目新しいことがあるわけではない。

さて、この時代に100kbpsの帯域を使って思ったことは、思ったほど遅くないということだ。これはどうしたわけだろう。アナログモデムの2倍程度の帯域でしかないわけだが・・・

これを考えてみると、まず、あの頃のアナログモデムやISDNは、スペック通りの帯域を実現していなかったはずだということが1点。それと、あのころは通信帯域だけではなく、コンピューター自体が遅かったという点もあるのだろう。CPUは遅いし、メモリは少ないしで、たとえダウンロードが完了したとしても、それをレンダリングするのに時間がかかっていたはずだ

まあ、今となっては年寄りの笑い話でしかない。しかし、年寄りといっても、私はまだ20代、コンピューター史の変化の凄まじさに、今更ながら呆然とするしかない。

と、こういうことをくどくどと書いていると、「青二才が何を聞いた風な口を聞きよるわい。あんな、ワシの若い頃はな、bpsじゃなくてボーと言っていたわい。あんな、300ボーの音響カプラがな」などと言い出す、本物の年寄りが現れかねないので、今回はこのへんで筆を休めよう。

2013-11-11

C++勉強会の場所の候補:ひと・まち交流館、ベーコン研究所

C++11の自由な参考書を販売している。また、その全内容をGitHubで公開している。ぜひとも読み、また気に入ったならば買ってもらいたい。

Gumroadで購入:C++11参考書:C++11の文法と機能

本の虫: C++参考書の販売:C++11の文法と機能

GitHub: EzoeRyou/cpp-book

GitHubからzipでダウンロード

GitHub Pagesでの閲覧:C++11の文法と機能

本の虫: C++11参考書の公開:C++11の文法と機能

本を売るための宣伝活動の一環として、あるいは単に知り合いと会う機会を作るため、C++の勉強会を主催しようと色々と京都市内を走り回って、捜し物をしている。日時は、今のところ2013年12月21日の土曜日が、ちょうど三連休の初日にあたって、都合がいいのではないかと思っている。

C++勉強会を主催することは、直接に私の金銭的利益にならないとしても、対面してC++を教育し、また私の名も広めることができる。自由な参考書は、対価を支払わなくても手に入れることができる。このため、対価を支払わせるには、啓蒙活動が必要になる。C++勉強会は啓蒙活動として最適だ。

また、常はインターネット上で馴染みの顔ぶれにリアルに集まる都合のいい機会を提供するという意味もある。

勉強会は直接の利益を求めていないものの、私には金がないので、勉強会を定期的に主催するためには、私自身の赤字を避けなければならない。私が勉強会の主催の準備に費やす時間は無視できるとして、さしあたって問題なのは、場所だ。自宅の中に何十人も入れないし、入れたところで椅子や机などの設備もない。

しかし、そういう場所は、金がかかる。少額の参加料を徴収して支払える額でなければならない。

実を言うと、単に会議室だけなら、無料か、無料同然で借りられる場所がある。いわゆる行政が持っている建物で、会議室などを貸し出しているものがあるのだ。京都市はそこそこの都会なので、そういう場所が山ほどある。たとえば、ここだ。

ひと・まち交流館 京都

90人、入れるような部屋もあり、テーブルと椅子も用意されている。

マイクやプロジェクターの貸出が有料だが、まあ、有料と言っても数千円だし、部屋自体が無料なので十分払える額だ。参加費を募るとしても、一人あたり500円もあれば足りるだろう。

広い部屋と机と椅子、マイクとプロジェクターがあれば、最低限、勉強会に必要なものは揃う。

問題は、この勉強会は、コンピューターとインターネット接続は常時あって当たり前という種類の人種が集まることだ。そういう種類の人種は、電源や無料のWiFiなしでは生きていけないのだ。電源についてはよくわからないので、明日あたり確かめる必要がある。また、WiFiはたぶんないだろう。

今の時代、無線による通信機器を持っている人も多いから、WiFiは優先度が低いにしても、電源は重要だ。今回集まる種類の人間は、不自由なCrysisがプレイできるほど電力効率の悪いラップトップを使っている可能性もある。何時間も電源なしで生き延びることはできないだろう。

また、営利を禁止しているというのも気になる点だ。営利の定義も確認しなければならない。今回、私は場所の費用のために、少額の参加費を徴収するつもりだし、購入もできるC++の自由な参考書の紹介もするだろうし、他の発表者も、あるいは自社の商用製品について紹介するかもしれない。どこまでが営利にあたるのか確かめなければならない。

それを考えながら色々と探すと、別の場所が見つかった。

ベーコン研究所(京都駅)

なんだか怪しげな名前だが、京都駅前から歩いて2分という都合のいい立地にあるらしい。なんと、プロジェクター、ホワイトボード、机、椅子、電源、無料WiFiまで含めて、一時間3000円だという。こちらを使う場合、参加費は1000円ぐらいに上げなければならないだろう。

そういえば、このベーコン研究所のTwitterアカウントは、昔、一時期だけフォローしていた記憶もある。詐欺では困ると足で現地を見てきたが、ちゃんと存在した。

場所は、徒歩2分かどうかはともかく、たしかに京都駅の近くだ。外からみてそれとわからない雑居ビルの3階と4階にある。1階は居酒屋か何かのようだ。実際に借りられる部屋をみてみたが、部屋の狭さ以外は、宣伝通りならば、快適そうだった。

問題は、部屋が狭いことだ。机と椅子を並べると、ぎっしり入って24人しか入れない。そもそも赤字にならないほど人が集まるかどうかもまだわからないのに、もう大勢の参加希望者がでたときの心配をするのは取らぬタヌキのなんとやらだが、24人というのは、私の今まで参加してきた勉強会の規模を考えても、やはり少ないように思われる。

部屋の狭さ以外は、ベーコン研究所は良さそうなので、ちょっと試しに一時間だけ借りて検証するのもいいかもしれない。

どこか他の場所も探してみるべきだろう。14日に東京に言って、15日に返ってくるので、正式に予約を入れるのはそれ以降になる。できれば11月中に場所を確保して、勉強会の告知を行いたい。

と同時に、私以外の発表者も募らなければならない。何人の発表希望者が出るのかによっても、部屋を借りる時間が変わってくる。私の今の考えでは、時間帯は、昼を挟むと昼飯やら色々と面倒なので、午後から夕方にかけて、行おうと思っている。

まだ正式には何も決まっていないし、正式に発表者募集も後で行うが、なにかC++か、あるいは関連する内容の発表をしたい人はboostcpp@gmail.comまで

変化しなければならない

この激動のような二週間を経て思ったことは、やはり、変化は必要なのだということだ。この数年、C++の参考書をだらだらと書くばかりで、まったく変化がなかった。怠惰はプログラマーの美徳だなどとうそぶきながら、何も変わっていなかったわけだ。

それが、引っ越しをしなければならなくなると急に決まった。引越しに伴い、今のコンピューターとインターネット接続も失うことになった。劇的な変化だ。

まず行ったのは、C++参考書のGitHubでの公開だ。とにかく、未完成だが公開しなければならない。このまま埋もれさせるわけには行かない。もちろん、GFDLのような自由を保証するコピーレフトなライセンスで公開するのだ。私が無きあとも、自由に使えるように意思表示しておかなければならない。

当初は、公開して、そのまま消えるつもりだったが、多くの誤字脱字の修正がpull requestで送られてきた。そのため、にわかにやる気を出し、自分でも驚く速さで、ともかくも一通り完成させた。

本の虫: C++参考書の販売:C++11の文法と機能

少なくとも、金を取っても恥ずかしくないと思える程度には完成したので、Gumroadで販売することにした。

C++11参考書をGumroadで購入

まだ昨日公開したばかりだが、少しだけ売れた。これは状況を変えるほどではないが、恵まれていると言える。このC++参考書は、自由なライセンスであるGFDLの元に公開したので、複製物を入手するにあたって、金を払う必要はないわけだ。しかも、圧縮して200KBほどのファイルである。それが、わずかとは言え売れるのだから、私はだいぶ恵まれていると言える。

また、親切にも、十分過ぎる性能のラップトップを譲り受け、また、帯域は狭いものの、どうやらインターネットの常時接続も維持できるようだ。また、世の中には、無料、あるいはコーヒー一杯程度の値段で数時間使えるWifiもあることを知った。

私は不自由が蔓延している携帯電話には興味を示さなかったのだが、どうやら今は、帯域や転送量が大幅に制限されるものの格安のSIMカードというものがでていて、これをモバイルWiFiルーターと組み合わせれば、携帯電話のつながるほとんどの場所で、ネット接続できるらしい。

これにより、私はC++の参考書の執筆に、家の中に閉じこもる必要もなくなった。

やはり、状況を劇的に変えるには、自らも劇的に変化しなければならないのだろう。

今後をどうするか。まず、貯金を切らした以上、収入が必要である。最低賃金の時間あたりいくらでバイトをするということもできる。しかし、とにかくギリギリまで、C++で稼ぐ方法を模索してみようと思っている。それには、劇的な変化が必要である。失うはずだったコンピューターとネット接続が維持できるが、このままではいけない。劇的な変化が必要である。

学習

まず、私は劇的に学ばなければならない。さしあたっては、gitを一通り学ぶ。私が今まで、gitを学ぼうとして学べなかったのは、最初から網羅的なドキュメントを読もうとしたからだろう。

Git - Reference

そうではなくて、最初は、全体像をつかむために、入門書を読むべきだったのだ。そして、深く学ぶよりも、まず使ってみるべきだったのだ。今回、GitHubを使う必要に迫られたことで、今まで学ぼうと思いつつも果たせなかったgitが、極めて限定的な範囲ではあるが、短時間で使えるようになった。習うより慣れろとはこのことだろうか。引っ越した後は、まずgitの全体を学ぶために、以下の本を読むつもりだ。

Git - Book

また、GNU/Linuxに移行してからも、C++参考書の執筆に追われていて、今まで適当にやっつけで済ませてきた多くのことを、学ばなければならない。たとえば、私はGNU/Linuxで一般的な知識の多くを知らない。Makefileやbashシェルスクリプトなどを、本格的に学ぶべきだ。いままでやっつけでいくつか書いていたので、書くには書けるが、知識が適当過ぎる。autoconfやautomakeも学びたいが、これはちょっと時間がかかりそうだ。

勉強会

私は今まで、勉強会というものには参加してこなかった。C++のことならたいてい自力で学べるし、その他のことだって、たいていは学べるはずだ。わざわざリアルで集まって、たったの数十分程度スライドと肉声による解説で、何が学べるというのか。自分が発表するならば、少しは学べるかもしれないが、そもそもが、スライドを見せながら肉声で数十分で話せる内容なのだから、詳細には至らず、表面的な紹介で終わってしまう。実に非効率的である。文章のほうがいい、と、そう思っていた。

しかし、勉強会は最近とても頻繁になっていることを考えれば、私は勉強会を主催するべきだと考える。勉強会は、直接金にはならないとしても、やはりリアルで集まって対面して教育をするのは、重要なのだろう。また、私の名前を売ることができ、間接的な利益があるかもしれぬ。どうやら、京都市で勉強会を開いても、それなりに需要はあるらしい。正式な告知は後ほど、勉強会告知用のサービスを提供しているWebサイトを使って行うが、だいたい、以下のように下見をしている。

まず、勉強会に使える場所が必要だ。少なくとも数十人が入れる部屋と、プロジェクターがなければならない。電源や無料のWiFi接続があればなおよい。今のところ、京都駅前にあるベーコンラボという怪しげな名前の場所が候補に上がっている。

京都の貸し会議室・レンタルスペース(京都駅)|ベーコンラボ

名前は怪しげだが、書いてあるとおりだとすれば、京都駅前から歩いていける場所にあって、プロジェクターも電源も無料WiFi接続も込みで、一時間3000円だという。唯一の欠点は、2,30人ぐらいしか入れないことだが、とにかく勉強会を主催するの初めてであるし、最初は小規模な方がいいだろう。そもそも集まるかどうかの問題もある。

京都駅前なので、実際に現地に赴いて確認する必要がある。

日時は、今のところ、2013年12月21日を予定している。ちょうど三連休の初日に当たるので、参加しやすいのではないかと思う。

購読できるC++記事

Gumroadには、一度限りの購入の他に、購読という支払い方法がある。これは、月額課金である。たとえば、このブログでいつも書いているようなC++記事を、月々500円ぐらいの課金で、一週間に一度配信するようなことを考えている。

このブログでC++の記事は常に書いているが、何の責任もないため、一日に何本も書いたり、何週間も書かなかったりしている。金を取って一週間に一本書くという制約を貸せば、安定したC++解説の供給ができるだろう。

私はペイウォール(見たければ金を払え)が嫌いである。問題は金を払うことにあるのではない。ペイウォールは面倒なのだ。たとえ無料でも、単なる閲覧にアカウントの作成やログインを必要とする記事は、それだけで読む気が失せてしまう。私が読みたくないものを、金を取って読ませるなど論外だ。それに、私はプログラミングの参考書は自由であるべきだと信じている。

いま考えているのは、このブログで記事を書きつつ、Gumroadでの購読へのリンクを貼ることだ。大勢が購読してくれれば、C++記事の執筆を維持できるというわけだ。

また、金を取る以上、そのようなC++記事は、ブログ以外にも、使いやすい形で公開すべきだと思う。所詮はHTMLというプレインテキストなのだから、GitHubで公開するのがいいのではないか。記事ごとに別のファイルにして、年と月でディレクトリにわけ、HTML/CSS/JavaScriptやスクリプトなどで処理しやすい形にしたい。

もちろん、そのような月々500円の購読を継続するためには、100人単位の購読者が必要だ。とにかくやるしかない。

とにかく、私はまだ恵まれている方だといえよう。

Acer Aspire 5750について

LenovoのThinkpad X121eはBIOSのバグにより文鎮化してしまったことは既に述べた。さて、また新たに、好意でラップトップを一台もらった。Acer Aspire 5750である。

基本的なスペックは、以下を参照(本来ならAcerのWebサイトを参照すべきなのだが、見当たらないのだ)

Acer Aspire 5750 review (LX.RLY02.097) | Expert Reviews

このラップトップは、2011年に発売されたものであるが、私にはもったいないぐらいにスペックが高い。今使っている6年前のBTOデスクトップより高い。

まず、メモリが増設してあり、16GBある。ラップトップとしては、この2013年でも十分なメモリ容量だ。HDDもSSDに交換されている。容量は128GBだが、ラップトップなのでそれほど容量はいらないので問題はない。

CPUは、Intel Core i5-2410Mだ。これは、ベンチマーク結果から比較すると私が今使っているQ6600と同等か、やや上の性能だ。

GPUはIntelのCPUに内蔵されている、HD3000である。これには、Intel公式に自由なドライバーが提供されている。結果として、このラップトップは、BIOSより上のソフトウェアは、完全に自由なソフトウェアになった。HD3000のパフォーマンスは低いが、そもそも私のラップトップの利用では、GPUの性能は必要ない。それよりもGPUのドライバーが自由なのは素晴らしいことだ。

パフォーマンスが高いだけではなく、このラップトップは、Ubuntu 13.10でサスペンドも問題なく行える。ラップトップはサスペンド周りに結構規格違反の不具合が多いのだが、これは問題なく動いた。

現在のところ、このラップトップは、ソフトウェアの対応と、ソフトウェアの実行の点で、すばらしいものだ。

ただし、どんなものにも難点はある。Acer Aspire 5750の難点は、ソフトウェアではなくハードウェアにある。

まず大きさだ。ディスプレイが15.6インチもある。ラップトップとしては相当に大きい。私が今までこんなに大きいラップトップを使ったことはない。ただし、大きいということは利点でもあるので、このこれは利点でも欠点でもない。ただ、持ち運ぶのに難点があるというだけだ。

ただし、ディスプレイは大きいのに、解像度が低い。たったの1366x768である。どうやら、この1366x768という解像度はパネルのサイズを問わず、ここ数年、広く使われているようだ。最近になってようやく、まともな解像度のディスプレイを組み込んだラップトップが、Mac以外でも出回るようになってきた。

キーボードが安っぽいパンタグラフだという点もある。この点で、LenovoのThinkpad X121eは、すばらしかった。あの小ささで、あのような素晴らしいキーボードが組み込めるとは驚きだった。残念ながら、X121eはBIOSに文鎮化のバグがあり、使うことはできないが、もし使えたら、私はむしろX121eを使いたかったと思うほど、内臓のキーボードが素晴らしかった。

キーボードにテンキーがあるのも難点だ。私はテンキーを使わない。むしろテンキーを取り除いて、キーピッチはそのままでもいいから、左右を開けて中央に配置してくれたほうがいいぐらいだ。

15.6インチのディスプレイを搭載している以上、テンキーを持ちながらも、キーピッチが結構広いので、その点ではまだいくらか使いやすい。

キーボードは、適当なUSBのキーボードでもつなげばいい。ただし、持ち運んで使うのが難しい。キーボードを別途持ち運ぶだけでも煩わしい。

結論としては、Acer Aspire 5750は、私にはもったいないぐらい素晴らしいラップトップだ。これにより、私は11月以降も、参考書を執筆できる環境を得た。

何とかして金を稼がなければならない。できればC++の参考書で稼ぎたい。Gumroadのような支払い方法もあることだし、いろいろと試すつもりだ。

ジェネリックlambda式を使ったbind1stの実装と、C++03を使った実装の比較

注意: std::bind1st, std::bind2nd, std::unary_function, std::binary_functionはC++11で非推奨機能となり、将来的には廃止される。

C++14 の Generic lambda で bind1st 書いてみた - C++でゲームプログラミング

実に面白い。ジェネリックラムダは、もちろんパラメーターパックが使えるので、大昔のbind1stは、以下のように実装できる。

#include <iostream>

template<typename F, typename T>
auto
bind1st(F func, T t){
    return [=](auto... args){
        return func(t, args...);
    };
}


int
plus(int a, int b){
    return a + b;
}

int
main(){
    auto plus3 = bind1st(&plus, 3);
    std::cout << plus3(5) << std::endl;
    std::cout << plus3(1) << std::endl;
    return 0;
}

読者の大半は、すでにC++14ユーザーであろうから、このようなコードは当たり前であり、古き時代の苦しさは分からないだろう。そのため、C++03でbind1stを実装してみよう。

// C++03当時のコード

#include <iostream>
#include <functional>

namespace ezoe {

template <class Fn>
class binder1st
    : public std::unary_function<
        typename Fn::second_argument_type,
        typename Fn::result_type>
{
protected:
    Fn op;
    typename Fn::first_argument_type value;

public:
    binder1st(  const Fn& x,
                const typename Fn::first_argument_type& y)
        : op(x), value(y)
    { }

    typename Fn::result_type
    operator()(const typename Fn::second_argument_type& x) const
    {
        return op( value, x ) ;
    }
} ;

template < class Operation, class T >
binder1st<Operation> bind1st(const Operation& op, const T& x)
{
    return binder1st<Operation>(op, typename Operation::first_argument_type(x)) ;
}

} // end namespace ezoe

// 関数ポインターでは使えない
struct plus
    : std::binary_function< int, int, int>
{
    int operator ()( int a, int b ) const
    {
        return a + b ;
    }
} ;

int main()
{
    auto plus3 = ezoe::bind1st(plus(), 3);
    std::cout << plus3(5) << std::endl;
    std::cout << plus3(1) << std::endl;
    return 0;
}

まず、binder1stというクラスを書かなければならない。これはめんどくさい。しかも、このbinder1stは、規格の規定する関数オブジェクトしか使えないのだ。関数オブジェクトとは、std::binary_funcitonから派生するか、あるいは第一実引数、第二実引数、戻り値の型をそれぞれ表す、first_argument_type, second_argument_type, result_typeというネストされた型名を持たなければならない。そのため、C++03版のplusは、クラスで実装しなければならない。関数ポインターは渡せないのだ。

一応、仮引数の型を得る方法はあるが、それには複雑怪奇なテンプレートメタプログラミングを使わなければならない。

C++14版は、関数ポインターでも問題なく渡せる。

C++14、いい時代になったものだ。

2013-11-10

C++参考書の販売:C++11の文法と機能

完成したC++11参考書:C++11の文法と機能の販売をGumroad.comで開始した。

Gumroadで購入:C++11参考書:C++11の文法と機能

直接のGumroadへのURLは:https://gum.co/IwMm

内容はC++11のコア言語の文法と機能を、規格に忠実に解説した自由な参考書だ。すでにGitHubで公開しているものと同一の内容だ。

GitHub: EzoeRyou/cpp-book

GitHubからzipでダウンロード

GitHub Pagesでの閲覧:C++11の文法と機能

本の虫: C++11参考書の公開:C++11の文法と機能

価格は、最低5000円以上の任意の額で購入できる。値段に関しては色々とあるだろうと思うが、筆者は、これでも安すぎると思っている。電子書籍に対価を支払う文化を根付かせなければならない。あまりに安すぎると意味がない。あまりに高すぎると払える人間が少なくなってしまう。対価を支払わずとも同一の複製物が得られる以上、ある程度高くても問題はない。

そのため、価格を最低5000円に設定した。自由な参考書の必要性に賛同する者は、より多く支払うこともできる。

購入するとダウンロードできるファイルは、通常のZIPフォーマットだ。参考書のフォーマットはXHTMLだ。このXHTMLは手で書いた単純なものであり、移植性が高く、また必要に応じてフォーマットの変換も容易だ。

本書には、ライセンスはGNU Free Documentation License(GFDL)という、コピーレフトなライセンスを採用している。そのため、GFDLの要件を守れば、改変や再配布の許諾を得られる。

本書は、C++11がまだC++0xと呼ばれていた2010年から、5年の歳月をかけて書いたものであり、購入して作者に対価を支払えば、筆者の生活の助けにもなり、筆者の次の参考書執筆の資金にもなる。

今回、販売にGumroadを選んだ理由は、最も単純であるという点からだ。まずUIが簡単だ。私の参考書はGFDLであるし、またファイルサイズも圧縮して数百KB程度なので、複雑な専用のダウンロードソフトウェアや、閲覧ソフトウェアは必要ないし、DRMなどもってのほかだ。単に金を払ってファイルをダウンロードできるプラットフォームがあればいい。

残念ながら、Gumroadでの購入はクレジットカードを必要とする。プライバシー上の懸念で、クレジットカードを持たない者は多い。それはもっともな懸念だ。本書のライセンスはGFDLであり、購入しなくても複製物を取得できるので、さしあたっては情報へのアクセスを妨げることはない。とはいえ、対価の支払いというのは、重要なことだ。

日本には、日本語で書かれたC++の規格準拠の参考書が必要である。少なくとも、現状の日本人のプログラマーの大半が英語を理解しない以上、日本語の参考書は必要である。筆者はプログラミングの参考書は自由でなければならないと信ずる。執筆には金が必要である。どのような形であれ、執筆活動を支える資金が存在しなければならない。思うに、執筆のための資金を得る方法には、3つある。

  1. 別の方法で資金を得て、執筆する

    これは今回、筆者がとった方法である。筆者は執筆前に働いて得た貯金で執筆した。

    しかしこれは、長期的には続かない。執筆自体が金を生まないからだ。

  2. スポンサーを得る

    C++03までの標準規格は、C++標準化委員会の日本支部のボランティアにより翻訳され、JIS規格として発行されている。これは、当時、国内にC++の規格の日本語訳を必要とする企業が大勢いて、そのようなスポンサーが自ら金を出して雇った代表を標準化委員会に送り込んでいたので、実現した。

    残念ながら、今の日本では、C++に対するスポンサーが減りつつある。当時のスポンサーも、今ではC++11の標準規格の日本語訳を出すほど積極的な支援をしていない。

  3. 参考書を売る

    これは最もわかりやすい方法だ。既存の紙書籍が商業販売されていることを考えると、最も身近な方法であるともいえる。

    ただし、紙書籍出版が面倒だ。組版、印刷、全国に流通、販売。どれをとってもとてつもないコストがかかる。そもそも、紙書籍の価値は年々減じつつある。紙書籍を数万冊売ったところで、何年間もの長期間の執筆の正当な対価が得られない。日本のプログラマー人口を推測するに、数万冊売れればよくやったほうで、10万冊売れれば御の字であり、100万冊売れれば全プログラマーに共通の宗教の存在を疑わなければならない。

    では、電子書籍はどうか。電子書籍や、電子データを販売するためのプラットフォームは多数ある。問題は、電子書籍に対価を払うという土壌が存在していないことだ。特に、自由な電子媒体に対価を支払う文化に乏しい。

不自由なプログラムの流通プラットフォームであるSteamや、AppleやMicrosoftのApp Storeの興隆を見、また彼らが情報の共有は悪であるとプロパガンダをタレ流していて、実際に不自由な電子媒体が売れていることを考えれば、電子媒体に対価を支払うという考え自体は、間違ってはいないように思う。問題は、不当な制限だ。自由な電子媒体は利用者に正当な自由を与えるので、不自由な電子媒体よりも価値が高い。その価値がまだ一般大衆に認識されていないだけだ。

自由な電子媒体に対価を支払う文化も、啓蒙次第で根付くのではないかと思う。

また、Gumroadでは、subscribe(購読)という課金方式がある。これは月々いくらを継続的に支払うサービスである。これを使って、例えば毎週、C++に関するちょっとした小さな記事(数時間から数日で書ける内容)を書いて配信すれば、購読者が出るだろうか。

今回、環境の変化に伴い、自分も大きく変化しなければならなくなった。GitHubでC++11参考書を公開したのもそのためだ。

当初は、貢献が得られるとは思わず、公開してそのまま消え去ろうかとも思っていたが、誤字脱字を修正するpull requestの多さに、にわかにやる気をだし、短時間に集中してまだ未執筆だった欠を埋め、C++11参考書を、一通り完成させた。本来ならば、もっと時間をかけてじっくりと書きたかったが、とにかく完成した。

私は当初、自由なプログラムなどが対価を得る方法としては、完成させるための作業に対価が支払われるべきだと思っていた。対価が支払われなければ、作業が行われず、当然完成もない。そのため、完成品が欲しければ、対価を支払わなければならない。ところが、どうも世間の認識は違うらしい。どうやら、世の中は、現物に対して対価を支払うものらしい。

現物、実際に手にとって動かせるもの、閲覧できるものは、たとえ現物の複製物が無料で手に入ったとしても、対価を支払いたいと考えるものらしい。彼らが単に無責任で言っているのかどうかの見極めも兼ねて、C++11の参考書を販売すべく、妥協点もあるものの、金をとっても恥ずかしくない程度には完成させた。

実に、この短期間で多くの変化があった。たとえば、私はgitを使うようになった。もちろん、やろうと思えば数時間学べばそれなりに使えるソフトウェアなのだが、私は必要に迫られなければ行動を起こせない怠惰な人間なので、どうしてもgitは、その価値を知りながらも、今の今まで使ってこなかった。この数年は、ただひたすらC++の参考書をだらだらと執筆するだけの日々だったので、この急激な変化には驚いている。

そして、当初、11月の半ばに失われるかと思ったコンピューター環境とインターネット接続も、どうやらC++11参考書の現物を公開したことにより、色々と支援があって、維持できる見込みが出てきた。まだ実際にその環境を使い始めてみなければわからないが、希望がある。

ああ、もっと早期に書き換えのC++11の参考書を、もっと広く公開しておくだったと後悔している。そうすれば、このような劇的な変化を体験せずに、確実に向上できたであろうに。

しかし、この劇的な変化は、怠惰な私には必要だったように思う。

劇的な向上に劇的な変化が必要なものであるとすれば、やはり変化し続けなければならないだろう。私はさらなる変化を計画している。

まず、勉強会を主催を考えている。まだ適切な場所を探している段階で、決まり次第、勉強会の告知と管理のための既存のプラットフォームを使って告知する予定だが、いまのところ、京都市内で、2013年12月21日に開くことを考えている。

また、月々少額の購読記事を書くことも考えている。

Canonical、商標権を使って批判を検閲しようと企てる

Linux Outfit Canonical Launches Campaign to Silence Privacy Critic | Wired Enterprise | Wired.com

fixubuntu.comというドメイン名、Fix Ubuntuというタイトルで、GNU/Linuxの有名なディストロであるUbuntuの、Dashにおける検索クエリ―ダダ漏れのオンライン検索を無効にするための一行シェルスクリプトを公開していたWebサイトが、Ubuntuの開発企業であるCanonicalから商標権侵害と取り下げの申し立てを受けた。

これは明らかに商標権を、その本来の目的から外れて悪用した検閲である。

fixubuntu.comの作者は取り下げ要求には応じなかった。この作者、Micah Leeは、EFFの技術スタッフであり、オンライン上の権利活動家であり、この手の安い脅しを送る相手としては不適切であったと言える。

LeeがEFFの弁護士と相談したところ、この文脈におけるUbuntuという商標の利用は、既存の商標法で認められているものであると判断したそうだ。

Leeはブログに反論を掲載した。

Canonical shouldn’t abuse trademark law to silence critics of its privacy decisions | micah.f.lee

まずLeeは、この文脈でのUbuntuロゴ画像の使用は、単に参照目的であり、権利の及ばないところであり、当然使用に制限があるものではないが、今回はUbuntuロゴを取り下げる。

さらに、注意書きを付け加えた。

注意:もしあなたが、1) 完全にアホ、2) 弁護士、3) その両方、である場合、このサイトはCanonical株式会社と関係あるいは許可をうけたものではないことに注意してもらいたい。このサイトはCanonicalのUbuntuユーザーに対するプライバシー侵害機能を批判するものであり、またどのようにして問題を修正できるかを教育するものである。ゆえに、明らかに、このサイトはCanonicalの許可を受けていない。我々の商標、Ubuntuの使用は単なる説明であり、一般にこのサイトを発見させ、また理解をさせるのに役立つものである。

さらにLeeは、もしCanonicalがUbuntuのプライバシー侵害のオンライン検索機能を、Opt-in、すなわちデフォルトで無効にし、ユーザーが明示的に有効にしなければならないように切り替えたならば、このサイトはその本来の目的を失うので、喜んで自発的に取り下げると宣言した。

Leeは、その無効のための処置は、以下のたった一行のコマンドの実行であり、技術的な困難性は一切ないと主張する。

gsettings set com.canonical.Unity.Lenses remote-content-search none

Canonical Blog: Trademarks, community and criticism

Canonicalはブログで、Ubuntuロゴの使用が取下げられ、またサイトがCanonicalとは関係がないと明示されたので、問題は解決された。批判を封じるのが目的ではないと答えた。

Mark ShuttleworthはGoogle+上で、弁解に追われている。

これはこっちの手違いだった。スマン。こちらの商標ガイドラインは、皮肉や批判(・・・はクソだサイト)を許可していて、だから要請というのは、ガイドラインに合致する利用であることを明示するように頼むことであるべきだった。

追記:CanonicalのSteve Georgeは返事を、http://blog.canonical.com/2013/11/08/trademarks-community-and-criticism/に上げた。

ただ、こちらとしても、Ubuntuロゴの使用には、いくつかの合意を課さなければならないのだよ。正当な利用というのは主観的なもので、だからこそ、Ubuntuという商標を守るために、ポリシーや同意が必要になるのだ。

この場合、こちらとしては、「許可を得ていると明示するならば商用をつかってもよい」と言うべきだった。たぶん、新人が間違えたのだろうが、それは起こりうることであり、この件でCanonicalを叩く必要はない。この問題を知らせてくれたJon Mastersに感謝する。

Mark Shuttleworth - Google+ - Canonical: Seriously? …

2013-11-09

最近、コンピューターの性能に対して保守的になっていた

最近、私はコンピューターの性能に対して、保守的になっていたように思う。

以前は財布の中身も考えた上で、それでも、高いパフォーマンスを持つコンピューターを欲しがっていた。ところが今は、あまりコンピューターの性能を気にしなくなっている。

もちろん、ここ4,5年、コンピューターの性能がそれほど上がっていないこともあるだろう。ただ、最近の私は、安定性と長期利用性を重視するようになっていたのだ。

安定性は大事だ。私は安定性のためならば、処理速度が下がってもいいと思っている。長期利用性も大事だ。コンピューターを使いやすく設定するのは面倒なので、よほどパフォーマンスが時代から遅れない限り、コンピューターを変えたくはない。それから、パーツの交換もしたくない。面倒だからだ。

最後のパーツ交換に関しては、残念ながら果たせていない。今のPCはかれこれもう6年は使っているが、GPUは性能に不満があったため三回取り替えたし、電源ユニットも壊れたので取り替えたし、CPUクーラーも壊れたので取り替えた。HDDもOSを変える際に取り替えている。私の今のPCは、一般人なら普通は買い変えるべきところを、パーツの交換でやり過ごしてきた。電源ユニットやCPUクーラーは粗悪だったのかもしれないが、壊れたのは保証も切れた4年ぐらい利用しての後だから、なんとも言えない。GPUは故障していないが、ここ6年の性能向上が著しかったのだ。

とはいえ、できるからといってやりたいとは限らない。パーツ交換には手間と時間がかかるからだ。

ところで、私が最後にノートPCを買ったのは、9年前のことである。そのノートPCも、5年ほど前に壊れたし、また、ノートPCを使う必要もなかったので、ノートPCからはだいぶ離れていた。

そして、今にわかにノートPCが必要な状況になったのだが、調べてみると、ノートPCを取り巻く状況が劇的に変わっている。

まず、ノートPCは圧倒的に安くなったということだ。以前、私が満足いくパフォーマンスのノートPCを買うには、パーツを指定して注文できる中国、韓国、台湾あたりのPCメーカーの直販で、15万から20万はしたものだ。それが、いまや私が満足できるパフォーマンスのノートPCの価格が、10万以下に落ち込んでいる。というより、今、20万もするノートPCといえば、日本の主要なボッタクリ価格メーカーとか、ノートPCで真面目にゲームができるような廃スペックのものとか、あるいは耐衝撃防塵防滴など、とにかく特殊なものしかない。

さらに、5万以下の安価なノートPCも一般的になっている。昔は小型のノートPCも、小型というだけで技術的に難しく高かった記憶があるが、いまや小型のPCが安い。

そもそも、ノートPCという物自体が、スマートフォンやタブレットといった新しい形のコンピューターに、客を奪われつつある。

ああ、時代は変わったものだ。ノートPCを使う必要性がないからとしばらく注目しないでいるだけで、タイムスリップしてきたかのような感覚を覚える。

ただし、一つ気になることがある。ノートPCの価格は、全体的に安くなったし、パフォーマンスや大きさといったバリエーションも増えたし、消費者としてはよろこばしいのだが、ひとつ気になることがある。ディスプレイの解像度がクソすぎることだ。

ここ数年で発売された、10インチ程度の小さく安いノートPCも、15インチもある大きくてそれなりのパフォーマンスを有するノートPCも、ディスプレイの解像度がクソすぎるのだ。

なぜか、1366x768というクソ解像度が多い。ディスプレイの大きさは違っても、解像度だけは同じ、しかもどれも申し合わせたように1366x768。なんだこれは。呪いか?

もちろん、ディスプレイの製造というのはCPUのようにはいかないこともあるのだろう。モダンなCPUは、あまりにも精密になりすぎて、完璧に製造することができないでいる。そのため、設計段階から、回路にある程度の冗長性を持たせ、一部が正しく製造できなくても問題ないようにしている。そして製造されたものに動作チェックを行い、より厳しい条件でも動作するものを、厳しい条件に設定してハイエンド、緩めの設定なら動作するものを、ミドルエンドからローエンドとしてい売っている。

ディスプレイとして今一般的な液晶パネルはこれが難しい。いかにドット欠けが許容されるとは言え、隣り合わせに連続して数十個のドット欠けは許容しがたい。ドット欠けが多いものをミドルエンドからローエンドとして売ることはできない。

つまり、液晶パネルは、CPUのように、プラス100ドルで上位品ということができない。そのため、どのPC製造者でも、パネルの差別化が難しいのだろう。

それにしても、十分な性能のCPU、GPU、メモリ容量、はては光学ディスクドライブまで取り付けておきながら、15インチや17インチで低PPCMのディスプレイを使うここ数年のノートPCは、やはり歪だ。

リーナス・トーバルズが、「まともな解像度」とか、「ノートPCが売れないのも当然だ」とか吠えたのも分かる。

2013-11-08

C++勉強会の構想

来週、歌舞伎座.tech#2 - connpassでC++14について話す。

話す内容は、C++14に追加されるコア言語の新機能すべてだ。当日に使うスライドはGitHubに上げている。

EzoeRyou/kabukiza-tech2-slide

当日は、発表20分、質疑応答10分という、あまり余裕のない発表となる。全部は発表できないし、その場で説明に時間のかかる質問には答えられないだろう。できれば、発表60分、質疑応答30分ぐらいは欲しいものだ。

これについて考えていたが、自分でもC++勉強会を主催するということを思いついた。もし、赤字にならなければ、勉強会を開催できる。私の住んでいる場所の都合上、開催地は京都になるだろう。人が集まれば開催できそうだ。C++の勉強会は、すでにBoost勉強会などが頻繁に行われている。京都は観光地であり、京都で勉強会が開かれるときは、観光ついでに宿泊して参加する人もいるらしく、それを考えると、参加者が結構ありそうな感じなのだ。

まだ何も決まっていない構想段階なのだが、とりあえず書き出してみる。

まず、勉強会に使える場所が必要だ。数十人は入り、プロジェクターが使える場所でなければならない。できれば、電源とWiFiもほしい。

京都市内にそういう場所を調べたところ、ひとつ見つかったので、後日調べる必要がある。

京都の貸し会議室・レンタルスペース(京都駅)|ベーコンラボ

京都駅の近く。椅子と机を配置すると24人参加できるらしい。プロジェクター、電源、WiFiと、追加料金もないそうだ。

日時は、今のところ、12月21日がちょうどいいのではないかと思っている。ちょうど三連休の初日にあたっている。

赤字を出さないという点から、参加費を徴収することになるだろう。

また、勉強会というからには、私以外にも発表者がいてほしいものだ。果たして発表者が集まるだろうか。

また、昨今、技術勉強会が盛んになっているため、この手の勉強会の開催告知や参加者管理を行えるWebサービスもある。例えば、以下のようなWebサイトだ。

connpass - 人が集まる。人と繋がるイベントサイト。

勉強会の経験が浅いために、色々と苦労しそうだ。とりあえずは来週末に東京で行われる勉強会の後に考えよう。

emplaceとVariadic Templatesの世界一わかりやすい説明

以下はC++03のinsertの原理である。

template < typename T >
class container
{
private :
    alignas(T) char storage[ sizeof(T) ] ;
    T * ptr = nullptr ;
public :

    void insert( const T & x )
    {
        ptr = ::new(storage) T( x ) ;
    }
} ;

insertとは、何らかの方法で確保されたストレージ上に、オブジェクトを構築するのだ。placement newを使えば、任意の生のストレージ上に、オブジェクトを構築することができる。

push_backのようなメンバーは、insertのやや特殊なものである。

C++11では、ムーブセマンティクスを取り入れたため、insertにはrvalueリファレンスをとるものが追加された。

void container::insert( T && x )
{
    ptr = ::new(storage) T( std::move(x) ) ;
}

ムーブは、ポインターなどの所有権の移動や、コピーの概念のないリソース(ファイルポインタ―やスレッドなど)を扱うのに使うことができる。

オーバーロードが面倒な場合は、forwardingというテクニックを使うことができる。これはPerfect fowardingとも呼ばれている。

template < typename T >
void f( T && x )
{
    // xがlvalueリファレンスならコピー
    // xがrvalueリファレンスならムーブ
    T y = std::forward<T>(x) ;
}

これは、テンプレート仮引数に&&を指定して、関数の仮引数として使うと、実引数推定で、実引数がlvalueリファレンスの場合、Tの型がlvalueリファレンスになり、&&は、単に無視されるためである。

これは、コピーとムーブ以外にコードが変わらないテンプレートを、わざわざ重複させる必要がなくなるという点で素晴らしいのだが、xがlvalueリファレンスかrvalueリファレンスかで、コピーとムーブを切り替えないといけないという意味でもある。幸い、C++は十分にコンパイル時条件分岐が発達している。xのリファレンスの種類はコンパイル時にわかるので、そのような切り分けも、当然コンパイル時に行える。それが標準ライブラリforwardだ。

さて、emplaceとはなにか。emplaceとは、上記のコピーやムーブすらすっ飛ばし、placement newの時点で、直接オブジェクト構築のためのコンストラクターの実引数を指定するメンバーである。

それはどういうことなのか。また、なぜ必要なのか。以下のようなクラスを考える。

struct S
{
    S( int a, int b, int c )
    { /* 重たい処理 */ }

    // コピーコンストラクター
    S( S const & s )
    { /* 重たい処理 */}

    // ムーブコンストラクター
    S( S && s )
    { /* 重たい処理 */ }
} ;

このクラスは、何らかの理由で、int型の実引数を3個とるコンストラクターも、コピーやムーブのコンストラクターも、重たい処理を必要とする。このようなクラスは、ムーブすらしたくない。できるだけ構築回数を減らしたいのだ。

もし、コンテナーの中でストレージ上にオブジェクトを構築するplacement newに、int型の実引数を3つ渡せたら・・・、それがemplaceである。

template < typename T >
class container
{
private :
    alignas(T) char storage[ sizeof(T) ] ;
    T * ptr = nullptr ;
public :

    void emplace( int a1, int a2, int a3 )
    {
        ptr = ::new(storage) T( a1, a2, a3 ) ;
    }
} ;

これにより、まさにコンテナーが内部でオブジェクトをストレージに構築するその場に、構築の際の実引数を渡すことができる。

しかしまて、なにもコンストラクターの取る実引数が、int型3個とは限らない。やはりemplaceはテンプレート化しておかねばならないだろう。無論、perfect forwardingするムーブにもばっちり対応しなければならない。

template < typename T >
class container
{
private :
    alignas(T) char storage[ sizeof(T) ] ;
    T * ptr = nullptr ;
public :

    template < typename A1 >
    void emplace( A1 && a1 )
    {
        ptr = ::new(storage) T( std::forward<A1>(a1) ) ;
    }
} ;

よし・・・これでいい。いやまて、よくない。よく見ろ。これはTのコンストラクターの実引数が1個の場合にしか対応していないではないか。2個や3個の場合はどうするのだ。そもそも、0個の場合だってあるのだぞ。

おお、それもそうだ。何、心配御無用、C++にはちゃんとオーバーロードというものがあるのだ。まあ、見てるがいい。


template < typename T >
class container
{
private :
    alignas(T) char storage[ sizeof(T) ] ;
    T * ptr = nullptr ;
public :

    void emplace ()
    {
        ptr new(storage) T( ) ;
    }

    template < typename A1 >
    void emplace( A1 && a1 )
    {
        ptr = ::new(storage) T( std::forward<A1>(a1) ) ;
    }

    template < typename A1, typename A2 >
    void emplace( A1 && a1, A2 && a2 )
    {
        ptr = ::new(storage) T(
            std::forward<A1>(a1),
            std::forward<A2>(a2)
        ) ;
    }

    template < typename A1, typename A2, typename A3 >
    void emplace( A1 && a1, A2 && a2, A3 && a3 )
    {
        ptr = ::new(storage) T(
            std::forward<A1>(a1),
            std::forward<A2>(a2),
            std::forward<A3>(a3)
        ) ;
    }
} ;

どうだ。0個から3個までの、どんな型の実引数にも、パーフェクトな転送で対応したぞ。

「俺の書いたコンストラクターは実引数を5個取るんだけど?」

何、5個? よしわかった。今すぐ書いてやろう。まずはコピペをして・・・

もう読者も問題がわかったことだろう。自分の書いたソースコード内で関数を丸ごとコピペしてなにか付け加えるというのは、大抵の場合、機械的な繰り返しである。上のようなコードは、パターンさえ指定してやれば、機械的に展開して生成できる種類のコードである。人間が手作業で行うと、間違いが多い。

ちなみに、現在のC++規格で推奨されている、一つの関数における仮引数の数は、256個である。グッドラック!

もちろん、本物のプログラマーは運などあてにしない。本物のプログラマーは、機械的にできるような作業をしない。本物のプログラマーの労力は、本物のプログラミングに使われるべきなのだ。そもそも、このようなパターンのあるコードを生成するのは、まさにプログラミングの仕事である。

Variadic Templatesは、このようなパターンの繰り返しを展開できるようになる。言うよりコードを見たほうが早い。

template < typename ... Types >
void container::emplace( Types ... args )
{
    ptr = ::new(storage) T( std::forward<Types>(args)... ) ;
}

なんと、これだけで、0個以上、実装が許す仮引数以下の、すべての個数の仮引数に対応できるのだ。

ellipsisとよばれる...を使って宣言されたテンプレート仮引数と、ellipsisを使って宣言された関数の仮引数は、パラメーターパックと呼ばれる。このパラメーターパックは、様々な場所で、...を適用することにより、そのパターンを保ったまま展開できる。これをパック展開と呼ぶ。

template < typename ... Types >
void f( Types ... args ) ;

template < typename ... Types >
void g( Types ... args ) ;
{
    f( args... ) ;
    f( sizeof(Types)... ) ;
    f( (args + 1)... ) ;
}

さて、その他の細々としたものも埋めた、containerの全体をみてみよう。

template < typename T >
class container
{
public :
    using value_type = T ;
    using pointer = T * ;

private :
    alignas(value_type) char storage[ sizeof(value_type) ] ;
    pointer ptr = nullptr ;

public :

    template < typename ... Types >
    void emplace( Types ... args )
    {
        check_destruct() ;

        ptr = ::new(storage) value_type( std::forward<Types>(args)... ) ;
    }

    container() { }
    container( container const & c )
        : ptr( make_value(c) )
    { }
    container( container && c )
        : ptr( make_value( std::move(c) ) )
    { }

    container & operator = ( container const & c )
    {
        if ( this != &c )
        {
            check_destruct() ;
            ptr = make_value( c ) ;
        }

        return *this ;
    }

    container & operator = ( container && c )
    {
        if ( this != &c )
        {
            check_destruct() ;
            ptr = make_value( std::move(c) ) ;
        }

        return *this ;
    }

    ~container()
    {
        check_destruct() ;
    }

private :

    pointer make_value( container const & c )
    {
        return ::new(storage) value_type( *c.ptr ) ;
    }

    pointer make_value( container && c )
    {
        return ::new(storage) value_type( std::move(*c.ptr) ) ;
    }


    void check_destruct()
    {
        if ( ptr == nullptr ) { return ; }

        ptr->~value_type() ;
        ptr = nullptr ;
    }
} ;

もちろん、やりだすときりがない。イテレーター、swapなどなど。

とにかく使ってみよう。本当に使えるのだろうか。ところで、一体どうやって、様々な実引数を取るクラスを書くのか。もちろんVariadic Templatesだ。

struct S
{
    template < typename ... Types >
    S( Types ... ) { }
} ;

int main()
{
    container<S> c ;

    c.emplace() ;
    c.emplace( 1 ) ;
    c.emplace( 1, 2, 3, 4, 5 ) ;
    c.emplace( 3.14, 'a', "hello" ) ;
}

さて、本当に呼び出せているのだろうか。念の為に、クラスSのコンストラクターに、古典的なprintfデバッグを仕掛けてみてはどうだろうか。

struct S
{
    template < typename ... Types >
    S( Types ... args)
    {
        // すべての実引数を標準出力に出力する
        print( args... ) ;
        std::cout << '\n' ;
    }
}

この関数テンプレートprintをどうやって書けばいいのか。これは、Variadic Templatesを再帰的に使えばよい。

struct S
{
    template < typename ... Types >
    S( Types ... args )
    {
        print( args... ) ;
        std::cout << "\n" ;
    }

    void print() { }

    template < typename T, typename ... Types >
    void print( T const & head, Types const & ... tail )
    {
        std::cout << head ;
        if ( sizeof...(tail) != 0)
        { std::cout << " , " ; }

        print( tail... ) ;
    }
} ;

sizeof...をパラメーターパックに使うことで、そのパラメーターパックにいくつのパラメーターが入っているのかを、コンパイル時に調べることができる。

さらに詳しくC++を学びたい場合は、私の書いた自由な参考書が役に立つだろう。

GitHub: EzoeRyou/cpp-book

GitHubからzipでダウンロード

GitHub Pagesでの閲覧:C++11の文法と機能

本の虫: C++11参考書の公開:C++11の文法と機能

2013-11-07

ClangがC++14の機能完全に到達! 繰り返す! C++14の機能完全に到達!

[llvm-project] Revision 194194

Clang - C++98, C++11, and C++14 Status

とうとう、ClangがC++14の機能を完全に実装し終えたそうだ。もちろん、まだ既知、あるいは未知のバグがあるだろうが、とにかくC++14の機能的には完全にそろった。

これは素晴らしい。

ちなみに、Hacker Newsでは、このSVNコミットのリヴィジョン番号が、194194であることに着目して、狙ったのかと言われている。

それに対して、100100から194194までの数字には、194個もの同じ3数字二つの組み合わせがあり、別に特別な数字ではない、また、123321のような、他の意味で興味深い数字まで含めると、実に多くの「面白い」数字があると反論されている。

また、Interesting number paradox(興味深い数字のパラドックス)を引くものもいた。

これは、「興味深くない自然数は存在しない」という主張だ。その証明方法は、「もし、興味深くない自然数の集合があったとして、その集合は、興味深くないという点において興味深いので、矛盾する」というものだ。

Clang is now feature complete for C++14 | Hacker News

LenovoのノートPC、Thinkpad X121eで、BIOS設定からカメラとマイクとBluetoothを無効にすると文鎮化

好意で譲り受けたLenovoのThinkpad X121eで、BIOS設定からカメラとマイクとBluetoothを無効にしたところ、文鎮化してしまった。

症状としては、電源を入れると、

  1. Lenovoロゴが表示
  2. "Configuration changed - Restart the system."と表示
  3. その後に自動的にリセットされる(少なくともディスプレイは一度停止する)
  4. 自動的に電源が入る
  5. 最初に戻る

という無限ループに陥る。通常通りにF1キーを押してBIOS設定に入ることもできず、F11キー連打でのBIOS設定リセットも通用しない。F1キーを押すと、Lenovoのロゴ画面では、BIOS設定に入ることを告げるメッセージが表示されるのだが、BIOS設定には入れず、やはり"Configuration changed - Restart the system."と表示される。どうやら、BIOSが設定を読み込むときに発生しているので、BIOS設定に入ろうが入るまいが発生するのではないかと思われる。

OSのブート以前の問題で、BIOSの設定を変更する方法もないので、どうしようもない。

ネット上で検索したところ、同じ症状に陥った者は、少数ながら存在するようで、やはりBIOS設定からカメラなどの有効/無効を切り替えられるデバイスを無効にしたという点で、共通している。

ネット上での同じ目にあった被害者によれば、ACアダプターとバッテリーを一度取り外してから起動しても効果がない。BIOS設定リセットのためのジャンパーは存在しないらしく、CMOS維持のためのバッテリーを一度取り外しても、やはり効果がないそうだ。郵送修理しかなく、修理内容は基盤交換だそうだ。

クロック周波数や電圧を変更したというのなら、分かる。ハードウェアが直接に損傷するかもしれないからだ。しかしこれは、BIOS設定で有効/無効を切り替えられるデバイスの無効化で発生するというこれは、明らかにファームウェアというソフトウェアの問題である。

一体どんなQAテストをしていたら、こんな不具合を見過ごすのだ。

せっかく、CPUがAMDのE300で遅い以外は実用的なラップトップが手に入ったというのに、なんと不運なことか。

ちなみに、サポートに電話をしたところ、この製品の保証期間は2013年1月までであり、いかなる理由であっても、有償修理になる。まずは郵送して見積もりをとるが、その見積だけで6900円だという。

ネット上に同等の不具合で修理を頼んだら基盤交換になったという報告があるが、もしそうだとすると、最低でも50300円かかる。

修理サービス - 引取り修理サービス料金

これが解せないところだ。これは明らかにBIOSの不具合である。ソフトウェアの問題である。経年劣化ではないのだ。製造した時点で存在した不具合だ。まともに考えたら回収するのが当然なぐらいの不具合だ。

この問題が、ネット上に既に報告例があり、実際に修理要請までされているというのに、問題が公式に認知されておらず、リコールもかかっていないというのは、Lenovoという存在自体に疑いを抱かずにいられない。

2013年に5万あれば、もっとマシなCPUを搭載したラップトップが買えるだろう。

教訓としては、Lenovoの製品を、私は推奨しない。

2013-11-06

暗黙に定義されたコピー代入演算子が、複数回派生されているvirtual基本クラスのコピー代入演算子を何度呼び出すかは未規定

以下の例を考える。

#include <iostream>

struct V
{
    V & operator = ( V const & )
    {
        std::cout << "V" << '\n' ;
        return *this ;
    }
} ;

struct A : virtual V { } ;
struct B : virtual V { } ;
struct C : A, B { } ; 


int main()
{
    C c1 ;   
    C c2 ;
    c1 = c2 ; // #1
}

#1で、V::operator =が何度呼び出されるかは、未規定である。

より正確に書くと、規格準拠の実装は、上記のコードで、V::operator =を一回呼び出してもいいし、二回呼び出してもいい。

GCCとClangは、二回呼び出すようだ。

2013-11-05

京都市の無料Wifiについて

京都市は、KYOTO WiFiという、無料のWifiを市内に配置している。

京都市:KYOTO WiFiの整備について~市内385箇所で無料インターネット~

その設置場所は、以下で確認できるようだが、これは最新の状況に対応していないように思われる。

KYOTO WiFi

その目的としては、主に観光客用だ。観光客が手軽にインターネットに接続できるようにする・・・はずだった。

KYOTO WiFiのアンテナは、主にバス停に設定されている。説明では、WiFiの設置箇所に、その存在とアクセス方法を説明したステッカーが貼られているそうである。

私が確認したところ、近所のバス停に、そのようなステッカーは一枚も確認できなかった。剥がれてしまったのかもしれないが、近所のバス停すべてにそのようなステッカーが確認できない以上、その存在がわからない。

したがって、KYOTO WiFiのアクセスポイントを探すには、ステッカーではなく、それっぽいアンテナを探さなければならない。あるいは、ラップトップを抱えて無線探しをすることになるだろう。

多くのあまりセキュリティに関心のない者は、そのへんの野良WiFiに片っ端から接続しようとするだろう。その結果として、存在を見つけるはずだ。

バス停等に設置されているタイプのKYOTO WiFiには、"KYOTO_WiFi 01"という名前が与えられている。このWiFiにはパスワードはかかっていない。ただし、接続しても、パケットは一切通らない。

ブラウザーを使って、HTTPかHTTPSプロトコルで、どこかのURLにGETを送ると、service.wi2.ne.jpドメインのWebサイトにリダイレクトされる。そこから、3時間有効な使い捨ての「ゲストコード」を入力する。ゲストコードの入力が終わったならば、3時間の間使えるようにある。

問題はゲストコードだ。ゲストコードを手に入れるには、kyoto@forguest.wi2.ne.jpにメールを送らなければならない。このメールアドレスにメールを送ると、ゲストコードが返信されてくる。メールは、日本語と英語で書かれている。

ここが問題だ。無料のWiFiでインターネットにつなぐ前に、メールの送受信を行う必要がある。これをどうするのか。

今は2013年である。誰もがメール送受信機能を持った携帯電話を所有する時代である。テキストメールは転送量が少ないので、海外から日本にやってきた観光客の携帯電話のローミングでも、それほどの値段にはならないだろう。つまり、問題はネット接続が存在しないのではなくて、通信費用が高すぎるところにあるのだろう。

あるいは、事前に取得するという方法がある。どうやら、このゲストコードの有効期間は、初回ログインから3時間らしいので、事前にゲストコードを取得すればいいはずだ(何日有効なのか不明だが)

だが、最大の問題は、この存在が知られていないということだ。一応、英語のページも用意したりと、周知に努めているらしい。

KYOTO WiFi

しかし、前述の通り、アンテナの存在は、その場所では分からない。貼られているべきステッカーは貼られていないし、もし貼られていたとしても、気づかれない。アンテナの方がよっぽど目立つありさまだ。

京都市は無料のWiFiを提供する意義があるのだろうか。思うに、WiFiのアクセスポイントを市内数百箇所に設置したところで、費用は、行政としてはたかが知れている。特に、京都市は観光都市である。京都市は多くの収益を観光から得ている。無料のWiFiを提供することによって、観光客が満足もし、また観光客の安全をも守れるのであれば(野良WiFiは悪意ある者が設置しているかも知れず危険である、もちろん、京都市がNSAであるかどうかの問題もあるが)、直接的な金銭利益にはならないとしても、間接的な利益は大きいのかも知れない。

KYOTO WiFiは、暗号化されていないので、利用するときには気をつけること。

2013-11-04

Linus Torvalds、Linuxの32bit版の優先度は低いと表明

[Phoronix] Linus Acknowledges 32-Bit Linux As Less Important

32-bit版のLinuxカーネルにおける、既存のある問題を修正したLinuxカーネル3.12に対するパッチのpullが、Linusによって退けられた。理由は、Linusは3.12のリリースを遅らせたくないからだという。すでに壊れていて、それほど問題になっていない問題を修正するのに、カーネルのリリースを遅らせたくないこと、それに、32-bit版の優先度は低いと言っている。

Linux-Kernel Archive: Re: [git pull] fixes for 3.12-final

On Sun, Nov 3, 2013 at 11:54 AM, Al Viro wrote:

> たしか、前にこういうことで32bit版のiget()が深刻に壊れて、
> それで、もうこういうことはしないと決めたんじゃなかったっけ。
> もう何年も前の話だけれど・・・

ああ、だが状況は変ったんだ。32-bitはもうそれほど重要じゃないし、iget()は以前ほど重要じゃない(すべての、「通常」のinode検索は、直接dentryポインターをみている)

まあ、ARMで64-bitが一般的になるには、まだ数年はかかるだろう。だが、もうすぐのことだ。それに、32-bit ARMは、x86-32ほど64bitの値に対して問題(レジスタを大量に使ってしまうこと)はないはずだ。

そういうわけで、なにかとてつもなく悲惨な問題が隠れているのでない限り、"u64 i_ino"が正しいやり方だ。今の32-bitカーネルでやっているようなヘンテコなworkaroundよりはね(しかも64-bitカーネルにとってはムダでしかない)

Linus

今や、多くのGNU/Linuxディストロは、64-bit版を提供しているし、Ubuntuも64-bit版の方を推奨し始めたし、時代が変わったということだろう。

xkcd: 暗号的、パスワード再利用

xkcd: Encryptic

暗号的

先日、ハッカーが1億5300万件ものAdobeユーザーのEメールアドレスと、暗号化されたパスワードと、パスワードのヒントを流出させた。

Adobeは不適切なパスワードの暗号化を行っていた。ブロックモード3DESを使ってしまったのだ。結果として、とても素晴らしいものが出来上がってしまった。

史上最大のクロスワードパズル

捕捉

先日、Adobeのユーザー登録情報が大規模に流出する事件があった。流出したのは、xkcdでも言及しているように、AdobeユーザーのEメールアドレスと、暗号化されたパスワードと、パスワードのヒントだ。この暗号化されたパスワードというのがクセモノだ。

モダンな暗号は、ブロックと呼ばれる決められたビット数単位で行われる。DESのブロック長は64bitである。もし、ブロックごとに独立して暗号化した場合、同じ値のブロックは、同じように暗号化されてしまう。

これを防ぐために、ブロック単位をまたぐような長い平文を暗号化する際は、次のブロックの暗号化は、前のブロックの結果に依存するようにするものだ。このブロック単位の暗号化の際に、どのように暗号化するかというのを、「モード」という。詳しくは、Wikipediaのブロック暗号モードを参照。

Block cipher mode of operation - Wikipedia, the free encyclopedia

パスワードという短い単位と、ブロック暗号モードの不適切な適用により、流出した暗号化されたパスワードは、同じパスワードが同じ暗号文になってしまっている。同じ暗号パスワードに設定されたヒントをかき集めれば、推測が容易になる。

これは、史上最大のクロスワードパズルと言える。

このクロスワードパズルを遊ぶのは、以下のような形になる。

7 Habits of Highly Effective Hackers: Can someone be targeted using the Adobe breach?

毎度おなじみのtitleテキストは、以下のようになっている。

<img title="どうせいつかは起こることだったわけだ。このデータでxkcd.com/792/風のパスワード再利用攻撃が行われるだろう。この攻撃から逃れられる賢い種類の人間は、Photoshopを割ったヤツだけだ。" ></img>

パスワード再利用攻撃というのは、多くに人間が、同じEメールアドレスとパスワードを複数のサービスに使いまわしていることに起因する攻撃だ。流出して判明したEメールアドレスとパスワードの組み合わせを、他の主要なWebサービスに試す攻撃だ。

xkcd.comの792は、xkcd: Password Reuseだ。

パスワード再利用

黒帽子「パスワードのエントロピーは問題じゃないんだ。本当の危険性は、パスワードの再利用にあるんだ」
白頭「なぜ?」
コンピューター「パスワードの強度が弱すぎます」

黒帽子「なんか簡単なWebサービスを立ちあげてみろよ。たとえば、イメージホスティングとかtweet記録とかさ。で、無料だからさ、数百万人がアカウント作るだろ」

黒帽子「そうなるとホレ、お前さんは今や、数百万人分のメアド、デフォルトユーザー名、パスワードのリストを持ってるわけだ」

黒帽子「大勢の人間が、強かろうが弱かろうが、同じパスワードを、たいていのアカウントで使いまわしてる」

黒帽子「でさ、そのリスト使って、プロクシ経由とかで、20か30ぐらいの主要なサイトとか、銀行とかPayPalとかに、自動ログインかけてみろよ」

黒帽子「まあ、数十万人分ぐらいの個人情報が得られるわな。しかもバレないときている」
白頭「で、その後どうするんだ?」

黒帽子「いやー、そっから先が難しいのよ、これが。俺も悩んでる」
白頭「お前やったのかよ?」
黒帽子「何で俺がカネ儲けにもならんサービスを大量に立ちあげてたと思ってたんだ?」

黒帽子「まあ、カネ儲けはできるわな。方法はともかく、注意深くやればさ。だが、最近の研究で明らかになったように、カネがあったところで幸せにはならんときている。日々を経済的に問題なく送れる以上のカネがあったって、どうにもならん」

黒帽子「人にイヤガラセもできるわな。でも、俺はイヤガラセならいつでもやってらぁ。政治や宗教問題で世界をひっかきまわしてるからな。でも1997年の3月のアレ以降、そういうのも面白くなくなってな」

黒帽子「そしてここにこうして座っている。さながら操り人形を手持ち無沙汰にしている人形使いってわけさ」
黒帽子「Googleが抱えている問題と同じさね」
白頭「うん?」

Googleにて

Google幹部「諸君、今や我々は世界中の情報を支配した。今こそ邪悪になる時だ。なにか計画は?」
幹部ババア「カネ儲けするとか?」

Google幹部「もうカネ儲けしてるだろ!」
別のGoogle幹部「毎週、世界中でCoD3:MWのトーナメント戦を開催するとか?」
Google幹部「そんなの邪悪じゃない!」
別のGoogle幹部「テレビを支配しよう!」
Google幹部「どうも我々は、邪悪をやることにかけては下手だな」

多くの人間が、主要なWebサービスでEメールやユーザー名とパスワードを使いまわすため、一箇所で漏れれば、主要なWebサービスすべてで漏れたのと同じになってしまうのだ。

Photoshopの未ライセンス品を使い、結果としてユーザー登録をしなかった種類の人間のみが、このパスワード再利用攻撃を逃れられるというのは、皮肉なものだ。

6年前と今のコンピューターの性能比較

「タダ飯の時代は終わった」(The free lunch is over.)とHerb Sutterは宣言した。

タダ飯というのは、コンピューターの性能向上にかかる期間があまりに短かった時代を表す言葉だ。一昔前は、コンピューターの性能が倍々に上がっていくので、今、コンピューターの性能が足りないために使えないソフトウェアでも、来年辺りには使えるようになっていたのだ。つまり、プログラマーは苦労せずしてタダ飯をかっ食らうことができるのだ。どうせ1年か2年待てば、パフォーマンスは問題にならなくなるのだ。今ソフトウェアを最適化する意味がない。

一昔前、我々はタダ飯を享受していた。集積回路の密度が9ヶ月、ないしは1年、そして1.5年で倍になり、回路を駆動させるクロック周波数も倍になっていくのだから、実質、1年ぐらいで、コンピューターの性能は倍になるのだ。すると、2年後には4倍に、3年後には8倍になってるだろう。

パフォーマンスなんて気にするな、プログラマーの諸君。飯はタダだぞ。

ところが、そのような素晴らしいタダ飯の時代は終わった。まずクロック周波数を引き上げることが難しくなり、純粋にクロックを倍にして性能の底上げをすることができなくなった。集積回路の密度は今も上がっているが、あまりに細かくなりすぎて、単純にクロックあたりの性能を倍にすることも難しくなった。そういうわけで、今のコンピューターは、以前ほど性能が上がらなくなっている。

私は、6年前に組んだコンピューターをいまだに使っている。たしかにこのコンピューターは今となっては遅い。しかし、まだ絶望的にパフォーマンスが不足しているわけではない。以前ならば、6年もたてば、コンピューターの性能は64倍になり、ソフトウェアも64倍の性能をあてにするようになり、6年前のコンピューターなど漬物石にしかならないはずであるが、今は、コンピューターの性能がそれほど伸びていないのだ。

たしかに、コンピューターを6年も使うには、色々と面倒なことがある。GPUは何度か交換している。CPUファンも壊れたので交換した。電源ユニットも壊れたので交換した。HDDもOSを入れ替える際に交換した。

とまあ、細かく見ていけば、純粋に6年前のコンピューターではないのだが、マザーボードとCPUとメモリーは変えていないし、HDDをSSDに変えたわけでもないので、まあ、ほとんどは6年前の性能だ。

さて、今のコンピューターの性能をつらつらおもんみるに、CPUのクロック周波数は変わっていない。CPUのクロックあたりの性能は、6年前より、3倍ほど向上したようだ。6年でたったの3倍とは、一昔前では考えられない。3倍程度の性能差というのは、ローエンドとミドルエンド程度の違いでしかない。なるほど、通りで絶望的なパフォーマンス不足を感じないわけだ。6年前のミドルエンドは、今のローエンド程度でしかないのだから。

かわりに、今やローエンドCPUでもマルチコアだったり、仮想化のような特定分野専用の支援機能があったり、電力効率を重視したりしているが、絶対的な性能がそれほど向上していないというのでは、もうタダ飯の時代ではない。

CPUより悲惨なのは、メモリだ。メモリの性能は、全然上がっていない。容量はともかく、メモリ帯域が全然上がっていない。ただでさえ鈍化したCPUの演算性能向上にすら追随できていないのだ。

このため、DOOM 3 BFGの最適化にもあるように、今のソフトウェアの最適化は、できるだけアクセスするメモリの範囲はキャッシュに収まる範囲に狭めなければならない。いくらメモリ容量があろうとも、縦横無尽にメモリ領域を読み書きして回るわけにはいかないのだ。なるべく狭い範囲に読み書きを分割して集中させなければならない。

私がPCを組んだ6年前というのは、確かちょうどDDR3が市場に出回るようになった頃だ。当時、私は価格を考慮して、安価なDDR2を選択したわけだが、まさかいまだに一般市場でDDR3を使っているとは思わなかった。DDR→DDR2→DDR3と、だいたい4年ぐらいの期間で世代交代しているのだが、DDR3はやけに長い。来年の2014年には、DDR4が一般市場に出てくるそうなのだが。

興味深いことに、GPUだけは、この6年間にかなり性能が向上したように思う。単なる演算性能だけではなく、機能的にも、よりprogrammableになっている。

ストレージは、SSDの登場によって一気に性能が上がった。どうも記憶が曖昧だが、6年前は、まだSSDが市場に出回っていなかったか、あったとしても、容量数十GBがウン万もしたはずである。

追記:AKIBA PC HotlineにSSDという言葉が初出したのが2007年のようだ。32GBで約8万円、64GBで約17万円したそうだ。

ただ、SSD自体としても、容量増加以外の性能向上が鈍いように思われる。これも、一種のメモリであるから、同じ問題なのだろうか。

まとめ

6年前と比べて、CPUはクロックあたりの演算性能が3倍になった。メモリはちょうどDDR2とDDR3の転換期だったために帯域が2倍になった。GPUは相当に性能とプログラミング性が向上した。ストレージはSSDにより一気に性能が上がり、2013年では容量的にもHDDを十分置き換えられるようになりつつある。

2013-11-03

自由なGPUプロジェクト、またもや失敗

[Phoronix] It Looks Like The Open-Source GPU Will Fail Again

Open Source Graphics Processor (GPU) by Francis Bruno — Kickstarter

Silicon Spectrumという会社が、FPGA上で2DのGPUを実装し、さらなる改良や3D機能の実装のために、三週間前からKickStarterでクラウドファンディングを募っていた。なんでも100万ドルの出資金が集まれば、さらなる改良もするし、ソースコードをLGPLv3で公開もするという。

先月の9日から始まっているので、今日で開始から25日目、締め切りまであと19日。今のところ集まったのは、たったの12440ドルだ。100万ドルには2桁も足りない。残りの98万ドルをポンと出す変人が19日以内に現れない限り、失敗する。

理由は色々と考えられる。自由なGPUにそれほど需要がないのかも知れない。動くものを公開しないで、将来の公開を約束しても、金が集まらないのかもしれない。

ただ、私が思うに、この試みが失敗した理由は、GPUが非力すぎる大昔の設計だからではないだろうか。

現時点でも、安価に手に入る、ドライバーから上は自由ソフトウェアで扱えるGPUより非力なのに、今後ますます他のGPUと性能差が開いていくとあっては、余程の自由ソフトウェア主義者しか興味を示さないだろう。

また、目標金額も多過ぎる。結局、ハードウェアはカネがかかるのだろう。

設計が公開された自由なGPUを作るというプロジェクトは、過去に何度も立ち上がっている。実装方法は様々で、専用の回路を製造するという方法もあれば、FPGA上で実装するというものもあった。いずれも、設計とかソフトウェアあたりまではそれなりに進むのだが、実ハードでの検証で躓く。やはり、カネがかかるのだろう。

自由なハードウェアが現れる日は来るのだろうか。

2013-11-02

DOOM 3 BFGの技術ノート

Doom3 BFG Documentation
Doom 3 BFG Technical Note

DOOM 3 BFGとは、2004年に発売された不自由なWindows用の、プログラムだけは自由なゲーム、DOOM 3を、最新のハードウェア用に移植したものである。id SoftwareのJ.M.P. van Waverenによって書かれた、移植のときの技術ノートが、とても興味深い。

まず、DOOM 3 BFGの移植は、結構難しかったらしい。というのも、オリジナルのDOOM 3は、2004年当時のローエンドからミドルエンドのハードウェアで、640x480で20fpsを出せるぐらいだった。これを、2012年のハードウェアで動くWindows、XBox360、PS3で、1280x720で安定して60FPSを出せるようにしなければならない。

DOOM 3は、当時としてはクソ重かった。技術的には野心的な作品だが、野心的すぎたために、見た目にしてはクソ重いという、アクション性が重要視されるゲームとしては最悪の出来だった。それに、ゲーム自体もあまり面白くなかった。私は、当時同時期に発売されたPainkillerこそが正統なDOOMとDOOM 2の後継であると思う。

それはともかく、解像度とFPSの差を考えると、DOOM 3 BFGは、現在のハードウェアで、当時の10倍速く走らなければならないということだ。

現在のハードウェアは、確かに当時より性能が上がっているが、その上がりぐらいは、バランスが良くない。

たとえばCPUは、サイクルあたりの命令実行数が上がった。これにより、性能は上がっているのだが、当時と比べて驚くほど上がっているわけではない。サイクル数はほとんど上がっていないからだ。もし、当時と同じペースでサイクル数が上がり続けていたら、今頃は近所のPCショップで10GHz超えのCPUがお手軽価格で買えたはずだ。

かわりに、最近のCPUはマルチコアになっている。ただし、これはプログラムを並列実行できるように書きなおさなければならない。オジリナルのDOOM 3は当時のハードウェアにあわせて、性能を必要とする処理はすべて単一のスレッドで実行されている。

一方、GPUの機能と性能は驚くほど向上した。もともとが極端な並列実行だったので、自然な発展だ。

まず問題になったのが、メモリだという。メモリ帯域はあまり向上していない。CPUやGPUの性能向上ほどメモリの性能は上がっていない。

例えばスキンメッシュだ。3Dモデルのアニメーションに合わせて大量の頂点、すなわち大量の浮動小数点数を、破綻しないように変更しなければならない。DOOM 3では、スキンメッシュはCPUで1フレームに一回だけ計算して、メモリに格納し、スキンメッシュが必要な場所で使っていたという。

ところが、メモリの性能がそれほど上がっていないために、これは現代のハードウェアでは、とても遅くなる。メモリの読み書きが発生すると、それだけでメモリ帯域を食うし、メモリキャッシュをふっとばすし、CPUとGPUの間のデータ転送の帯域も食う。

そこで、DOOM 3 BFGでは、計算済みのスキンメッシュをキャッシュせず、CPUだろうとGPUだろうと、スキンメッシュが必要なその場で計算をするのだという。現代のハードウェアでは、そもそもスキンメッシュをストリーミングする事自体にコストがかかり、ストリーミングしながら計算したところで、ストリーミングより遅くなることはないのだという。つまり、計算は無料なのだ。

これにより計算結果をメモリに書きだす必要もなくなり、貴重なメモリ帯域を節約できる。また、スキンメッシュが計算済みかどうかなどの「状態」をなくすことができ、管理する状態(state)を削減することに成功した。状態を減らす(stateless)ことは、並列処理にも都合がいい。

たとえば、DOOM 3 BFGでは至って普通のシーンである、影を落とす物体に影を落とす光源が二つあるといったようなシーンでは、1フレームあたり、CPUとGPUを合わせて、7回のスキンメッシュの計算を行わなければならない。DOOM 3では一回だけ計算してキャッシュしていたのにくらべると、実に7倍の計算量であり、当然、7倍のFLOPSが必要になるが、現代のハードウェアでは、むしろ速くなるのだという。

その他に変更したのは、データ構造だ。たとえば、DOOM 3では、独自実装の双方向リストを使っていた。

template< class type >
class idLinkList {
    idLinkList * head;
    idLinkList * next;
    idLinkList * prev;
    type * owner;
};

まあ、よくある形だ。これは、型の特殊化ごとにコードを生成してふくれ上がるという問題もあるがもっとも大きな問題は、双方向リストを管理するためのidlinkList<T>のメモリと、要素のtypeのメモリを、別々に確保することだ。

これは、キャッシュの都合上、とてもよろしくない。

DOOM 3 BFGでは、intrusiveな実装に書き換えたという。そのような実装では、typeにあたる要素の型はこういう形になる。

class idMyClass {
    bool valid;
    byte otherMembers[64];
    idMyClass * next;
};

このidMyClassのような型のオブジェクトは、配列としてメモリ上で連続した領域に確保される。idListは、その連続したメモリ上に確保されたオブジェクトへのインデックスを保持するようにした。これにより、要素の追加削除のたびにメモリの確保や解放がなくなり、またメモリが一箇所に集められることにより、キャッシュに乗りやすくなったという。

また、DOOM 3では、idHashTableもよく用いられていたが、この実装も、やはり管理するためのメモリと、要素のためのメモリは別々に確保されていたので、パフォーマンス上の問題があった。多くのハッシュテーブルの利用は、単にリストを使ってもパフォーマンス的に問題がないので、リストを使うようにしたという。また、どうしてもハッシュテーブルのパフォーマンス特性が欲しい場合でも、やはり連続したメモリ領域に確保された要素オブジェクトへのインデックスを保持するintrusiveな実装のidHashIndexを使ったという。

技術ノートでは結論として、DOOM 3を再び最適化することにより、現在のハードウェアの制約を見出したとしている。また、メモリキャッシュを意識することがとても重要だとしている。

この技術ノートを読んで、もはや現代のコンピューターの性能を、単に整数や浮動小数点数の演算能力で測るのは、もはや正しくないのではないかと思った。メモリ帯域とかストレージ帯域、あるいはネットワーク帯域などで測ったほうが、むしろいいのではないかという感想も持った。