void doBoss(int size, int matrSize, int initStyle){ double* matr1 = NULL; double* matr2 = NULL; double* bufferMatr = NULL; double* recvBuffer = NULL; double* matrErg = NULL; int i = 1; int j = 0; int h = 0; int workerSize = size -1; int receiveBufferSize = 0; int recvElem = 0; int rows = matrSize; int workerRows = 0; int workerRowDiff = 0; int offset = 0; int bufferMatrSize = 0; struct timeval start,end; long runtime; //runtime in us; float runtimeSec; //runtime in sec; float flops; MPI_Status status; //recv status; int recvSize; //number of received entries; matr1 = (double*)malloc(matrSize*matrSize*sizeof(double)); matr2 = (double*)malloc(matrSize*matrSize*sizeof(double)); receiveBufferSize = matrSize; if(workerSize & 0x01 && workerSize > 1){ //odd amount of worker receiveBufferSize*=((matrSize/workerSize)+1); }else{ receiveBufferSize*=(matrSize/workerSize); } recvBuffer = (double*)malloc(receiveBufferSize*sizeof(double)); matrErg = (double*)malloc(matrSize*matrSize*sizeof(double)); if(initStyle == INIT_STYLE_RANDOM){ initMatrixRandom(matr1,matrSize,TRUE); initMatrixRandom(matr2,matrSize,TRUE); }else{ initMatrix(matr1,matrSize,TRUE); // matr1[i,j] = i + j; initMatrix(matr2,matrSize,FALSE); // matr2[i,j] = i * j; } matr2 = reorderMatrix(matr2,matrSize); initMatrixRandom(matrErg,matrSize,FALSE); //matrErg = 0.0; #if DEBUG == TRUE printf("Matr1\n"); plot(matr1,matrSize); printf("Matr2\n"); plot(matr2,matrSize); #endif gettimeofday(&start,NULL); //send Matrices to the worker-nodes for(i = 1;i < size;i++){ MPI_Send(matr1, matrSize*matrSize, MPI_DOUBLE, i, 1, MPI_COMM_WORLD); MPI_Send(matr2, matrSize*matrSize, MPI_DOUBLE, i, 2, MPI_COMM_WORLD); } //check if there something left to do for the boss if(matrSize % workerSize > 0){ for(i = 1; i <= workerSize; i++){ if(workerSize & 0x01 && workerSize > 1){ //odd amount of worker workerRows=((matrSize/workerSize)+1); }else{ workerRows=(matrSize/workerSize); } workerRowDiff = matrSize - i * workerRows; if(workerRowDiff < 0){ workerRows = workerRows + workerRowDiff; } //initial Value for rows = matrSize //if rows > 0 => there are work to do rows = rows - workerRows; } #if DEBUG == TRUE printf(" Boss should calculate %d rows \n",rows); #endif if(rows > 0){ offset = (matrSize - rows)*matrSize; bufferMatrSize = matrSize*rows; bufferMatr = (double*)malloc(bufferMatrSize*sizeof(double)); for(i = 0;i < rows; i++){//rows of the result-matrix for(j = 0; j < matrSize; j++){//colums of the result-matrix for(h = 0; h < matrSize; h++){ *(bufferMatr+j+i*matrSize)+=(*(matr1+h+offset+i*matrSize))*(*(matr2+j*matrSize+h)); } } } } } //gather Results from worker-nodes for(i = 1; i < size; i++){ MPI_Recv(recvBuffer,receiveBufferSize,MPI_DOUBLE,i,0,MPI_COMM_WORLD,&status); MPI_Get_count(&status,MPI_DOUBLE,&recvSize); for(j = 0; j < recvSize; j++){ *(matrErg+recvElem+j)= *(recvBuffer+j); } #if DEBUG == TRUE printf("Received elements %d current amount of elements %d\n",recvSize,recvElem); #endif recvElem += recvSize; } if(rows > 0){ for(i = 0; i < bufferMatrSize;i++){ *(matrErg+recvElem+i)= *(bufferMatr+i); } } gettimeofday(&end,NULL); #if DEBUG == TRUE printf("Result\n"); plot(matrErg,matrSize); #endif runtime = calcRuntime(&start,&end); runtimeSec = (float)runtime/1e6; flops = (2*size*size)/(runtimeSec); //?? printf("#runtime[us] runtime[sec] flop size\n"); printf("%ld %f %f %d\n",runtime,runtimeSec,flops,matrSize); if(matr1 != NULL){ #if DEBUG == TRUE printf("Release memory for matr1\n"); #endif free(matr1); } if(matr2 != NULL){ #if DEBUG == TRUE printf("Release memory for matr2\n"); #endif free(matr2); } if(matrErg != NULL){ #if DEBUG == TRUE printf("Release memory for matrErg\n"); #endif free(matrErg); } if(recvBuffer != NULL){ #if DEBUG == TRUE printf("Release memory for recvBuffer\n"); #endif free(recvBuffer); } if(bufferMatr != NULL){ #if DEBUG == TRUE printf("Release memory for bufferMatr\n"); #endif free(bufferMatr); } }
void calculateNeighbours(int* iv_id, int* im_pos, int* im_nbs, double* iv_ss, int* iv_type, int* nP, int* pP, double* phiP) { //Initialise input variables int* v_id = iv_id; int* m_pos = im_pos; int* m_nbs = im_nbs; int* v_type = iv_type; double* v_ss = iv_ss; int n = *nP; int p = *pP; double phi = *phiP; //Initialise temporary variables bool clsenb = false; int d = 0; int itmp = 0; double dtmp = 0; int* col = new int[n]; int* new_order = new int[n]; int* id_order = new int[n]; int* v_id_copy = new int[n]; int* m_pos_copy = new int[p*n]; int* m_nbs_tmp = new int[2*n]; double* v_tmp = new double[n]; //initialise new arrrays as required. for(int i = 0; i < n; i++) { m_nbs_tmp[2*i] = 0; m_nbs_tmp[2*i + 1] = 0; v_tmp[i] = 0; } // *********************************************************** // --Outer Loop: for dimension d, get left and right neighbours: // *********************************************************** // start with column 1 (zero indexed in C) for(d = 0; d < p; d++) { // --get the order of this column (1. copying contents of column to feed into mergesort). // -- (2. Create order, returned in 'new_order') for(int i = 0; i < n; i++) { col[i] = m_pos[d*n + i]; } morder(col, n, new_order); // --Perform re-ordering of 'm_nbs' and 'v_id' based on this order. // --Need inverse of v_id for returning results - returned in 'id_order' reorderMatrix(m_pos, m_pos_copy, new_order, n, p); reorderVec(v_id, v_id_copy, new_order, n); morder(v_id, n, id_order); // ********************************************************* // --Inner Loop: This is the actual data generation: the 'Get Neighbours' part of the script. // ********************************************************* for(int i = 0; i < n-1; i++) { // --Insert above and below neighbours from the current order into m_nbs output. m_nbs_tmp[i] = v_id[i+1]; m_nbs_tmp[n + i+1] = v_id[i]; // --Calculate metrics by assessing the entire row (1:p) for(int c = 0; c < p; c++) { //Get position of neighbour in dimension c. By looking at Right neighbour @ n+1, and left // neighbour @ n, we can re-use a single distance value, as the only difference will be the sign. // we're not concerned with the sign. itmp = distance. Define nb as close:= abs(dist) < 1. itmp = m_pos[i+1 + c*n] - m_pos[i + c*n]; ((itmp > 1) || (itmp < -1)) ? clsenb = false : clsenb = true; // .....For 'Right' Neighbour................ if (!clsenb) { m_nbs_tmp[i] = 0; } // Add square distance to sum of sqs. v_tmp[i] += itmp*itmp; // .....Repeat for 'Left' Neighbour............ if (!clsenb) { m_nbs_tmp[n + i+1] = 0; } v_tmp[i+1] += itmp*itmp; } // ********************************************************* // --End of inner loop // ********************************************************* } // --Calculate root sum of squared distance and add to root sum of square distance from other // dimensional orderings. First and last entry only have one neighbour, so to avoid changing the // denominator later on, we double these. Minimum value to add is 1 to avoid DIV/0 Errors. for(int i = 1; i < n-1; i++) { dtmp = v_tmp[id_order[i]]; if (dtmp < 1) { v_ss[i] +=1; } else { v_ss[i] += sqrt(dtmp); } } // (first and last - separately to avoid p*n 'if' comparisons in the for loop.) dtmp = v_tmp[id_order[0]]; (dtmp < 1) ? v_ss[0] += 2 : v_ss[0] += 2*sqrt(dtmp); dtmp = v_tmp[id_order[n-1]]; (dtmp < 1) ? v_ss[n-1] += 2 : v_ss[n-1] += 2*sqrt(dtmp); // Clear sum of squares array to start from scratch for next dim. for(int i = 1; i <n; i++) { v_tmp[i] = 0; } // Input neighbours into output array. Need to reorder based on original id now. for(int i = 0; i < n; i++) { m_nbs[2*d*n + i] = m_nbs_tmp[id_order[i]]; m_nbs[(2*d+1)*n + i] = m_nbs_tmp[id_order[i] + n]; } // ********************************************************* // --End of outer loop // ********************************************************* } // *****Final operation: Density Calculation.*************** // --Compute density = p/n. If density > phi, then point is interior; type = 1. for(int i = 0; i < n; i++) { if (p/v_ss[i] > phi) { v_type[i] = 1; } else { v_type[i] = 0; } } delete[] col; delete[] new_order; delete[] id_order; delete[] v_id_copy; delete[] m_pos_copy; delete[] m_nbs_tmp; delete[] v_tmp; return; }