Using pipes and structures with dynamically allocated variables in C - 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);

Related

Stuck at counting array elements greater than x in an array in C/MPI

So, I have this problem where I have an array and I must find the count of numbers that are greater than the number of index k in my array. So I implemented a master-worker strategy where I have a master that takes care of the I/O and split the work to the workers. In the master thread I have created the array in a matrix-like shape, so I could pass the sub-arrays easily to the workers (I know this sounds weird). Then also in the master thread I read all the values from the input to my sub-arrays and set the comp (comparison value) to the value of the k index value.
Then I pass the work portion size, the value for comparison and work data around to all the threads (including the master that gets its share of work). Finally, every worker do its job and report its result to the master, that while receiving the data from the workers will add their values to its own and then print the total result on the screen.
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <math.h>
int main(int argc, char *args[]){
int rank, psize;
MPI_Status status;
MPI_Init(&argc, &args);
MPI_Comm_size(MPI_COMM_WORLD, &psize);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
int *workvet, worksize, comp;
if(rank == 0){
int tam, k;
int **subvets, portion;
scanf("%d", &tam);
scanf("%d", &k);
portion = ceil((float)tam/(float)psize);
subvets = malloc(sizeof(int) * psize);
for(int i = 0; i < psize; i++)
subvets[i] = calloc(portion, sizeof(int));
for(int i = 0; i < psize; i++){
for(int j = 0; j < portion; j++){
if((i*j+j) < tam)
scanf("%d ", &subvets[i][j]);
if((i*j+j) == k)
comp = subvets[i][j];
}
}
for(int i = 1; i < psize; i++){
MPI_Send(&portion, 1, MPI_INT, i, i, MPI_COMM_WORLD);
MPI_Send(&comp, 1, MPI_INT, i, i, MPI_COMM_WORLD);
MPI_Send(subvets[i], portion, MPI_INT, i, i, MPI_COMM_WORLD);
}
workvet = calloc(portion, sizeof(int));
workvet = subvets[0];
worksize = portion;
} else {
MPI_Recv(&worksize, 1, MPI_INT, 0, rank, MPI_COMM_WORLD, &status);
MPI_Recv(&comp, 1, MPI_INT, 0, rank, MPI_COMM_WORLD, &status);
workvet = calloc(worksize, sizeof(int));
MPI_Recv(workvet, worksize, MPI_INT, 0, rank, MPI_COMM_WORLD, &status);
}
int maior = 0;
for(int i = 0; i < worksize; i++){
if(workvet[i] > comp)
maior++;
}
if(rank == 0){
int temp;
for(int i = 1; i < psize; i++){
MPI_Recv(&temp, 1, MPI_INT, i, rank, MPI_COMM_WORLD, &status);
maior += temp;
}
printf("%d nĂºmeros maiores que %d", maior, comp);
} else {
MPI_Send(&maior, 1, MPI_INT, 0, rank, MPI_COMM_WORLD);
}
MPI_Finalize();
}
My problem is that it looks like its stuck in a loop, and when trying to debug I put an printf in the main for that does the comparison in the sub-arrays and did infinite printing, however, when I put the same print anywhere else in the code, it won't be printed. I don't have any idea where I'm failing and have no idea on how I can debug my code.
Input data:
10 // size
7 // k
1 2 3 4 5 6 7 8 9 10 // elements
So, my program should count how many elements are greater than the element of index 7, which corresponds to the value 8, and this should return 2 in this case.
This is prefaced by my top comment re. tam being unitialized.
There are a number of additional issues ...
You're doing scanf to get a value for comp, but in the loops below it, you're assigning a new value to it (i.e. the prompted value is being trashed). That may be perfectly fine if the original value is treated as a default [if the loop fails to assign a new value], but it seems a bit rickety to me.
AFAICT, you are trying to loop on workvet in all processes. But, for the client ones, this does nothing because you don't send back the result [see below].
The clients are sending back maior but they never compute a value for it. And, main does not receive that value. It computes one of its own.
maior has no definition in your posted code. And, therefore is unitialized [even in main].
It looks like you want the clients to send back a single scalar value of their computed value of maior, but they do no calculation for it.
Thus, the clients send back a garbage maior value that the main process tries to sum.
You're sending portion to the clients, but they receive it as worksize. And, after main sends it, it assigns portion to worksize. I'd recommend using the same name in all places to reduce some confusion.
You've not provided any sample data so it's hard to debug this further here. Part of the problem is that only some of the values in subvets are initialized with the scanf in main, based on the if [or so it appears ...].
So, the clients will loop over possibly unitialized values in the given subvets array [sent to the client which receives it as workvet].
If the setup loops for subvets are correct as far as which values to send (that is, only certain selected values should be sent), I'm not sure you can do what you want with the 2D array method you have.
Without a problem statement describing the input data and what you want to do with it, it's difficult to divine what would be the correct code, but ...
A few guesses ...
You're calculating highest in all processes [probably useless in main], but then nobody does anything with it. My guess is that you want to calculate this in the client processes only. And, send this back to main as maior.
Then, main can sum the maior values from all the clients?
UPDATE:
I actually changed maior to highest to post the issue here, so it would make a bit of sense (maior is greater in portuguese) but failed to do so for all instances
As I mentioned, I guessed as much -- no worries. Side note: In fact, your English is quite good. And, it was nice of you to translate the code. Some others post in English, but leave the code in their native language. This can slow things down a bit. Sometimes, I've put the code into Google translate just to try to make sense of it.
I just updated the code without the translation to reflect what I'm working on. So, for the subvets part I actually thought of this being a matrix, where I would send each of its lines as being one array to each of the worker threads, and the if statement is there to only read up until the size of the array has been reached, thus, leaving the rest of the values as 0 (because I used calloc, thus making this approach fit to the problem I have to solve)
There's really no need for a 2D array. Just fill a 1D array, and then give each worker different offsets and counts into that single array [see below].
By trying to do everything in a single function main, this is probably what caused some of the problems with separating main and worker tasks.
By splitting things up into [more] functions, this can make things easier. We can use the same variable names in master and worker for the same data without any naming conflicts.
Also, a good maxim ... Don't replicate code
The various MPI_* calls take a lot of parameters because they're general purpose. Isolating them to wrapper functions can make things simpler and debugging easier.
Note that the second argument to MPI_Send/MPI_Recv is a count and not number of bytes (hence, not sizeof) (i.e. a bug). By putting them in wrapper functions, the call could be fixed once in a single place.
I did make a slight change to the split logic. In your code [AFAICT] you were having the main/master process do some of the calculation. That's fine but I prefer to have the main process available as a control process and not encumbered by much data calculation. So, in my version, only the worker processes actually process the array.
Sometimes it helps to isolate the calculation algorithm/logic from the MPI code. I did this below by putting it in a function docalc. This allowed the adding of a diagnostic cross check at the end.
Anyway, below it the code. It's been heavily refactored and has many comments:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <math.h>
// _dbgprt -- debug print
#define _dbgprt(_fmt...) \
do { \
printf("%d: ",myrank); \
printf(_fmt); \
} while (0)
#ifdef DEBUG
#define dbgprt(_fmt...) \
_dbgprt(_fmt)
#else
#define dbgprt(_fmt...) \
do { \
} while (0)
#endif
int myrank; // current rank
int numproc; // number of processes in comm group
// dataload -- read in the data
int *
dataload(FILE *xfsrc,int worksize)
{
int *workvet;
// get enough space
workvet = calloc(worksize,sizeof(int));
// fill the array
for (int idx = 0; idx < worksize; ++idx)
fscanf(xfsrc,"%d",&workvet[idx]);
return workvet;
}
// docalc -- count number of values greater than limit
int
docalc(int *workvet,int worksize,int k)
{
int count = 0;
for (int idx = 0; idx < worksize; ++idx) {
if (workvet[idx] > k)
count += 1;
}
return count;
}
// sendint -- send some data
void
sendint(int rankto,int *data,int count)
{
int tag = 0;
// NOTE: second argument is an array _count_ and _not_ the number of bytes
MPI_Send(data,count,MPI_INT,rankto,tag,MPI_COMM_WORLD);
}
// recvint -- receive some data
void
recvint(int rankfrom,int *data,int count)
{
int tag = 0;
MPI_Status status;
MPI_Recv(data,count,MPI_INT,rankfrom,tag,MPI_COMM_WORLD,&status);
}
// worker -- perform all worker operations
void
worker(void)
{
int master = 0;
// get array count
int worksize;
recvint(master,&worksize,1);
// get limit value
int k;
recvint(master,&k,1);
// allocate space for data
int *workvet = calloc(worksize,sizeof(int));
// get that data
recvint(master,workvet,worksize);
// calculate number of elements higher than limit
int count = docalc(workvet,worksize,k);
// send back result
sendint(master,&count,1);
}
// master -- perform all master operations
void
master(int argc,char **argv)
{
int isfile;
FILE *xfsrc;
int workrank;
// get the data either from stdin or from a file passed on the command line
do {
isfile = 0;
xfsrc = stdin;
if (argc <= 0)
break;
xfsrc = fopen(*argv,"r");
if (xfsrc == NULL) {
perror(*argv);
exit(1);
}
isfile = 1;
} while (0);
// get number of data elements
int worksize;
fscanf(xfsrc,"%d",&worksize);
// get limit [pivot]
int k;
fscanf(xfsrc,"%d",&k);
dbgprt("master: PARAMS worksize=%d k=%d\n",worksize,k);
// read in the data array
int *workvet = dataload(xfsrc,worksize);
if (isfile)
fclose(xfsrc);
// get number of workers
// NOTE: we do _not_ have the master do calculations [for simplicity]
// usually, for large data, we want the master free to control things
int numworkers = numproc - 1;
// get number of elements for each worker
int workper = worksize / numworkers;
dbgprt("master: LOOP numworkers=%d workper=%d\n",numworkers,workper);
// send data to other workers
int remain = worksize;
int offset = 0;
int portion;
for (workrank = 1; workrank < numproc; ++workrank,
offset += portion, remain -= portion) {
// get amount for this worker
portion = workper;
// last proc must get all remaining work
if (workrank == (numproc - 1))
portion = remain;
dbgprt("master: WORK/%d offset=%d portion=%d\n",
workrank,offset,portion);
// send the worker's data count
sendint(workrank,&portion,1);
// send the pivot point
sendint(workrank,&k,1);
// send the data to worker
sendint(workrank,&workvet[offset],portion);
}
// accumulate count
int total = 0;
int count;
for (workrank = 1; workrank < numproc; ++workrank) {
recvint(workrank,&count,1);
total += count;
}
printf("%d numbers bigger than %d\n",total,k);
// do cross check of MPI result against a simple single process solution
#ifdef CHECK
count = docalc(workvet,worksize,k);
printf("master count was %d -- %s\n",
count,(count == total) ? "PASS" : "FAIL");
#endif
}
// main -- main program
int
main(int argc,char **argv)
{
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numproc);
MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
// skip over program name
--argc;
++argv;
if (myrank == 0)
master(argc,argv);
else
worker();
MPI_Finalize();
return 0;
}

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.

