source: CIVL/examples/mpi/collective/reduceScatterOptimized/reduceScatter_optimized.c

main
Last change on this file was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 2.5 KB
Line 
1/* An reproduce of an advanced reduce-scatter algorithm presented in
2 * paper "Efficient Implementation of Reduce-Scatter in MPI"
3 * (https://dl.acm.org/citation.cfm?id=1895529) with simple stubs for
4 * functions that are omitted in the paper.
5 */
6
7#include "mpi.h"
8#include "stdlib.h"
9#include "stdio.h"
10#include "string.h"
11#include "assert.h"
12
13#define LOW 0
14#define HIGH 1
15#define MAX(a, b) if(*(a) < *(b)) *(a) = *(b)
16#define MIN(a, b) if(*(a) > *(b)) *(a) = *(b)
17
18void init_offsets(int * offsets, int size, int *recvcnts);
19
20void init_s_high(double * s_high, int n);
21
22void reduce(double * buf0, double * buf1, int n, MPI_Op op);
23
24int reduce_scatter_double(void *sendbuf, void *recvbuf, int *recvcnts,
25 MPI_Op op, MPI_Comm comm)
26{
27 int rank, size;
28
29 MPI_Comm_rank(comm, &rank);
30 MPI_Comm_size(comm, &size);
31
32 int offs[size];
33 double * tarrsend, *tarrrecv;
34 double * s[2];
35
36 init_offsets(offs, size, recvcnts);
37 tarrsend = (double*)sendbuf + offs[rank];
38 tarrrecv = (double *)malloc(sizeof(double) * recvcnts[rank]);
39 s[LOW] = (double *)malloc(sizeof(double) * recvcnts[rank]);
40 s[HIGH] = (double *)malloc(sizeof(double) * recvcnts[rank]);
41 init_s_high(s[HIGH], recvcnts[rank]);
42 memcpy(s[LOW], tarrsend, sizeof(double) * recvcnts[rank]);
43
44 for (int h = 1; h < size; h++) {
45 int dst = (rank + h) % size;
46 int src = (rank + size - h) % size;
47
48 tarrsend = (double*)sendbuf + offs[dst];
49 MPI_Sendrecv(tarrsend, recvcnts[dst], MPI_DOUBLE, dst, h, tarrrecv,
50 recvcnts[rank], MPI_DOUBLE, src, h, comm, MPI_STATUS_IGNORE);
51 if (src < rank)
52 reduce(s[LOW], tarrrecv, recvcnts[rank], op);
53 else
54 reduce(s[HIGH], tarrrecv, recvcnts[rank], op);
55 }
56 reduce(s[LOW], s[HIGH], recvcnts[rank], op);
57 memcpy(recvbuf, s[LOW], recvcnts[rank] * sizeof(double));
58 // finish up:
59 free(tarrrecv);
60 free(s[LOW]);
61 free(s[HIGH]);
62 return 0;
63}
64
65void init_offsets(int * offsets, int size, int *recvcnts) {
66 offsets[0] = 0;
67 for (int i = 1; i < size; i++)
68 offsets[i] = offsets[i - 1] + recvcnts[i - 1];
69}
70
71void init_s_high(double * s_high, int n) {
72 for (int i = 0; i < n; i++) s_high[i] = 0;
73}
74
75void reduce(double * buf0, double * buf1, int n, MPI_Op op) {
76 switch (op) {
77 case MPI_MAX:
78 for (int i = 0; i < n; i++)
79 MAX(buf0+i, buf1+i);
80 break;
81 case MPI_MIN:
82 for (int i = 0; i < n; i++)
83 MIN(buf0+i, buf1+i);
84 break;
85 case MPI_SUM:
86 for (int i = 0; i < n; i++)
87 buf0[i] += buf1[i];
88 break;
89 default:
90 assert(0);
91 }
92}
93
Note: See TracBrowser for help on using the repository browser.