1 ////////////////////////////////////////////////////////////////////////////////
2 //  Copyright (c) 2014-2015 Oregon University
3 //
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 
8 // Naive SMP version implemented with futures.
9 
10 #include <hpx/hpx_init.hpp>
11 #include <hpx/include/actions.hpp>
12 #include <hpx/include/lcos.hpp>
13 #include <hpx/include/util.hpp>
14 
15 #include <apex_api.hpp>
16 
17 #include <cmath>
18 #include <cstdint>
19 #include <iostream>
20 #include <list>
21 #include <random>
22 #include <vector>
23 
24 double do_work(std::uint64_t n);
25 
26 HPX_PLAIN_ACTION(do_work, do_work_action);
27 
do_work(std::uint64_t n)28 double do_work(std::uint64_t n) {
29     double result = 1;
30     for(std::uint64_t i = 0; i < n; ++i) {
31         result += std::sin((double)i) * (double)i;
32     }
33     return result;
34 }
35 
36 
next_locality(const std::vector<double> & probs)37 size_t next_locality( const std::vector<double> & probs) {
38     static std::default_random_engine generator;
39     static std::uniform_real_distribution<double> distribution(0.0, 1.0);
40     const double eps = 1e-9;
41     double r = distribution(generator);
42 
43     size_t i = 0;
44     for(const double p : probs) {
45         r -= p;
46         if(r < eps) {
47             return i;
48         }
49         ++i;
50     }
51     return 0;
52 }
53 
hpx_main(boost::program_options::variables_map & vm)54 int hpx_main(boost::program_options::variables_map& vm)
55 {
56     // extract command line argument, i.e. fib(N)
57     std::uint64_t n = vm["n-value"].as<std::uint64_t>();
58     std::uint64_t units = vm["units"].as<std::uint64_t>();
59     std::uint64_t blocks = vm["blocks"].as<std::uint64_t>();
60 
61     // Keep track of the time required to execute.
62     hpx::util::high_resolution_timer t;
63 
64     std::vector<hpx::naming::id_type> localities = hpx::find_all_localities();
65     std::vector<double> probabilities(localities.size());
66     probabilities[0] = 1.0;
67 
68     std::cout << "There are " << localities.size() << " localities." << std::endl;
69     std::cout << "Units: " << units << " n: " << n << std::endl;
70 
71     for(std::uint64_t block = 0; block < blocks; ++block) {
72         std::cout << "Block " << block << std::endl;
73         std::list<std::uint64_t> work(units, n);
74         std::list<hpx::lcos::future<double> > futures;
75         for(std::uint64_t & item : work) {
76             do_work_action act;
77             size_t next = next_locality(probabilities);
78             std::cout << "Will issue work to loc " << next << std::endl;
79             futures.push_back(hpx::async(act, localities[next], item));
80         }
81         std::cout << "Issued work for block " << block << std::endl;
82         hpx::lcos::wait_all(futures.begin(), futures.end());
83         std::cout << "Work done for block " << block << std::endl;
84     }
85 
86 
87     char const* fmt = "elapsed time: {1} [s]\n";
88     hpx::util::format_to(std::cout, fmt, t.elapsed());
89 
90     return hpx::finalize(); // Handles HPX shutdown
91 }
92 
register_policy(void)93 void register_policy(void) {
94     apex::register_periodic_policy(1000000, [](apex_context const& context) {
95         std::cout << "Periodic policy!" << std::endl;
96         return APEX_NOERROR;
97     });
98 }
99 
100 ///////////////////////////////////////////////////////////////////////////////
main(int argc,char * argv[])101 int main(int argc, char* argv[])
102 {
103     // Configure application-specific options
104     boost::program_options::options_description
105        desc_commandline("Usage: " HPX_APPLICATION_STRING " [options]");
106 
107     desc_commandline.add_options()
108         ( "n-value",
109           boost::program_options::value<std::uint64_t>()->default_value(1000000),
110           "n value for do_work")
111         ;
112 
113     desc_commandline.add_options()
114         ( "units",
115           boost::program_options::value<std::uint64_t>()->default_value(100),
116           "units of work per block")
117         ;
118 
119     desc_commandline.add_options()
120         ( "blocks",
121           boost::program_options::value<std::uint64_t>()->default_value(10),
122           "blocks before program completion")
123         ;
124     hpx::register_startup_function(register_policy);
125 
126     // Initialize and run HPX
127     return hpx::init(desc_commandline, argc, argv);
128 }
129