mex made from c code crashes in loop, but not when ran once

I have a function written in C that i turn into a matlab executible (mex file). The C-function works fine when called once from matlab's command line, however when called 1000+ times in a for-loop it spontaneously crashes. This happens even if I feed it the same input at each iteration of the for-loop.
I am afraid I have a lurking c-bug. some issue with repeated memory allocation but I dont know enough c to fix it :(
I have narrowed the problem down to the WHILE loop in the below code (if the whole while-loop is commented out prior to compiling the problem goes away). Please help!
#include "mex.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int sum_array(double a[], int from ,int to);
// to compile this code in matlab do: mex -v ranksort.c
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
#define B_OUT plhs[0]
#define A_IN prhs[0]
int i,j,count,M,N; //declare some integers
double *list,*sort_list,*rank_idx,*sort_idx,*ranksOrigOrder;//declare some pointers to doubles which will be allocated dynamically
int *rank_list,*tielocs,*orig_indices;
//set values based on input:
M=mxGetM(A_IN);//get input row num
N=mxGetN(A_IN);//get input col num
if (M>N)
count=M; //get dimensions of A (columns...data must always be in columns)
else
count=N;
list =mxGetPr(A_IN); //grab data from pointer to inputted data
sort_list = calloc(count,sizeof(double)); //allocate size and fill w/zeros all my 'double' arrays
rank_idx =calloc(count,sizeof(double));
sort_idx=calloc(count,sizeof(double));
ranksOrigOrder=calloc(count,sizeof(double));
tielocs =calloc(count+2,sizeof(double));
orig_indices=calloc(count,sizeof(int)); //allocate size and fill w/ zeros all my 'int' arrays
rank_list =calloc(count,sizeof(int));
if (sort_list==NULL||tielocs==NULL||rank_list==NULL||orig_indices==NULL||ranksOrigOrder==NULL||rank_idx==NULL||list==NULL){ puts ("Error (re)allocating memory"); exit (1); }
B_OUT = mxCreateDoubleMatrix(M, N, mxREAL); //create a matlab-style struct for output...
ranksOrigOrder = mxGetPr(B_OUT); // set in-code variable to its pointer
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CODE BODY STARTS HERE ~~~~~~~~~~~~~~~~~~~~*/
/*Calculate the rank for each element in the arr_list*/
for(i=0; i<count; i++){
for(j=0; j<i; j++){
if(list[i] >= list[j])
rank_list[i]++;
else
rank_list[j]++;
}
}
for(i=0; i<count; i++){
sort_list[rank_list[i]] = list[i];
orig_indices[rank_list[i]] =i;
sort_idx[i]=i+1;
}
int tiesIdx=0; int *ties = NULL;
for (i=0; i<count-1;i++){
if (sort_list[i]>= sort_list[i+1]){
ties = (int*) realloc (ties, (tiesIdx) *sizeof(int)); //reallocate size of array
if (ties==NULL){ puts ("Error (re)allocating memory"); exit (1); }
ties[tiesIdx]=i; //add location of tie to newly grown array
tiesIdx++; //found a tie
}
}
// // append 2 after last element to ties
ties = (int*) realloc (ties, (tiesIdx) * sizeof(int));
//reallocate size of array
if (ties==NULL){ puts ("Error (re)allocating memory"); exit (1); }
ties[tiesIdx]=count+1;
tiesIdx++;
int tiecount=0; //step thru all the found ties
// NO IN-LOOP CRASHING if this while loop is commented out....
while (tiecount<tiesIdx){
int tiestart =ties[tiecount]; //grab this tie to check if it is one of a pair or a member of an island of consecutives
int ntied=2;
while (ties[tiecount+1] == ties[tiecount] + 1){ //while it's a consecutive one...
tiecount++;
ntied++;
}
double mysum = (double)sum_array(sort_idx,tiestart,tiestart+ntied)/(double)ntied;
for (int t=tiestart; t<tiestart+ntied;t++){
sort_idx[t]=mysum;
}
tiecount++;
}
for (i=0; i<count;i++){
ranksOrigOrder[orig_indices[i]]=sort_idx[i];
}
free(sort_list);
free(tielocs);
free(rank_list);
free(orig_indices);
free(rank_idx);
free(sort_idx);
return;
}
int sum_array(double a[], int from ,int to){
int i, sum=0;
for (i=from; i<to; i++){
sum = sum + (int)a[i];
}
return(sum);
}
Take a look at this chunk of code:
// // append 2 after last element to ties
ties = (int*) realloc (ties, (tiesIdx) * sizeof(int));
//reallocate size of array
if (ties==NULL){ puts ("Error (re)allocating memory"); exit (1); }
ties[tiesIdx]=count+1;
tiesIdx++;
int tiecount=0; //step thru all the found ties
// NO IN-LOOP CRASHING if this while loop is commented out....
while (tiecount<tiesIdx){
Your are re-allocating space for tiesIdx element, and a little after you want to access tiesIdx position of the ties array. This is Undefined Behaviour because of your array have to be indexed from 0 to tiesIdx-1
After that you inc tiesIdx by 1 and then perform a loop on that incremented var, that is obviously Undefined Behaviour because you will index array out of bounds.
Furthermore the inner loop:
while (ties[tiecount+1] == ties[tiecount] + 1){ //while it's a consecutive one...
tiecount++;
ntied++;
}
is not checking for array bounds: if all elements of ties are consecutive you'll index the array out of bounds.
NOTE: You have a memory leakage on ranksOrigOrder that it is not free().

Discrepancies in Matrix Data Communicated Between Parent and Child Process

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.

Matrix Multiply with Threads (each thread does single multiply)

I'm looking to do a matrix multiply using threads where each thread does a single multiplication and then the main thread will add up all of the results and place them in the appropriate spot in the final matrix (after the other threads have exited).
The way I am trying to do it is to create a single row array that holds the results of each thread. Then I would go through the array and add + place the results in the final matrix.
Ex: If you have the matrices:
A = [{1,4}, {2,5}, {3,6}]
B = [{8,7,6}, {5,4,3}]
Then I want an array holding [8, 20, 7, 16, 6, 12, 16 etc]
I would then loop through the array adding up every 2 numbers and placing them in my final array.
This is a HW assignment so I am not looking for exact code, but some logic on how to store the results in the array properly. I'm struggling with how to keep track of where I am in each matrix so that I don't miss any numbers.
Thanks.
EDIT2: Forgot to mention that there must be a single thread for every single multiplication to be done. Meaning for the example above, there will be 18 threads each doing its own calculation.
EDIT: I'm currently using this code as a base to work off of.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define M 3
#define K 2
#define N 3
#define NUM_THREADS 10
int A [M][K] = { {1,4}, {2,5}, {3,6} };
int B [K][N] = { {8,7,6}, {5,4,3} };
int C [M][N];
struct v {
int i; /* row */
int j; /* column */
};
void *runner(void *param); /* the thread */
int main(int argc, char *argv[]) {
int i,j, count = 0;
for(i = 0; i < M; i++) {
for(j = 0; j < N; j++) {
//Assign a row and column for each thread
struct v *data = (struct v *) malloc(sizeof(struct v));
data->i = i;
data->j = j;
/* Now create the thread passing it data as a parameter */
pthread_t tid; //Thread ID
pthread_attr_t attr; //Set of thread attributes
//Get the default attributes
pthread_attr_init(&attr);
//Create the thread
pthread_create(&tid,&attr,runner,data);
//Make sure the parent waits for all thread to complete
pthread_join(tid, NULL);
count++;
}
}
//Print out the resulting matrix
for(i = 0; i < M; i++) {
for(j = 0; j < N; j++) {
printf("%d ", C[i][j]);
}
printf("\n");
}
}
//The thread will begin control in this function
void *runner(void *param) {
struct v *data = param; // the structure that holds our data
int n, sum = 0; //the counter and sum
//Row multiplied by column
for(n = 0; n< K; n++){
sum += A[data->i][n] * B[n][data->j];
}
//assign the sum to its coordinate
C[data->i][data->j] = sum;
//Exit the thread
pthread_exit(0);
}
Source: http://macboypro.wordpress.com/2009/05/20/matrix-multiplication-in-c-using-pthreads-on-linux/
You need to store M * K * N element-wise products. The idea is presumably that the threads will all run in parallel, or at least will be able to do, so each thread needs its own distinct storage location of appropriate type. A straightforward way to do that would be to create an array with that many elements ... but of what element type?
Each thread will need to know not only where to store its result, but also which multiplication to perform. All of that information needs to be conveyed via a single argument of type void *. One would typically, then, create a structure type suitable for holding all the data needed by one thread, create an instance of that structure type for each thread, and pass pointers to those structures. Sounds like you want an array of structures, then.
The details could be worked a variety of ways, but the one that seems most natural to me is to give the structure members for the two factors, and a member in which to store the product. I would then have the main thread declare a 3D array of such structures (if the needed total number is smallish) or else dynamically allocate one. For example,
struct multiplication {
// written by the main thread; read by the compute thread:
int factor1;
int factor2;
// written by the compute thread; read by the main thread:
int product;
} partial_result[M][K][N];
How to write code around that is left as the exercise it is intended to be.
Not sure haw many threads you would need to dispatch and I am also not sure if you would use join later to pick them up. I am guessing you are in C here so I would use the thread id as a way to track which row to process .. something like :
#define NUM_THREADS 64
/*
* struct to pass parameters to a dispatched thread
*/
typedef struct {
int value; /* thread number */
char somechar[128]; /* char data passed to thread */
unsigned long ret;
struct foo *row;
} thread_parm_t;
Where I am guessing that each thread will pick up its row data in the pointer *row which has some defined type foo. A bunch of integers or floats or even complex types. Whatever you need to pass to the thread.
/*
* the thread to actually crunch the row data
*/
void *thr_rowcrunch( void *parm );
pthread_t tid[NUM_THREADS]; /* POSIX array of thread IDs */
Then in your main code segment something like :
thread_parm_t *parm=NULL;
Then dispatch the threads with something like :
for ( i = 0; i < NUM_THREADS; i++) {
parm = malloc(sizeof(thread_parm_t));
parm->value = i;
strcpy(parm->somechar, char_data_to-pass );
fill_in_row ( parm->row, my_row_data );
pthread_create(&tid[i], NULL, thr_insert, (void *)parm);
}
Then later on :
for ( i = 0; i < NUM_THREADS; i++)
pthread_join(tid[i], NULL);
However the real work needs to be done in thr_rowcrunch( void *parm ) which receives the row data and then each thread just knows its own thread number. The guts of what you do in that dispatched thread however I can only guess at.
Just trying to help here, not sure if this is clear.

Resources