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でいってみようか。