Line data Source code
1 : #include "Communicate/CommunicatorLogging.hpp"
2 :
3 : #include <fstream>
4 : #include <iomanip>
5 :
6 : #include "Utility/Inform.h"
7 :
8 : #include "Communicate/Communicator.h"
9 : #include "Communicate/LogEntry.h"
10 :
11 : namespace ippl {
12 : namespace mpi {
13 0 : void Communicator::printLogs(const std::string& filename) {
14 0 : std::vector<LogEntry> localLogs = gatherLocalLogs();
15 :
16 0 : std::vector<LogEntry> allLogs;
17 0 : if (rank() == 0) {
18 0 : allLogs = gatherLogsFromAllRanks(localLogs);
19 : } else {
20 0 : sendLogsToRank0(localLogs);
21 : }
22 :
23 0 : if (rank() == 0) {
24 0 : writeLogsToFile(allLogs, filename);
25 : }
26 0 : }
27 :
28 0 : std::vector<LogEntry> Communicator::gatherLocalLogs() {
29 0 : std::vector<LogEntry> localLogs;
30 :
31 0 : buffer_handlers_m.forAll([&](auto& loggingHandler) {
32 0 : const auto& logs = loggingHandler.getLogs();
33 0 : localLogs.insert(localLogs.end(), logs.begin(), logs.end());
34 0 : });
35 :
36 0 : return localLogs;
37 0 : }
38 :
39 0 : void Communicator::sendLogsToRank0(const std::vector<LogEntry>& localLogs) {
40 0 : std::vector<char> buffer = serializeLogs(localLogs);
41 :
42 0 : int logSize = buffer.size();
43 :
44 0 : this->send(logSize, 1, 0, 0);
45 0 : this->send<char>(buffer.data(), logSize, 0, 0);
46 0 : }
47 :
48 0 : std::vector<LogEntry> Communicator::gatherLogsFromAllRanks(
49 : const std::vector<LogEntry>& localLogs) {
50 0 : std::vector<LogEntry> allLogs = localLogs;
51 :
52 0 : for (int rank = 1; rank < size_m; ++rank) {
53 : int logSize;
54 0 : Status status;
55 :
56 0 : this->recv(logSize, 1, rank, 0, status);
57 :
58 0 : std::vector<char> buffer(logSize);
59 0 : this->recv<char>(buffer.data(), logSize, rank, 0, status);
60 :
61 0 : std::vector<LogEntry> deserializedLogs = deserializeLogs(buffer);
62 0 : allLogs.insert(allLogs.end(), deserializedLogs.begin(), deserializedLogs.end());
63 0 : }
64 :
65 0 : return allLogs;
66 0 : }
67 :
68 0 : std::vector<char> serializeLogs(const std::vector<LogEntry>& logs) {
69 0 : std::vector<char> buffer;
70 :
71 0 : for (const auto& logEntry : logs) {
72 0 : std::vector<char> serializedEntry = logEntry.serialize();
73 0 : buffer.insert(buffer.end(), serializedEntry.begin(), serializedEntry.end());
74 0 : }
75 :
76 0 : return buffer;
77 0 : }
78 :
79 0 : std::vector<LogEntry> deserializeLogs(const std::vector<char>& buffer) {
80 0 : std::vector<LogEntry> logs;
81 0 : size_t offset = 0;
82 :
83 0 : while (offset < buffer.size()) {
84 0 : LogEntry logEntry = LogEntry::deserialize(buffer, offset);
85 :
86 0 : logs.push_back(logEntry);
87 :
88 0 : offset += logEntry.serialize().size();
89 0 : }
90 0 : return logs;
91 0 : }
92 :
93 0 : void Communicator::writeLogsToFile(const std::vector<LogEntry>& allLogs,
94 : const std::string& filename) {
95 0 : Inform logFile(0, filename.c_str(), Inform::OVERWRITE, 0);
96 0 : logFile.setOutputLevel(1);
97 :
98 0 : logFile << "Timestamp,Method,Rank,MemorySpace,usedSize,FreeSize,Parameters" << endl;
99 :
100 0 : for (const auto& log : allLogs) {
101 0 : auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
102 0 : log.timestamp.time_since_epoch())
103 0 : .count();
104 :
105 0 : logFile << timestamp << "," << log.methodName << "," << log.rank << ","
106 0 : << log.memorySpace << "," << log.usedSize << "," << log.freeSize;
107 :
108 0 : logFile << ",\"";
109 0 : bool first = true;
110 0 : for (const auto& [key, value] : log.parameters) {
111 0 : if (!first) {
112 0 : logFile << "; ";
113 : }
114 0 : logFile << key << ": " << value;
115 0 : first = false;
116 : }
117 0 : logFile << "\"" << endl;
118 : }
119 :
120 0 : logFile.flush();
121 0 : }
122 :
123 : } // namespace mpi
124 : } // namespace ippl
|