MPI_AllGather not gather properly...all elements end up the same value? - c

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <time.h>
#define h 1
#define XY0 0
#define MAX_XY 5
#define N 2 //particles per subdomain
#define BLOCKS 4
#define a 1
#define b 1
float velocityX(float x, float y);
float velocityY(float x, float y);
int malloc2dfloat(float ***array, int length);
int main (int argc, char **argv)
{
typedef struct {
float xcoord;
float ycoord;
float velx;
float vely;
} particle;
int points= (int) floor((MAX_XY - XY0)/h) + 1;
int procsize = 2;
int myid, nproc;
MPI_Datatype particletype, oldtypes[1];
MPI_Aint offset[1], extent;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
int startElementX, startElementY, endElementX, endElementY;
particle* sub_pars = (particle*)malloc(sizeof(particle)*N);
offset[0] = 0;
int blockcounts[1];
blockcounts[0] = 4;
oldtypes[0] = MPI_FLOAT;
MPI_Type_struct(1, blockcounts, offset, oldtypes, &particletype);
MPI_Type_commit(&particletype);
particle* particles = (particle*)malloc(sizeof(particle) * N * procsize*procsize);
if (nproc != procsize*procsize){
printf("Must use np=4 -- split into 4 blocks");
MPI_Abort(MPI_COMM_WORLD,1);
}
srand(time(NULL)+myid);
if (myid == 0)
{
float mins[4];
startElementX = 0;
startElementY = 0;
endElementX = (points/procsize)-1;
endElementY = (points/procsize) -1;
}
else if (myid == 1)
{
startElementX = 0;
startElementY = (points/procsize);
endElementX = (points/procsize) -1;
endElementY = points - 1;
}
else if (myid == 2)
{
startElementX = (points/procsize);
startElementY = 0;
endElementX = points - 1;
endElementY = (points/procsize) -1;
}
else
{
startElementX = (points/procsize);
startElementY = (points/procsize);
endElementX = points-1;
endElementY = points-1;
}
int i;
float localmin;
float mag;
for (i=0; i<N; i++)
{
sub_pars[i].xcoord = ((startElementX + rand()/(RAND_MAX / (endElementX-startElementX+1)+1)))*h + XY0;
printf("%f\n", sub_pars[i].xcoord);
sub_pars[i].ycoord = ((startElementY + rand()/(RAND_MAX / (endElementY-startElementY+1)+1)))*h + XY0;
sub_pars[i].velx = velocityX(sub_pars[i].xcoord, sub_pars[i].ycoord);
sub_pars[i].vely = velocityY(sub_pars[i].xcoord, sub_pars[i].ycoord);
mag = sqrt(sub_pars[i].velx*sub_pars[i].velx + sub_pars[i].vely*sub_pars[i].vely);
if (i==0 || localmin > mag) localmin = mag;
}
printf("localmin of %d is %.2f \n", myid, localmin);
MPI_Allgather(&sub_pars, 1, particletype, particles ,1, particletype, MPI_COMM_WORLD);
MPI_Finalize();
if(myid == 0)
{
int k;
for (k=0; k<N*4; k++)
{
printf("test %.2f \n", particles[i].xcoord);
}
}
return 0;
}
float velocityX(float x, float y)
{
float temp = (a+(b*(y*y-x*x))/((x*x+y*y)*(x*x+y*y)));
return temp;
}
float velocityY(float x, float y)
{
float temp = (-1*(2*b*x*y)/((x*x+y*y)*(x*x+y*y)));
return temp;
}
It just returns the same value for all the particles, but I know they are being calculate correctly within each thread, so something is wrong with my MPI_Allgather, can someone please explain how it should look?

You have made a very common mistake: the & (address-of) operator in the first argument that you pass to MPI_Allgather is unnecessary. sub_pars is already a pointer and calling MPI_Allgather with &sub_pars passes a pointer to the pointer (a location somewhere in the stack frame of the main() routine) instead of pointer to the actual data.

Related

OpenMP paralleling GSL Ordinary Differential Equations calculation

