I have searched many explanations, but I think I could not figure out how I can do this situation. I want to do something like that:
Using master processor, I am creating a dynamic 2D array. Then I want to;
1- send this array to other processors. And each processor prints this 2D array
2- send part of this array to others. And each processor prints their part to the screen.
For example; I have 2D array 11*11 and 4 processors. rank 0 is master. Others are slaves. For the first situation, I want to send all array to rank 1, rank 2, and rank 3. And for the second situation, I want to share rows to slaves. 11/3 = 3. Therefore rank 1 takes 3 rows, rank 2 takes 3 rows, and rank 3 takes 5 rows.
Here is my code:
int processorID;
int numberOfProcessors;
int main(int argc, char* argv[]){
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD ,&numberOfProcessors);
MPI_Comm_rank(MPI_COMM_WORLD ,&processorID);
double **array;
if(MASTER){
array = (double**) malloc(11*sizeof(double *));
for(i=0; i<11; i++){
array[i] = (double *) malloc(11*sizeof(double));
}
for(i=0; i<11; i++){
for(j=0; j<11; j++){
array[i][j] = i*j;
}
}
}
MPI_Bcast(array, 11*11, MPI_DOUBLE, 0, MPI_COMM_WORLD);
if(SLAVE){
for(i=0; i<11; i++){
for(j=0; j<11; j++){
printf("%f ", array[i][j]);
}
}
}
MPI_Finalize();
return 0;
}
according to these link ; MPI_Bcast a dynamic 2d array ; I need to create my array as;
if (MASTER){
array = (double**) malloc(121*sizeof(double))
for(i=0; i<11; i++){
for(j=0; j<11; j++){
array[i][j] = i*j; // this is not working.
}
}
}
but if I do this, I cannot initialize each member in the array. Inner for loops are not working. I could not find any way to solve it.
And for my second question, I followed this link sending blocks of 2D array in C using MPI . I think I need to change the inside of if(SLAVE). I should create 2D subArrays for each slave processor. And I need to use MPI_Scatterv. But I could not understand completely.
int main() {
...
...
MPI_Scatterv() // what must be here?
if(SLAVE){
if(processorID = numberOfProcessor-1){
subArray = (double**) malloc(5*sizeof(double *)); // beacuse number of row for last processor is 5
for(i=0; i<11; i++){
array[i] = (double *) malloc(11*sizeof(double));
}
}
else {
subArray = (double**) malloc(3*sizeof(double *));
for(i=0; i<11; i++){
array[i] = (double *) malloc(11*sizeof(double));
}
}
}
}
C does not really have multidimensional arrays. I would recommend storing your values in a regular 1D buffer, and then calculating correct indices from 1D values. Like so:
double* data = (double*)malloc(sizeof(double)*11*11);
// Now, to access data[i][j], simply do:
data[j + i*11] = ...; // this "maps" 2D indices into 1D
This will spare you all the trouble with the hierarchical malloc-ing, and it can easily be passed to the MPI APIs.
You can't use an array of pointers (what you are incorrectly calling a "2D array"), because each row pointer is not portable to another node's address space.
The code you quoted for creating a 2D array in a linear memory allocation is perfectly correct, all you need to do is index that memory in row major order, so that the loops become:
double* array = (double*) malloc(121*sizeof(double));
if (MASTER){
for(i=0; i<11; i++){
for(j=0; j<11; j++){
array[j+i*11] = i*j; // row major indexing here
}
}
}
/* Scatter code follows */
You can safely scatter this sort of array to multiple nodes.
Related
I'm attempting to combine row/column 2-D arrays outputted from each process into a single complete 2-D array on all processes. Essentially, I have a large NxN 2-D array (4000x4000 +) that requires the same operation to be carried out on all elements. My intention is to break this down into either sections of rows or columns that each process will complete. I need each process to have the entirety of the array once all sections have been completed.
I have looked at multiple examples of using these MPI instructions but could not find one that combined rows/columns from N processes. Could someone please inform me as to how I can implement this?
Below is a boilerplate example of what I'm trying to achieve. Each process creates a master matrix and then calculates the set of rows it's responsible for. It then creates a 2-D array of that size and copies the data from the master. It then carries out its operation on each element of the 2-D array. I then need to use Allgatherv to collect each process's 2-D array and combine them to overwrite the master matrix. Please note that it is not important whether I use rows or columns from my point of view, I believed sticking to one and not trying to create multiple submatrices would allow me to easily increase the number of processes running without added complexity.
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
double **alloc_2d_array(int m, int n) {
double **x;
int i;
x = (double **)malloc(m*sizeof(double *));
x[0] = (double *)calloc(m*n,sizeof(double));
for ( i = 1; i < m; i++ )
x[i] = &x[0][i*n];
return x;
}
void main(int argc, char *argv[]) {
int n = 8;
int rank, size;
int root_rank = 0;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
// Report active to console
printf("Rank: %d, reporting!\n", rank);
// Make master matrix
double ** master_matrix = alloc_2d_array(n, n);
// Set starting values in master matrix
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
master_matrix[i][j] = i*n+j;
}
}
// Calculate each ranks section of matrix
int interval = n/size;
int section_end = interval*(rank+1);
int section_start = section_end - interval;
if (rank == size-1) {
section_end += n % size;
}
int section_length = section_end-section_start;
printf("Start: %d, End: %d\n", section_start, section_end);
// Make local rows
double ** local_sect = alloc_2d_array(section_length, n);
// Set local rows to master_matrix rows
for (int i=0; i<section_length; i++) {
local_sect[i] = master_matrix[i];
}
// Carry out operation (in this example, adding 7)
for (int i=0; i<section_length; i++) {
for (int j=0; j<n; j++) {
local_sect[i][j] = local_sect[i][j]+7;
}
}
// Use Allgatherv to overwrite master matrix to new complete matrix
// MPI_Allgatherv(my_values, my_values_count, MPI_INT, buffer, counts, displacements, MPI_INT, MPI_COMM_WORLD);
// Print new master matrix out on all processes
printf("NEW MASTER MATRIX\n");
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
printf("%f ", master_matrix[i][j]);
}
printf("\n");
}
MPI_Finalize();
}
I'll suggest reading more indepth about MPI_Type_create_subarray which allow you to create subarrays from multidimensional arrays , by that you can then gather them together with MPI_Gatherv and have them connect to each other like you want.
You might wanna check this example that I've encountered in the past:
How to combine subarrays of different widths using only one array for send and receive in MPI
I'm trying to dynamically allocate a 2D INT array in C in order to return a transposed matrix, I've done several research on the topic, and it should work this way, however I keep struggling with the program.
I tried it many different ways now (offset, pointer arithmetic), I didn't find a fix for the problem.
I'm either getting trash values or the program crashes (no seg fault, error code crash).
I'm also loooking for a proper version to allocate the memory, I've seen several versions on stackoverflow, the one I would preferrably like to use, is allocating pointer space and the integer space afterwards (the one I'm trying to use in the example below).
// Convert a matrix to it's transposed version. Returns a two dimensional array (pointer)
int **getTransposedMatrix(int *matrix, int dimension_h, int dimension_w){
int **transposedMatrix = (int **) malloc(dimension_w * sizeof(int*));
for(int row=0; row<dimension_w; row++){
transposedMatrix[row] = (int*) malloc(dimension_w * sizeof(int));
}
for(int row=0; row<dimension_h; row++){
for(int column=0; column<dimension_w; column++){
transposedMatrix[column][row] = *(matrix + row * dimension_w + column);
printf("%d ", transposedMatrix + (row * dimension_w + column));
}
printf("\n");
}
return **transposedMatrix;
}
I appreciate any help :)
I would not bother with a "2D array" such as the one you are setting up, where you're allocating the rows separately. Below is my version which uses a single array and calculates offsets into it accordingly.
int *getTransposedMatrix(int *matrix, int dimension_w, int dimension_h)
{
int *transposed = malloc(dimension_w * dimension_h * sizeof(int));
for (int row = 0; row < dimension_h; row++) {
for (int col = 0; col < dimension_w; col++) {
transposed[col * dimension_h + row] = matrix[row * dimension_w + col];
}
}
return transposed;
}
ideone with some test examples
The objective is to sort a i x j matrix of words in a 1D matrix of words in alphabetical order(every row in the original matrix is already sorted). The matrix is read from a file and stored in a three star pointer ***index, it is dynamically allocated like this (in a separate function):
char ***index;
index= (char ***) malloc(*row * sizeof(char **));
...
for (int i = 0; i < *row; ++i){
index[i]= (char **) malloc(*col * sizeof(char **));
for (int j=0; j<*col; j++) {
fscanf(fp,"%s",tmp);
index[i][j]=strdup(tmp);
}
}
I then pass the index to my sorting function: char **sort_data(char ***index, int row,int col).
It is nothing special just a merge sort algorithm that:
checks the first elements of each row of ***index
moves the "smallest" word to **sortedIndex
substitutes the sorted word with a new one from the same row.
char **sort_data(char ***index, int row,int col){
int i,posInIndex,smallestCharPos,*tracker;
char **sortedindex,*buffer;
sortedindex=(char **) malloc((row*col)*sizeof(char*));
tracker= (int*) calloc(row, sizeof(int));
posInIndex=0;
while (posInIndex<row*col) {
smallestCharPos=-1;
for (i=0; i<row; i++) {
if ((smallestCharPos==-1)||(strcmp(index[i][tracker[i]], buffer)<0)) {
smallestCharPos=i;
buffer=index[i][tracker[i]];
}
}
sortedindex[posInIndex]=index[smallestCharPos][tracker[smallestCharPos]];
posInIndex++;
tracker[smallestCharPos]++;
}
free(tracker);
return (sortedindex);
}
After some iterations(depends on matrix size) of the for loop, I get a EXC_BAD_ACCESS (code=1, address=0x14000001f5) at the if statement which leads me to believe it's an issue with my memory allocation but i cannot spot the mistake.
An example of a matrix to sort would be (this particular matrix gives me trouble after 10 iterations of the for loop):
milano torino venezia
bari genova taranto
firenze napoli roma
bologna cagliari palermo
The problem is that you don't track when you are done with a row. Even if you have already used all words of a row, you just continue looking at the row as if there are more words to handle.
You need to add some code to skip the rows that are fully handled already.
Try changing this:
if ((smallestCharPos==-1)||(strcmp(index[i][tracker[i]], buffer)<0)) {
...
}
to
if (tracker[i] < col)
{
if ((smallestCharPos==-1)||(strcmp(index[i][tracker[i]], buffer)<0)) {
...
}
}
I am trying to program Conway's Game of Life in C. I have created a 2 dimensional array representing the cells. I attempted to solve the game using a system of coordinates.
I wrote a function to create an array that brute forced all possible combinations of the neighbor's coordinates.
Then I looped through the 2d array of cells using a double nested for loop, and counted the number of dead and living neighboring cells.
I have a conditional that checks if the neighboring cells are alive, dead, or non existing (this occurs if the cell in the game is on the edge or the corner of the array).
The only problem is, no matter what I try, I am always counting the wrong number of living and dead cells, which results in subsequent incorrect generations.
I'm pretty sure this is because the system of coordinates that I am using to keep track of the cells does not correspond to the arrays. (I have tried to fix this, and failed)
My question is, what is the correct way to access specific cells inside the 2D arrays, such that the rows and columns of the arrays correspond to the x and y axis?
void bruteforceNeighbors(int ** coord, int i, int j){
array[0][0] = i-1;
array[0][1] = j-1;
array[1][0] = i-1;
array[1][1] = j;
array[2][0] = i-1;
array[2][1] = j+1;
array[3][0] = i;
array[3][1] = j-1;
array[4][0] = i;
array[4][1] = j+1;
array[5][0] = i+1;
array[5][1] = j-1;
array[6][0] = i+1;
array[6][1] = j;
array[7][0] = i+1;
array[7][1] = j+1;
}
//world is the 2d array
char ** world = (char **)malloc(sizeof(char *)*rows);
for (int i =0;i < rows; i++){
world[i] = (char *) malloc(sizeof(char)*columns);
}
You are reserving space for an array of char * but using int ** inside the function, change to
int **world = malloc(sizeof(int *) * rows);
for (int i =0; i < rows; i++) {
world[i] = malloc(sizeof(int) * columns);
}
I have some matrix which I want to cycle through blocks, the matrix could be of many different sizes, but I can know the size, is there a way to fast cycle through blocks?
i.e: to fast output the indexes of the blocks, suppose a matrix of 4*4 I should have:
Block1: (0,0),(0,1)(1,0)(1,1)
Block2: (0,2),(0,3)(1,2)(1,3)
Block3: (2,0),(2,1)(3,0)(3,1)
Block4: (2,2),(2,3)(3,2)(3,3)
Where the indexes are (row,col).
For blocks I mean a submatrix of size sqrt(matrixSize)* sqrt(matrixSize) where matrix is a matrix of matrixSize*matrixSize.
For example a matrix of 4*4 has 4 blocks of 2*2, a 9*9 has 9 blocks of 3*3...
I am working in C, but I think that the pseudocode is useful also, I only need the loop on the indexes.
I managed to do it, it's coded in c ...
The variable 'matrix_size' contains the number of rows(or columns) of the matrix.
The variable 'block' contains the precomputed size of one block of the matrix i.e: the sqrt of matrix_size.
for(int i = 0; i< matrix_size; i++)
{
fprintf(stdout, "Block %u: ", i);
for(int k= ((i/block)*block) ; k < (((i/block)*block) + block) ;k++)
{
for(int j = ((i%block)*block) ; j< (((i%block)*block) + block); j++)
{
fprintf(stdout,"(%u,%u)",k,j);
}
}
fprintf(stdout, "\n");
}