Discrepancies in Matrix Data Communicated Between Parent and Child Process - c

For a project of mine, I am required to pass matrices (which, later on will be of various sizes determined at run-time) between processes, and perform operations on them. This will be performed on a UNIX system.
While teaching myself about fork() and pipe(), I managed to establish two one-way pipes between the processes (one from parent to child and vice versa) to some extent.
===========================================================
Here is my code:
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define READ_END 0
#define WRITE_END 1
#define MATRIX_N 2
void print_mat(int**, int);
int main(void){
// INITIALIZE
int **w_mat, **r_mat, **return_mat, i, j;
int fd1[2];
int fd2[2];
pid_t pid;
// Allocate memory for respective arrays
w_mat = (int**) malloc(sizeof(int *) * MATRIX_N);
for( i = 0 ; i < MATRIX_N ; i++ ){
*(w_mat + i) = (int*) malloc (sizeof(int *) * MATRIX_N);
}
r_mat = (int**) malloc(sizeof(int *) * MATRIX_N);
for( i = 0 ; i < MATRIX_N ; i++ ){
*(r_mat + i) = (int*) malloc (sizeof(int *) * MATRIX_N);
}
return_mat = (int**) malloc(sizeof(int *) * MATRIX_N);
for( i = 0 ; i < MATRIX_N ; i++ ){
*(return_mat + i) = (int*) malloc (sizeof(int *) * MATRIX_N);
}
// Assign initial values to matrix for writing
w_mat[0][0] = 2;
w_mat[0][1] = 7;
w_mat[1][0] = 12;
w_mat[1][1] = 9;
// Initialize and check pipes respectively
if( pipe(fd1) == -1){
fprintf(stderr, "Pipe failed");
return 1;
}
if( pipe(fd2) == -1){
fprintf(stderr, "Pipe failed");
return 1;
}
// Fork a child, then check it
pid = fork();
if( pid < 0 ){
fprintf(stderr, "Fork failed");
}
if( pid > 0 ){ /* PARENT */
// Close unnecessary pipe ends
close(fd1[READ_END]);
close(fd2[WRITE_END]);
printf("\nMatrix to send to child: ");
print_mat(w_mat, MATRIX_N);
// Write to pipe 1, matrix for child, then close pipe
write(fd1[WRITE_END], w_mat, MATRIX_N * MATRIX_N * sizeof(int*));
// Wait for child to process values, write, and terminate
wait(NULL);
// Read values from pipe 2
read(fd2[READ_END], return_mat, MATRIX_N * MATRIX_N * sizeof(int*));
printf("\nDoubled matrix received from child: ");
print_mat(return_mat, MATRIX_N);
// Close used pipe ends
close(fd2[READ_END]);
close(fd1[WRITE_END]);
}else{ /* CHILD */
// Close unnecessary pipe ends
close(fd1[WRITE_END]);
close(fd2[READ_END]);
// Read from pipe 1 the matrix from the parent
read(fd1[READ_END], r_mat, MATRIX_N * MATRIX_N * sizeof(int*));
printf("\nReceived matrix from parent to double: ");
print_mat(r_mat, MATRIX_N);
// Double the values in the matrix from parent
for( i = 0 ; i < MATRIX_N ; i++ ){
for( j = 0 ; j < MATRIX_N ; j++){
r_mat[i][j] = r_mat[i][j] * MATRIX_N;
}
}
printf("\nDoubled matrix to send to parent: ");
print_mat(r_mat, MATRIX_N);
// Write to pipe 2, the doubled matrix to be received by parent
write(fd2[WRITE_END], r_mat, MATRIX_N * MATRIX_N * sizeof(int*));
// Close used pipe ends
close(fd2[WRITE_END]);
close(fd1[READ_END]);
}
// Terminate
return 0;
}
===========================================================
The problem arises when running the program:
===========================================================
Matrix to send to child:
| 2 7 |
| 12 9 |
Received matrix from parent to double:
| 2 7 |
| 12 9 |
Doubled matrix to send to parent:
| 4 14 |
| 24 18 |
Doubled matrix received from child:
| 2 7 |
| 12 9 |
===========================================================
The array before writing is correct, and it seems as if somehow in the midst of writing it to pipe 2 from the child and reading it back in from said pipe once the child terminates; the values return to what they were. I don't believe it could be either process tampering with it, as each has its own variable array to store the data, and aside from the pipes there is really no instance where, in the if-statement of my program, either process directly affects the array of another--To the best of my knowledge, that is.
Could there, in fact, be an instance in which the parent or child indirectly affects the written and read arrays which I am not considering? If so, how could I keep this in check? If not, where exactly did I go wrong? Was my pipe implementation inherently flawed? I'm not really sure what to look for.
Also; in the far-left of field instance that my matrix printing function is the culprit, here is that:
void print_mat(int** a, int n){
int i, j;
for( i = 0 ; i < n ; i++){
printf("\n| ");
for( j = 0 ; j < n ; j++){
printf("%d", a[i][j]);
if( j != n - 1){
printf(" ");
}
}
printf(" |\n");
}
}

Each matrix is an array of pointers, where each pointer points to an array of ints. Therefore the method that you are using to pass the matrix between the parent and child won't work the way you want it to.
What you are doing is passing four pointers across the pipe (of which only the first two are valid). Since the child is a carbon copy of the parent, those pointers do in fact point to the original matrix in the parent's address space. Therefore, the parent prints the original matrix.
What you want to do is pass the integer values across the pipe and reconstruct the matrix on the other side. Code similar to the print_mat function is needed to write the individual values into the pipe. On the receiving side, those values need to be read and stored at the proper locations in the array.
Let me see if I can clarify with an example. If the array was declared as
int w_mat[2][2];
then you could transfer the entire array like this
write(fd1[WRITE_END], w_mat, 2*2 * sizeof(int) );
But in fact the array is equivalent to this
int *w_mat[2];
w_mat[0] = malloc( 2 * sizeof(int) );
w_mat[1] = malloc( 2 * sizeof(int) );
Therefore, the line
write(fd1[WRITE_END], w_mat, MATRIX_N * MATRIX_N * sizeof(int*));
is writing four int * to the pipe. That's bad for two reasons.
The array only has two pointers in it
Passing pointers across the pipe is not the same as sending the data across the pipe.

Related

Reading element by element works but reading a chunk won't

