c - 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);
}
}