I'm trying to parallelize my code, but i got errors. I need to calc a Cauchy problem (it's already done) but than i need to parallelize it using OpenMP lib.
I've tried to write some code with OpenMP, but it's not working.
I've created a struct to collect result.
struct Dots {
double par;
double x;
double y;
};
This is my target function with parameter.
int ode_func (double x, const double y[], double f[], void *params)
{
double mu = *(int *)params;
f[0] = x + 2 * y[0] / (1 + mu * mu);
return GSL_SUCCESS;
}
This is the main function. I currently didn't find a way how to create a array of arrays of struct, but this is not the main problem.
void calc_cauchy_problem(struct Dots ArrayOfDots[], double x_start, double x_end, double y_start,
int count) {
int dim = 1;
double x = x_start;
double y[1] = {y_start};
int mu = 5;
int param = 0;
gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new (&sys,
gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
int status = 0;
#pragma omp parallel for shared(ArrayOfDots) private(sys, param, d, status)
for (int param = 1; param < mu; param++) {
gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new (&sys,
gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
for (int i = 1; i <= count; i++)
{
double xi = x_start + i * (x_end - x_start) / count;
int status = gsl_odeiv2_driver_apply(d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
// ArrayOfDots[i].par = mu;
// ArrayOfDots[i].x = xi;
// ArrayOfDots[i].y = y[0];
}
gsl_odeiv2_driver_free (d);
}
}
The main
int main() {
double x_start = 0;
double x_end = 10;
double y_start = 0;
int count = 10;
struct Dots ArrayOfDots[count];
calc_cauchy_problem(ArrayOfDots, x_start, x_end, y_start, count);
return 0;
}
It's compiled successfully with this gcc main.c -o main -fopenmp -lgsl -std=gnu11 but when i launch it i got error
gsl: driver.c:354: ERROR: integration limits and/or step direction not consistent
Default GSL error handler invoked.
I think that the main problem with this #pragma omp parallel for shared(ArrayOfDots) private(sys, param, d, status) but i have no idea how to rewrite this in the other way.
Thanks for your responses.
UPD:
With Kaveh Vahedipour help my code partially start to work. It means that half of my for cycle start to work.
UPD UPD:
After another investigations i had the following code:
It's compile and run, but i got Process finished with exit code 4 and printf("Elapsed time = %f\n", omp_get_wtime() - start_time); don't print anything.
struct Dots {
double par;
double x;
double y;
};
int ode_func (double x, const double y[], double f[], void *params)
{
double mu = *(int *)params;
f[0] = (x + 2 * y[0]) / (1 + mu * mu);
return GSL_SUCCESS;
}
void calc_cauchy_problem(double x_start, double x_end, double y_start,
int count, int param1, int param2) {
int dim = 1;
double x = x_start;
double y[1] = {y_start};
int param = param1;
int j = 0;
int status = 0;
char filename[10];
#pragma omp parallel for private(param, status, x, y)
for (param = param1; param <= param2; param++) {
struct Dots ArrayOfDots[count];
gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
gsl_odeiv2_driver * d =
gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
for (int i = 1; i <= count; i++) {
double xi = x_start + i * (x_end - x_start) / count;
int status = gsl_odeiv2_driver_apply(d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
ArrayOfDots[i].par = param;
ArrayOfDots[i].x = xi;
ArrayOfDots[i].y = y[0];
}
gsl_odeiv2_driver_free (d);
}
}
int main() {
double start_time = omp_get_wtime();
double x_start = 0;
double x_end = 10;
double y_start = 0;
const int count = 500;
int param1 = 1;
int param2 = 10;
calc_cauchy_problem(x_start, x_end, y_start, count, param1, param2);
printf("Elapsed time = %f\n", omp_get_wtime() - start_time);
return 0;
}
Add x to private loop vars: private(sys, param, d, status, x). Please get back to me, if you still experience issues.
void calc_cauchy_problem(double x_start, double x_end, double y_start,
int count, int param1, int param2) {
int dim = 1;
double x = x_start;
double y[1] = {y_start};
int param = param1;
int j = 0;
int status = 0;
char filename[10];
#pragma omp parallel for private(param, status, x, y)
for (param = param1; param <= param2; param++) {
struct Dots ArrayOfDots[count];
gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
gsl_odeiv2_driver * d =
gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
for (int i = 1; i <= count; i++) {
double xi = x_start + i * (x_end - x_start) / count;
int status = gsl_odeiv2_driver_apply(d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
ArrayOfDots[i].par = param;
ArrayOfDots[i].x = xi;
ArrayOfDots[i].y = y[0];
}
//write_data_to_file(param, count, ArrayOfDots);
for (int i = 0; i < count; ++i) {
printf ("%d: %f, %f, %f\n", omp_get_thread_num(),
ArrayOfDots[i].par, ArrayOfDots[i].x, ArrayOfDots[i].y);
}
gsl_odeiv2_driver_free (d);
}
}
Seems like this version works fine. I think problem was with this struct Dots ArrayOfDots[count]; and when i try to push values to this struct.
ArrayOfDots[i].par = param;
ArrayOfDots[i].x = xi;
ArrayOfDots[i].y = y[0];
Here is the full code.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>
// GSL lib includes
#include <gsl/gsl_sf_bessel.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_odeiv2.h>
int ode_func (double x, const double y[], double f[], void *params)
{
double mu = *(int *)params;
f[0] = (x + 2 * y[0]) / (1 + mu * mu);
return GSL_SUCCESS;
}
void calc_cauchy_problem(double x_start, double x_end, double y_start,
int count, int param1, int param2) {
#pragma omp parallel for
for(int param = param1; param < param2; param++) {
gsl_odeiv2_system sys = {ode_func, NULL, 1, &param};
gsl_odeiv2_driver * d =
gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rk8pd,
1e-6, 1e-6, 0.0);
int i;
double x = x_start, x1 = x_end;
double y[1] = { y_start };
for (i = 1; i <= count; i++)
{
double xi = i * x1 / count;
int status = gsl_odeiv2_driver_apply (d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
// printf ("%d %d %.5e %.5e\n", omp_get_thread_num(), param, x, y[0]);
}
gsl_odeiv2_driver_free (d);
}
}
int main() {
double start_time = omp_get_wtime();
double x_start = 0;
double x_end = 10;
double y_start = 0;
const int count = 100000;
int param1 = 1;
int param2 = 20;
calc_cauchy_problem(x_start, x_end, y_start, count, param1, param2);
printf("Elapsed time = %f\n", omp_get_wtime() - start_time);
return 0;
}
Really thanks to Kaveh Vahedipour.

MPI_SEND and MPI_RECIEVE have no Reference by Compile

I am trying to compile an MPI program with mpicc. The compiler complains only that there is no reference to MPI_RECIVE and MPI_SEND, and ends the compile error. I have #include in the .c file.
Can someone tell me how I can fix this?
Here ist the Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <mpi.h>
#include "random.h"
#include "md5tool.h"
/* horizontal size of the configuration */
#define XSIZE 1024
/* "ADT" State and line of states (plus border) */
typedef char State;
typedef State Line[XSIZE + 2];
/* determine random integer between 0 and n-1 */
#define randInt(n) ((int)(nextRandomLEcuyer() * n))
/* random starting configuration */
static void initConfig(Line *buf, int lines){
int x, y;
initRandomLEcuyer(424243);
for (y = 1; y <= lines; y++) {
for (x = 1; x <= XSIZE; x++) {
buf[y][x] = randInt(100) >= 50;
}
}
}
/* annealing rule from ChoDro96 page 34
* the table is used to map the number of nonzero
* states in the neighborhood to the new state
*/
static State anneal[10] = {0, 0, 0, 0, 1, 0, 1, 1, 1, 1};
/* a: pointer to array; x,y: coordinates; result: n-th element of anneal,
where n is the number of neighbors */
#define transition(a, x, y) \
(anneal[(a)[(y)-1][(x)-1] + (a)[(y)][(x)-1] + (a)[(y)+1][(x)-1] +\
(a)[(y)-1][(x) ] + (a)[(y)][(x) ] + (a)[(y)+1][(x) ] +\
(a)[(y)-1][(x)+1] + (a)[(y)][(x)+1] + (a)[(y)+1][(x)+1]])
/* treat torus like boundary conditions */
static void boundary(Line *buf, int lines){
int x,y;
for (y = 0; y <= lines+1; y++) {
/* copy rightmost column to the buffer column 0 */
buf[y][0 ] = buf[y][XSIZE];
/* copy leftmost column to the buffer column XSIZE + 1 */
buf[y][1+1] = buf[y][1 ];
}
for (x = 0; x <= XSIZE+1; x++) {
/* copy bottommost row to buffer row 0 */
buf[0][x ] = buf[lines][x];
/* copy topmost row to buffer row lines + 1 */
buf[lines+1][x] = buf[1][x ];
}
}
/* make one simulation iteration with lines lines.
* old configuration is in from, new one is written to to.
*/
//umschreiben
/**
static void simulate(Line *from, Line *to, int lines){
boundary(from, lines);
for (y = 1; y <= lines; y++) {
for (x = 1; x <= XSIZE; x++) {
to[y][x ] = transition(from, x , y);
}
}
}
*/
/* --------------------- measurement ---------------------------------- */
int main(int argc, char** argv){
int lines, its;
int i;
Line *from, *to, *temp, *next;
char* hash;
assert(argc == 3);
lines = atoi(argv[1]);
its = atoi(argv[2]);
from = malloc((lines + 2) * sizeof(Line));
to = malloc((lines + 2) * sizeof(Line));
MPI_Init(NULL, NULL);
// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
// Get the rank of the process
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
if(world_rank == 0){
int y;
next = malloc((lines + 2) * sizeof(Line));
initConfig(from, lines);
for (i = 0; i < its; i++) {
boundary(from, lines);
int z;
for(z = 0; z < world_size;z++){
if(z !=world_rank ){
MPI_SEND(from,(lines + 2) * sizeof(Line),MPI_CHARACTER,z,0,MPI_COMM_WORLD);
}
}
MPI_Status status;
for(z = 0; z < world_size;z++){
if(z !=world_rank ){
MPI_RECIVE(next,(lines + 2) * sizeof(Line),MPI_CHARACTER,z,1,&status);
if(status.MPI_ERROR){
//TODO
MPI_Abort(MPI_COMM_WORLD,1);
}
for (y = 1; y <= (lines%world_size+lines/world_size); y++) {
stpcpy(to[y*z],next[y*z]);
}
}
}
temp = from;
from = to;
to = temp;
}
hash = getMD5DigestStr(from[1], sizeof(Line) * (lines));
printf("hash: %s\n", hash);
free(next);
}else{
int x,y;
MPI_Status status;
for(i = 0; i < its; i++){
MPI_RECIVE(from,(lines + 2) * sizeof(Line),MPI_CHARACTER,0,0,&status);
if(status.MPI_ERROR){
MPI_Abort(MPI_COMM_WORLD,2);
}
for (y = 1; y <= (lines%world_size+lines/world_size); y++) {
for (x = 1; x <= XSIZE; x++) {
to[y*world_rank][x ] = transition(from, x , y*world_rank);
}
}
MPI_SEND(to,(lines + 2) * sizeof(Line),MPI_CHARACTER,0,1,MPI_COMM_WORLD);
}
}
MPI_Finalize();
free(from);
free(to);
free(hash);
return 0;
}
This is a C a Sequence implementation which I wrote for the university as a homework assignment.
Are you talking about MPI_Send and MPI_Recv ?
Don't know about any MPI_SEND or MPI_RECIV function...
I think you just mispelled them.
BTW: here is a great tutorial about how to use them http://mpitutorial.com/tutorials/mpi-send-and-receive/

How do I find distance between couple of points (x, y) from origin, and then sort the points, who is closest to (0, 0)?

i need to enter number of points(x,y), and then sort the points,from the closest one to (0,0) to the one that is far.. for example:
Enter number of points: 3
Enter point: 1 6
Enter point: 2 5
Enter point: 4 4
Sorted points:(2,5) (4,4) (1,6)
now i did a function that will find the distance,and i did an array and put the distance between two coordinate x and y,and i want to use merge sort to sort the array, my problem is how to go back and print the actual coordinate x y ... (i hope you would understand the problem),what can i do? i thought of putting the cordinate an array and sort them but that won't work :\
(and i didn't learn struct so i can't use unless if there is no other way ...)
plz anyone can help me i really have no idea have to continue:\
#include <stdio.h>
#include <stdlib.h>
void Enter_numbers(int x,int *z,int *first_coordinate,int *second_coordinate);
int distance(int a,int b);
void merge(int a[], int na, int b[], int nb, int c[]);
int merge_sort(int ar[], int n);
int main()
{
int x;
int *z;
int *first_coordinate;
int *second_coordinate;
printf("Enter number of points: ");
scanf("%d",&x);
z=(int*)malloc(x*sizeof(int));
first_coordinate=(int*)malloc(x*sizeof(int));
second_coordinate=(int*)malloc(x*sizeof(int));
Enter_numbers(x,z,first_coordinate,second_coordinate);
free(z);
free(first_coordinate);
free(second_coordinate);
return 0;
}
int distance(int a,int b)
{
int dis;
dis=((a*a)+(b*b));
return dis;
}
void Enter_numbers(int x,int *z,int *first_coordinate,int *second_coordinate)
{
int a=0,b=0;
int i=0;
int diss=0;
while(x>0)
{
printf("Enter points: ");
scanf("%d %d",&a,&b);
diss=distance(a,b);
z[i]=diss;
first_coordinate[i]=a;
second_coordinate[i]=b;
++i;
x--;
}
}
and the merge sort function i will use after i figure what to do :
int merge_sort(int ar[], int n)
{
int len;
int *temp_array, *base;
temp_array = (int*)malloc(sizeof(int)*n);
if(temp_array == NULL) {
printf("Dynamic Allocation Error in merge_sort");
return FAILURE;
}
for (len = 1; len < n; len *= 2) {
for (base = ar; base < ar + n; base += 2 * len) {
merge(base, len, base + len, len, temp_array);
memcpy(base, temp_array, 2*len*sizeof(int));
}
}
free(temp_array);
return SUCCESS;
}
and here is merge ...
void merge(int a[], int na, int b[], int nb, int c[])
{
int ia, ib, ic;
for(ia = ib = ic = 0; (ia < na) && (ib < nb); ic++)
{
if(a[ia] < b[ib]) {
c[ic] = a[ia];
ia++;
}
else {
c[ic] = b[ib];
ib++;
}
}
for(;ia < na; ia++, ic++) c[ic] = a[ia];
for(;ib < nb; ib++, ic++) c[ic] = b[ib];
}
I would use a struct for solving this task.
If you haven't learned struct yet, this seems to be a good time to learn it.
Note: If you really can't use stuct, see the last part of the answer.
With struct it could be something like:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int x;
int y;
int squared_distance;
} dpoint;
int squared_dst(int x, int y)
{
return (x*x + y*y);
}
// Compare function used for sorting
int compare_dpoint_dst(const void * e1, const void * e2)
{
dpoint* p1 = (dpoint*)e1;
dpoint* p2 = (dpoint*)e2;
if (p1->squared_distance > p2->squared_distance) return 1;
if (p1->squared_distance < p2->squared_distance) return -1;
return 0;
}
void print_dpoint(dpoint dp)
{
printf("(%d, %d) : sd = %d\n", dp.x, dp.y, dp.squared_distance);
}
#define N 5
int main(void) {
// Array of points (fixed size for simplicity)
dpoint ps[N];
// Dummy input (for simplicity)
int x[N] = {1,5,2,3,4};
int y[N] = {9,3,7,1,3};
for (int i = 0; i < N; ++i)
{
ps[i].x = x[i];
ps[i].y = y[i];
}
// Calculate squared distance for all points
for (int i = 0; i < N; ++i)
{
ps[i].squared_distance = squared_dst(ps[i].x, ps[i].y);
}
printf("unsorted:\n");
for (int i = 0; i < N; ++i)
{
print_dpoint(ps[i]);
}
// Sort the points
qsort (ps, sizeof(ps)/sizeof(*ps), sizeof(*ps), compare_dpoint_dst);
printf("sorted:\n");
for (int i = 0; i < N; ++i)
{
print_dpoint(ps[i]);
}
return 0;
}
Notice that you can do the sorting on the squared distance so that you don't need square root in the program.
The program above will generate:
unsorted:
(1, 9) : sd = 82
(5, 3) : sd = 34
(2, 7) : sd = 53
(3, 1) : sd = 10
(4, 3) : sd = 25
sorted:
(3, 1) : sd = 10
(4, 3) : sd = 25
(5, 3) : sd = 34
(2, 7) : sd = 53
(1, 9) : sd = 82
No use of struct
If you for some reason can't use struct, you can use a shadow array to track the sorting but you'll have to write your own sorting. I don't recommend this approach - learn about structinstead. Anyway, it could be something like:
int x[N];
int y[N];
int sd[N]; // squared distance
int sw[N]; // swap order
// read input and calculate distance
// ...
// Fill sw with 0, 1, 2, ....
for (int i=0; i < N; ++i) sw[i] = i;
mySort(sd, sw, N);
// Now you can use sw for printing
for (int i=0; i < N; ++i)
{
// print element sw[i]
printf("(%d,%d)\n", x[sw[i]], y[sw[i]]);
}
}
void mySort(int sd[], int sw[], int N)
{
// .... code for sorting
// ....
// Assume that you need to swap element i and j here
temp = sd[i];
sd[i] = sd[j];
sd[j] = temp;
// Then do exactly the same for sw
temp = sw[i];
sw[i] = sw[j];
sw[j] = temp;
// ....
// ....
}

wrong allocate memory matrix C?

I'm developing a program that read from CSV file and calculate score with a method "calculateMLpa". The method receive array of char and array of 10 float, and transform array of float in matrix 3x3. When read the position 3rd number from array, insert in matrix the 4th number and same for 6th number.
I.E.
array value[]={0.000000;123.814934;234.000000;100.000000;166.000000; 203.086639;383.000000;186.000000;338.000000;173.098419 }
array traj[]={"0-0";"0-1";"0-2";"1-0";"1-1";"1-2";"2-0";"2-1";"2-2"}
Xn_val[]={"0","1","2"}
When transform in matrix the result is:
123.814934 234.000000 166.000000
166.000000 203.086639 186.000000
186.000000 338.000000 173.098419
While the expected for [0;2] is 100.000000 and for [1;2]=383.000000, but when print the currently value of traj it's correct.
How can I fix this problem?
The code is all here:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <math.h>
#include <stdbool.h>
#include <ctype.h>
#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
int csv_parse ( char *line, int size )
{
char *p;
char *dp;
int inquote;
int na;
int nTo_comma;
char prevc = ',';
char *list[256];
dp = NULL;
// inquote = 0;
na = 0;
prevc = ';';
nTo_comma=0;
for ( p = line; *p != '\n'; p++ )
{
nTo_comma++;
list[nTo_comma] = p;
if(*p == prevc)
{
printf("%s\t", list);
return na;
}
}
printf("\n");
return na;
}
double calculateMLpa(const char *Xn_val[], char *traj[], float value[], double alphaxixj, double tauxi, int sz, int dim) {
double mlx = 0;
double v;
double alphaxi;
char *state;
int i;
int p;
int j;
int k;
// int sz = sizeof(Xn_val) / sizeof(int);
// int dim = sizeof(traj) / sizeof(char);
double trns[sz][sz];
double m[sz];
char *trat="-";
// m[xi] values: the number of transitions leaving the state xi
printf("%d %d \n",sz,dim);
int cont=0;
for (i = 0; i <= sz; i++) {
m[i] = 0.0;
for (j = 0; j <= sz; j++) {
v = 0.0;
int newlength = strlen(Xn_val[i])+strlen(trat)+strlen(Xn_val[j])+1;
state = malloc(sizeof(char)*newlength);
if(state != NULL){
state[0] = '\0';
strcat(state,Xn_val[i]);
strcat(state,trat);
strcat(state,Xn_val[j]);
printf("%s ",state);
}else {
printf(stderr,"malloc failed!\n");
}
// for (k=0; k<=dim;++k){
if (traj[cont] != NULL ){
if (strcmp(traj[cont],state)==0){
v = value[cont+1];
printf("%f \n",v);
}
}
trns[i][j] = v;
printf("%f - \n",trns[i][j]);
if (strcmp(Xn_val[i],Xn_val[j])!=0)
m[i] = m[i] + v;
cont++;
}
}
for (i=0;i<=sz;++i){
for(j=0;j<=sz;++j){
printf("%f ",trns[i][j]);
}
printf("\n");
}
for (p=0;p<=sz;++p){
printf("%f - \n",m[p]);
}
printf("%f %f\n",trns[0][1],trns[0][2]);
alphaxi = alphaxixj * (((double) sz) - 1.0);
alphaxi = alphaxixj;
printf("%d ",sz);
for (i = 0; i <= sz; i++) {
for (j = 0; j <= sz; j++) {
// xi!=xj
if (strcmp(Xn_val[i], Xn_val[j])!=0) {
mlx = mlx + lgamma(alphaxixj + trns[i][j]) - lgamma(alphaxixj);
}
// xi
else {
mlx = mlx + lgamma(alphaxi) - lgamma(alphaxi + m[i]);
mlx = mlx + lgamma(alphaxi + m[i] + 1.0)+ (alphaxi + 1.0) * log(tauxi);
mlx = mlx - lgamma(alphaxi + 1.0)- (alphaxi + m[i] + 1.0) * log(tauxi + trns[i][j]);
}
}
}
return (mlx);
}
#define MAXFLDS 200 /* maximum possible number of fields */
#define MAXFLDSIZE 32 /* longest possible field + 1 = 31 byte field */
void parse(char *record, char *delim, char arr[][MAXFLDSIZE], int *fldcnt) {
char*p = strtok(record, delim);
int fld = 0;
while (p) {
strcpy(arr[fld], p);
fld++;
p = strtok('\0', delim);
}
*fldcnt = fld;
}
void main() {
printf("inizio\n");
FILE *pf;
int N=20;
bool first=true;
const char *a[]={"0","1","2"};
char *traject[]={"0-0","0-1","0-2","1-0","1-1","1-2","2-0","2-1","2-2"};
double bs=0;
char *trat="-";
pf=fopen("//home//user//prova.csv","r");
float array[10][10];
float *t;
char *str= "hello";
char *state;
t = (float *)malloc(N * sizeof(float));
int f=0;
if (pf)
{
size_t i, j, k;
char buffer[BUFSIZ], *ptr;
/*
* Read each line from the file.
*/
for ( i = 0; fgets(buffer, sizeof buffer, pf); ++i )
{
/*
* Parse the comma-separated values from each line into 'array'.
*/
for ( j = 0, ptr = buffer; j < ARRAYSIZE(*array); ++j, ++ptr )
{
array[i][j] = strtof(ptr, &ptr);
}
}
fclose(pf);}
else /* fopen() returned NULL */
{
perror(pf);
}
for(f=0; f<10; ++f){
if(f==0){}
else if(f==1 && array[f][8]==0)
array[f][8]=123.8149353;
t[f]=array[f][8];
//printf("%f \n",t[f]);
}
for (f=0;f<10; ++f){
printf("%f - ",t[f]);
}
//printf("%s, %s, %s \n",a[0],a[1],a[2]);
printf("start\n");
int sz = sizeof(a) / sizeof(char);
int dim = sizeof(traject) / sizeof(char);
printf("%d , %d \n",sz,dim);
bs=calculateMLpa(a,traject,t,1.0,0.1,sz,dim);
printf("done \n");
printf("%f ",bs);
}
EDIT
I try to pass array size
sz=sizeof(a)/sizeof(char)
dim = sizeof(traject) / sizeof(char);
but their value is 24 and 72 respectively, and the execution stops at 0-2 value 100.000000
Arrays passed to functions decay to pointers to the start of the array. So
#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
Will not return anything meaningful when checking for its size in that case
To fix, pass the Array size as an additional Argument.
One major problem is that when you pass arrays to functions, they decay to pointers, and the sizeof trick you use to get the array size will not work.
You need to pass the actual array sizes as arguments.

Mandelbrot message queue blocking - C

I'm having problems in using message queues in this program
it is supposed to launch a number of processes that is passed by argument to the program by the command prompt but it only launches and calculates the points for one process... the others don't get to launch ..
Please help me .
This is the program that creates the message queues and outputs the selected data into pgm format
only the first process gets to run the other processes don't
can anybody tell me why ?
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
void output_pgm(char *filename,double *buffer, int nx, int ny, double max) {
int i;
FILE *file;
file = fopen(filename,"w");
fprintf(file,"P2\n");
fprintf(file,"%d %d\n",nx,ny);
fprintf(file,"%d\n",(int)max);
for (i=0; i<nx*ny; i++) {
if (!(i%nx)) fprintf(file,"\n");
fprintf(file,"%d ",(int)buffer[i]);
}
fclose(file);
}
void main(int argc,char *argv[]) {
if(argc != 2) {
} else {
int n = atoi(argv[1]);
int i = 0;
struct msgbuf {
long mtype;
int x;
int y;
double value;
};
struct envio {
long mtype;
long type;
int ny;
double yM1;
double yM2;
};
key_t key = 123;
key_t key2 = 124;
int msgflg = IPC_CREAT | 0666;
int msqid = msgget(key,msgflg);
int msqid2 = msgget(key2,msgflg);
switch(fork()) {
case -1:
printf("Erro de fork");
break;
case 0:
printf("Oi: %d\n",n);
double *b;
int x,y,i,m;
double *ptr = b = malloc(1000*1000*sizeof(double));
printf("Chego(1)\n");
struct msgbuf a;
struct envio c;
size_t buflen = sizeof(a) - sizeof(long);
size_t len2 = sizeof(c) - sizeof(long);
printf("Chego(2)\n");
int msid = msgget(key,msgflg);
int msid2 = msgget(key2,msgflg);
printf("Chego(3)\n");
double aux = -1.0;
double multiplier = ((1.0/n) * 2);
c.mtype = 300;
int ny = (int)(1000/n);
for(i = 0; i < n; i++) {
c.type = (i+1);
c.ny = (int)(1000/n);
c.yM1 = aux;
c.yM2 = aux+multiplier;
printf("Chego aqui(2)\n");
if(msgsnd(msid2,&c,len2,0) < 0) {
perror("Erro do 1o envio\n");
}
}
for(m = 0; m < n; m++) {
printf("Entrei no ciclo(1)\n");
for(y = 0; y <ny ;y++) {
//printf("Chego(4)\n");
for(x = 0; x < 1000;x++) {
if(msgrcv(msid,&a,buflen,(long)(m+1),0) < 0) {
perror("Erro na recepcao:\n ");
}
//printf("Chego(5)\n");
b[a.y * ny + a.x] = a.value;
}
}
b = b + (1000/n)*1000;
}
output_pgm("mandel.pgm", ptr, 1000, 1000, 255);
//msgctl(msid, IPC_RMID, NULL);
//msgctl(msid2, IPC_RMID, NULL);
printf("Processo 1\n");
break;
default:
for(i = 0;i < n;i++) {
switch(fork()) {
case -1:
printf("Erro de fork");
case 0:
exit(0);
break;
default:
printf("Fui lancado\n");
execlp("/home/hyper/Documents/SO2/TP3-4/rec","rec",0);
break;
}
}
break;
}
}
};
The for loop in this program is run only once
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
double type;
struct senbuf {
long mtype;
int x;
int y;
double value;
};
int max_iterations = 256;
double compute_point(double ci, double cr) {
int iterations = 0;
double zi = 0;
double zr = 0;
while ((zr*zr + zi*zi < 4) && (iterations < max_iterations)) {
double nr, ni;
/* Z <-- Z^2 + C */
nr = zr*zr - zi*zi + cr;
ni = 2*zr*zi + ci;
zi = ni;
zr = nr;
iterations ++;
}
return iterations;
}
/* The "compute" function computes the Mandelbrot function over every
point on a grid that is "nx" points wide by "ny" points tall, where
(xmin,ymin) and (xmax,ymax) give two corners of the region the
complex plane.
*/
void compute(int msqid,int nx, int ny, double xmin, double xmax,
double ymin, double ymax,long type2 ) {
double delta_x, delta_y;
int x, y;
struct senbuf sen;
delta_x = (xmax - xmin)/nx;
delta_y = (ymax - ymin)/ny;
size_t buflen = sizeof(sen) - sizeof(long);
for (y=0; y<ny; y++) {
//printf("Ja entrei aqui");
double y_value = ymin + delta_y * y;
for (x=0; x<nx; x++) {
double x_value = xmin + delta_x * x;
sen.mtype = type;
sen.x = x;
sen.y = y;
sen.value = compute_point(x_value,y_value);
if(msgsnd(msqid,&sen,buflen,0) < 0) {
perror("Erro no envio:");
};
// printf("%f",sen.a[y*nx + x]);
//buffer[y*nx + x] = compute_point(x_value, y_value);
}
}
printf("Ja mandei %d\n",type2);
/*sen.mtype=500;
sen.test = -1;
printf("Ja to a sair\n");
msgsnd(msqid,&sen,buflen,IPC_NOWAIT);*/
}
/* Output the data contained in the buffer to a Portable Greymap format
image file. The parameter "max" should be an upper bound for the
data values in the buffer.
*/
void output_pgm(char *filename,double *buffer, int nx, int ny, double max) {
int i;
FILE *file;
file = fopen(filename,"w");
fprintf(file,"P2\n");
fprintf(file,"%d %d\n",nx,ny);
fprintf(file,"%d\n",(int)max);
for (i=0; i<nx*ny; i++) {
if (!(i%nx)) fprintf(file,"\n");
fprintf(file,"%d ",(int)buffer[i]);
}
fclose(file);
}
int main()
{
int msqid;
int msqid2;
struct recep {
long mtype;
long type;
int ny;
double yM1;
double yM2;
};
struct recep a;
size_t len = sizeof(a) - sizeof(long);
key_t key = 124;
msqid = msgget(key, 0666);
if(msgrcv(msqid, &a, len, 300, 0) < 0) {
perror("Error checking");
};
printf("Dados :\n Tipo : %d\n Ny: %d\n,yM1 : %f\n yM2: %f\n",a.type,a.ny,a.yM1,a.yM2);
type = a.type;
printf("Vou iniciar o compute");
key_t key2 = 123;
msqid2 = msgget(key2,0666);
compute(msqid2,1000,a.ny, -1.0, 1.0,a.yM1,a.yM2,a.type);
}
In your first switch statement you create one child doing whatever it is doing. The parent falls into a second switch statement in which the child immediately exits and the parent is overlaid with the "rec" executable. The parent no longer executes at point - it is the program "rec". You are never going to execute more than one pass of the loop because the code that is executing is gone at that point. If you want multiple instances of "rec" running you should be using execlp on the children not the parent.
EDIT
There are two system calls wait and waitpid that provides various options. The simpler of these is wait and should be sufficient for what you are doing. Define and increment a counter in the parent for each child you create. Then instead of just exiting the parent you wait for all the children to finish. Something as simple as this should suffice:
for (int i = 0; i < counter; i++)
{
wait(NULL);
}

Resources