使用 OpenMP 的 Viterbi 算法

Posted

技术标签:

【中文标题】使用 OpenMP 的 Viterbi 算法【英文标题】:Viterbi algorithm with OpenMP 【发布时间】:2014-04-29 01:08:39 【问题描述】:

我正在尝试在 OpenMP 的帮助下实现 Viterbi algorithm。到目前为止,我的测试表明并行程序的执行时间大约是顺序程序执行时间的 4 倍。这是我的代码:

#include <omp.h>
#include <stdio.h>
#include <time.h>

#define K 39 // num states
#define T 1500 // num obs sequence

int states[K];
double transition[K][K];
double emission[K][K];
double init_prob[K];
int observation[T];

using namespace std;

void generateValues()

    srand(time(NULL));

    for(int i=0; i<T; i++)
    
        observation[i] = rand() % K;
    

    for(int i=0; i<K; i++)
    
        states[i] = i;
        init_prob[i] = (double)rand() / (double)RAND_MAX;
        for(int j=0;j<K;j++)
        
            transition[i][j] = (double)rand() / (double)RAND_MAX;
            srand(time(NULL));
            emission[i][j] = (double)rand() / (double)RAND_MAX;
        
    


int* viterbi(int *S, double *initp, int *Y, double A[][K], double B[][K])

    double T1[K][T];
    int T2[K][T];

    #pragma omp parallel for
    for(int i=0; i<K; ++i)
    
        T1[i][0] = initp[i];
        T2[i][0] = 0;
    

    for(int i=1; i<T; ++i)
    
        double max, temp;
        int argmax;

        #pragma omp parallel for private (max, temp, argmax)
        for(int j=0; j<K; ++j)
        
            max = -1;

            #pragma omp parallel for
            for(int k=0; k<K; ++k)
            
                temp = T1[k][i-1] * A[k][j] * B[k][Y[i-1]];

                if(temp > max)
                
                    max = temp;
                    argmax = k;
                
            

            T1[j][i] = max;
            T2[j][i] = argmax;
        
    

    int Z[T];
    int X[T];   

    double max = -1, temp;
    #pragma omp parallel for
    for(int k=0; k<K; ++k)
    
        temp = T1[k][T-1];

        if(temp > max)
                   
            max = temp;
            Z[T-1] = k;
        
    

    X[T-1] = S[Z[T-1]];

    for(int i=T-1; i>0; --i)
    
        Z[i-1] = T2[Z[i]][i];
        X[i-1] = S[Z[i-1]];
    

    return X;


int* viterbiNoOmp(int *S, double *initp, int *Y, double A[][K], double B[][K]) // the same as before, minus the #pragma omp

int main()

    clock_t tStart;
    int *path;

    generateValues();
    double sumOmp = 0;
    for(int i=0;i<6;i++)
    
        double start = omp_get_wtime();
        path = viterbi(states, init_prob, observation, transition, emission);
        double end = omp_get_wtime();
        sumOmp += end - start;
    

    double sumNoOmp = 0;
    for(int i=0;i<6;i++)
    
        tStart = clock();
        path = viterbiNoOmp(states, init_prob, observation, transition, emission);

        sumNoOmp += ((double)(clock() - tStart)/CLOCKS_PER_SEC);
    

    for (int i=0;i<T;i++)
    
        printf("%d, ", path[i]);
    

    printf("\n\ntime With Omp: %f\ntime without Omp: %f", sumOmp/6, sumNoOmp/6);
    return 0;

我做错了什么?

【问题讨论】:

【参考方案1】:

首先,您在第一次测量中使用了omp_get_wtime() 函数,而在第二次测量中,您使用了clock()

同时使用omp_get_wtime(),您会看到一点改进

其次,不要使用sumNoOmp += ((double)(clock() - tStart)/CLOCKS_PER_SEC); 只需使用sumNoOmp = ((double)(clock() - tStart)/CLOCKS_PER_SEC);

现在让我们继续您的代码: 尝试并行嵌套循环有点棘手 尝试将#pragma omp parallel for 仅用于外循环并观察结果

【讨论】:

以上是关于使用 OpenMP 的 Viterbi 算法的主要内容,如果未能解决你的问题,请参考以下文章

Forward-backward算法和Viterbi算法有啥区别?

试图更好地理解 VITERBI 算法

维特比算法(Viterbi)

自然语言处理之维特比(Viterbi)算法

用matlab viterbi算法怎么求传输

最通俗易懂的解说viterbi维特比算法!