首页 > 解决方案 > Openmp 在调用指定函数时的不良行为

问题描述

亲爱的,我遇到了并行范例(openmp)的问题。也许这是一个微不足道的问题。我试图两次调用同一个函数来初始化与某个结构相关的两个变量。

如果尝试在没有并行性的情况下初始化每个变量,则该函数运行良好并正确返回每个变量。但是,如果我尝试使用 openmp,则该功能不起作用(它给出了错误的答案)。

请参阅下面的代码。

附言。该函数仅使用这些值来创建一些结构,即这些值在函数内部的任何时刻都不会改变。

我尝试使用“#omp parallel for”、标准的“#omp parallel”甚至“#omp parallel private(g, r, s)”。

//this is on version
#pragma omp parallel for
  for(int i = 0; i < 2; i++){
    if(i == 0)
      h[i] = fastContComplete(r, cromo->g, 1);
    else
      h[i] = fastContComplete(s, cromo->g, 0);
  }

//the second try
 #pragma omp parallel private(r, s, cromo)
  {
    i = omp_get_thread_num();
    if(i == 0)
      h[i] = fastContComplete(r, cromo->g, 1);
    else
      h[i] = fastContComplete(s, cromo->g, 0);
  }

下面我提供了函数 fastContComplete 的算法及其依赖关系。要使用它,您可以使用函数 criarGrafo(int n) 创建一个随机结构 grafo,然后可以使用上述两种不同的方式测试函数 fasContComplete。抱歉,我不能让算法更短:(

void fastContAux(int k, int *cam, int K, int i,int *v,grafo *h, grafo *g, int clique){

  if(h == NULL || g == NULL){
    printf("Error... Grafos inacessíveis fastContAux!\n\n");
    exit(0);
  }
  if(v == NULL){
    printf("Error... vetor inacessível fastContAux!\n\n");
    exit(0);
  }

  if(k > 1){
    int m = i;
    int *v1;
    int key = 1;
    int l;

    while(m < g->size && key ==1){
      m++;
      if(v[m] == 0)
        key = 1;
      else
        key = 0;
    }
    if(m < g->size){

      v1 = (int *)malloc(sizeof(int)*g->size);

      while(m < g->size){
        if(v[m] == 1){
          for(int j = m+1; j < g->size; j++){
            if(v[j] == 1){
              if(edge(m, j, g) == clique)
                v1[j] = 1;
              else
                v1[j] = 0;
            }
            else{
              v1[j] = 0;
            }
          }
          cam[K-k] = m;
          fastContAux(k - 1, cam, K, m, v1, h, g, clique);
        }
        m++;
      }
      free(v1);
    }
  }
  if(k == 1){
    for(int j = i+1; j < g->size; j++){
      if(v[j] == 1){
        h->aux++;
        cam[K-k] = j;
        for(int t = 0; t < K; t++){
          for(int u = t+1; u < K; u++){
            setEdge(edge(cam[t], cam[u], h) + 1, cam[t], cam[u], h);
          }
        }
      }
    }
  }
}

grafo *fastContComplete(int k, grafo *g, int clique){
  int *v;
  grafo *h, *haux;
  int l;
  int *cam;

  if(k < 1){
    printf("Error... não existe grafo completo de tamanho nulo ou negativo! \n\n");
    exit(0);
  }

  h = criarGrafo(g->size);
  if(k == 1){
    h->aux = h->size;
    return h;
  }

  int nthreads = 4;
#pragma omp parallel private(v, cam, haux) shared(g, h, clique) num_threads(nthreads)
  {
    v = (int *)malloc(sizeof(int)*g->size);
    cam = (int *)malloc(sizeof(int)*k);
    haux = criarGrafo(g->size);
    for(int i = 0 + omp_get_thread_num(); i < g->size - k + 1; i += nthreads){
      cam[0] = i;
      for(int j = i+1; j < g->size; j++){
        if(edge(i, j, g) == clique)
          v[j] = 1;
        else
          v[j] = 0;
      }

      fastContAux(k-1, cam, k, i, v, haux, g, clique);
    }

#pragma omp critical (alimentando)
    {

      h->aux += haux->aux;
      for(int l1 = 0; l1 < h->size; l1++){
        for(int l2 = l1+1; l2 < h->size; l2++){
          setEdge(edge(l1, l2, haux)+edge(l1, l2, h), l1, l2, h);
        }
      }

    }

    free(cam);
    free(v);
  }
  return h;

}
void setEdge(float valor, int i, int j, grafo *g){
  if(g == NULL){
    printf("Aconteceu um erro de acesso na função setEdge.\n Grafo passado NULO\n\n");
    exit(0);
  }
  if(g->adj == NULL){
    printf("Aconteceu um erro de acesso na função setEdge.\n Grafo passado NULO não iniciado devidamente\n\n");
  }

  g->adj[formu(i, j, g->size) - 1] = valor;
}
float edge(int i, int j, grafo *g){
  if(g == NULL){
    printf("Aconteceu um erro de acesso na função edge.\n Grafo passado NULO\n\n");
    exit(0);
  }
  if(g->adj == NULL){
    printf("Aconteceu um erro de acesso na função edge.\n Grafo passado NULO não iniciado devidamente\n\n");
  }
  return g->adj[formu(i, j, g->size) - 1];
}
int formu(int i, int j, int n){
  int t;
  if(i < j){
    t = (2*n - i - 1)*i/2;
    return t + (j - i);
  }
  else{
    t = (2*n - j - 1)*j/2;
    return t + (i - j);
  }
}

typedef struct Grafo{

  int size;
  float *adj;
  int aux; //utilizada apenas em situaçoes de comparações                                                                 

} grafo;

grafo *gnp(int n){
  grafo *g;

  g = criarGrafo(n);

  for(int i = 0; i < g->size; i++){
    for(int j = i+1; j < g->size; j++){
      setEdge(((float) (rand()%2)), i, j, g);
    }
  }
  return g;
}

grafo *criarGrafo(int n){
  if(n > 1){
    grafo *g;
    g = (grafo *)malloc(sizeof(grafo));
    if(g == NULL){
      printf("Error ao alocar memória para criar um grafo\n\n\n");
      exit(0);
    }
    g->size = n;
    g->adj = (float *)malloc(n*(n-1)*sizeof(float *)/2);
    if(g->adj == NULL){
      printf("Error ao alocar memória para criar arestas de um grafo\n\n\n");
      exit(0);
    }
    for(int i = 0; i < n; i++){
      for(int j = i+1; j < n; j++){
        setEdge(0, i, j, g);
      }
    }
    g->aux = 0;
    return g;
  }
  else{
    if(n == 1){
      grafo *g;
      g = (grafo *)malloc(sizeof(grafo));
      if(g == NULL){
        printf("Error ao alocar memória para criar um grafo\n\n\n");
        exit(0);
      }
      g->size = n;
      g->adj = NULL;
      g->aux = 0;
      return g;
    }

    printf("Error função Criar Grafo! Valor passado muito pequeno ou negativo (n = %d)\n\n",n);
    exit(0);
  }
}

标签: cparallel-processingopenmp

解决方案


推荐阅读