boost::threadのお勉強
遅ればせながらboost::threadでマルチスレッドのお勉強中なのです。
1.46.xのときは妙なメモリリークが消えなくて途中で投げ出したんだけど、(boost proが)1.47.0になったら解消したので、実験再開。
時間稼ぎに大きめのカーネルの畳み込みを試したら、8並列で6倍強の速度が出ました。
// threadtest set cores // #include "stdafx.h" #include <opencv/cxcore.h> #include <opencv/highgui.h> #include <iostream> #include <boost/bind.hpp> #include <boost/thread.hpp> using namespace std; using namespace boost; // 時間稼ぎに大きめのカーネルで畳み込み void convolution(IplImage *src, IplImage *dst, int core) { SetThreadAffinityMask(GetCurrentThread(), 1 << core); int K = 11, K2 = K * K; unsigned char *st, *dt; for (int y = K / 2; y < dst->height - K / 2; y++) { dt = (unsigned char*)(dst->imageData + y * dst->widthStep); for (int x = K / 2; x < dst->width - K / 2; x++) { int sum = 0; for (int yy = -K / 2; yy <= K / 2; yy++) { st = (unsigned char*)(src->imageData + (y + yy) * src->widthStep); for (int xx = -K / 2; xx <= K / 2; xx++) { sum += *(st + x + xx); } } sum /= K2; *(dt + x) = sum; } } return; } int _tmain(int argc, _TCHAR* argv[]) { int imageset = 100, cores = 8; if (argc >= 2) { imageset = _ttoi(argv[1]); } if (argc >= 3) { cores = _ttoi(argv[2]); } // 準備:必要な枚数の画像を用意 IplImage **src, **dst; try { src = new IplImage*[cores]; dst = new IplImage*[cores]; for (int i = 0; i < cores; i++) { src[i] = cvCreateImage(cvSize(1280, 1024), IPL_DEPTH_8U, 1); dst[i] = cvCreateImage(cvSize(1280, 1024), IPL_DEPTH_8U, 1); } } catch (bad_alloc& ) { cerr << "memory exhaust." << endl; return -1; } // 1スレッド処理 t.start(); for (int i = 0; i < imageset; i++) { for (int j = 0; j < cores; j++) { convolution(src[j], dst[j], j); } } cout << "single thread : " << t.get() << endl; // 複数スレッド実行 t.start(); for (int i = 0; i < imageset; i++) { thread_group tg; for (int j = 0; j < cores; j++) { tg.create_thread(bind(&convolution, src[j], dst[j], j)); } tg.join_all(); } cout << "multi thread : " << t.get() << endl; // 後始末:画像を開放 for (int i = 0; i < cores; i++) { cvReleaseImage(&src[i]); cvReleaseImage(&dst[i]); } delete [] src; delete [] dst; return 0; }
ニューラルネットみたいな、個々の演算量が極端に小さい場合の、create_threadのオーバーヘッドはどのぐらいになるかな。次の実験は小パッチのCNNでいってみようか。