I am trying to determine whether an element exits in a vector using N processes and if true, return all its positions. Each process receives an index and a step. The index is from 0 to "numberOFProcesses -1" and each process check element starting from index, incremented by step.
How it works: Let us assume we have 4 processes. Process 0 checks elements 0,4,8..., process 1 checks 1,5,9... etc.
How did I implement this: I got 2 pipes: one pipes is used for positions; the second pipe is to store the number of occurrences of the target. Whenever a process find the target it increments the number of occurrences and writes the index to the "index" pipe and, finally, upon exiting job, it writes to "occurrences" pipe the number of occurrences, if any, and return true or false. I initially wanted to directly return the number of occurrences but I realized that "WEXITSTATUS" uses only 8 bits and that might be an issue.
The problem: Attempting to read a chunk of size "occurrences" fails or gives invalid results. Reading a value at a time seems to work fine. I have also checked it using valgrind and gdb, but I cannot seem to find the problem. Valgrind reports a ton of issues when attempting to read the chunk, but 0 errors when reading one at time. The reading of occurrences is done only if the process has found the target.
P.S. I know I can leave it like that, but it wouldn't make sense reading multiple times.
Now, for some code:
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <sys/signal.h>
#include <sys/types.h>
/**
* #brief basic defines
*
*/
#define MAX_RAND 100
#define TRUE 1
#define FALSE 0
#define CHILDREN 0
#define READ 0
#define WRITE 1
int size = 13;
int *array;
int target;
int index_pipe[2];
int occurences_pipe[2];
/**
* #brief this populates the array with random number
*
* #param array the given array
* #param size the size of the array
*/
void populate(int *array, int size)
{
for (int i = 0; i < size; i++)
{
array[i] = rand() % MAX_RAND;
}
}
/**
* #brief this determines whether an elements occurs in an array and writes to pipes the number
* of occurences and the the indexes on which resides the target
*
* #param target the value we are looking for
* #param index the index of the process, i.e. the process id
* #param step the step, i.e. the number of processes
* #return int the search status. This returns true if "target occurs", FALSE otherwise
*/
int search(int target, int index, int step)
{
int i = index;
int numberOfOccurences = 0;
/**
* #brief each process will start at position index and will check values starting with index, incrementing with step
* ex: process 0 will check 0,4,8,12..
* process 1 will check 1,5,9,13...
*/
while (i < size)
{
if (target == array[i])
{
/**
* #brief if the target occues increment the number of occurences and write an index to pipe
*
*/
numberOfOccurences++;
write(index_pipe[WRITE], &i, sizeof(int));
}
i += step;
}
/**
* #brief write occurences to pipe if, and only if, the number of occurences is not 0,
* i.e. we have found the target at least once and return TRUE or FALSE
*
*/
if (numberOfOccurences != 0)
{
write(occurences_pipe[WRITE], &numberOfOccurences, sizeof(int));
return TRUE;
}
return FALSE;
}
/**
* #brief this prints a given array
*
* #param array the array we want to print
* #param size the size of the array
*/
void printArray(int *array, int size)
{
printf("Array: \n");
for (int i = 0; i < size; i++)
{
printf("%d ", array[i]);
}
printf("\n");
}
/**
* #brief entry point
*
* #return int EXIT_SUCCESS
*/
int main()
{
/**
* #brief initialize and allocate memory
*
*/
size = 13;
array = (int *)malloc(sizeof(int) * size);
pipe(index_pipe);
pipe(occurences_pipe);
int numerOfProccesses = 3;
int target = 15;
int totalOccurences = 0;
int status = -1;
int exit_status = -1;
int occurences = -1;
populate(array, size);
array[size - 1] = target;
printArray(array, size);
size_t processes[numerOfProccesses];
/**
* #brief create childrens and put them to work
*
*/
for (int i = 0; i < numerOfProccesses; i++)
{
processes[i] = fork();
if (CHILDREN == processes[i])
{
/**
* #brief get the search status and exit
*
*/
int exit_status = search(target, i, numerOfProccesses);
exit(exit_status);
}
}
/**
* #brief wait for children to exit
*
*/
for (int i = 0; i < numerOfProccesses; i++)
{
/**
* #brief wait for each children. If a children is done AND it has found taget, i.e. returned TRUE,
* then read the number of occurrences from pipe
*
*/
wait(&status);
if (WIFEXITED(status))
{
exit_status = WEXITSTATUS(status);
if (exit_status == TRUE)
{
read(occurences_pipe[READ], &occurences, sizeof(int));
totalOccurences += occurences;
}
}
}
/**
* #brief if the number of occurrences is 0, then we have'nt found target
*
*/
if (totalOccurences == 0)
{
printf("%d not found \n", target);
}
else
{
/**
* #brief else allocate memory for an array of size "occurrences" and read from index pipe
*
*/
printf("Found %d on %d positions\n", target, totalOccurences);
int *indexes = (int *)malloc(sizeof(int) * 3);
// for (int i = 0; i < totalOccurences; i++)
// {
// int value;
// read(index_pipe[READ], &value, sizeof(int));
// printf("Read %d \n", value);
// }
int pipe_status;
pipe_status = read(index_pipe[READ], indexes, totalOccurences);
printf("Pipe read %d bytes\n", pipe_status);
printArray(indexes, totalOccurences);
}
return 0;
}
Expected output:
Array:
83 86 77 15 93 35 86 92 49 21 62 27 15
Found 15 on 2 positions
Read 3
Read 12
Array:
3 12
I get this when reading a chunk at a time:
Array:
83 86 77 15 93 35 86 92 49 21 62 27 15
Found 15 on 2 positions
Pipe read 2 bytes
Array:
3 0
P.S. I wrote this on a linux machine. I compiled this using: gcc -g -o search search.c -Wextra
...
read(occurences_pipe[READ], &occurences, sizeof(int));
totalOccurences += occurences;
int *indexes = (int *)malloc(sizeof(int) * 3);
read(index_pipe[READ], indexes, totalOccurences);
Well, you are reading an unknown number of bytes, which is the sum of occurences of the numbers found within each process from the pipe and saving it into sizeof(int) * 3 bytes, which can possibly overflow. Also the totalOccurences is the sum from all the processes. I think you meant to:
int *indexes = (int *)malloc(sizeof(int) * totalOccurences);
read(index_pipe[READ], indexes, sizeof(int) * totalOccurences);
I like this idea of concurency and single pipes to communicate with multiple processes. You can speed things up a bit, by using realloc + read(index_pipe[READ], ..., sizeof(int) * occurences) right in the reading if (exit_status == TRUE) loop. That way you could earlier free the data buffered in pipe.
I don't think there is the need for occurences_pipe if you are just interested in the sum of all occurences. You can just set O_NONBLOCK on the index_pipe[READ], and read from it byte by byte (or chunk by chunk) until all threads will finish and the read will return 0. The sum of all occurences is the number of bytes read from index_pipe after all threads exited divided by sizeof(int).
I think that threads would be better suited for such task, you are copying the whole array between processes on fork, when using pthreads each thread would use the same memory.
And, for the love of K&R, don't cast the result of malloc.

