stdio.hとmpi.hの順番によるエラー
mpiccとかmpiiccとかで以下のようなプログラムをコンパイルする時、stdio.hとmpi.hの順番を変えろ、というエラーが出る事がある。
#include <stdio.h> #include <mpi.h> int main(void){ printf("Hello\n"); }
$ mpiicc test.cc /opt/intel/impi/4.1.0.030/intel64/include/mpicxx.h(95): catastrophic error: #error directive: "SEEK_SET is #defined but must not be for the C++ binding of MPI. Include mpi.h before stdio.h" #error "SEEK_SET is #defined but must not be for the C++ binding of MPI. Include mpi.h before stdio.h" ^ compilation aborted for test.cc (code 4)
指示通り、mpi.hとstdio.hを入換えても良いのだが、大きなコードでそれをやるのは面倒。-DMPICH_IGNORE_CXX_SEEKオプションをつけてコンパイルすると、このエラーは出ない。
$ mpiicc -DMPICH_IGNORE_CXX_SEEK test.cc
コンストラクタを持つクラスの配列
コンストラクタに引数が必要なクラスを配列で宣言する時、どうやってその引数を渡すのかわからなかったんだけど、こうすればできた。
class Test{ public: const int value; Test (int i) : value(i) {}; }; int main(void){ Test c[3] = {1,2,3}; printf("%d %d %d\n",c[0].value, c[1].value, c[2].value); }
$ c++ test.cc $ ./a.out 1 2 3
RubyからMac OS Xのスクリーンショットを撮る
RubyからCocoaを叩いてMac OS Xのスクリーンショットを撮るサンプル。
$ sudo port install rb-cocoa
を実行すること。
なぜか「全体のスクリーンのRect」を意味するOSX::CGRectInfinite定数が見つからなかったので、 OSX::NSScreen.screensで、スクリーンリストを取得、その0番目が全体スクリーンなので、そのframeを手に入れ、 そのwidthとheightからOSX::CGRectを作成、そいつをCGWindowListCreateImageの引数に入れて呼んでいる。
require 'osx/cocoa' f = OSX::NSScreen.screens[0].frame cr = OSX::CGRectMake(0,0,f.width,f.height) screenshot = OSX::CGWindowListCreateImage(cr, OSX::KCGWindowListOptionOnScreenOnly, OSX::KCGNullWindowID, OSX::KCGWindowImageDefault) c = OSX::CIImage.imageWithCGImage(screenshot) bitmaprep = OSX::NSBitmapImageRep.alloc.initWithCIImage(c) blob = bitmaprep.representationUsingType_properties(OSX::NSJPEGFileType,nil) blob.writeToFile_atomically("test.jpg",false)
スクリーンショットはNSObject。これをCIImageを経由してNSBitmapImageRepにして、ファイルタイプにJPGを指定してからファイル名を指定して保存する。
Lion + OpenMPのバグ?
Mac OS X 10.7.4 (Lion) + gcc 4.2.1 で、OpenMPがたまにバグる。
エラーメッセージは以下のような感じ。
===================================================================================== = BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES = EXIT CODE: 6 = CLEANING UP REMAINING PROCESSES = YOU CAN IGNORE THE BELOW CLEANUP MESSAGES ===================================================================================== APPLICATION TERMINATED WITH THE EXIT STRING: Abort trap: 6 (signal 6)
gdbで見たらこんな感じ。
Program received signal SIGABRT, Aborted. 0x00007fff88389bf2 in __psynch_mutexwait () (gdb) up #1 0x00007fff867281a1 in pthread_mutex_lock () (gdb) up #2 0x00000001000022c4 in gomp_barrier_destroy () (gdb) up #3 0x0000000100001f5b in gomp_team_end ()
まだよくわからないが、Snow Leopardでは問題が生じないのでOS 依存の可能性あり。ちなみにgccのバージョンは4.2.1。
$ mpic++ --version i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00) Copyright (C) 2007 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
'Hoge::v' is not a variable in clause 'shared'
C++でOpemMP並列をする際、
error: 'Hoge::v' is not a variable in clause 'shared'
というエラーが出る事がある。これは、クラスのメンバ変数をshared指定しようとした時のエラー。例えば以下がサンプル。
#include <iostream> #include <omp.h> #include <vector> class Hoge{ private: std::vector<int> v; public: void func(void){ int tid; #pragma omp parallel shared(v) private(tid) { tid = omp_get_thread_num(); #pragma omp critical v.push_back(tid); } for(int i=0;i<v.size();i++){ std::cout << v[i] << std::endl; } }; }; int main(void){ Hoge h; h.func(); }
これをコンパイルすると、
test.cc: In member function 'void Hoge::func()': test.cc:10: error: 'Hoge::v' is not a variable in clause 'shared'
こんなエラーがでる。調べてみたが、どうもクラスのメンバ変数をshared指定できないようなので、一度別のテンポラリ変数を使って後でコピーするしかないらしい。こんな感じ。
#include <iostream> #include <omp.h> #include <vector> class Hoge{ private: std::vector<int> v; public: void func(void){ int tid; std::vector<int> vtmp; #pragma omp parallel shared(vtmp) private(tid) { tid = omp_get_thread_num(); #pragma omp critical vtmp.push_back(tid); } for(int i=0;i<vtmp.size();i++){ v.push_back(vtmp[i]); } for(int i=0;i<v.size();i++){ std::cout << v[i] << std::endl; } }; }; int main(void){ Hoge h; h.func(); }
実行結果。
$ g++ -fopenmp test.cc $ export OMP_NUM_THREADS=4;./a.out 2 1 0 3