私はこのテストアプリケーションを作成しました。0から9999までの反復を経て、範囲内の整数ごとに、役に立たないが計算集約的な関数を計算します。その結果、プログラムは関数値の合計を出力します。複数のスレッドで実行するために、InterlockedIncrementを使用しています。増分後に反復回数が10000未満の場合、スレッドはこの反復を処理します。それ以外の場合は終了します。
なぜそれが私が望むほどスケーリングしていないのか疑問に思います。5スレッドの場合、1スレッドの場合は36秒であるのに対し、8秒で実行されます。これにより、最大4.5のスケーラビリティが得られます。OpenMPを使った実験中(わずかに異なる問題で)、スケーラビリティが大幅に向上しました。
ソースコードを以下に示します。
PhenomIIX6デスクトップでWindows7OSを実行しています。他にどのようなパラメータが関連しているのかわからない。
この最適ではないスケーラビリティについて説明していただけませんか。どうもありがとう。
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <vector>
#include <windows.h>
#include <iostream>
#include <cmath>
using namespace std;
using namespace boost;
struct sThreadData
{
sThreadData() : iterCount(0), value( 0.0 ) {}
unsigned iterCount;
double value;
};
volatile LONG g_globalCounter;
const LONG g_maxIter = 10000;
void ThreadProc( shared_ptr<sThreadData> data )
{
double threadValue = 0.0;
unsigned threadCount = 0;
while( true )
{
LONG iterIndex = InterlockedIncrement( &g_globalCounter );
if( iterIndex >= g_maxIter )
break;
++threadCount;
double value = iterIndex * 0.12345777;
for( unsigned i = 0; i < 100000; ++i )
value = sqrt( value * log(1.0 + value) );
threadValue += value;
}
data->value = threadValue;
data->iterCount = threadCount;
}
int main()
{
const unsigned threadCount = 1;
vector< shared_ptr<sThreadData> > threadData;
for( unsigned i = 0; i < threadCount; ++i )
threadData.push_back( make_shared<sThreadData>() );
g_globalCounter = 0;
DWORD t1 = GetTickCount();
vector< shared_ptr<thread> > threads;
for( unsigned i = 0; i < threadCount; ++i )
threads.push_back( make_shared<thread>( &ThreadProc, threadData[i] ) );
double sum = 0.0;
for( unsigned i = 0; i < threadData.size(); ++i )
{
threads[i]->join();
sum += threadData[i]->value;
}
DWORD t2 = GetTickCount();
cout << "T=" << static_cast<double>(t2 - t1) / 1000.0 << "s\n";
cout << "Sum= " << sum << "\n";
for( unsigned i = 0; i < threadData.size(); ++i )
cout << threadData[i]->iterCount << "\n";
return 0;
}
編集:このテストプログラムのサンプル出力を添付します(1および5スレッド):