並列思考によるソフトウェア開発

スレッド・プログラミング実践入門
Aug 5, 2011
ソフトウェア＆ソリューションズ統括部
ソフトウェア製品部

Intel、インテル、 Intel ロゴ、「Intel.さあ、その先へ。」ロゴ、Intel Core、MMX、Pentium、Xeon、VTune は、
アメリカ合衆国およびその他の国における Intel Corporation またはその子会社の商標または登録商標です。
© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

並列化の手順事例• アーキテクチャーのスレッド化とソフトウェア
開発との関係を示す• 時間のかかる領域をスレッド化するために必要な作業を素早くプロトタイプ作成し、計画できるようにする2

並列プログラミングの概念

並列化プログラミングで直面する 3 つの課題
• スケーラビリティー
• 正当性
• 容易な
プログラミングと保守

3スレッド化の例

Hello World
DWORD
WINAPI
HelloFunc(LPVOID)
DWORD
WINAPI
HelloFunc(LPVOID){{ cout << "Hello Thread¥n";returncout0;<< "Hello Thread¥n";}return 0;}

int main() {HANDLE hThread[numThreads];for (int i = 0; i < numThreads; i++)hThread[i] = CreateThread (NULL, 0, HelloFunc,
NULL, 0, NULL );for (int i = 0; i < numThreads; i++)// Clean up thread handles
hThread[i] = CreateThread (NULL, 0, HelloFunc,
for (int i = 0; i < numThreads; i++)
NULL, 0, NULL );CloseHandle (hThread[i]);// returnClean 0;up thread handles} for (int i = 0; i < numThreads; i++)
CloseHandle (hThread[i]);return 0;

4© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

スレッド化の例

Hello World（変更後）for (int i = 0; i < numThreads; i++)hThread[i] = CreateThread (NULL, 0, HelloFunc,
NULL, 0, NULL );getchar();// Clean up thread handles
for (int i = 0; i < numThreads; i++)
CloseHandle (hThread[i]);return 0;

サンプル・コードの変更“Hello World Thread <スレッド番号>” メッセージに変更するには？

5Hello World Thread #1
Hello World Thread #0.. .. .. ..
© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

並列プログラミングの概念

アムダールの法則
並列化のスピードアップ（スケーリング）の上限を説明
オーバーヘッドの影響を考慮する際に役立つ
n=2
0.5

0.0
0.25

P

Tparallel = {(1-P) + P/n + O} Tserial
P/2

n = プロセッサーの数

(1-P)

…

(1-P)

Tserial+P/

スケーリング = Tserial / Tparallel

1.0/0.75= 2.0
1.33
1.0/0.5 =シリアルコードがスケーリングを制限する
6© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

並列プログラミングの概念

並列プログラミング・モデル
機能分割
タスクの並列処理
同じ問題の独立したタスク
UI タスク、UI 更新、生産と消費のパラダイム
並列演算と次の表示タスク

データ分割
異なるデータで実行される同じ演算
例: 行列の乗算
7© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

並列プログラミングの概念

アプリケーションをスレッド化する際によくある質問•

どこをスレッド化すればいいのか?

•

スレッド化に必要な時間は?

•必要な再設計の回数は?

•選択した領域をスレッド化する価値はあるか?

•

どの程度のスピードアップを期待すべきか?

•

パフォーマンスは期待値を満たすことができるか?

•

プロセッサーを追加すれば性能が向上するか?

•

どのスレッドモデルを使用すべきか?

8© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

ケーススタディー

素数生成
main

FindPrimes(start,end)

TestForPrimes(number)NO

ShowProgress

YES
Increment Count9© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

ケーススタディー

素数生成

bool TestForPrime(int val){// let’s start checking from 3
int limit, factor = 3;
limit = (long)(sqrtf((float)val)+0.5f);
while( (factor <= limit) &&(val % factor))factor ++;

2
3 3
5 3,5
return (factor > limit);}
7 3,5,7
9 3
void FindPrimes(int start, int end){
11 3,5,7,9,11// start is always odd
13 3,5,7,9,11,13
int range = end - start + 1;
for( int i for(= start;i <= iend;
i+=i+=
2 2){){
int i = start;<= end;15 3
if( TestForPrime(i)) )if( TestForPrime(i)17 3,5,7,9,11,13,15,17
gPrimesFound++;gPrimesFound++;}ShowProgress(i, range);
ShowProgress(i,range);}}

10© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

ケーススタディー

ソフトウェア開発サイクル
解析と設計•インテル® VTune™ Amplifier XE•インテル® パフォーマンス・ライブラリー： IPP と MKL•OpenMP* , インテル® Cilk™ Plus (インテル® コンパイラー)•明示的なスレッディング (Win32*, Pthreads)•インテル® スレッディング・ビルディング・ブロック(TBB)•インテル® Parallel Advisor

正当性のデバッグ•インテル® Inspector XE•インテル・デバッガー

パフォーマンスのチューニング
•インテル® スレッディング・ビルディング・ブロック•インテル® VTune™ Amplifier XE

検証•インテル® Inspector XE

11© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

解析 － サンプリング
bool TestForPrime(int val)
{ // let’s start checking from 3
int limit, factor = 3;
limit = (long)(sqrtf((float)val)+0.5f);
while( (factor <= limit) &&(val % factor))factor ++;シングルスレッド “Prime” アプリケーションの解析にVTune™ Amplifier XE のサンプリングを使用する}

return (factor > limit);

void FindPrimes(int start, int end){// start is always odd
int range = end - start + 1;
for( int i = start; i <= end; i+= 2 ){if( TestForPrime(i) )gPrimesFound++;ShowProgress(i, range);}}

時間のかかる領域を特定する
12© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

解析 － 呼び出しツリー
スレッド化する呼び出
しツリーのレベル

スレッド化する呼び出しツリーのレベルを特定する
13© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

解析
どこをスレッド化すればいいのか?
FindPrimes()
選択した領域をスレッド化する価値はあるか?
依存関係が少ない
データを並列化できる
実行時間の多く（ 90% 以上）を占める

14© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

設計
予想されるメリットは?

スケーリング（２P） = 100/(100/2) = ~2.0 X（2: シングルコア DP もしくはデュアルコア・システムでの実行を想定）

最小限の作業で予想されるメリットを判断する方法は?

OpenMP* を使用した素早いプロトタイプ作成
スレッド化に必要な時間は?
必要な再設計の回数は?

15© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

OpenMP 入門

OpenMP*
Fork-join 型の並列処理:
マスタスレッドは必要に応じて、スレッドのチームを生成する
並列処理は徐々に追加される。つまり、逐次処理
プログラムは並列処理プログラムへ進化する

マスタ
スレッド
並列領域
16
© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

設計
#pragma omp parallel for
for( int i = start; i <= end; i+= 2 ){OpenMP*if( TestForPrime(i) )for ループでワークシェアを定義する

gPrimesFound++;

この並列領域のスレッドを
ShowProgress(i,range);
ここで作成する}

17© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

設計
予想されるメリットは?
最小限の作業で予想されるメリットを判断する方法は?

12.82 / 12.96 = 0.98 X のスケーリング
スレッド化に必要な時間は?
必要な再設計の回数は?
可能な最良のスケーリングか?

18© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

正当性のデバッグ

毎回答えが同じであるか?
このスレッドの実装は正しいか?

19© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

データ競合
複数のスレッドで同じ変数が同時にアクセスされること例:
a=1、b=2 （a、b はグローバル変数）の場合を考える
スレッド 1:
x=a+b;

スレッド 2:b = 42 ;x の値は?
スレッド1 をスレッド2 の前に実行した場合
スレッド1 をスレッド2 の後に実行した場合
スレッド1 をスレッド2 と同時に実行した場合
どのような場合に発生するか?

x=1+2 =3x = 1 + 42 = 4320
© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

正当性のデバッグ
インテル® Inspector XE は、データの競合、ストール、およびデッドロックなどのスレッド化の問題を正確に検出する
インテル® Inspector XE

Primes.exe

Primes.exe

バイナリー
インストルメント
ランタイム
データ
コレクター

（インストルメント済み）+DLL（インストルメント済み）

結果ファイル
21© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成インテル® Inspector XE で問題を検出

22© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

正当性のデバッグ#pragma omp parallel for
for( int i = start; i <= end; i+= 2 ){if( TestForPrime(i) )#pragma omp atomic
gPrimesFound++;

アトミック演算でインクリメントする

ShowProgress(i, range);}#pragma omp critical{

クリティカル・セクションを作成する

gProgress++;
percentDone = (int)(gProgress/range *200.0f+0.5f)}

23© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

正当性のデバッグ
スレッド化に必要な時間は?
必要な再設計の回数は?

インテル® Inspector XE で検出された依存関係は、2 つだけなので必要な作業は少ない

24© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

パフォーマンス
12.82 /13.04 = 0.98 X のパフォーマンスは最適か?
このアルゴリズムから期待できる最良のパフォーマンスか?

25© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

パフォーマンスのチューニング
インテル® VTune™ Amplifier XE は、スレッド化したアプリ
ケーションのパフォーマンス・ボトルネックを正確に検出する
インテル® VTune™ Amplifier XE

Primes.exe

バイナリー
インストルメント
ランタイム・
データ
コレクター

Primes.exe（インストルメント済み）+DLL（インストルメント済み）

結果ファイル26© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

なぜスケールしないか？

並列処理中の printf では、暗黙の同期が生じる
27© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

2 つのロックの影響

28© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

パフォーマンス
この実装には2つの同期呼び出しが含まれるよりコストが少ない同期方法はないか？
#pragma omp atomic#pragma omp critical

設計段階に戻る29© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成 － パス 2

設計
目標
Windows* API を使用して実装する
コンテンション（競合）を除去する
プログレス更新を別々のスレッドで行う必要がある
タスクの並列処理をデータの並列処理に導入する

30© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

一般的なパフォーマンス問題
•
•
•
•
•

並列化によるオーバーヘッド
スレッド作成によるスケジューリングなど
同期化
共有データの過度な使用、同じ同期化オブジェクトの競合
ロードバランス
ワークロードの不適切な配分
粒度
不十分な実行単位
その他の問題（VTune™ Amplifier XE）
メモリー帯域、フォルス・シェア

31© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成 － パス 2

タスクの並列処理の設計
ステップ 1: Win32 API を利用した素数生成のスレッド化
メインルーチンでスレッドを生成しワークロードを分散
for( int i = 0; i < nThreads; ++i ){data[i].start = newStart + i * range/nThreads;
data[i].end = data[i].start + range/nThreads;
if( (data[i].start % 2) == 0 )data[i].start += 1;
data[i].range = range;
data[i].thread = i;hThread[i]= CreateThread(NULL, 0, FindPrimes,(LPVOID)(&data[i]), 0, NULL);}
WaitForMultipleObjects(nThreads, hThread, TRUE, INFINITE);
for( i = 0; i < nThreads; ++i )primesFound += data[i].primesFound;32© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成 － パス 2

タスクの並列処理の設計
ステップ 1: Win32 API を利用した素数生成のスレッド化
スレッドルーチンで引数を受け取り展開
DWORD WINAPI FindPrimes(void *pData){
PrimeData *p = (PrimeData *)pData;for( int i = p->start; i < p->end; i += p->skip ){if( TestForPrime(i) )p->primesFound++;ShowProgress(i, p->range);}}

return 0;

33© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成 － パス 2

タスクの並列処理の設計
ステップ 2: プログレス更新へのタスクの並列処理の追加
メインルーチンでプログレス更新スレッドを生成
for( int i = 0; i < nThreads; ++i ){data[i].start = newStart + i * range/nThreads;
data[i].end = data[i].start + range/nThreads;
if( (data[i].start % 2) == 0 )data[i].start += 1;
data[i].range = range;
data[i].thread = i;hThread[i]= CreateThread(NULL, 0, FindPrimes,(LPVOID)(&data[i]), 0, NULL);}
hThread[i] = CreateThread(NULL, 0, ShowProgressThread,(LPVOID) range, 0, NULL);
WaitForMultipleObjects(nThreads, hThread, TRUE, INFINITE);

34© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成 － パス 2

タスクの並列処理の設計
ステップ 2: プログレス更新へのタスクの並列処理の追加
プログレス更新ルーチンで引数を展開
DWORD WINAPI ShowProgressThread(void *val){
int percentDone = 0, range = (int)val;
while( percentDone < 100 ){percentDone = (int)((float)gProgress/(float)range *200.0f + 0.5f);
printf("¥b¥b¥b¥b%3d%%", percentDone);}}return 0;35© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成 － パス 2

