Se trabaja sobre una matriz de números reales, A de dimensión NxN. Se genera una matriz F, NxN, con cada fila la fila correspondiente de A con los datos ordenados de menor a mayor, y otra matriz C, NxN, con cada columna la columna correspondiente de A con los datos ordenados de menor a mayor. Finalmente se actualiza A=F+C.
Se resuelven varios problemas. Para cada problema la función a paralelizar tiene parámetros:
Input parameter:
int N: número de filas y columnas
Input/Output parameter:
double *A: matriz de dimensión NxN
La entrada tiene en la primera línea el número de problemas. Para cada problema hay una línea con cinco valores: N, la semilla para la generación aleatoria de datos, los valores mínimo y máximo para la generación, y un valor que indica cada cuantos elementos se escribe un elemento a la salida.
3 10 4 -20 20 1 1300 18 -250 250 370 1700 17 -200 200 907
/* CPP_CONTEST=2018Junio CPP_PROBLEM=A CPP_LANG=CPP+OPENMP CPP_PROCESSES_PER_NODE=calisto 1 */ #include < stdlib.h > #include < omp.h > extern void escribir(double *,int,int); void copiar(int n,double *vd,int ldvd,double *vo,int ldvo) //se copia el vector vo en el vd //como los datos pueden no estar contiguos se accede a ellos con los ld { int i; for(i=0;i < n;i++) vd[i*ldvd]=vo[i*ldvo]; } void ordenar(int n,double *m) { int i,j; double t; for(i=0;i < n;i++) for(j=i+1;j < n;j++) { if(m[i] > m[j]) { t=m[i]; m[i]=m[j]; m[j]=t; } } } void ordenarfilas(int n,double *A,double *F) { int i; for(i=0;i < n;i++) { copiar(n,&F[i*n],1,&A[i*n],1); //se copia la fila de A en la correspondiente de F ordenar(n,&F[i*n]); //y se ordena la fila en F } } void trasponer(int n,double *m) { int i,j; double t; for(i=0;i < n;i++) for(j=i+1;j < n;j++) { t=m[i*n+j]; m[i*n+j]=m[j*n+i]; m[j*n+i]=t; } } void ordenarcolumnas(int n,double *A,double *C) { int i; for(i=0;i < n;i++) { copiar(n,&C[i*n],1,&A[i],n); //se copia la columna de A en la fila correspondiente de C ordenar(n,&C[i*n]); //y se ordena la fila en C } trasponer(n,C); //se pasan las filas de C, que tienen las columnas ordenadas de A, a las columnas correspondientes } void sumar(int n,double *vd,double *vo1,double *vo2) { int i; for(i=0;i < n*n;i++) vd[i]=vo1[i]+vo2[i]; } void sec(int n,double *A) { double *F=new double[n*n]; double *C=new double[n*n]; ordenarfilas(n,A,F); #ifdef DEBUG escribir(F,n,n); #endif ordenarcolumnas(n,A,C); #ifdef DEBUG escribir(C,n,n); #endif sumar(n,A,F,C); #ifdef DEBUG escribir(A,n,n); #endif delete[] F; delete[] C; }
esquema-openmp.cpp (no modificable, lo usa mooshak para entrada/salida y evaluación, se proporciona para experimentación en local)
#include < stdlib.h > #include < stdio.h > #include < sys/time.h > #include < omp.h > #include < signal.h > #include < unistd.h > //Prueba de Metodología de la Programación Paralela //junio 2018 //Ordenación de filas y columnas y suma. Versión OpenMP con paralelización independiente de funciones //Esquema para entrada/salida, validación y toma de tiempos void generar(double *m, int t,int lv,int uv) { int i; for (i = 0; i < t; i++) { m[i] =(1. * rand() / RAND_MAX)*(uv-lv)+lv; } } void escribir(double *m, int N,int M) { int i, j; for (i = 0; i < N; i++) { for (j = 0; j < M; j++) printf("%.6lf ", m[i * M + j]); printf("\n"); } printf("\n"); } void escribirresult(double *a,int N,int salida) { int i; for(i=0;i < N;i++) { if((i%salida)==0) { printf("%.10lf \n",a[i]); } } printf("\n"); } /* c c mseconds - returns elapsed milliseconds since Jan 1st, 1970. c */ long long mseconds(){ struct timeval t; gettimeofday(&t, NULL); return t.tv_sec*1000 + t.tv_usec/1000; } static void alarm_handler(int sig) { fprintf(stderr, "Time Limit Exceeded\n"); abort(); } extern void sec(int n,double *A); int main(int argc,char *argv[]) { int N; //tamaño matriz double *A; int cuantos; //número de problemas int semilla; //semilla para generación aleatoria int lv,uv; //valores inferior y superior para generación aleatoria int salida; //indica cada cuantos elementos se escribe uno a la salida long long ti,tf,tt=0; FILE *stats_file = fopen("stats", "w"); struct sigaction sact; sigemptyset(&sact.sa_mask); sact.sa_flags = 0; sact.sa_handler = alarm_handler; sigaction(SIGALRM, &sact, NULL); alarm(60); /* time limit */ scanf("%d",&cuantos); for(int i=0;i < cuantos;i++) { scanf("%d",&N); scanf("%d",&semilla); scanf("%d",&lv); scanf("%d",&uv); scanf("%d",&salida); A = (double *) calloc(sizeof(double),N*N); srand(semilla); generar(A,N*N,lv,uv); #ifdef DEBUG escribir(A,N,N); #endif ti=mseconds(); sec(N,A); tf=mseconds(); #ifdef DEBUG escribir(A,N,N); #endif if(i!=0) tt+=tf-ti; escribirresult(A,N*N,salida); free(A); } fprintf(stats_file, "%Ld\n", tt); fclose(stats_file); return 0; }