-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparallel_dot.c
More file actions
148 lines (127 loc) · 4.38 KB
/
parallel_dot.c
File metadata and controls
148 lines (127 loc) · 4.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/* File: parallel_dot.c
* Purpose: compute a dot product of a vector distributed among
* the processes. Uses a block distribution of the vectors.
*
* Compile: mpicc -g -Wall -o parallel_dot parallel_dot.c
* Run: mpiexec -n <number of processes> ./parallel_dot
*
* Input: n: global order of vectors
* x, y: the vectors
* Output: the dot product of x and y.
*
* Notes:
* 1. n, the global order of the vectors must be divisible by p,
* the number of processes.
* 2. Result returned by Parallel_dot is valid only on process 0
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
void Read_vector(char* prompt, float local_v[], int local_n, int n,
int my_rank, MPI_Comm comm);
float Serial_dot(float x[], float y[], int m);
float Parallel_dot(float local_x[], float local_y[], int local_n,
MPI_Comm comm);
int main(void) {
float* local_x;
float* local_y;
int n;
int local_n; /* = n/p */
float dot;
int p;
int my_rank;
MPI_Comm comm;
MPI_Init(NULL, NULL);
comm = MPI_COMM_WORLD;
MPI_Comm_size(comm, &p);
MPI_Comm_rank(comm, &my_rank);
if (my_rank == 0) {
printf("Enter the order of the vectors\n");
scanf("%d", &n);
}
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
local_n = n/p;
local_x = malloc(local_n*sizeof(float));
local_y = malloc(local_n*sizeof(float));
Read_vector("the first vector", local_x, local_n, n, my_rank, comm);
Read_vector("the second vector", local_y, local_n, n, my_rank, comm);
dot = Parallel_dot(local_x, local_y, local_n, comm);
if (my_rank == 0)
printf("The dot product is %f\n", dot);
free(local_x);
free(local_y);
MPI_Finalize();
return 0;
} /* main */
/*---------------------------------------------------------------
* Function: Read_vector
* Purpose: Read a vector from stdin and distributed it by blocks
* among the processes
* In args: prompt: prompt user for input
* local_n: size of this process' piece
* n: size of global vector
* my_rank, comm: usual MPI variables
* Out arg: local_v: this process' piece of the vector
*/
void Read_vector(
char* prompt /* in */,
float local_v[] /* out */,
int local_n /* in */,
int n /* in */,
int my_rank /* in */,
MPI_Comm comm /* in */) {
int i;
float* temp;
if (my_rank == 0) {
temp = malloc(n*sizeof(float));
printf("Enter %s\n", prompt);
for (i = 0; i < n; i++)
scanf("%f", &temp[i]);
MPI_Scatter(temp, local_n, MPI_FLOAT, local_v, local_n, MPI_FLOAT,
0, comm);
free(temp);
} else {
MPI_Scatter(temp, local_n, MPI_FLOAT, local_v, local_n, MPI_FLOAT,
0, comm);
}
} /* Read_vector */
/*---------------------------------------------------------------
* Function: Serial_dot
* Purpose: Compute a dot product of two local vectors
* In args: x: local vector
* y: local vector
* n: number of components in x and y
* Ret val: dot product of local vectors x and y
*/
float Serial_dot(
float x[] /* in */,
float y[] /* in */,
int n /* in */) {
int i;
float sum = 0.0;
for (i = 0; i < n; i++)
sum += x[i]*y[i];
return sum;
} /* Serial_dot */
/*---------------------------------------------------------------
* Function: Parallel_dot
* Purpose: Compute a dot product of two distributed vectors
* In args: local_x: this process' piece of the first dist vect
* local_y: this process' piece of the second dist vect
* local_n: number of components in x, y
* comm: communicator for MPI_Reduce
* Ret val: global dot product of the distributed vectors
* Note: This version returns the result only on process 0
*/
float Parallel_dot(
float local_x[] /* in */,
float local_y[] /* in */,
int local_n /* in */,
MPI_Comm comm /* in */) {
float local_dot;
float dot = 0.0;
local_dot = Serial_dot(local_x, local_y, local_n);
MPI_Reduce(&local_dot, &dot, 1, MPI_FLOAT, MPI_SUM, 0, comm);
return dot;
} /* Parallel_dot */