Trouble with Assigning Jobs to Child Processes in C

I am working on a C program that reduces a PGM image. My algorithm should split the job into four unique tasks that my child processes handle, but they each are performing the same task as the child that went before them.
To be more specific, my program should write in four columns of the reduced image to form a completed image, but all I ever get is the first column and only the first column. I have confirmed that each child copies the job of the child before it by skipping the first child. When I do this, only the second column is shown in the result.
Below is a section of my source code:
int cc = cols/selection;
int rr = rows/selection;
unsigned char image2[rr][cc]; //creates the space for output image
char temp[rr][cc];
/*
/* Main part of program
/* reduces image by selecting every nth pixel and adding it to
/* image2.
*/
tp = 5; /* type==5 */
for (int x = 0; x < numChildren; x++){
if((childpids[x] = fork()) == -1)
{
perror("fork");
exit(1);
}
if(childpids[x] == 0)
{
/* Child process closes input*/
close(fd[0]);
/* Send 2D int array through output*/
for (i=0; i< rr; i++)
for(j = (cc / numChildren) * x; j < (cc / numChildren) * (x+1); j++)
{
temp[i][j]=imagePtr[((i*selection)*cols + (j*selection))];
}
write(fd[1], &temp, sizeof(temp));
exit(x);
}
else
{
/* Parent process closes output*/
close(fd[1]);
/* Read in a 2D int array from input*/
nbytes = read(fd[0], temp, sizeof(temp));
for (i=0; i< rr; i++)
for(j = 0; j < cc; j++)
{
image2[i][j]=temp[i][j];
}
}
}
imagePtr2=(image_ptr) image2;
printf("\n Now writing to image file ... \n");
//creates output image
write_pnm(imagePtr2, argv[2], rr, cc, tp);
Please note that some functions used are part of a library that was given to me for the purpose of writing this program.

Using pipes and structures with dynamically allocated variables in C

