0

I'm working on an MPI program and I have the following code for each of my processes:

#define CELL(A,X,Y,MX,MY) (*(A+Y*MX+X))
int bs_x = 1;
int bs_y = 1;

int *this_data=calloc((bs_y+2)*(bs_x+2), sizeof(int));

//...

int *recv_top = calloc(bs_x, sizeof(int));
int *recv_left = calloc(bs_x, sizeof(int));

// Now I make some operations and I want to assign 
// the value of recv_top and recv_left to this_data

for(i=0; i<bs_x; ++i) CELL(this_data, i+1, 0, bs_x+2, bs_y+2) = recv_top[i]; // Sets both (0,1) and (1,0) to recv_top!!
for(i=0; i<bs_x; ++i) CELL(this_data, 0, i+1, bs_x+2, bs_y+2) = recv_left[i]; // Again sets both (0,1) and (1,0) to recv_left!!

Now the problem comes when I check the value of the element (1,0) and I found out that the first call also saves the value of recv_top in the element (0,1):

for(i=0; i<bs_x; ++i) CELL(this_data, i+1, 0, bs_x+2, bs_y+2) = recv_top[i];
if (rank == 4)
{
    printf("Rank 4 value at (%d,0) = %d\n", 1, CELL(this_data,1,0,bs_x+2,bs_y+2));
    printf("Rank 4 value at (0,%d) = %d\n", 1, CELL(this_data,0,1,bs_x+2,bs_y+2));
}
//Rank 4 value at (1,0) = 12
//Rank 4 value at (0,1) = 12

And the next:

for(i=0; i<bs_x; ++i) CELL(this_data, 0, i+1, bs_x+2, bs_y+2) = recv_left[i];
if (rank == 4)
{
    printf("Rank 4 value at (%d,0) = %d\n", 1, CELL(this_data,1,0,bs_x+2,bs_y+2));
    printf("Rank 4 value at (0,%d) = %d\n", 1, CELL(this_data,0,1,bs_x+2,bs_y+2));
}
//Rank 4 value at (1,0) = 1024
//Rank 4 value at (0,1) = 1024

Updates also (1,0).

They shouldn't do that since they are not the same:

CELL(this_data, 0, i+1, bs_x+2, bs_y+2) = (*(this_data+(i+1)*(bs_x+2))
CELL(this_data, i+1, 0, bs_x+2, bs_y+2) = (*(this_data+i+1))

Any ideas what I'm doing wrong?

questing
  • 162
  • 1
  • 10
  • So very cryptic... :( Did you try to run this in a debugger and look at the pointers you are producing with your code? I'm honestly having really hard time following the logic – YePhIcK Jun 27 '14 at 22:38
  • 4
    `#define CELL(A,X,Y,MX,MY) (*(A+Y*MX+X))` : Parenthesis must. E.g. `Y` replace to `i+1`. not `(i+1)` – BLUEPIXY Jun 27 '14 at 22:42
  • You aren't even using the 5th parameter for your macro `CELL`, why is it even there? – Utkan Gezer Jun 27 '14 at 22:43
  • YePhlcK, I run it with Valgrind and it only gives at the beginning some warnings about accessing uninitialized values. – questing Jun 27 '14 at 22:44
  • ThoAppelsin, this is a parallelization of an already made code. The parameter was there, and it doesn't hurt. Or you think that's the problem? – questing Jun 27 '14 at 22:45
  • BLUEPIXY, I'm sorry but I did not understand. What's the problem with the parenthesis? – questing Jun 27 '14 at 22:46
  • @mancuernita No, it was just a comment. I wouldn't give the answer as a comment, as BLUEPIXY has done and does it every now and then... – Utkan Gezer Jun 27 '14 at 22:47
  • 1
    see @YePhIcK's answer. also if you use gcc, try gcc -E -P prog.c – BLUEPIXY Jun 27 '14 at 22:48

1 Answers1

3

the code #define CELL(A,X,Y,MX,MY) (*(A+Y*MX+X)) should be

#define CELL(A,X,Y,MX,MY) ( *( (A) + (Y) * (MX) + (X) ) )

Note the parenthesis!

BTW, why not use an inline function?With an inline function you will have a much better code.

In your version the code

CELL(this_data, 0, i+1, bs_x+2, bs_y+2)

expands into:

*(this_data+i+1*bs_x+2+bs_y+2)

which seems different from what you'd expect

UPDATE

I still suggest you make it into an inline function!

inline void CELL(int* A, int X, int Y, int MX, int MY, int newValue)
{
  int * cell = A + Y * MX + X;
  *cell = newValue;
}
YePhIcK
  • 5,816
  • 2
  • 27
  • 52
  • Awesome!! I just tried and it was that. Do you mind explaining the difference? EDIT: Posted before you could explain further, thanks again! – questing Jun 27 '14 at 22:49
  • 4
    Forgetting to add the parenthesis in C macro definitions is a common source of problems: http://stackoverflow.com/questions/7186504/c-macros-and-use-of-arguments-in-parentheses – hugomg Jun 27 '14 at 22:59