タスクの並列処理の設計
ステップ 2: プログレス更新へのタスクの並列処理の追加
FindPrimeスレッドルーチンで更新処理を変更
DWORD WINAPI FindPrimes(void *pData){
PrimeData *p = (PrimeData *)pData;for( int i = p->start; i < p->end; i += p->skip ){if( TestForPrime(i) )p->primesFound++;gProgress++;}}

return 0;36© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成 － パス 2

再設計された素数

スケーリングは 12.82 / 0.23 = 55.73 X
このアルゴリズムから期待できる最良のパフォーマンスか?

37© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成 － パス 2

設計 － レビュー
必要な再設計の回数は?

別々のスレッドへの I/O 処理の割り当ては簡単にでき、パフォーマンスが向上する

38© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成 － パス 2

正当性のデバッグの再確認

このバグは致命的か? このバグは修正可能か?

その前にパフォーマンスをチェック!
39© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成 － パス 2

パフォーマンス

明白なロード・インバランス。2 つのスレッドで負荷が異なっている

設計段階に戻る40© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成 － パス 3

設計の再確認目標：ロード・インバランスを解決する
データ分割のアルゴリズムを再確認して必要な変更を行う
for( int i = 0; i < nThreads; ++i ){data[i].start = newStart;
data[i].end = end;if( (data[i].start % 2) == 0 )data[i].start += 1;
data[i].range = range;
data[i].skip = 2 * nThreads;
data[i].thread = i;hThread[i]= CreateThread(NULL, 0, FindPrimes,(LPVOID) (&data[i]), 0, NULL);}

41© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成 － パス 3

設計の再確認目標：ロード・インバランスを解決する
データ分割のアルゴリズムを再確認して必要な変更を行う
DWORD WINAPI FindPrimes(void *pData){
PrimeData *p = (PrimeData *)pData;for( int i = p->start+2*p->thread; i < p->end; i += p->skip ){if( TestForPrime(i) )p->primesFound++;}}gProgress++;

return 0;42© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成 － パス 3

パフォーマンスの再確認

パフォーマンスのスケーリングは12.82 /0.19 = 67.47 X
このアルゴリズムはプロセッサーが増加すると適切にスケールするか？
43© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成 － パス 3

パフォーマンス

ロード・インバランスが解決されている。

44© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

比較解析

プログレス更新
スレッドを使用した場合

シリアル

ロードバランスを改善した場合OpenMP*45© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

素数生成

比較解析
55.73 X

67.47 X

アプリケーションをスレッド化するには、ソフトウェア
開発サイクル全体を何度も繰り返す必要がある
46© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

要点の繰り返し

質問の再確認
•
•
•
•
•
•
•
•

どこをスレッド化すればいいのか?
選択した領域をスレッド化する価値はあるか?
スレッド化に必要な時間は?
必要な再設計の回数は?
どの程度のスピードアップを期待すべきか?
パフォーマンスは期待値を満たすことができるか?
プロセッサーを追加すれば性能が向上するか?
どのスレッドモデルを使用すべきか?

47© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

まとめ
•

•
•

アプリケーションをスレッド化するには、設計、デバッグ、およびパフォーマンスのチューニングサイクルを何度も繰り返す必要があるツールを使用することで生産性を向上できる
デュアルコアおよびマルチコア・プロセッサーの能力を引き出す48© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

参考資料

49
© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

InterlockedIncrement（） を利用#pragma omp parallel for
for( int i = start; i <= end; i += 2 ) {if( TestForPrime(i) ) {globalPrimes[InterlockedIncrement((LPLONG)&gPrimesFound)] = i;}
ShowProgress(i, range);}

void ShowProgress( int val, int range ){….
long localProgress;
localProgress = InterlockedIncrement((LPLONG)&gProgress);
percentDone = (int)((float)localProgress/(float)range *200.0f + 0.5f);….
}

3.08/0.53 = 5.81X のスケーリング

スケーリングは最善か？
50© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

インテル® VTune™ Amplifier XE:
ネイティブ・スレッド
スレッドの動きを理解する
シリアル・パフォーマンス
プログラム中で最適化により最も恩恵を受けられるシリアル処理のコードを特定する
パラレル・パフォーマンス
演算リソースを完全に利用するような、並列化レベ
ルの目標を設定

51© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