I'm writting a program that needs to pass a matrix from a parent process to its child (that's why I'm using the fork() instruction). I've just read this and this to solve the problem myself, but I still can't understand how to use the read() and write() instructions with the pipe I've created so far. I know these instructions write series of bytes, but I'm not sure about using them with structures or dynamically allocated variables (like a matrix).
Here is the code I used to test (note the comments I put):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
// Structure definition (Matrix)
typedef struct {
int **mat;
int rows;
int cols;
} Matrix;
int main() {
// Create the pipe
int file_desc[2];
if (pipe(file_desc) != 0) exit(1);
// Create two processes
if (fork() == 0) {
/** Instructions for the child process */
// Read the matrix structure from the pipe
Matrix *received = NULL;
read(file_desc[0], received, sizeof *received);
if (received != NULL) {
// Print the received matrix
int i, j;
printf("The matrix I've just *received* from the parent is:\n");
for (i = 0; i < received->cols; i++) {
for (j = 0; j < received->rows; j++) printf("%d\t", received->mat[i][j]);
printf("\n");
}
} else printf("received = NULL :'(\n");
} else {
/** Instructions for the parent process */
/* Create a matrix dinamically.
* In fact, in the real program I have a function to create a matrix given the
* rows and columns, and fill it with random values, so it returns a Matrix *
* (pointer to Matrix), but for testing purposes I've only written this
* (also useful if I need an array of Matrix elements, for example)
* */
Matrix *myMatrix = calloc(1, sizeof *myMatrix);
// Put the contents into the variable
myMatrix->rows = 2;
myMatrix->cols = 2;
myMatrix->mat = calloc(myMatrix->rows, sizeof *(myMatrix->mat));
int i, j;
for (i = 0; i < myMatrix->cols; i++)
(myMatrix->mat)[i] = calloc(myMatrix->cols, sizeof **(myMatrix->mat));
// Fill the matrix with some values (testing)
(myMatrix->mat)[0][0] = 4;
(myMatrix->mat)[0][1] = 2;
(myMatrix->mat)[1][0] = 1;
(myMatrix->mat)[1][1] = 3;
// Print the matrix
printf("The matrix I've just filled in the parent is:\n");
for (i = 0; i < myMatrix->cols; i++) {
for (j = 0; j < myMatrix->rows; j++) printf("%d\t", myMatrix->mat[i][j]);
printf("\n");
}
// Write the matrix structure to the pipe (here is where I have the problem!)
write(file_desc[1], myMatrix, sizeof *myMatrix);
// Wait for the child process to terminate
wait(0);
printf("The child process has just finished, the parent process continues.\n");
}
return 0;
}
In fact, I tried first with a pointer to an int and it worked. But when I run this program, I receive this output:
The matrix I've just filled in the parent is:
4 2
1 3
received = NULL :'(
The child process has just finished, the parent process continues.
And I don't know why I get the NULL -- I'm almost sure I'm using the write() instruction incorrectly. Any help about this will be appreciated =)
EDIT: I think the matrix should be converted to text, for example, and then pass the string to the child, parse it and convert it to a Matrix structure again. I don't know if this approach is the best. Is there another approach besides this one?
EDIT: I tried the same code with a static variable (changing int **mat; to int mat[2][2]; inside the structure declaration) but the user should change the matrix size.
This is a serious problem:
Matrix *received = NULL;
read(file_desc[0], received, sizeof *received);
Received is a null pointer. That read is going to try to write data to NULL, which is an invalid address. It would be much simpler to write:
Matrix received;
read(file_desc[0], &received, sizeof received);

MPI runtime error: Either Scatterv count error, segmentationfault, or gets stuck

