26 #ifndef _SF_PARALLEL_UTILS_H
27 #define _SF_PARALLEL_UTILS_H
57 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
64 T bsize = (gmax - gmin) / size + 1;
71 for(
size_t i=0; i<dest.size(); i++)
72 dest[i] = (idx[i] - gmin) / bsize;
79 for(
size_t i=0; i<perm.
size(); i++)
80 snd_idx[i] = idx[perm[i]];
107 template<
class T,
class V>
112 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
119 T bsize = (gmax - gmin) / size + 1;
126 for(
size_t i=0; i<dest.size(); i++)
127 dest[i] = (idx[i] - gmin) / bsize;
135 for(
size_t i=0; i<perm.
size(); i++) {
136 snd_idx[i] = idx[perm[i]];
137 snd_val[i] = val[perm[i]];
155 template<
class T,
class V>
160 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
167 T bsize = (gmax - gmin) / size + 1;
175 for(
size_t i=0; i<dest.size(); i++)
176 dest[i] = (idx[i] - gmin) / bsize;
186 for(
size_t i=0; i<perm.
size(); i++) {
187 snd_idx[i] = idx[perm[i]];
188 snd_cnt[i] = cnt[perm[i]];
192 for(
size_t i=0; i<perm.
size(); i++) {
193 const V* read = val.
data() + dsp[perm[i]];
194 V* write = snd_val.
data() + snd_dsp[i];
196 for(T j=0; j<snd_cnt[i]; j++)
204 grph_entr.
configure(dest, snd_cnt, comm);
207 vector<T> rec_cnt(rsize), rec_dsp, out_dsp;
210 out_val.
resize(rsize_entr);
223 for(
size_t i=0; i<perm.
size(); i++)
224 out_cnt[i] = rec_cnt[perm[i]];
228 for(
size_t i=0; i<perm.
size(); i++) {
229 const V* read = rec_val.
data() + rec_dsp[perm[i]];
230 V* write = out_val.
data() + out_dsp[i];
232 for(T j=0; j<out_cnt[i]; j++)
255 MPI_Comm_rank(comm, &rank); MPI_Comm_size(comm, &size);
256 long int lsize = vec.
size();
263 nwr += fwrite(vec.
data(),
sizeof(V), vec.
size(), fd);
269 for(
int pid=1; pid < size; pid++)
272 MPI_Send(&lsize, 1, MPI_LONG, 0,
SF_MPITAG, comm);
273 MPI_Send(vec.
data(), lsize*
sizeof(V), MPI_BYTE, 0,
SF_MPITAG, comm);
275 else if (rank == 0) {
279 MPI_Recv(&rsize, 1, MPI_LONG, pid,
SF_MPITAG, comm, &stat);
282 MPI_Recv(wbuff.
data(), rsize*
sizeof(V), MPI_BYTE, pid,
SF_MPITAG, comm, &stat);
284 nwr += fwrite(wbuff.
data(),
sizeof(V), rsize, fd);
290 MPI_Bcast(&nwr, 1, MPI_LONG, 0, comm);
298 size_t root_write(FILE* fd, V* vec,
const size_t vec_size, MPI_Comm comm)
301 vecbuff.
assign(vec_size, vec,
false);
305 vecbuff.
assign(0, NULL,
false);
327 MPI_Comm_rank(comm, &rank); MPI_Comm_size(comm, &size);
328 long int lsize = vec.
size();
336 nrd += fread(vec.
data(),
sizeof(V), vec.
size(), fd);
339 for(
int pid=1; pid < size; pid++)
343 MPI_Recv(&rsize, 1, MPI_LONG, pid,
SF_MPITAG, comm, &stat);
346 nrd += fread(rbuff.
data(),
sizeof(V), rsize, fd);
348 MPI_Send(rbuff.
data(), rsize*
sizeof(V), MPI_BYTE, pid,
SF_MPITAG, comm);
352 MPI_Send(&lsize, 1, MPI_LONG, 0,
SF_MPITAG, comm);
355 MPI_Recv(vec.
data(), lsize*
sizeof(V), MPI_BYTE, 0,
SF_MPITAG, comm, &stat);
358 MPI_Bcast(&nrd, 1, MPI_LONG, 0, comm);
380 MPI_Comm_rank(comm, &rank); MPI_Comm_size(comm, &size);
381 long int lsize = vec.
size();
393 for(
size_t i=0; i<vec.
size(); i++) {
394 nrd += fscanf(fd,
"%ld", &ibuff);
399 for(
size_t i=0; i<vec.
size(); i++) {
400 nrd += fscanf(fd,
"%lf", &fbuff);
408 for(
int pid=1; pid < size; pid++)
412 MPI_Recv(&rsize, 1, MPI_LONG, pid,
SF_MPITAG, comm, &stat);
415 for(
long int i=0; i<rsize; i++) {
417 nrd += fscanf(fd,
"%ld", &ibuff);
421 nrd += fscanf(fd,
"%lf", &fbuff);
426 MPI_Send(rbuff.
data(), rsize*
sizeof(V), MPI_BYTE, pid,
SF_MPITAG, comm);
430 MPI_Send(&lsize, 1, MPI_LONG, 0,
SF_MPITAG, comm);
433 MPI_Recv(vec.
data(), lsize*
sizeof(V), MPI_BYTE, 0,
SF_MPITAG, comm, &stat);
436 MPI_Bcast(&nrd, 1, MPI_LONG, 0, comm);
444 MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank);
446 size_t line_count = 0;
448 FILE* fd = fopen(file.c_str(),
"r");
454 divide(fsize, size, chunk_sizes);
457 for(
int chunk_size : chunk_sizes) {
459 fread(chunk.
data(), chunk_size, 1, fd);
461 for(
unsigned char c : chunk)
462 if(c ==
'\n') line_count++;
467 fprintf(stderr,
"%s error: Cannot open file %s!\n", __func__, file.c_str());
471 MPI_Bcast(&line_count,
sizeof(
size_t), MPI_BYTE, 0, comm);
479 size_t root_read(FILE* fd, V* vec,
const size_t vec_size, MPI_Comm comm)
482 vecbuff.
assign(vec_size, vec,
false);
484 size_t nrd =
root_read(fd, vecbuff, comm);
486 vecbuff.
assign(0, NULL,
false);
495 size_t root_read_ascii(FILE* fd, V* vec,
const size_t vec_size, MPI_Comm comm,
bool int_type)
498 vecbuff.
assign(vec_size, vec,
false);
502 vecbuff.
assign(0, NULL,
false);
522 template<
class T,
class V>
548 template<
class T,
class V>
555 sort_parallel(comm, idx, cnt, vec, srt_idx, srt_cnt, srt_vec);
563 template<
class T,
class V>
569 idxbuff.
assign(vec_size, idx,
false);
570 vecbuff.
assign(vec_size, vec,
false);
574 idxbuff.
assign(0, NULL,
false);
575 vecbuff.
assign(0, NULL,
false);
582 template<
class T,
class V>
584 const size_t idx_size,
const size_t vec_size, MPI_Comm comm)
589 idxbuff.
assign(idx_size, idx,
false);
590 cntbuff.
assign(idx_size, cnt,
false);
591 vecbuff.
assign(vec_size, vec,
false);
595 idxbuff.
assign(0, NULL,
false);
596 cntbuff.
assign(0, NULL,
false);
597 vecbuff.
assign(0, NULL,
false);
607 MPI_Comm_size(comm, &size), MPI_Comm_rank(comm, &rank);
610 for (
size_t i=0; i<vec.
size() / dpn; i++ ) {
611 for(
short j=0; j<dpn-1; j++)
612 fprintf(fd,
"%g ",
double(vec[i*dpn + j]) );
613 fprintf(fd,
"%g\n",
double(vec[i*dpn + (dpn-1)]) );
618 for(
int pid=1; pid < size; pid++)
622 MPI_Recv(&rsize, 1, MPI_LONG, pid,
SF_MPITAG, comm, &stat);
624 MPI_Recv(wbuff.
data(), rsize*
sizeof(T), MPI_BYTE, pid,
SF_MPITAG, comm, &stat);
626 for (
size_t i=0; i<wbuff.
size() / dpn; i++ ) {
627 for(
short j=0; j<dpn-1; j++)
628 fprintf(fd,
"%g ",
double(wbuff[i*dpn + j]) );
630 fprintf(fd,
"%g\n",
double(wbuff[i*dpn + (dpn-1)]) );
634 long int lsize = vec.
size();
635 MPI_Send(&lsize, 1, MPI_LONG, 0,
SF_MPITAG, comm);
636 MPI_Send(vec.
data(), lsize*
sizeof(T), MPI_BYTE, 0,
SF_MPITAG, comm);
641 template<
class T,
class S>
643 std::string file,
short dpn = 1)
648 MPI_Comm_rank(comm, &rank);
656 fd = fopen(file.c_str(),
"w");
658 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.