title: Using MPI_Reduce in c
body: <p>I am trying to write a program in c using the MPI library.
  In my program I am solving TSP (but not with any special algorithm...).
  My input parameters are <code>int nCites</code>, <code>int xCoord[]</code> and <code>int yCoord[]</code>.
  I am bundling them into <code>Coordinates</code> and using <code>MPI_Bcast</code> to make them available to all the threads.  </p>
  
  <p>My problem is this: after I've finished calculating the weight of all the paths in each thread, I want to reduce them into one single result, the best one. I've tried using <code>MPI_Reduce</code>, but something, and this is where I get confused, causes a segmentation fault (only in one of the threads, usually <code>root</code>).</p>
  
  <p>This is the main code and structs:</p>
  
  <pre><code>typedef struct Coordinates_t {
      int* x;
      int* y;
      int n;
  } Coordinates;
  
  typedef struct PathAndLength_t {
      int* path;
      int pathSize;
      int length;
  } PathAndLength;
  
  void comparePaths(void* a, void* b, int* len, MPI_Datatype* dataType) {
      ...
  }
  
  int tsp_main(int nCites, int xCoord[], int yCoord[], int P[]){
      int numOfProcs, rank;
      if (MPI_Comm_size(MPI_COMM_WORLD, &amp;numOfProcs))
          throw "Error: MPI_Comm_size failed";
      if (MPI_Comm_rank(MPI_COMM_WORLD, &amp;rank))
          throw "Error: MPI_Comm_rank failed";
  
      Coordinates crds;
      crds.x = xCoord;
      crds.y = yCoord;
      crds.n = nCites;
  
      MPI_Datatype data;
      createInDataType(&amp;crds, &amp;data);
  
      if (MPI_Bcast(&amp;crds, 1, data, 0, MPI_COMM_WORLD))
          throw "Error: MPI_Comm_size failed";
  
          ...
  
      PathAndLength* pal = (PathAndLength*)malloc(sizeof(PathAndLength));
      pal-&gt;path = (int*)malloc(sizeof(int)*crds.n);
  
      pal-&gt;length = min_length;
      for (int i = 0; i &lt; crds.n; ++i) {
          (pal-&gt;path)[i] = min_path[i];
      }
      pal-&gt;pathSize = crds.n;
      MPI_Datatype outDatatype;
      MPI_Op op;
  
      createOutDataType(pal, &amp;outDatatype);
  
      MPI_Op_create(&amp;comparePaths, 1, &amp;op);
  
      PathAndLength* result = (PathAndLength*)malloc(sizeof(PathAndLength));
      result-&gt;path = (int*)malloc(sizeof(int)*crds.n);
      MPI_Reduce(pal, result, crds.n, outDatatype, op, 0, MPI_COMM_WORLD);
  
      ...
  
      return result-&gt;length;
  }
  </code></pre>
  
  <p>And these are the <code>createOutDataType</code> and <code>createInDataType</code> I use in my code:</p>
  
  <pre><code>void createInDataType(Coordinates* indata, MPI_Datatype* message_type_ptr) {
      // Build a derived datatype
      int block_lengths[3];
      MPI_Aint displacements[3];
      MPI_Aint addresses[4];
      MPI_Datatype typelist[3];
  
      // First specify the types
      typelist[0] = typelist[1] = typelist[2] = MPI_INT;
  
      // Specify the number of elements of each type
      block_lengths[0] = block_lengths[1] = indata-&gt;n;
      block_lengths[2] = 1;
  
      // Calculate the displacements of the members relative to indata
      MPI_Address(indata, &amp;addresses[0]);
      MPI_Address(indata-&gt;x, &amp;addresses[1]);
      MPI_Address(indata-&gt;y, &amp;addresses[2]);
      MPI_Address(&amp;indata-&gt;n, &amp;addresses[3]);
      displacements[0] = addresses[1] - addresses[0];
      displacements[1] = addresses[2] - addresses[0];
      displacements[2] = addresses[3] - addresses[0];
  
      // Create the derived type
      MPI_Type_struct(3, block_lengths, displacements, typelist, message_type_ptr);
  
      // Commit it so that it can be used
      MPI_Type_commit(message_type_ptr);
  }
  
  void createOutDataType(PathAndLength* outdata, MPI_Datatype* message_type_ptr) {
      // Build a derived datatype
      int block_lengths[2];
      MPI_Aint displacements[2];
      MPI_Aint addresses[3];
      MPI_Datatype typelist[2];
  
      // First specify the types
      typelist[0] = MPI_INT;
      typelist[1] = MPI_INT;
  
      // Specify the number of elements of each type
      block_lengths[0] = outdata-&gt;pathSize;
      block_lengths[1] = 1;
  
      // Calculate the displacements of the members relative to outdata
      MPI_Address(outdata, &amp;addresses[0]);
      MPI_Address(outdata-&gt;path, &amp;addresses[1]);
      MPI_Address(&amp;outdata-&gt;length, &amp;addresses[2]);
      displacements[0] = addresses[1] - addresses[0];
      displacements[1] = addresses[2] - addresses[0];
  
      // Create the derived type
      MPI_Type_struct(2, block_lengths, displacements, typelist, message_type_ptr);
  
      // Commit it so that it can be used
      MPI_Type_commit(message_type_ptr);
  }
  </code></pre>
  
  <p>Sorry for including so much code, but I couldn't decide what, if any, was irrelevant...<br>
  Thank you.</p>