/*
Matricefilenames:
small matrix A.bin of dimension 100 × 50
small matrix B.bin of dimension 50 × 100
large matrix A.bin of dimension 1000 × 500
large matrix B.bin of dimension 500 × 1000
An MPI program should be implemented such that it can
• accept two file names at run-time,
• let process 0 read the A and B matrices from the two data files,
• let process 0 distribute the pieces of A and B to all the other processes,
• involve all the processes to carry out the the chosen parallel algorithm
for matrix multiplication C = A * B ,
• let process 0 gather, from all the other processes, the different pieces
of C ,
• let process 0 write out the entire C matrix to a data file.
*/
int main(int argc, char *argv[]) {
printf("Oblig 2 \n");
double **matrixa;
double **matrixb;
int ma,na,my_ma,my_na;
int mb,nb,my_mb,my_nb;
int i,j,k;
int myrank,numprocs;
int konstanta,konstantb;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
if(myrank==0) {
read_matrix_binaryformat ("small_matrix_A.bin", &matrixa, &ma, &na);
read_matrix_binaryformat ("small_matrix_B.bin", &matrixb, &mb, &nb);
}
//mpi broadcast
MPI_Bcast(&ma,1,MPI_INT,0,MPI_COMM_WORLD);
MPI_Bcast(&mb,1,MPI_INT,0,MPI_COMM_WORLD);
MPI_Bcast(&na,1,MPI_INT,0,MPI_COMM_WORLD);
MPI_Bcast(&nb,1,MPI_INT,0,MPI_COMM_WORLD);
fflush(stdout);
int resta = ma % numprocs;//rest antall som har den største verdien
//int restb = mb % numprocs;
if (myrank == 0) {
printf("ma : %d",ma);
fflush(stdout);
printf("mb : %d",mb);
fflush(stdout);
}
MPI_Barrier(MPI_COMM_WORLD);
if (resta == 0) {
my_ma = ma / numprocs;
printf("null rest\n ");
fflush(stdout);
} else {
if (myrank < resta) {
my_ma = ma / numprocs + 1;//husk + 1
} else {
my_ma = ma / numprocs; //heltalls divisjon gir nedre verdien !
}
}
my_na = na;
my_nb = nb;
double **myblock = malloc(my_ma*sizeof(double*));
for(i=0;i<na;i++) {
myblock[i] = malloc(my_na*sizeof(double));
}
//send_cnt for scatterv
//________________________________________________________________________________________________________________________________________________
int* send_cnta = (int*)malloc(numprocs*sizeof(int));//array med antall elementer sendt til hver prosess array[i] = antall elementer , i er process
int tot_elemsa = my_ma*my_na;
MPI_Allgather(&tot_elemsa,1,MPI_INT,&send_cnta[0],1,MPI_INT,MPI_COMM_WORLD);//arrays i c må sendes &array[0]
//send_disp for scatterv
//__________________________________________________________________________________
int* send_dispa = (int*)malloc(numprocs*sizeof(int)); //hvorfor trenger disp
// int* send_dispb = (int*)malloc(numprocs*sizeof(int));
//disp hvor i imagechars første element til hver prosess skal til
fflush(stdout);
if(resta==0) {
send_dispa[myrank]=myrank*my_ma*my_na;
} else if(myrank<=resta) {
if(myrank<resta) {
send_dispa[myrank]=myrank*my_ma*my_na;
} else {//my_rank == rest
send_dispa[myrank]=myrank*(my_ma+1)*my_na;
konstanta=myrank*(my_ma+1)*my_na;
}
}
MPI_Bcast(&konstanta,1,MPI_INT,resta,MPI_COMM_WORLD);
if (myrank>resta){
send_dispa[myrank]=((myrank-resta)*(my_ma*my_na))+konstanta;
}
MPI_Allgather(&send_dispa[myrank],1,MPI_INT,&send_dispa[0],1,MPI_INT,MPI_COMM_WORLD);
//___________________________________________________________________________________
printf("print2: %d" , myrank);
fflush(stdout);
//recv_buffer for scatterv
double *recv_buffera=malloc((my_ma*my_na)*sizeof(double));
MPI_Scatterv(&matrixa[0], &send_cnta[0], &send_dispa[0], MPI_UNSIGNED_CHAR, &recv_buffera[0], my_ma*my_na, MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD);
for(i=0; i<my_ma; i++) {
for(j=0; j<my_na; j++) {
myblock[i][j]=recv_buffera[i*my_na + j];
}
}
MPI_Finalize();
return 0;
}
OLD:I get three type of errors. I can get scatterv count error, segmentationfault 11, or the processes just get stuck. It seems to be random which error I get. I run the code with 2 procs each time. When it gets stuck it gets stuck before the printf("print2: %d" , myrank);. When my friend runs the code on his own computer also with two prosesses, he does not get past by the first MPI_Bcast. Nothing is printed out when he runs it. Here is a link for the errors I get: http://justpaste.it/zs0
UPDATED PROBLEM: Now I get only a segmentation fault after " printf("print2: %d" , myrank); " before the scatterv call. EVEN if I remove all the code after the printf statement I get the segmentation fault, but only if I run the code for more than two procs.
I'm having a little difficulty tracing what you were trying to do. I think you're making the scatterv call more complicated than it needs to be though. Here's a snippet I had from a similar assignment this year. Hopefully it's a clearer example of how scatterv works.
/*********************************************************************
* Scatter A to All Processes
* - Using Scatterv for versatility.
*********************************************************************/
int *send_counts; // Send Counts
int *displacements; // Send Offsets
int chunk; // Number of Rows per Process (- Root)
int chunk_size; // Number of Doubles per Chunk
int remainder; // Number of Rows for Root Process
double * rbuffer; // Receive Buffer
// Do Some Math
chunk = m / (p - 1);
remainder = m % (p - 1);
chunk_size = chunk * n;
// Setup Send Counts
send_counts = malloc(p * sizeof(int));
send_counts[0] = remainder * n;
for (i = 1; i < p; i++)
send_counts[i] = chunk_size;
// Setup Displacements
displacements = malloc(p * sizeof(int));
displacements[0] = 0;
for (i = 1; i < p; i++)
displacements[i] = (remainder * n) + ((i - 1) * chunk_size);
// Allocate Receive Buffer
rbuffer = malloc(send_counts[my_rank] * sizeof(double));
// Scatter A Over All Processes!
MPI_Scatterv(A, // A
send_counts, // Array of counts [int]
displacements, // Array of displacements [int]
MPI_DOUBLE, // Sent Data Type
rbuffer, // Receive Buffer
send_counts[my_rank], // Receive Count - Per Process
MPI_DOUBLE, // Received Data Type
root, // Root
comm); // Comm World
MPI_Barrier(comm);
Also, this causes a segfault on my machine, no mpi... Pretty sure it's the way myblock is being allocated. You should do what #Hristo suggested in the comments. Allocate both matrices and the resultant matrix as flat arrays. That would eliminate the use of double pointers and make your life a whole lot simpler.
#include <stdio.h>
#include <stdlib.h>
void main ()
{
int na = 5;
int my_ma = 5;
int my_na = 5;
int i;
int j;
double **myblock = malloc(my_ma*sizeof(double*));
for(i=0;i<na;i++) {
myblock = malloc(my_na*sizeof(double));
}
unsigned char *recv_buffera=malloc((my_ma*my_na)*sizeof(unsigned char));
for(i=0; i<my_ma; i++) {
for(j=0; j<my_na; j++) {
myblock[i][j]=(float)recv_buffera[i*my_na + j];
}
}
}
Try allocating more like this:
// Allocate A, b, and y. Generate random A and b
double *buff=0;
if (my_rank==0)
{
int A_size = m*n, b_size = n, y_size = m;
int size = (A_size+b_size+y_size)*sizeof(double);
buff = (double*)malloc(size);
if (buff==NULL)
{
printf("Process %d failed to allocate %d bytes\n", my_rank, size);
MPI_Abort(comm,-1);
return 1;
}
// Set pointers
A = buff; b = A+m*n; y = b+n;
// Generate matrix and vector
genMatrix(m, n, A);
genVector(n, b);
}

