検索スペースをn個に分割するn回検索のコードを記述しています。 並列コードとOpenMPディレクティブがないコード、すなわちシリアル実行を比較すると、並列コードはシリアルコードよりも何度も遅いことがわかりました。両方のプログラムを何度も実行した後は、並列コードでスピードアップはほとんど見られませんでしたが、毎回ではありませんでした。これはおそらくキャッシュの階層構造によるものです。私は4GBのRAMを搭載したクアッドコアプロセッサでプログラムを実行しています。OpenMPを使用したn回検索の高速化なし
答えによるとNo speedup with OpenMPメモリバインドされたパフォーマンスとロードバランシングは、配列SIZE 100
などの小さな問題には適用されません。私は同期を使用していません。配列サイズを10000000に増やしてみましたが、パラレルコードの出力が必ずしも速くはありません。多くの場合、シリアルコードはパラレルコードよりも優れています。
によるhttp://pages.tacc.utexas.edu/~eijkhout/pcse/html/omp-loop.htmlワークシェアリングコンストラクトの最後の暗黙のバリアは、nowait
句で取り消すことができます。私もnowait
節を追加しようとしましたが、私もhttps://software.intel.com/en-us/articles/openmp-loop-schedulingを参照してスケジュール(動的)とスケジュール(自動)を試みましたが、それでも同じ問題がありました。
コード:
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#define SIZE 100
#define NUM_THREADS 4
int* a;
int num;
void nary(int num)
{
int found = 0, low = 0, high = SIZE, step;
int i = 0;
while(!found && low <= high)
{
step = (high-low)/NUM_THREADS;
printf("Low :- %d\tHigh :- %d\tStep :- %d\n", low,high,step);
printf("\n");
#pragma omp parallel for num_threads(NUM_THREADS) shared(low,high,step)
for (i = 0; i < NUM_THREADS; ++i)
{
printf("First element :- %d by thread :- %d\n", a[low+step*i],omp_get_thread_num());
if (a[low+step*i] == num)
{
found = 1;
}
}
printf("\n");
/* First block */
if (a[low+step] > num)
{
high = low + step - 1;
printf("First \nLow :- %d \nHigh :- %d\n\n",low,high);
}
/* Last block */
else if (a[low+step*(NUM_THREADS-1)] < num)
{
low = low + step * (NUM_THREADS-1) + 1;
printf("Last\nLow :- %d \nHigh :- %d\n\n",low,high);
}
/* Middle blocks */
else{
#pragma omp parallel for num_threads(NUM_THREADS) schedule(static) shared(low,high,step)
for (i = 1; i < (NUM_THREADS-1); ++i)
{
if (a[low+step*i] < num && a[low+step*(i+1)] > num)
{
low = low + step*i + 1;
high = low + step*(i+1) - 1;
}
}
printf("middle\nLow :- %d \nHigh :- %d\n\n",low,high);
}
}
if (found == 1)
{
printf("Element found\n");
}
else
{
printf("Element Not found\n");
}
}
int main()
{
int i = 0;
int startTime = omp_get_wtime();
/* Dynamically allocate memory using malloc() */
a = (int*)malloc(sizeof(int) * SIZE);
#pragma omp parallel for schedule(static)
for (i = 0; i < SIZE; ++i)
{
a[i] = i;
}
printf("Enter the element to be searched :- \n");
scanf("%d", &num);
nary(num);
printf("\nExecution time :- %f\n", omp_get_wtime()-startTime);
return 0;
}
並列実行出力:
Enter the element to be searched :-
20
Low :- 0 High :- 100 Step :- 25
First element :- 0 by thread :- 0
First element :- 50 by thread :- 2
First element :- 25 by thread :- 1
First element :- 75 by thread :- 3
First
Low :- 0
High :- 24
Low :- 0 High :- 24 Step :- 6
First element :- 6 by thread :- 1
First element :- 18 by thread :- 3
First element :- 0 by thread :- 0
First element :- 12 by thread :- 2
Last
Low :- 19
High :- 24
Low :- 19 High :- 24 Step :- 1
First element :- 20 by thread :- 1
First element :- 21 by thread :- 2
First element :- 19 by thread :- 0
First element :- 22 by thread :- 3
middle
Low :- 19
High :- 24
Element found
Execution time :- 26.824379
シリアル実行出力:
Enter the element to be searched :-
20
Low :- 0 High :- 100 Step :- 25
First element :- 0 by thread :- 0
First element :- 25 by thread :- 0
First element :- 50 by thread :- 0
First element :- 75 by thread :- 0
First
Low :- 0
High :- 24
Low :- 0 High :- 24 Step :- 6
First element :- 0 by thread :- 0
First element :- 6 by thread :- 0
First element :- 12 by thread :- 0
First element :- 18 by thread :- 0
Last
Low :- 19
High :- 24
Low :- 19 High :- 24 Step :- 1
First element :- 19 by thread :- 0
First element :- 20 by thread :- 0
First element :- 21 by thread :- 0
First element :- 22 by thread :- 0
middle
Low :- 19
High :- 24
Element found
Execution time :- 4.349347
これの背後にある理由は何か?これは、条件付きブロック内のコードまたはforループに多くの条件文があるためですか?
新しいスレッドを開始するには時間がかかります。並行して実行される作業の量は、それを得るのに十分な大きさでなければなりません。 –
コードは完全にCのようですが、C++にタグを付けることを決めた理由は何ですか? – Zulan
@BoPersson配列サイズ10000で試しましたが、同じ結果を返しました – daemon7osh