openMP的最长公共子序列

时间:2014-01-10 19:17:47

标签: c openmp lcs

我正在使用openMP编写Longest Common Subsequence算法的并行版本。

顺序版本如下(并且它可以正常工作):

// Preparing first row and first column with zeros
for(j=0; j < (len2+1); j++)
    score[0][j] = 0;

for(i=0; i < (len1+1); i++)
    score[i][0] = 0;

// Calculating scores
for(i=1; i < (len1+1); i++) {
    for(j=1; j < (len2+1) ;j++) {
        if (seq1[i-1] == seq2[j-1]) {
               score[i][j] = score[i-1][j-1] + 1;
        }
        else {
            score[i][j] = max(score[i-1][j], score[i][j-1]);
        }
    }
}

关键部分是填写得分矩阵,这是我尝试主要并行化的部分。

一种方法(我选择)是:通过反对角线填充矩阵,因此始终满足左,上和左上依赖。简而言之,我跟踪对角线(第三个循环,下面的变量 i )并且线程平行填充该对角线。 为此,我写了这段代码:

void parallelCalculateLCS(int len1, int len2, char *seq1, char *seq2) {

int score[len1 + 1][len2 + 1];
int i, j, k, iam;
char *lcs = NULL;

for(i=0;i<len1+1;i++)
    for(j=0;j<len2+1;j++)
        score[i][j] = -1;

#pragma omp parallel default(shared) private(iam)
{
    iam = omp_get_thread_num();
// Preparing first row and first column with zeros
    #pragma omp for
    for(j=0; j < (len2+1); j++)
        score[0][j] = iam;

    #pragma omp for
    for(i=0; i < (len1+1); i++)
        score[i][0] = iam;

// Calculating scores
    for(i=1; i < (len1+1); i++) {
        k=i;
        #pragma omp for
        for(j=1; j <= i; j++) {
            if (seq1[k-1] == seq2[j-1]) {
                //  score[k][j] = score[k-1][j-1] + 1;
                score[k][j] = iam;
            }
            else {
            //  score[k][j] = max(score[k-1][j], score[k][j-1]);
                score[k][j] = iam;
            }
            #pragma omp atomic
            k--;
        }
    }

}
}

前两个循环(第一行和第一列)正常工作,并且线程以平衡的方式填充单元格。

当填充矩阵(对角线)时,没有什么效果好。我试图调试它,但似乎线程随机地动作和写东西。

我无法弄清楚出了什么问题,因为在前两个循环中根本没有问题。

有什么想法吗?

P.S。我知道以对角方式访问矩阵对缓存不友好,线程可能不平衡,但我现在只需要它就可以工作了。

P.S。 #2我不知道它是否有用,但我的CPU最多有8个线程。

2 个答案:

答案 0 :(得分:0)

以下嵌套for循环

 #pragma omp for
 for(j=1; j <= i; j++) 

将并行执行,每个线程的j值不同,没有特定的顺序。 由于omp for部分中未指定任何内容,因此默认情况下将在所有线程之间共享k。因此,根据线程的顺序,k将在未知时间递减(即使使用omp atomic)。因此,对于固定的jk的值可能会在执行for循环体(在if子句之间,...)之间发生变化。

答案 1 :(得分:0)

#pragma omp atomic表示处理器将一次执行一个操作。您正在寻找#pragma omp for private(k):处理器将不再共享相同的值。再见,弗朗西斯