我有以下代码,我已经实现了一个显式任务版本:
int waves = N_a + N_b +1; /*considering N_a == N_b */
#pragma omp parallel firstprivate(a, gap, waves) private(temp, wave, ii, i) shared(np, mp, elements)
{
#pragma omp master
{
for(wave = 0; wave < waves; ++wave) {
// 0 <= wave < n-1
if(wave < N_a-1) {
elements = wave+1;
np = wave+1;
mp = 0+1;
}
// n-1 <= wave < m
else if(wave < N_b) {
elements = N_a;
np = N_a-1+1;
mp = wave-(N_a-1)+1;
}
// m <= wave < m+n-1
else {
elements = N_a-1-(wave-N_b);
np = N_a-1+1;
mp = wave-(N_a-1)+1;
}
for(ii = 0; ii < elements; ii+=chunk) {
min = MIN(elements,ii + chunk);
#pragma omp task firstprivate(ii, np, mp, chunk, elements)
{
for (i = ii; i < min; i++)
{
temp[0] = H[(np-i)-1][(mp+i)-1] + similarity(seq_a[a][(np-i)-1],seq_b[a][(mp+i)-1]);
temp[1] = H[(np-i)-1][(mp+i)]-gap;
temp[2] = H[(np-i)][(mp+i)-1]-gap;
temp[3] = 0;
H[(np-i)][(mp+i)] = find_array_max(temp,4);
}
} // task
} //for loop
#pragma omp taskwait
}
}
}
奇怪的是,在执行代码时,1个线程的性能要比2个,4个,8个和16个线程的性能好得多。只有一个并行区域,我已经对内部for循环进行了剥离,因此每个“块”数量的元素都将有助于创建任务。
我坚持创建一个任务实现,因为这里的元素值会不断变化,我觉得代码有可能通过高效的任务实现来抵制非结构化并行性。
我在Intel xe12版本编译器上尝试这个。以下是我观察的样本块大小的读数:256和N_a = N_b = 4096:
1个主题:1.237560 2个主题:7.223232 4个主题:4.579173 8个主题:3.663661 16个主题:4.425525
我注意到gcc编译器的类似行为。有人可以为什么一线程的代码比多线程更好。 我也看到N_a = N_b = 1024,2048和8192的相似结果。
感谢。
答案 0 :(得分:2)
所有代码都由#pragma omp master
保护,只允许主线程运行所有计算。你必须删除这个pragma(或者有什么理由吗?)才能看到至少一些缩放。