折角たくさんコアがあるけど、並列プログラミングは面倒だという方に指示されているのかどうか解りませんが、OpenMPを使ったときのメモを。
#ifdef _OPENMP #pragma omp parallel #endif for( int i = 0; i < permu_cnt; ++i){ ... などとすると、マルチコア化されるという魔法のような話です。 スレッド数は環境変数OMP_NUM_THREADSで設定できます。GNU g++は4.2からOpenMPに正式対応したということですが、手元にIntel C++ Compiler11.0があったので、これでコンパイルしました。 言われたとおり、 -openmp ってつけたらコンパイルは出来たのに、実行すると、 dyld: Library not loaded: libiomp5.dylib Referenced from: /Users/***呼び出し元のバイナリ*** Reason: image not found Trace/BPT trap というエラーが・・・ /opt/intel/Compiler/11.0/056/lib に、libiomp5.dylibがあったので、LD_LIBRARY_PATHに追加すればいいのか?と思ってやってみるも失敗。 あり?と少し悩みましたが、iccのコンパイルオプションに、 -static-intel を追加すればOKです。 なんか、とりあえずマルチスレッドで動いてます。8コアMacProなので、5コアくらい使って5倍になったらいいかなというところです。 スポンサーサイト
|
terminate called after throwing an instance of 'boost::exception_detail::clone_impl
what(): boost::bad_any_cast: failed conversion using boost::any_cast Abort trap Boostのprogram_optionsで、たとえば以下のようにしてvmを用意したとします。 variables_map vm; store(po::parse_command_line(argc, argv, opt), vm); notify(vm); vm["data"]などとして、コマンドライン引数にアクセスしますが、これがあらかじめ指定されたものではないと、冒頭のエラーが出ます。 自分でもよく忘れるので、こうしてGoogleに覚えておいてもらおうとメモしてみました。 |
C++もSTLやBoostを使うと、横着なプログラムが書けるので好きなのですが、ちょっとしたシミュレーションなどでぼけーっと適当なプログラムを書いていると、実行時のメモリ消費量が4Gを超えてしまい、code=12でmallocエラーが出てしまって、寂しい思いをしたりします。
g++でコンパイルするとき、-m64オプションを付ければ、プログラム自体はすぐに64ビット化できるのですが、Boostのライブラリ(program optionsなので動作に関係はないのですが・・・)を使っていて、これを32bitでビルドしていると、リンクできずにコンパイルに失敗します。 というわけで、Boostのビルドが必要なライブラリの64bit版がほしくなって、作ってみました。 ~/Downloads/boost_1_37_0$ あたりで、 ./configure --prefix=/usr/local/lib/x86_64 これで、自動的にtools/jam/src/bin.macosxx86/bjamがbuildされます。 直接bjamを使ってもよいのですが、せっかくMakefileがあるので、これを変更します。 2行目の BJAM_CONFIG= を、以下のように変更します。 BJAM_CONFIG=address-model=64 architecture=x86 これで、あとは普通に make sudo make install でOKです。 できるファイルは、32bit版と同じ名前になるので、ディレクトリで分けておいた方がいいかもしれません。 /usr/local/lib/x86_64/lib となって、なんか、かっこ悪いですが・・・ ちなみに、BoostのPython関係のライブラリのビルドには失敗します。 Pythonが64bitじゃないからかなーと勝手に思っていますが、原因を究明する元気がありません。 まあ、32ビット版使えばいいし。 |
C++でコマンドラインから起動するプログラムを作っていると、やっぱり引数をパースしてくれるライブラリが欲しくなります。少し探したら、さすがboost。ありました。boost.program_optionsを使えばよいようです。
#include <boost/program_options.hpp> namespace po = boost::program_options; int main (int argc, char **argv) { po::options_description opt("options"); opt.add_options() ("help,h","display this help") ("data,d",po::value<string>(),"data file") ("cls,c",po::value<string>(),"class file") ("trees,t",po::value<int>()->default_value(100000), "number of trees (default=100,000)") ("M,m", po::value<int>(), "m (default=sqrt(number of attributes)") ("prefix,p", po::value<string>(), "prefix of output files") ("attr_list,al", po::value<string>(), "list of attributes (file with no header)") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, opt), vm); po::notify(vm); string data_file; string cls_file; if( vm.count("help") || !vm.count("data") ){ cout << opt << endl; // ヘルプ表示 return 0; }else{ //プログラムの実行のための準備 data_file = vm["data"].as<string>(); cls_file = vm["cls"].as<string>(); } なんとなく、見ればわかると思います。add_optionsで追加するとき、最初に書くのが正式名称で、カンマで区切って省略形です。実際に使うときは、--data=で指定するか、-d で指定するかですね。 プログラムの中でアクセスするときは、正式名称で。省略形は、1文字のみです。省略形では、スペースや=などを使わず続けて書くことが出来ます。 ただ、boost_optionsを使おうと思うと、boostをビルドする必要があります。 Unix系OSとCygwinでは簡単です。Windowsではいろいろ面倒がありそうですが・・・ boostを展開したディレクトリで、 ./configure make make install です。/usr/localなどにboostのヘッダファイルをインストールしている場合など、書き込み権限があるか確認してください。また、configureのオプションでインストール先を変更することも可能です。私は、MacOSでsudoつけただけですが。 ~$ g++ -I /usr/local/include/boost-1_34_1/ ***.cpp /usr/local/lib/libboost_program_options.a でコンパイル出来ます。コマンドライン引数のヘルプを半ば自動で生成してくれるので楽です。 options: -h [ --help ] display this help -d [ --data ] arg data file -c [ --cls ] arg class file -t [ --trees ] arg (=100000) number of trees (default=100,000) -m [ --M ] arg m (default=sqrt(number of attributes) -p [ --prefix ] arg prefix of output files -a [ --attr_list ] arg list of attributes (file with no header) ちなみに、Pythonで似たようなことを実現してくれるモジュールに、getoptとoptparseモジュールがありますが、optparseの方が現代的(オブジェクト指向由来の発想)なので、後者のほうがいいでしょう。 |
Pythonでは、どうしても速度が出ないところを最近、C++で書いてます。8年ぶりに触ってみると、STLが当たり前になったり、Boostが便利だったりで、かなり心地いいですが、どうしても方言みたいなものが出てきてしまいます。少しはまったので、メモっておきます。
vectorをかき混ぜるのに、random_shuffleという関数が、algorithmの中に定義されています。その他、random_sampleとrandom_sample_nというのもあるように見えるのですが、実はこれは、SGIによる拡張らしく、標準ではないらしい。 gcc バージョン 4.1.3で、試したのは、algorithmの代わりに、ext/algorithmをincludeする方法です。うまくいきますが、なんだかなー。誰も教えてくれないし。 やっぱり、C++は世界が巨大すぎるか?時代は、Dなんじゃないでしょうか?そのうち触ってみます。 |
| ホーム |
|