1
1
#include " MetropolisHasting.h"
2
+
3
+ MetropolisHasting::MetropolisHasting (
4
+ const AlgorithmParameter& parameter,
5
+ const std::vector<float >& stocksdata,
6
+ const std::map<std::string, int >& deviceNameToWorkload
7
+ ) :WigginsAlgorithm{ parameter ,stocksdata , deviceNameToWorkload } {
8
+ this ->BurnIn ();
9
+ }
10
+
11
+ static int sycl_strogest_cpu_selector (const sycl::device& d) {
12
+ return d.is_cpu ();
13
+ }
14
+
15
+ bool mh_sample (
16
+ const ProbabilityDomain current_q,
17
+ ProbabilityDomain& new_domain,
18
+ const AlgorithmParameter& parameters,
19
+ oneapi::dpl::normal_distribution<float >& theta_normal,
20
+ oneapi::dpl::normal_distribution<float >& mu_normal,
21
+ oneapi::dpl::normal_distribution<float >& sigma_normal,
22
+ oneapi::dpl::uniform_real_distribution<float >& zero_one_uniform,
23
+ int tsLength,
24
+ oneapi::dpl::minstd_rand& engine,
25
+ const cl::sycl::accessor<float , 1 , sycl::access::mode::read>& returns
26
+ ) {
27
+ ProbabilityDomain p{ theta_normal (engine) , mu_normal (engine), sigma_normal (engine) };
28
+ ProbabilityDomain q = current_q + p;
29
+ const float current_f = probability (current_q, tsLength, engine, returns);
30
+ const float purposed_f = probability (q, tsLength, engine, returns);
31
+ const bool accepted = (purposed_f / current_f) > zero_one_uniform (engine);
32
+ new_domain = ((int )accepted) * q + ((int )(1 ^ accepted)) * current_q;
33
+ return accepted;
34
+ }
35
+
36
+ void MetropolisHasting::BurnInInternal () {
37
+ using namespace cl ::sycl;
38
+ queue q (sycl_strogest_cpu_selector);
39
+ unsigned int seed = std::chrono::system_clock::now ().time_since_epoch ().count ();
40
+ buffer<float , 1 > result (range<1 >{3 });
41
+ q.submit ([&, this ](handler& h) {
42
+ const AlgorithmParameter parameter = this ->m_parameter ;
43
+ accessor returnsAccessor (m_returns, h, read_only);
44
+ accessor resultAccessor (result, h, write_only);
45
+ int tsLength = m_returns.size ();
46
+ ProbabilityDomain start = this ->start ;
47
+ h.single_task ([=]() {
48
+ oneapi::dpl::minstd_rand engine (seed, 0 );
49
+ oneapi::dpl::normal_distribution<float > theta_normal (0 .0f , parameter.m_volatility_theta .guassian_step_sd );
50
+ oneapi::dpl::normal_distribution<float > mu_normal (0 .0f , parameter.m_volatility_mu .guassian_step_sd );
51
+ oneapi::dpl::normal_distribution<float > sigma_normal (0 .0f , parameter.m_volatility_sigma .guassian_step_sd );
52
+ oneapi::dpl::uniform_real_distribution<float > zero_one_uniform (0 .0f , 1 .0f );
53
+ ProbabilityDomain oldDomain{ start }, nextDomain;
54
+ for (int i = 0 ; i < parameter.m_BurnIn ; i++) {
55
+ mh_sample (
56
+ oldDomain,
57
+ nextDomain,
58
+ parameter,
59
+ theta_normal,
60
+ mu_normal,
61
+ sigma_normal,
62
+ zero_one_uniform,
63
+ tsLength,
64
+ engine,
65
+ returnsAccessor
66
+ );
67
+ oldDomain = nextDomain;
68
+ }
69
+ resultAccessor[0 ] = nextDomain.theta ;
70
+ resultAccessor[1 ] = nextDomain.mu ;
71
+ resultAccessor[2 ] = nextDomain.sigma ;
72
+ });
73
+ }).wait ();
74
+ host_accessor resultHostAccessor (result, read_write);
75
+ this ->start .theta = resultHostAccessor[0 ];
76
+ this ->start .mu = resultHostAccessor[1 ];
77
+ this ->start .sigma = resultHostAccessor[2 ];
78
+ }
79
+
80
+ static cl::sycl::event exectue_wiggins_algorithm_on_device (
81
+ cl::sycl::queue& q, const AlgorithmDeviceData& device_data, int workItems,
82
+ const AlgorithmParameter& parameter, const ProbabilityDomain& start,
83
+ cl::sycl::buffer<float , 1 > returns, cl::sycl::buffer<float , 1 >& theta,
84
+ cl::sycl::buffer<float , 1 >& mu, cl::sycl::buffer<float , 1 >& sigma
85
+ ) {
86
+ using namespace cl ::sycl;
87
+
88
+ int tsLength = returns.size ();
89
+ unsigned int seed = std::chrono::system_clock::now ().time_since_epoch ().count ();
90
+ // run the MNC Algorithm, write result to theta mu sigma buffer
91
+ return q.submit ([&](handler& h) {
92
+ accessor thetaAccessor (theta, h, write_only);
93
+ accessor muAccessor (mu, h, write_only);
94
+ accessor sigmaAccessor (sigma, h, write_only);
95
+ accessor returnsAccessor (returns, h, read_only);
96
+ h.parallel_for (range<1 >(workItems), [=](id<1 > thread_id) {
97
+ oneapi::dpl::minstd_rand engine (seed, thread_id);
98
+ oneapi::dpl::normal_distribution<float > theta_normal (0 .0f , parameter.m_volatility_theta .guassian_step_sd );
99
+ oneapi::dpl::normal_distribution<float > mu_normal (0 .0f , parameter.m_volatility_mu .guassian_step_sd );
100
+ oneapi::dpl::normal_distribution<float > sigma_normal (0 .0f , parameter.m_volatility_sigma .guassian_step_sd );
101
+ oneapi::dpl::uniform_real_distribution<float > zero_one_uniform (0 .0f , 1 .0f );
102
+ ProbabilityDomain oldDomain{ start }, nextDomain;
103
+ mh_sample (
104
+ oldDomain,
105
+ nextDomain,
106
+ parameter,
107
+ theta_normal,
108
+ mu_normal,
109
+ sigma_normal,
110
+ zero_one_uniform,
111
+ tsLength,
112
+ engine,
113
+ returnsAccessor
114
+ );
115
+ thetaAccessor[thread_id] = nextDomain.theta ;
116
+ muAccessor[thread_id] = nextDomain.mu ;
117
+ sigmaAccessor[thread_id] = nextDomain.sigma ;
118
+ });
119
+ });
120
+
121
+ }
122
+
123
+ void MetropolisHasting::iterateInternal () {
124
+ /*
125
+ using namespace cl::sycl;
126
+ std::vector<cl::sycl::event> events;
127
+ std::vector<cl::sycl::buffer<float, 1> > thetaHists;
128
+ std::vector<cl::sycl::buffer<float, 1> > muHists;
129
+ std::vector<cl::sycl::buffer<float, 1> > sigmaHists;
130
+ float mu_lower = this->m_parameter.m_volatility_mu.mean - this->m_parameter.m_volatility_mu.buffer_range_sigma_multiplier * this->m_parameter.m_volatility_mu.sd;
131
+ float mu_higher = this->m_parameter.m_volatility_mu.mean + this->m_parameter.m_volatility_mu.buffer_range_sigma_multiplier * this->m_parameter.m_volatility_mu.sd;
132
+ uint32_t DiscreteQuanta = this->m_parameter.m_DiscretCountOfContinuiosSpace;
133
+ for (int deviceIndex = 0; deviceIndex < this->m_QueuesAndData.size(); deviceIndex++) {
134
+ const int workItems = ceil(this->m_parameter.m_GraphUpdateIteration * this->m_QueuesAndData[deviceIndex].second.m_workload_fraction);
135
+
136
+ thetaHists.emplace_back(workItems);
137
+ muHists.emplace_back(workItems);
138
+ sigmaHists.emplace_back(workItems);
139
+ events.push_back(
140
+ exectue_wiggins_algorithm_on_device(
141
+ this->m_QueuesAndData[deviceIndex].first,
142
+ this->m_QueuesAndData[deviceIndex].second, workItems,
143
+ this->m_parameter, this->start,
144
+ this->m_returns,
145
+ thetaHists.back(), muHists.back(), sigmaHists.back()
146
+ )
147
+ );
148
+ }
149
+ for (int deviceIndex = 0; deviceIndex < this->m_QueuesAndData.size(); deviceIndex++) {
150
+ const int workItems = ceil(this->m_parameter.m_GraphUpdateIteration * this->m_QueuesAndData[deviceIndex].second.m_workload_fraction);
151
+ host_accessor thetaList(thetaHists[deviceIndex], read_only);
152
+ for (int index = 0; index < workItems; index++) {
153
+ float theta = thetaList[index];
154
+ uint32_t thetaHistIndex = DistributionIndex(
155
+ this->m_parameter.m_volatility_theta.lower,
156
+ this->m_parameter.m_volatility_theta.upper,
157
+ DiscreteQuanta,
158
+ theta
159
+ );
160
+ this->m_response.theta.data[thetaHistIndex] += 1;
161
+ this->m_response.theta.sum += theta;
162
+ }
163
+
164
+ host_accessor muList(muHists[deviceIndex], read_only);
165
+ for (int index = 0; index < workItems; index++) {
166
+ float mu = muList[index];
167
+ uint32_t muHistIndex = DistributionIndex(
168
+ mu_lower,
169
+ mu_higher,
170
+ DiscreteQuanta,
171
+ mu
172
+ );
173
+ this->m_response.mu.data[muHistIndex] += 1;
174
+ this->m_response.mu.sum += mu;
175
+
176
+ }
177
+
178
+
179
+ host_accessor sigmaList(sigmaHists[deviceIndex], read_only);
180
+ for (int index = 0; index < workItems; index++) {
181
+ float sigma = sigmaList[index];
182
+ uint32_t thetaHistIndex = DistributionIndex(
183
+ this->m_parameter.m_volatility_sigma.lower,
184
+ this->m_parameter.m_volatility_sigma.upper,
185
+ this->m_parameter.m_DiscretCountOfContinuiosSpace,
186
+ sigma
187
+ );
188
+ this->m_response.theta.data[thetaHistIndex] += 1;
189
+ this->m_response.theta.sum += sigma;
190
+ }
191
+ }
192
+ */
193
+ this ->iteration_count ++;
194
+ }
195
+
196
+ void MetropolisHasting::BurnIn () {
197
+ this ->processing = std::async (std::launch::async, &MetropolisHasting::BurnInInternal, this );
198
+ }
199
+ void MetropolisHasting::iterate () {
200
+ this ->processing = std::async (std::launch::async, &MetropolisHasting::iterateInternal, this );
201
+ }
0 commit comments