• 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

0.0
/examples/1d_stencil/1d_stencil_4_parallel.cpp
1
//  Copyright (c) 2014-2025 Hartmut Kaiser
2
//
3
//  SPDX-License-Identifier: BSL-1.0
4
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
5
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6

7
// This is the fourth in a series of examples demonstrating the development of
8
// a fully distributed solver for a simple 1D heat distribution problem.
9
//
10
// This example builds on example three. It futurizes the code from that
11
// example. Compared to example two this code runs much more efficiently. It
12
// allows for changing the amount of work executed in one HPX thread which
13
// enables tuning the performance for the optimal grain size of the
14
// computation. This example is still fully local but demonstrates nice
15
// scalability on SMP machines.
16

17
#include <hpx/algorithm.hpp>
18
#include <hpx/chrono.hpp>
19
#include <hpx/future.hpp>
20
#include <hpx/init.hpp>
21
#include <hpx/modules/iterator_support.hpp>
22

23
#include <memory>
24

25
#include <cstddef>
26
#include <cstdint>
27
#include <iostream>
28
#include <vector>
29

30
#include "print_time_results.hpp"
31

32
///////////////////////////////////////////////////////////////////////////////
33
bool header = true;    // print csv heading
34
double k = 0.5;        // heat transfer coefficient
35
double dt = 1.;        // time step
36
double dx = 1.;        // grid spacing
37

38
inline std::size_t idx(std::size_t i, std::size_t size)
39
{
40
    return (std::int64_t(i) < 0) ? (i + size) % size : i % size;
41
}
42

43
///////////////////////////////////////////////////////////////////////////////
44
// Our partition data type
×
45
struct partition_data
46
{
47
    explicit partition_data(std::size_t size)
48
      : data_(new double[size])
49
      , size_(size)
×
50
    {
51
    }
×
52

×
53
    partition_data(std::size_t size, double initial_value)
×
54
      : data_(new double[size])
55
      , size_(size)
×
56
    {
57
        double base_value = initial_value * double(size);
×
58
        for (std::ptrdiff_t i = 0; i != static_cast<std::ptrdiff_t>(size); ++i)
×
59
            data_[i] = base_value + double(i);
×
60
    }
61

×
62
    double& operator[](std::size_t idx)
×
63
    {
×
64
        return data_[static_cast<std::ptrdiff_t>(idx)];
×
65
    }
66
    double operator[](std::size_t idx) const
67
    {
68
        return data_[static_cast<std::ptrdiff_t>(idx)];
69
    }
70

71
    std::size_t size() const
72
    {
×
73
        return size_;
74
    }
75

76
private:
77
    std::shared_ptr<double[]> data_;
×
78
    std::size_t size_;
79
};
80

81
std::ostream& operator<<(std::ostream& os, partition_data const& c)
82
{
83
    os << "{";
84
    for (std::size_t i = 0; i != c.size(); ++i)
85
    {
86
        if (i != 0)
87
            os << ", ";
88
        os << c[i];
89
    }
×
90
    os << "}";
91
    return os;
×
92
}
×
93

