No Such Blog or Diary

«Prev || 1 | 2 | 3 |...| 6 | 7 | 8 |...| 57 | 58 | 59 || Next»

即席ラーメンタイマー in bash

あらかじめ .bashrc に次を追加しておく.

function timer { sleep $1; while true; do echo -e -n '\a'; sleep 1; done }

1. カップラーメンに湯を注ぐ.

1.5 必要ならターミナルを起動.

2. 好みの時間(秒数)にタイマーセット.

timer 165

3. 時間が来たらビープでお知らせがくるのでのびる前に食べれ.

C言語のクイズ

適当なXを持ってきて以下の二つの文が等価でないことを示せ:

X += e;
X = X + e;

まあ,副作用のある関数 f の呼び出しを X に上手く入れられれば等価でないことを言えるのだけど,単純に X を f() にしただけでは左辺値じゃないと怒られる.何かでくるんで左辺値にすればオッケー.

f()を含んだ左辺値になる式は色々あるけれど,例えば配列へのアクセス a[f()] なんてのはその候補.さて,では,そのような式の中で最小のものは何なんだろうか? ゴルフする人間としては気になる.

で,さっき思いついたけど,ポインタを返す副作用のある関数 f を持ってきて X に *f() を入れれば以下の二つの文は等価じゃない.

 *f() += e;
 *f() = *f() + e;

これが最小の解なのだろうか?

lastprivate の罠

OpenMP の parallel for でローカルの値を外に持ち出す指定のひとつ lastprivate の意味を間違って覚えていると罠にハマる.last private であって last assigned private ではなかった.

下のようなプログラムを書いた.いつでも 2 が表示されて欲しい,つまり,lastprivate指定の変数は最後に代入された値を外に持ち出してくれると期待していた.

#include <omp.h>
#include <iostream>
 
struct mystruct {
  int f;
  mystruct() : f(-1) {}
  mystruct(int f) : f(f) {}
};
 
int main(int argc, char *argv[])
{
  mystruct ms(1);
#pragma omp parallel for lastprivate(ms)
  for(int i = 0; i < 4; i++) {
    if(i == 2) {
      mystruct msi(2);
      ms = msi;
    }
  }
  std::cout << ms.f << std::endl;  
  return 0;
}

が,実行してみると以下のような結果になった.

> OMP_NUM_THREADS=1 ./lastprivate 
2
> OMP_NUM_THREADS=2 ./lastprivate 
2
> OMP_NUM_THREADS=3 ./lastprivate 
2
> OMP_NUM_THREADS=4 ./lastprivate 
-1

何かというと,lastprivate指定の変数は最後のプロセスの持つローカルな値をグローバルにコピーしてループを終了する,という仕組みであったと.確かにOpenMPの仕様にはそう書いてあるし,逐次実行時に最後に実行される反復で値を代入しない場合にはオブジェクトの初期値になっちゃうよ,とも書いてある.上のプログラムでの最終反復(i = 3)では変数 ms に値が代入されないため,その初期値(-1)になってループ終了と.

うーん,find みたいに最後に条件を満たすインデックスを探すとかいうループすらもOpenMPだと簡単に書けないのか… (FORTRAN なら MAX での reduction 指定ができるので可能だけど).

lastassignedprivate とかいうディレクティブの方が使い勝手が良いと思うのは気のせいだろうか? 変数についてフラグ一個持てば直ぐに実装できるのに… とりあえず OpenMP の reduction の制限がきつすぎるのが良くない.

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 のループなわけで,それが内側にあると下手すりゃ同期が増えて無駄なのに.こんなのは非効率かつ非明確なプログラムであって百害あって一利なし.

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

閑話休題.

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

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

やっぱりわからん

C++で,与えられたクラスがとあるメソッドを実装しているか否かを判定したかったのだけど結局適切な方法が分からず.http://stackoverflow.com/questions/257288/possible-for-c-template-to-check-for-a-functions-existence とか見てテンプレート化されてないメソッドの存在判定はできるようになったのだけど,テンプレート化されたメソッドの存在判定がうまくできないというオチ.

まだまだC++力が足りない今日この頃.

«Prev || 1 | 2 | 3 |...| 6 | 7 | 8 |...| 57 | 58 | 59 || Next»
Search
Feeds

Page Top