Home > Archives > 2010年09月

2010年09月

std::result_of 便利だなぁ

引数に関数オブジェクトを取るテンプレート関数の戻り値の型が,その引数の関数オブジェクトの戻り値の型に依存することはしばしばある(変なギミックの付いたライブラリとか書くと特に).関数プログラミングよろしく結果のオブジェクトを作って返すような関数を作っているときには戻り値の型をどうにか推論しないといけない.

んで,どうやって推論したもんかなぁとか思ってたら c++0x なら std::result_of が使えることを発見.これ使うと,例えば vector の要素に関数適用して新しい vector 返すとかいう関数がこう書ける(vector 返すとかバカなプログラムだなぁ.例だからいいか.):

template <typename F, typename A>
std::vector<typename std::result_of<F(A)>::type>
map(const F& f, const std::vector<A> &v)
{
  std::vector<typename std::result_of<F(A)>::type> r;
  for(auto it = v.begin(); it != v.end(); it++)
    r.push_back(f(*it));
  return r;
}

std::result_of 無しだと関数オブジェクトに戻り値の型をtypedefさせるかテンプレート引数増やして明示してもらうかしないとならんと思うので std::result_of は結構便利なんじゃないかと思った今日この頃.コードがすっきりしているかどうかは判断が難しいけど.

きれいなプログラマが欲しい

d 次元ベクトル n 本の和を求めるプログラムを書け.つまり,s と x_i をベクトルとして s = \SUM_{i = 0}^{n-1} x_i を計算せよ.ただし,d ≪ n とする.なお,後で和を求める部分を並列化する予定なのでそれを考慮してね.

という注文に対して,次のプログラムが返ってきた.

for(int j = 0; j < d; j++)
  for(int i = 0; i < n; i++)
     s[j] += x[i * d + j];

何故こうなった?

元々の計算式を元にプログラムの構造を考えればループの順番が不自然だと思うのだけど… 何故にわざわざベクトルの次元のループを外側に持ってきだのだろうか? 構造的に不自然な上に配列 x の読み込みが連続でなくて時間的にも不利になると思うのだけど.そして二つのループのうち並列化すべきは i のループなわけで,それが内側にあると下手すりゃ同期が増えて無駄なのに.こんなのは非効率かつ非明確なプログラムであって百害あって一利なし.

なんていうことを考えずにプログラムを書くのが普通なのだろうか? よくわからん.とりあえずきれいなプログラムを書く事を最優先して欲しい.

閑話休題.

効率改善のためにとある仕組みを導入しようとしている場合,その仕組みが本当に効率を上げられるのかどうかを事前にちゃんと考えて欲しい.効率改悪の仕組みとか入れてもしょうがないし,効率改善が出来ず無駄にプログラムを汚くしてもしょうがないし.

どこかに泉はないのだろうか?

Home > Archives > 2010年09月

Search
Feeds

Page Top