Appending a value to the end of a dynamic array

Well I have been studying a little C this winter break and in my adventures I stumbled upon an issue with a Dynamic Array.
It's a fairly simple program really. What I am trying to do is to create an array that holds the numbers of the Fibonacci series. Here is the code:
#include <stdio.h>
#include <stdlib.h>
int dynamic_arry_append(int* arry, int* number, int* size);
int main() {
int i, n, size = 3, *arry = NULL, fibarr[size];
printf("Dynamic array, Fibonacci series. \n");
printf("Capture upto element: ");
scanf("%d", &n);
i = 0;
// passing the first elements
fibarr[0] = 0;
fibarr[1] = 1;
fibarr[2] = 1;
while ( i < n ) {
printf("**%d\n",fibarr[0]);
dynamic_arry_append( arry, &fibarr[0], &size );
fibarr[0] = fibarr[1];
fibarr[1] = fibarr[2];
fibarr[2] = fibarr[1] + fibarr[0];
i++;
}
for ( i = 0 ; i < size ; i++)
printf("Element %d of the array: %d.\n", i, arry[i]);
return 0;
}
int dynamic_arry_append(int* arry, int* number, int* size) {
int i;
int bacon = *size; // first name i thought of
bacon++;
int *new_addr = realloc(arry, bacon * sizeof(int));
if( new_addr != NULL ) {
arry = new_addr;
arry[bacon-1] = *number;
// printf for easier debugging, or so i thought
for ( i = 0 ; i < bacon ; i++ )
printf("%d\t%d\n", i+1, arry[i]);
printf("\n");
*size = bacon;
} else {
printf("Error (re)allocating memory.");
exit (1);
}
return 0;
}
At least in my mind this works. However, in practice I get funny results:
Dynamic array, Fibonacci series.
Capture upto element: 5
**0 // next fibonacci number
1 5256368
2 5246872
3 1176530273
4 0
**1
1 5256368
2 5246872
3 1768053847
4 977484654
5 1
**1
1 5256368
2 5246872
3 1551066476
4 1919117645
5 1718580079
6 1
**2
1 5256368
2 5246872
3 977484645
4 1852397404
5 1937207140
6 1937339228
7 2
**3
1 5256368
2 5246872
3 1551071087
4 1953724755
5 842231141
6 1700943708
7 977484653
8 3
/* Code::Blocks output */
Process returned -1073741819 (0xC0000005) execution time : 17.886 s
Press any key to continue.
I am really baffled by this error, and after searching around I found no solution...Can anyone help? Thank you very much.
#include <stdio.h>
#include <stdlib.h>
int * dynamic_array_append(int * array, int size);
int main() {
int i, n, size=0, *array = NULL;
printf("Dynamic array, Fibonacci series. \n");
printf("Capture upto element: ");
scanf("%d", &n);
for (i=0 ; i<n ; i++)
array = dynamic_array_append(array, i);
for (i=0 ; i<n ; i++)
printf("array[%d] = %d\n", i, array[i]);
return 0;
}
int * dynamic_array_append(int * array, int size)
{
int i;
int n1, n2;
int new_size = size + 1;
int * new_addr = (int *) realloc(array, new_size * (int)sizeof(int));
if (new_addr == NULL) {
printf("ERROR: unable to realloc memory \n");
return NULL;
}
if (size == 0 || size == 1) {
new_addr[size] = size;
return new_addr;
}
n1 = new_addr[size-1];
n2 = new_addr[size];
new_addr[new_size-1] = new_addr[new_size-2] + new_addr[new_size-3];
return new_addr;
}
/*
Output:
Dynamic array, Fibonacci series.
Capture upto element: 10
array[0] = 0
array[1] = 1
array[2] = 1
array[3] = 2
array[4] = 3
array[5] = 5
array[6] = 8
array[7] = 13
array[8] = 21
array[9] = 34
*/
Points to note:
The newly (re)allocated array should be returned back to main and stored in a pointer-to-int (or) pass pointer-to-pointer-to-int and update it accordingly once after reallocing
The fibarr is not needed. It doesn't solve any problem.
You don't have to pass the size and the number. Just send the size and it will pick the n-1 and n-2 to calculate n.
This is considered to be highly inefficient. Because if you know the n then you can allocate memory for n integers in one shot and calculate the fib series.
The problem may be that the arry pointer variable is passed by value to the function dynamic_arry_append. That means, that changes that you make to the arry variable within that function will not be reflected by any variables outside of that function. For example:
int *a = NULL;
someFunc(a);
// a will still be NULL here no matter what someFunc does to it.
You should declare your fibarr as a pointer (so name it differently) not an array. And you should pass to your dynamic_arry_append the address of that pointer, like &fibarr. And you should initialize fibarr in your main with calloc. At last you should dynamically update (and keep, and pass) the size of the allocated array.
You are not returning the new address of the array... and you are reading/writing not your memory. Run the program with all error messages under debugger and you'll see the problem is in this line:
dynamic_arry_append( arry, &fibarr[0], &size );

Resources