- ベストアンサー
マルチスレッド環境での配列使用について
現在、C++を利用してマルチスレッド環境の開発を行っています。 マルチスレッドで排他的に変数を扱う場合、クリティカルセクションや ミューテックスを使用することで、排他制御をおこなうことができますが、 このように、配列の要素ごとに排他制御を行うことは可能でしょうか? たとえば、 int ary[10]; のような配列があれば、a[0]~a[9]まで要素をそれぞれ排他制御によって データの矛盾を避けたいと考えています。 パフォーマンスの関係上、できるだけ、配列全体をロックするのは避けたいと 思っています。 どうぞよろしくお願いします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
マルチスレッド環境での効率的な短時間のin-memory排他的処理は、 次のような形で実現可能です。 H/W命令として cswap: compare and swap 或いは相当の命令がpowerpc,intel他最近の machineでサポートされているので、それを有効活用します。 http://ja.wikipedia.org/wiki/コンペア・アンド・スワップ H/W 命令については 例えば "instruction manual cmpxchg intel"でサーチ下さい。 Intel(R) Architecture Software Developer's Manual, Volume 2: Instruction Set Reference Manual lock-cmpxchg サブルーチン実装例については google code search でサーチ下さい。 http://www.google.com/codesearch/advanced_code_search "compare and swap" lang:c++ etc. "cmpxchg" lang:assembly etc. 概略の動作は次のような形で実現します。 C++は使っていないので次は擬似コーディングとして参照下さい。 data-blockに関してのlockが必要な場合、int ary[i]相当のlockwordを data-blockとは別に設けて、そのlockwordにより排他制御を実現します。 data update: loop: xold = ary[i]; // generate new data xnew = xold +delta; // xprev = cswapsub(&ary[i],xold,xnew); if (xprev!=xold) { // call delay_sub to suppress excessive cswap contention; // about 500-inst. or 0.5microsec // (about 10*lock-cmpxchg inst.time ?) // try to avoid memory store in loop as much as possible goto loop; } ... data reference: loop: xold = ary[i]; ... data handling // reference xprev = cswapsub(&ary[i],xold,xold); // check ary[i] data same while processing if (xprev!=xold) { // call delay_sub to suppress excessive cswap contention; // about 500-inst. or 0.5microsec // try to avoid memory store in loop as much as possible } int cswapsub(int* &data, olddata, newdata) { ... }
その他の回答 (2)
- machongola
- ベストアンサー率60% (434/720)
こんばんは。windowsで良ければ、 「InterlockedExchange()API」 http://msdn.microsoft.com/ja-jp/library/cc429230.aspx を使用するか、配列の個数分クリティカルセクションリソースを用意して、各要素に応じたクリティカルセクションリソースをロックすれば出来ると思います。 アラもあるとは思いますので、以下参考程度に(InterlockedExchangeの方です)。 // consoe.cpp : コンソール アプリケーションのエントリ ポイントを定義します。 // #include "stdafx.h" #define NOMINMAX #include <windows.h> #include <process.h> #include <iostream> #include <algorithm> #include <cmath> static const int NUMARR = 10; static const int NUMTHREAD = 2; unsigned WINAPI ThreadA(void* p) { LPLONG a = static_cast<LPLONG>(p); for(int i = 0; i < 12000; ++i) { for(int n = 0; n < NUMARR; n += 2) { const LONG v = ::InterlockedExchange(&a[n], 0); ::InterlockedExchange(&a[n], v + (std::rand() % 100)); } ::Sleep(0); } return 0; } unsigned WINAPI ThreadB(void* p) { LPLONG a = static_cast<LPLONG>(p); for(int i = 0; i < 25000; ++i) { for(int n = 1; n < NUMARR; n += 2) { const LONG v = ::InterlockedExchange(&a[n - 1], 0); ::InterlockedExchange(&a[n - 1], v); ::InterlockedExchange(&a[n], v / std::max(std::rand() % 100, 1)); } ::Sleep(0); } return 0; } int _tmain(int argc, _TCHAR* argv[]) { LONG a[NUMARR] = {0,0,0,0,0,0,0,0,0,0}; HANDLE threads[NUMTHREAD] = { reinterpret_cast<HANDLE>(::_beginthreadex(NULL, 0, &::ThreadA, a, 0, NULL)), reinterpret_cast<HANDLE>(::_beginthreadex(NULL, 0, &::ThreadB, a, 0, NULL)), }; ::WaitForMultipleObjects(NUMTHREAD, threads, TRUE, INFINITE); for(int i = 0; i < NUMTHREAD; ++i) ::CloseHandle(threads[i]); for(int i = 0; i < NUMARR; ++i) std::cout << "a[" << i << "] = " << a[i] << std::endl; return 0; }
- επιστημη(@episteme)
- ベストアンサー率46% (546/1184)
できますよ、配列に見せかけたクラスを作ればいい。