measurements.cpp 2.84 KB
Newer Older
Lukas Weber's avatar
Lukas Weber committed
1 2
#include "measurements.h"
#include <fmt/format.h>
3
#include <mpi.h>
4 5
namespace loadl {

Lukas Weber's avatar
Lukas Weber committed
6 7 8 9 10 11 12 13 14 15
bool measurements::observable_name_is_legal(const std::string &obs_name) {
	if(obs_name.find('/') != obs_name.npos) {
		return false;
	}
	if(obs_name.find('.') != obs_name.npos) {
		return false;
	}
	return true;
}

16
void measurements::register_observable(const std::string &name, size_t bin_size, size_t vector_length) {
Lukas Weber's avatar
Lukas Weber committed
17 18 19 20 21
	if(!observable_name_is_legal(name)) {
		throw std::runtime_error(
		    fmt::format("Illegal observable name '{}': names must not contain / or .", name));
	}

22
	observables_.emplace(name, observable{name, bin_size, vector_length});
Lukas Weber's avatar
Lukas Weber committed
23 24 25 26 27 28 29 30 31 32
}

void measurements::checkpoint_write(const iodump::group &dump_file) {
	for(const auto &obs : observables_) {
		obs.second.checkpoint_write(dump_file.open_group(obs.first));
	}
}

void measurements::checkpoint_read(const iodump::group &dump_file) {
	for(const auto &obs_name : dump_file) {
33
		register_observable(obs_name);
34
		observables_.at(obs_name).checkpoint_read(obs_name, dump_file.open_group(obs_name));
Lukas Weber's avatar
Lukas Weber committed
35 36 37 38 39 40 41 42 43
	}
}

void measurements::samples_write(const iodump::group &meas_file) {
	for(auto &obs : observables_) {
		auto g = meas_file.open_group(obs.first);
		obs.second.measurement_write(g);
	}
}
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
void measurements::mpi_sendrecv(int target_rank) {
	int rank;
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);

	if(rank == target_rank) {
		return;
	}

	if(mpi_checked_targets_.count(target_rank) == 0) {
		if(rank < target_rank) {
			unsigned long obscount = observables_.size();
			MPI_Send(&obscount, 1, MPI_UNSIGNED_LONG, target_rank, 0, MPI_COMM_WORLD);
			for(auto& [name, obs] : observables_) {
				(void)obs;
				int size = name.size()+1;
				MPI_Send(&size, 1, MPI_INT, target_rank, 0, MPI_COMM_WORLD);
				MPI_Send(name.c_str(), size, MPI_CHAR, target_rank, 0, MPI_COMM_WORLD);
			}
		} else {
			unsigned long obscount;
			MPI_Recv(&obscount, 1, MPI_UNSIGNED_LONG, target_rank, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
			if(obscount != observables_.size()) {
				throw std::runtime_error{fmt::format("ranks {}&{} have to contain identical sets of registered observables. But they contain different amounts of observables! {} != {}.", target_rank, rank, obscount, observables_.size())};
			}
			
			for(auto& [name, obs] : observables_) {
				(void)obs;
				int size;
				MPI_Recv(&size, 1, MPI_INT, target_rank, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
				std::vector<char> buf(size);
				MPI_Recv(buf.data(), size, MPI_CHAR, target_rank, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
				if(std::string{buf.data()} != name) {
					throw std::runtime_error{fmt::format("ranks {}&{} have to contain identical sets of registered observables. Found '{}' != '{}'.", target_rank, rank, name, std::string{buf.data()})};
				}
			}
80
		}
81 82 83 84 85 86
		mpi_checked_targets_.insert(target_rank);
	}
	
	for(auto& [name, obs] : observables_) {
		(void)name;
		obs.mpi_sendrecv(target_rank);
87 88
	}
}
89

90
}