並列化によるオーバーヘッド
スレッド生成のオーバーヘッド
アクティブなスレッドの数の増加に従ってオーバー
ヘッドは急激に増加する

ソリューション
再使用可能なスレッドやスレッドプールを使用する
スレッド作成によるオーバーヘッドを吸収する
アクティブなスレッドの数を相対的に一定にする

52© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

同期•

ヒープ・コンテンション
ヒープからの割り当ては暗黙的な同期化を引き起こす
スタックに割り当てるか、スレッドローカル格納領域を利用•

アトミック更新とクリティカル・セクション
単純な共有データの更新ではアトミック演算（インターロッ
ク・ファミリー）を利用できる。可能な場合は常にアトミック更新を利用する•

クリティカル・セクションと mutex
クリティカル・セクション・オブジェクトはユーザー空間に存在する。プロセス境界を超える可視性が必要ないときにクリティカル・セクション・オブジェクトを利用する。より少ない
オーバーヘッド
いくつかのアプリケーションで便利な可変スピンウェイト53© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

ロード・インバランス
不適切なワークロードはアイドルスレッドや時間の浪費の原因となる

時間

ビジー
アイドル

54
© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

粒度
粗粒度

比率: ~2.5X~3X
シリアル

並列化可能な部分

細粒度

シリアル

並列化可能な部分

比率: ~1.10X~1.05X

55© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

最適化に関する注意事項

インテル® コンパイラー、関連ライブラリーおよび関連開発ツールには、インテル製マイクロプロセッサーおよび互換
マイクロプロセッサーで利用可能な命令セット（ SIMD 命令セットなど） 向けの最適化オプションが含まれているか、あるいはオプションを利用している可能性がありますが、両者では結果が異なります。また、インテル® コンパイラー用の特定のコンパイラー・オプション（ インテル® マイクロアーキテクチャーに非固有のオプションを含む） は、インテル
製マイクロプロセッサー向けに予約されています。これらのコンパイラー・オプションと関連する命令セットおよび特定のマイクロプロセッサーの詳細は、『インテル® コンパイラー・ユーザー・リファレンス・ガイド』の「コンパイラー・オプション」を参照してください。インテル® コンパイラー製品のライブラリー・ルーチンの多くは、互換マイクロプロセッサーよりもインテル製マイクロプロセッサーでより高度に最適化されます。インテル® コンパイラー製品のライブラリー・ルーチ
ンの多くは、互換マイクロプロセッサーよりもインテル製マイクロプロセッサーでより高度に最適化されます。インテル® コンパイラー製品のコンパイラーとライブラリーは、選択されたオプション、コード、およびその他の要因に基づいてインテル製マイクロプロセッサーおよび互換マイクロプロセッサー向けに最適化されますが、インテル製マイクロプロ
セッサーにおいてより優れたパフォーマンスが得られる傾向にあります。
インテル® コンパイラー、関連ライブラリーおよび関連開発ツールは、互換マイクロプロセッサー向けには、インテル
製マイクロプロセッサー向けと同等レベルの最適化が行われない可能性があります。これには、インテル® ストリーミ
ング SIMD 拡張命令 2（ インテル® SSE2）、インテル® ストリーミング SIMD 拡張命令 3（ インテル® SSE3）、ストリーミン
グ SIMD 拡張命令 3 補足命令 (SSSE3) 命令セットに関連する最適化およびその他の最適化が含まれます。
インテルでは、インテル製ではないマイクロプロセッサーに対して、最適化の提供、機能、効果を保証していません。
本製品のマイクロプロセッサー固有の最適化は、インテル製マイクロプロセッサーでの使用を目的としています。インテルでは、インテル® コンパイラーおよびライブラリーがインテル製マイクロプロセッサーおよび互換マイクロプロセッ
サーにおいて、優れたパフォーマンスを引き出すのに役立つ選択肢であると信じておりますが、お客様の要件に最適なコンパイラーを選択いただくよう、他のコンパイラーの評価を行うことを推奨しています。インテルでは、あらゆるコ
ンパイラーやライブラリーで優れたパフォーマンスが引き出され、お客様のビジネスの成功のお役に立ちたいと願っております。お気づきの点がございましたら、お知らせください。
改訂 #20110307

58© 2011 Intel Corporation. 無断での引用、転載を禁じます。 記載内容は予告なしに変更されることがあります。
＊その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。