SIRIUS 7.5.0
Electronic structure library and applications
communicator.cpp
Go to the documentation of this file.
1// Copyright (c) 2013-2022 Anton Kozhevnikov, Thomas Schulthess
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
5// the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
8// following disclaimer.
9// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
10// and the following disclaimer in the documentation and/or other materials provided with the distribution.
11//
12// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
13// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
15// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
16// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
18// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
20/** \file communicator.cpp
21 *
22 * \brief Definitions.
23 *
24 */
25
26#include "communicator.hpp"
27
28namespace sirius {
29
30namespace mpi {
31
33{
34 static int num_ranks{-1};
35 if (num_ranks == -1) {
36 char name[MPI_MAX_PROCESSOR_NAME];
37 int len;
38 CALL_MPI(MPI_Get_processor_name, (name, &len));
39 std::vector<size_t> hash(mpi::Communicator::world().size());
40 hash[mpi::Communicator::world().rank()] = std::hash<std::string>{}(std::string(name, len));
41 mpi::Communicator::world().allgather(hash.data(), 1, mpi::Communicator::world().rank());
42 std::sort(hash.begin(), hash.end());
43
44 int n{1};
45 for (int i = 1; i < (int)hash.size(); i++) {
46 if (hash[i] == hash.front()) {
47 n++;
48 } else {
49 break;
50 }
51 }
52 int m{1};
53 for (int i = (int)hash.size() - 2; i >= 0; i--) {
54 if (hash[i] == hash.back()) {
55 m++;
56 } else {
57 break;
58 }
59 }
60 num_ranks = std::max(n, m);
61 }
62
63 return num_ranks;
64}
65
66int get_device_id(int num_devices__)
67{
68 static int id{-1};
69 if (num_devices__ == 0) {
70 return id;
71 }
72 if (id == -1) {
73 #pragma omp single
74 {
75 int r = mpi::Communicator::world().rank();
76 char name[MPI_MAX_PROCESSOR_NAME];
77 int len;
78 CALL_MPI(MPI_Get_processor_name, (name, &len));
79 std::vector<size_t> hash(mpi::Communicator::world().size());
80 hash[r] = std::hash<std::string>{}(std::string(name, len));
81 mpi::Communicator::world().allgather(hash.data(), 1, r);
82 std::map<size_t, std::vector<int>> rank_map;
83 for (int i = 0; i < mpi::Communicator::world().size(); i++) {
84 rank_map[hash[i]].push_back(i);
85 }
86 for (int i = 0; i < (int)rank_map[hash[r]].size(); i++) {
87 if (rank_map[hash[r]][i] == r) {
88 id = i % num_devices__;
89 break;
90 }
91 }
92 }
93 assert(id >= 0);
94 }
95 return id;
96}
97
98} // namespace mpi
99
100} // namespace sirius
Contains declaration and implementation of mpi::Communicator class.
int get_device_id(int num_devices__)
Get GPU device id associated with the current rank.
int num_ranks_per_node()
Get number of ranks per node.
Namespace of the SIRIUS library.
Definition: sirius.f90:5
auto hash(void const *buff, size_t size, uint64_t h=5381)
Simple hash function.
Definition: math_tools.hpp:95