• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

71.28
/libs/core/batch_environments/src/batch_environment.cpp
1
//  Copyright (c) 2007-2025 Hartmut Kaiser
2
//  Copyright (c)      2013 Thomas Heller
3
//
4
//  SPDX-License-Identifier: BSL-1.0
5
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
6
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7

8
#include <hpx/config.hpp>
9
#include <hpx/batch_environments/batch_environment.hpp>
10
#include <hpx/batch_environments/detail/alps_environment.hpp>
11
#include <hpx/batch_environments/detail/flux_environment.hpp>
12
#include <hpx/batch_environments/detail/pbs_environment.hpp>
13
#include <hpx/batch_environments/detail/pjm_environment.hpp>
14
#include <hpx/batch_environments/detail/slurm_environment.hpp>
15
#include <hpx/modules/asio.hpp>
16
#include <hpx/modules/errors.hpp>
17
#include <hpx/modules/type_support.hpp>
18

19
#include <asio/io_context.hpp>
20
#include <asio/ip/host_name.hpp>
21

22
#include <cstddef>
23
#include <iostream>
24
#include <string>
25
#include <utility>
26
#include <vector>
27

28
#include <hpx/config/warnings_prefix.hpp>
29

64✔
30
namespace hpx::util {
64✔
31

64✔
32
    batch_environment::batch_environment(std::vector<std::string>& nodelist,
64✔
33
        bool have_mpi, bool debug, bool enable)
64✔
34
      : agas_node_num_(0)
64✔
35
      , node_num_(static_cast<std::size_t>(-1))
64✔
36
      , num_threads_(static_cast<std::size_t>(-1))
37
      , num_localities_(static_cast<std::size_t>(-1))
64✔
38
      , debug_(debug)
64✔
39
    {
40
        if (!enable)
41
            return;
42

43
        struct onexit
64✔
44
        {
45
            explicit onexit(batch_environment const& env) noexcept
46
              : env_(env)
47
            {
48
            }
49

50
            onexit(onexit const&) = delete;
51
            onexit(onexit&&) = delete;
52

53
            onexit& operator=(onexit const&) = delete;
64✔
54
            onexit& operator=(onexit&&) = delete;
55

64✔
56
            ~onexit()
57
            {
×
58
                if (env_.debug_)
59
                {
×
60
                    std::cerr << "batch_name: " << env_.batch_name_
61
                              << std::endl;
×
62
                    std::cerr << "num_threads: " << env_.num_threads_
×
63
                              << std::endl;
64
                    std::cerr << "node_num_: " << env_.node_num_ << std::endl;
65
                    std::cerr << "num_localities: " << env_.num_localities_
64✔
66
                              << std::endl;
67
                }
68
            }
69

70
            batch_environment const& env_;
71
        };
72

64✔
73
        onexit _(*this);
64✔
74

75
        batch_environments::detail::alps_environment const alps_env(
76
            nodelist, debug);
×
77
        if (alps_env.valid())
×
78
        {
×
79
            batch_name_ = "ALPS";
×
80
            num_threads_ = alps_env.num_threads();
81
            num_localities_ = alps_env.num_localities();
82
            node_num_ = alps_env.node_num();
83
            return;
64✔
84
        }
64✔
85

86
        batch_environments::detail::pjm_environment const pjm_env(
87
            nodelist, have_mpi, debug);
×
88
        if (pjm_env.valid())
×
89
        {
×
90
            batch_name_ = "PJM";
×
91
            num_threads_ = pjm_env.num_threads();
92
            num_localities_ = pjm_env.num_localities();
93
            node_num_ = pjm_env.node_num();
64✔
94
            return;
64✔
95
        }
96

97
        batch_environments::detail::flux_environment const flux_env;
64✔
98
        if (flux_env.valid())
64✔
99
        {
64✔
100
            batch_name_ = "FLUX";
64✔
101
            num_localities_ = flux_env.num_localities();
102
            node_num_ = flux_env.node_num();
103
            return;
104
        }
×
105

×
106
        batch_environments::detail::slurm_environment const slurm_env(
107
            nodelist, debug);
108
        if (slurm_env.valid())
×
109
        {
×
110
            batch_name_ = "SLURM";
×
111
            num_threads_ = slurm_env.num_threads();
×
112
            num_localities_ = slurm_env.num_localities();
113
            node_num_ = slurm_env.node_num();
64✔
114
            return;
115
        }
116

74✔
117
        batch_environments::detail::pbs_environment const pbs_env(
118
            nodelist, have_mpi, debug);
74✔
119
        if (pbs_env.valid())
120
        {
121
            batch_name_ = "PBS";
122
            num_threads_ = pbs_env.num_threads();
56✔
123
            num_localities_ = pbs_env.num_localities();
124
            node_num_ = pbs_env.node_num();
125
            return;
56✔
126
        }
127
    }
128

129
    // This function returns true if a batch environment was found.
130
    bool batch_environment::found_batch_environment() const noexcept
131
    {
132
        return !batch_name_.empty();
56✔
133
    }
134

135
    // this function initializes the map of nodes from the given a list of nodes
112✔
136
    std::string batch_environment::init_from_nodelist(
137
        std::vector<std::string> const& nodes, std::string const& agas_host,
56✔
138
        [[maybe_unused]] bool have_tcp)
139
    {
56✔
140
        if (debug_)
141
            std::cerr << "got node list" << std::endl;
142

143
        std::string nodes_list;
56✔
144
        bool found_agas_host = false;
145

56✔
146
#if defined(HPX_HAVE_NETWORKING)
56✔
147
        ::asio::io_context io_service;
148

56✔
149
        std::size_t agas_node_num = 0;
150
        for (std::string const& s : nodes)
56✔
151
        {
152
            if (!s.empty())
153
            {
154
                if (debug_)
155
                    std::cerr << "extracted: '" << s << "'" << std::endl;
56✔
156

157
#if defined(HPX_HAVE_PARCELPORT_TCP)
56✔
158
                if (!found_agas_host &&
159
                    ((agas_host.empty() && nodes_.empty()) || s == agas_host))
160
                {
56✔
161
                    found_agas_host = true;
56✔
162
                    agas_node_ = s;
56✔
163
                    agas_node_num_ = agas_node_num;
56✔
164
                }
165

112✔
166
                if (have_tcp)
167
                {
168
                    ::asio::ip::tcp::endpoint ep =
169
                        util::resolve_hostname(s, 0, io_service);
170

171
                    if (0 == nodes_.count(ep))
172
                    {
56✔
173
                        if (debug_)
174
                            std::cerr << "incrementing agas_node_num"
×
175
                                      << std::endl;
×
176
                        ++agas_node_num;
177
                    }
178

56✔
179
                    std::pair<std::string, std::size_t>& data = nodes_[ep];
180
                    if (data.first.empty())
×
181
                        data.first = s;
182
                    ++data.second;
183
                }
×
184
#else
185
                if (!found_agas_host && (agas_host.empty() || s == agas_host))
186
                {
187
                    found_agas_host = true;
188
                    agas_node_ = s;
189
                    agas_node_num_ = agas_node_num;
×
190
                }
191
#endif
192
                nodes_list += s + ' ';
×
193
            }
×
194
        }
195
#endif
196

197
        // if an AGAS host is specified, it needs to be in the list of nodes
56✔
198
        // participating in this run
199
        if (!agas_host.empty() && !found_agas_host)
200
        {
201
            throw hpx::detail::command_line_error("Requested AGAS host (" +
202
                agas_host + ") not found in node list");
203
        }
204

192✔
205
        if (debug_)
206
        {
192✔
207
            if (!agas_node_.empty())
208
            {
209
                std::cerr << "using AGAS host: '" << agas_node_
210
                          << "' (node number " << agas_node_num_ << ")"
211
                          << std::endl;
212
            }
213

64✔
214
#if defined(HPX_HAVE_PARCELPORT_TCP)
215
            std::cerr << "Nodes from nodelist:" << std::endl;
216
            node_map_type::const_iterator const end = nodes_.end();
64✔
217
            // clang-format off
218
            for (node_map_type::const_iterator it = nodes_.begin(); it != end;
219
                 ++it)
220
            {
32✔
221
                std::cerr << (*it).second.first << ": " << (*it).second.second
222
                          << " (" << (*it).first << ")" << std::endl;
32✔
223
            }
224
            // clang-format on
225
#endif
56✔
226
        }
227
        HPX_UNUSED(nodes);
56✔
228
        return nodes_list;
56✔
229
    }
230

56✔
231
    // The number of threads is either one (if no PBS/SLURM information was
232
    // found), or it is the same as the number of times this node has been
233
    // listed in the node file. Additionally, this takes into account the number
64✔
234
    // of tasks run on this node.
235
    std::size_t batch_environment::retrieve_number_of_threads() const noexcept
236
    {
64✔
237
        return num_threads_;
64✔
238
    }
239

64✔
240
    // The number of localities is either one (if no PBS information was found),
241
    // or it is the same as the number of distinct node names listed in the node
242
    // file. In case of SLURM we can extract the number of localities from the
243
    // job environment.
244
    std::size_t batch_environment::retrieve_number_of_localities()
64✔
245
        const noexcept
246
    {
247
        return num_localities_;
64✔
248
    }
64✔
249

250
    // Try to retrieve the node number from the PBS/SLURM environment
64✔
251
    std::size_t batch_environment::retrieve_node_number() const noexcept
252
    {
253
        return node_num_;
64✔
254
    }
255

64✔
256
    std::string batch_environment::host_name() const
257
    {
258
        std::string hostname = ::asio::ip::host_name();
259
        if (debug_)
×
260
            std::cerr << "asio host_name: " << hostname << std::endl;
261
        return hostname;
×
262
    }
263

264
    std::string batch_environment::host_name(
265
        [[maybe_unused]] std::string const& def_hpx_name) const
266
    {
267
#if defined(HPX_HAVE_PARCELPORT_TCP)
268
        std::string host = nodes_.empty() ? def_hpx_name : host_name();
269
#else
270
        std::string host = host_name();
271
#endif
272
        if (debug_)
273
            std::cerr << "host_name: " << host << std::endl;
274
        return host;
275
    }
276

277
    // We either select the first host listed in the node file or a given host
278
    // name to host the AGAS server.
279
    std::string batch_environment::agas_host_name(
280
        std::string const& def_agas) const
281
    {
282
        std::string host = agas_node_.empty() ? def_agas : agas_node_;
283
        if (debug_)
284
            std::cerr << "agas host_name: " << host << std::endl;
285
        return host;
286
    }
287

288
    std::size_t batch_environment::agas_node() const noexcept
289
    {
290
        return agas_node_num_;
291
    }
292

293
    // Return a string containing the name of the batch system
294
    std::string batch_environment::get_batch_name() const
295
    {
296
        return batch_name_;
297
    }
298
}    // namespace hpx::util
299

300
#include <hpx/config/warnings_suffix.hpp>
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc