使用 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 算法的主要内容,如果未能解决你的问题,请参考以下文章