11 #ifndef _SF_PARALLEL_UTILS_H
12 #define _SF_PARALLEL_UTILS_H
42 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
49 T bsize = (gmax - gmin) / size + 1;
56 for(
size_t i=0; i<dest.size(); i++)
57 dest[i] = (idx[i] - gmin) / bsize;
64 for(
size_t i=0; i<perm.
size(); i++)
65 snd_idx[i] = idx[perm[i]];
92 template<
class T,
class V>
97 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
104 T bsize = (gmax - gmin) / size + 1;
111 for(
size_t i=0; i<dest.size(); i++)
112 dest[i] = (idx[i] - gmin) / bsize;
120 for(
size_t i=0; i<perm.
size(); i++) {
121 snd_idx[i] = idx[perm[i]];
122 snd_val[i] = val[perm[i]];
140 template<
class T,
class V>
145 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
152 T bsize = (gmax - gmin) / size + 1;
160 for(
size_t i=0; i<dest.size(); i++)
161 dest[i] = (idx[i] - gmin) / bsize;
171 for(
size_t i=0; i<perm.
size(); i++) {
172 snd_idx[i] = idx[perm[i]];
173 snd_cnt[i] = cnt[perm[i]];
177 for(
size_t i=0; i<perm.
size(); i++) {
178 const V* read = val.
data() + dsp[perm[i]];
179 V* write = snd_val.
data() + snd_dsp[i];
181 for(T j=0; j<snd_cnt[i]; j++)
189 grph_entr.
configure(dest, snd_cnt, comm);
192 vector<T> rec_cnt(rsize), rec_dsp, out_dsp;
195 out_val.
resize(rsize_entr);
208 for(
size_t i=0; i<perm.
size(); i++)
209 out_cnt[i] = rec_cnt[perm[i]];
213 for(
size_t i=0; i<perm.
size(); i++) {
214 const V* read = rec_val.
data() + rec_dsp[perm[i]];
215 V* write = out_val.
data() + out_dsp[i];
217 for(T j=0; j<out_cnt[i]; j++)
240 MPI_Comm_rank(comm, &rank); MPI_Comm_size(comm, &size);
241 long int lsize = vec.
size();
248 nwr += fwrite(vec.
data(),
sizeof(V), vec.
size(), fd);
254 for(
int pid=1; pid < size; pid++)
257 MPI_Send(&lsize, 1, MPI_LONG, 0,
SF_MPITAG, comm);
258 MPI_Send(vec.
data(), lsize*
sizeof(V), MPI_BYTE, 0,
SF_MPITAG, comm);
260 else if (rank == 0) {
264 MPI_Recv(&rsize, 1, MPI_LONG, pid,
SF_MPITAG, comm, &stat);
267 MPI_Recv(wbuff.
data(), rsize*
sizeof(V), MPI_BYTE, pid,
SF_MPITAG, comm, &stat);
269 nwr += fwrite(wbuff.
data(),
sizeof(V), rsize, fd);
275 MPI_Bcast(&nwr, 1, MPI_LONG, 0, comm);
283 size_t root_write(FILE* fd, V* vec,
const size_t vec_size, MPI_Comm comm)
286 vecbuff.
assign(vec_size, vec,
false);
290 vecbuff.
assign(0, NULL,
false);
312 MPI_Comm_rank(comm, &rank); MPI_Comm_size(comm, &size);
313 long int lsize = vec.
size();
321 nrd += fread(vec.
data(),
sizeof(V), vec.
size(), fd);
324 for(
int pid=1; pid < size; pid++)
328 MPI_Recv(&rsize, 1, MPI_LONG, pid,
SF_MPITAG, comm, &stat);
331 nrd += fread(rbuff.
data(),
sizeof(V), rsize, fd);
333 MPI_Send(rbuff.
data(), rsize*
sizeof(V), MPI_BYTE, pid,
SF_MPITAG, comm);
337 MPI_Send(&lsize, 1, MPI_LONG, 0,
SF_MPITAG, comm);
340 MPI_Recv(vec.
data(), lsize*
sizeof(V), MPI_BYTE, 0,
SF_MPITAG, comm, &stat);
343 MPI_Bcast(&nrd, 1, MPI_LONG, 0, comm);
365 MPI_Comm_rank(comm, &rank); MPI_Comm_size(comm, &size);
366 long int lsize = vec.
size();
378 for(
size_t i=0; i<vec.
size(); i++) {
379 nrd += fscanf(fd,
"%ld", &ibuff);
384 for(
size_t i=0; i<vec.
size(); i++) {
385 nrd += fscanf(fd,
"%lf", &fbuff);
393 for(
int pid=1; pid < size; pid++)
397 MPI_Recv(&rsize, 1, MPI_LONG, pid,
SF_MPITAG, comm, &stat);
400 for(
long int i=0; i<rsize; i++) {
402 nrd += fscanf(fd,
"%ld", &ibuff);
406 nrd += fscanf(fd,
"%lf", &fbuff);
411 MPI_Send(rbuff.
data(), rsize*
sizeof(V), MPI_BYTE, pid,
SF_MPITAG, comm);
415 MPI_Send(&lsize, 1, MPI_LONG, 0,
SF_MPITAG, comm);
418 MPI_Recv(vec.
data(), lsize*
sizeof(V), MPI_BYTE, 0,
SF_MPITAG, comm, &stat);
421 MPI_Bcast(&nrd, 1, MPI_LONG, 0, comm);
429 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
431 size_t line_count = 0;
433 FILE* fd = fopen(file.c_str(),
"r");
439 divide(fsize, size, chunk_sizes);
442 for(
int chunk_size : chunk_sizes) {
444 fread(chunk.
data(), chunk_size, 1, fd);
446 for(
unsigned char c : chunk)
447 if(c ==
'\n') line_count++;
452 fprintf(stderr,
"%s error: Cannot open file %s!\n", __func__, file.c_str());
456 MPI_Bcast(&line_count,
sizeof(
size_t), MPI_BYTE, 0, comm);
464 size_t root_read(FILE* fd, V* vec,
const size_t vec_size, MPI_Comm comm)
467 vecbuff.
assign(vec_size, vec,
false);
469 size_t nrd =
root_read(fd, vecbuff, comm);
471 vecbuff.
assign(0, NULL,
false);
480 size_t root_read_ascii(FILE* fd, V* vec,
const size_t vec_size, MPI_Comm comm,
bool int_type)
483 vecbuff.
assign(vec_size, vec,
false);
487 vecbuff.
assign(0, NULL,
false);
507 template<
class T,
class V>
533 template<
class T,
class V>
540 sort_parallel(comm, idx, cnt, vec, srt_idx, srt_cnt, srt_vec);
548 template<
class T,
class V>
554 idxbuff.
assign(vec_size, idx,
false);
555 vecbuff.
assign(vec_size, vec,
false);
559 idxbuff.
assign(0, NULL,
false);
560 vecbuff.
assign(0, NULL,
false);
567 template<
class T,
class V>
569 const size_t idx_size,
const size_t vec_size, MPI_Comm comm)
574 idxbuff.
assign(idx_size, idx,
false);
575 cntbuff.
assign(idx_size, cnt,
false);
576 vecbuff.
assign(vec_size, vec,
false);
580 idxbuff.
assign(0, NULL,
false);
581 cntbuff.
assign(0, NULL,
false);
582 vecbuff.
assign(0, NULL,
false);
592 MPI_Comm_size(comm, &size), MPI_Comm_rank(comm, &rank);
595 for (
size_t i=0; i<vec.
size() / dpn; i++ ) {
596 for(
short j=0; j<dpn-1; j++)
597 fprintf(fd,
"%g ",
double(vec[i*dpn + j]) );
598 fprintf(fd,
"%g\n",
double(vec[i*dpn + (dpn-1)]) );
603 for(
int pid=1; pid < size; pid++)
607 MPI_Recv(&rsize, 1, MPI_LONG, pid,
SF_MPITAG, comm, &stat);
609 MPI_Recv(wbuff.
data(), rsize*
sizeof(T), MPI_BYTE, pid,
SF_MPITAG, comm, &stat);
611 for (
size_t i=0; i<wbuff.
size() / dpn; i++ ) {
612 for(
short j=0; j<dpn-1; j++)
613 fprintf(fd,
"%g ",
double(wbuff[i*dpn + j]) );
615 fprintf(fd,
"%g\n",
double(wbuff[i*dpn + (dpn-1)]) );
619 long int lsize = vec.
size();
620 MPI_Send(&lsize, 1, MPI_LONG, 0,
SF_MPITAG, comm);
621 MPI_Send(vec.
data(), lsize*
sizeof(T), MPI_BYTE, 0,
SF_MPITAG, comm);
626 template<
class T,
class S>
628 std::string file,
short dpn = 1)
633 MPI_Comm_rank(comm, &rank);
641 fd = fopen(file.c_str(),
"w");
643 fprintf(stderr,
"%s error: Cannot open file %s for writing! Aborting!\n", __func__, file.c_str());
#define SF_MPITAG
the MPI tag when communicating
Functions related to mesh IO.
Functions related to EMI mesh IO.
The vector class and related algorithms.
The class holds the communication graph for a MPI_Exchange() call.
vector< T > rcnt
Number of elements received from each rank.
void configure(const vector< V > &dest, MPI_Comm comm)
Set up the communication graph.
A vector storing arbitrary data.
size_t size() const
The current size of the vector.
void resize(size_t n)
Resize a vector.
void assign(InputIterator s, InputIterator e)
Assign a memory range.
T * data()
Pointer to the vector's start.
void write_data_ascii(const MPI_Comm comm, const vector< T > &idx, const vector< S > &data, std::string file, short dpn=1)
void dsp_from_cnt(const vector< T > &cnt, vector< T > &dsp)
Compute displacements from counts.
size_t file_size(FILE *fd)
return file size from a file descriptor
void print_vector(MPI_Comm comm, const vector< T > &vec, const short dpn, FILE *fd)
void interval(vector< T > &vec, size_t start, size_t end)
Create an integer interval between start and end.
void sort_parallel(MPI_Comm comm, const vector< T > &idx, vector< T > &out_idx)
Sort index values parallel ascending across the ranks.
void binary_sort_copy(vector< T > &_V, vector< S > &_W)
T sum(const vector< T > &vec)
Compute sum of a vector's entries.
void divide(const size_t gsize, const size_t num_parts, vector< T > &loc_sizes)
divide gsize into num_parts local parts with even distribution of the remainder
size_t root_write_ordered(FILE *fd, const vector< T > &idx, const vector< V > &vec, MPI_Comm comm)
Write index value pairs to disk in ordered permutation.
T global_min(const vector< T > &vec, MPI_Comm comm)
Compute the global minimum of a distributed vector.
size_t root_count_ascii_lines(std::string file, MPI_Comm comm)
count the lines in a ascii file
void MPI_Exchange(commgraph< T > &grph, vector< S > &send, vector< S > &recv, MPI_Comm comm)
Exchange data in parallel over MPI.
size_t root_read(FILE *fd, vector< V > &vec, MPI_Comm comm)
Read binary data into a vector.
void binary_sort(vector< T > &_V)
T global_max(const vector< T > &vec, MPI_Comm comm)
Compute the global maximum of a distributed vector.
size_t root_read_ascii(FILE *fd, vector< V > &vec, MPI_Comm comm, bool int_data)
Read binary data into a vector.
size_t root_write(FILE *fd, const vector< V > &vec, MPI_Comm comm)
Write vector data binary to disk.