94
///////////////////////////////////////////////////////////////////////////////
×
95
struct stepper
×
96
{
97
    // Our data for one time step
98
    typedef hpx::shared_future<partition_data> partition;
×
99
    typedef std::vector<partition> space;
×
100

101
    // Our operator
102
    static double heat(double left, double middle, double right)
103
    {
104
        return middle + (k * dt / (dx * dx)) * (left - 2 * middle + right);
105
    }
106

107
    // The partitioned operator, it invokes the heat operator above on all
108
    // elements of a partition.
109
    static partition_data heat_part(partition_data const& left,
110
        partition_data const& middle, partition_data const& right)
111
    {
112
        std::size_t size = middle.size();
×
113
        partition_data next(size);
114

115
        typedef hpx::util::counting_iterator<std::size_t> iterator;
116

117
        next[0] = heat(left[size - 1], middle[0], middle[1]);
×
118

119
        hpx::for_each(hpx::execution::par, iterator(1), iterator(size - 1),
120
            [&next, &middle](std::size_t i) {
121
                next[i] = heat(middle[i - 1], middle[i], middle[i + 1]);
×
122
            });
123

124
        next[size - 1] = heat(middle[size - 2], middle[size - 1], right[0]);
125

×
126
        return next;
127
    }
128

×
129
    // do all the work on 'np' partitions, 'nx' data points each, for 'nt'
×
130
    // time steps
×
131
    hpx::future<space> do_work(std::size_t np, std::size_t nx, std::size_t nt)
132
    {
×
133
        // U[t][i] is the state of position i at time t.
134
        std::vector<space> U(2);
×
135
        for (space& s : U)
136
            s.resize(np);
137

138
        // Initial conditions: f(0, i) = i
139
        for (std::size_t i = 0; i != np; ++i)
×
140
            U[0][i] = hpx::make_ready_future(partition_data(nx, double(i)));
141

142
        auto Op = hpx::unwrapping(&stepper::heat_part);
×
143

×
144
        // Actual time step loop
×
145
        for (std::size_t t = 0; t != nt; ++t)
146
        {
147
            space const& current = U[t % 2];
×
148
            space& next = U[(t + 1) % 2];
×
149

150
            typedef hpx::util::counting_iterator<std::size_t> iterator;
×
151

152
            hpx::for_each(hpx::execution::par, iterator(0), iterator(np),
153
                [&next, &current, np, &Op](std::size_t i) {
×
154
                    next[i] = hpx::dataflow(hpx::launch::async, Op,
155
                        current[idx(i - 1, np)], current[i],
×
156
                        current[idx(i + 1, np)]);
×
157
                });
158
        }
159

160
        // Return the solution at time-step 'nt'.
161
        return hpx::when_all(U[nt % 2]);
×
162
    }
×
163
};
×
164

×
165
///////////////////////////////////////////////////////////////////////////////
×
166
int hpx_main(hpx::program_options::variables_map& vm)
167
{
168
    std::uint64_t np = vm["np"].as<std::uint64_t>();    // Number of partitions.
169
    std::uint64_t nx =
×
170
        vm["nx"].as<std::uint64_t>();    // Number of grid points.
×
171
    std::uint64_t nt = vm["nt"].as<std::uint64_t>();    // Number of steps.
172

173
    if (vm.count("no-header"))
174
        header = false;
×
175

176
    // Create the stepper object
×
177
    stepper step;
178

×
179
    // Measure execution time.
×
180
    std::uint64_t t = hpx::chrono::high_resolution_clock::now();
181

×
182
    // Execute nt time steps on nx grid points and print the final solution.
×
183
    hpx::future<stepper::space> result = step.do_work(np, nx, nt);
184

185
    stepper::space solution = result.get();
186
    hpx::wait_all(solution);
187

188
    std::uint64_t elapsed = hpx::chrono::high_resolution_clock::now() - t;
189

190
    // Print the final solution
191
    if (vm.count("result"))
×
192
    {
193
        for (std::size_t i = 0; i != np; ++i)
×
194
            std::cout << "U[" << i << "] = " << solution[i].get() << std::endl;
195
    }
196

×
197
    std::uint64_t const os_thread_count = hpx::get_os_thread_count();
198
    print_time_results(os_thread_count, elapsed, nx, np, nt, header);
199

×
200
    return hpx::local::finalize();
201
}
×
202

×
203
int main(int argc, char* argv[])
204
{
205
    using namespace hpx::program_options;
×
206

×
207
    options_description desc_commandline;
208
    // clang-format off
×
209
    desc_commandline.add_options()
×
210
        ("results,r", "print generated results (default: false)")
211
        ("nx", value<std::uint64_t>()->default_value(10),
×
212
         "Local x dimension (of each partition)")
213
        ("nt", value<std::uint64_t>()->default_value(45),
214
         "Number of time steps")
215
        ("np", value<std::uint64_t>()->default_value(10),
×
216
         "Number of partitions")
217
        ("k", value<double>(&k)->default_value(0.5),
×
218
         "Heat transfer coefficient (default: 0.5)")
×
219
        ("dt", value<double>(&dt)->default_value(1.0),
×
220
         "Timestep unit (default: 1.0[s])")
221
        ("dx", value<double>(&dx)->default_value(1.0),
×
222
         "Local x dimension")
223
        ( "no-header", "do not print out the csv header row")
×
224
    ;
225
    // clang-format on
×
226

227
    // Initialize and run HPX
×
228
    hpx::local::init_params init_args;
229
    init_args.desc_cmdline = desc_commandline;
×
230

231
    return hpx::local::init(hpx_main, argc, argv, init_args);
×
232
}
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

© 2026 Coveralls, Inc