Алгоритм Витерби с OpenMP

Я пытаюсь реализовать Алгоритм Витерби с помощью OpenMP. Пока что мой тест показывает, что время выполнения параллельной программы примерно в 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;
}

Что я делаю неправильно?

0

Решение

Прежде всего, вы использовали для первого измерения 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 только для внешнего цикла и следите за результатом

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]