Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Functions
computeenvironment.cpp File Reference
#include <qle/math/basiccpuenvironment.hpp>
#include <qle/math/computeenvironment.hpp>
#include <qle/math/openclenvironment.hpp>
#include <qle/math/randomvariable.hpp>
#include <qle/math/randomvariable_io.hpp>
#include <qle/math/randomvariable_opcodes.hpp>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/variance.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/timer/timer.hpp>
#include "toplevelfixture.hpp"

Go to the source code of this file.

Functions

 BOOST_AUTO_TEST_CASE (testEnvironmentInit)
 
 BOOST_AUTO_TEST_CASE (testSimpleCalc)
 
 BOOST_AUTO_TEST_CASE (testSimpleCalcWithDoublePrecision)
 
 BOOST_AUTO_TEST_CASE (testLargeCalc)
 
 BOOST_AUTO_TEST_CASE (testRngGeneration)
 
 BOOST_AUTO_TEST_CASE (testReplayFlowError)
 
 BOOST_AUTO_TEST_CASE (testRngGenerationMt19937)
 
 BOOST_AUTO_TEST_CASE (testConditionalExpectation)
 

Function Documentation

◆ BOOST_AUTO_TEST_CASE() [1/8]

BOOST_AUTO_TEST_CASE ( testEnvironmentInit  )

Definition at line 66 of file computeenvironment.cpp.

66 {
67 BOOST_TEST_MESSAGE("testing enviroment initialization");
68 ComputeEnvironmentFixture fixture;
69 auto init = []() {
70 for (auto const& d : ComputeEnvironment::instance().getAvailableDevices()) {
71 ComputeEnvironment::instance().selectContext(d);
72 ComputeEnvironment::instance().context().init();
73 BOOST_TEST_MESSAGE(" device '" << d << "' initialized.");
74 for (auto const& [field, value] : ComputeEnvironment::instance().context().deviceInfo()) {
75 BOOST_TEST_MESSAGE(" " << std::left << std::setw(30) << field << ": '" << value << "'");
76 }
77 BOOST_TEST_MESSAGE(" " << std::left << std::setw(30) << "supportsDoublePrecision"
78 << ": " << std::boolalpha
79 << ComputeEnvironment::instance().context().supportsDoublePrecision());
80 }
81 };
82 BOOST_CHECK_NO_THROW(init());
83}

◆ BOOST_AUTO_TEST_CASE() [2/8]

BOOST_AUTO_TEST_CASE ( testSimpleCalc  )

Definition at line 85 of file computeenvironment.cpp.

85 {
86 ComputeEnvironmentFixture fixture;
87 const std::size_t n = 1024;
88 for (auto const& d : ComputeEnvironment::instance().getAvailableDevices()) {
89 BOOST_TEST_MESSAGE("testing simple calc on device '" << d << "'.");
90 ComputeEnvironment::instance().selectContext(d);
91 auto& c = ComputeEnvironment::instance().context();
92
93 BOOST_TEST_MESSAGE(" do first calc");
94
95 auto [id, _] = c.initiateCalculation(n);
96 std::vector<double> rx(n, 4.0);
97 auto x = c.createInputVariable(&rx[0]);
98 auto y = c.createInputVariable(3.0);
99 auto z = c.applyOperation(RandomVariableOpCode::Add, {x, y});
100 auto w = c.applyOperation(RandomVariableOpCode::Mult, {z, z});
101 c.declareOutputVariable(w);
102 std::vector<std::vector<double>> output(1, std::vector<double>(n));
103 c.finalizeCalculation(output);
104 for (auto const& v : output.front()) {
105 BOOST_CHECK_CLOSE(v, 49.0, 1.0E-8);
106 }
107
108 BOOST_TEST_MESSAGE(" do second calc using same kernel");
109
110 c.initiateCalculation(n, id, 0);
111 std::vector<double> rx2(n, 5.0);
112 c.createInputVariable(&rx2[0]);
113 c.createInputVariable(1.0);
114 std::vector<std::vector<double>> output2(1, std::vector<double>(n));
115 c.finalizeCalculation(output2);
116 for (auto const& v : output2.front()) {
117 BOOST_CHECK_CLOSE(v, 36.0, 1.0E-8);
118 }
119 }
120}
static constexpr std::size_t Add
static constexpr std::size_t Mult
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [3/8]

BOOST_AUTO_TEST_CASE ( testSimpleCalcWithDoublePrecision  )

Definition at line 122 of file computeenvironment.cpp.

122 {
123 ComputeEnvironmentFixture fixture;
124 const std::size_t n = 1024;
125 for (auto const& d : ComputeEnvironment::instance().getAvailableDevices()) {
126 BOOST_TEST_MESSAGE("testing simple calc (double precision) on device '" << d << "'.");
127 ComputeEnvironment::instance().selectContext(d);
128 auto& c = ComputeEnvironment::instance().context();
129
130 if (!c.supportsDoublePrecision()) {
131 BOOST_TEST_MESSAGE("device does not support double precision - skipping the test for this device.");
132 continue;
133 }
134
135 BOOST_TEST_MESSAGE(" do first calc");
136
137 double dblPrecNumber = 1.29382757483823819;
138
140 settings.useDoublePrecision = true;
141 auto [id, _] = c.initiateCalculation(n, 0, 0, settings);
142 std::vector<double> rx(n, dblPrecNumber);
143 auto x = c.createInputVariable(&rx[0]);
144 auto y = c.createInputVariable(dblPrecNumber);
145 auto z = c.applyOperation(RandomVariableOpCode::Add, {x, y});
146 auto w = c.applyOperation(RandomVariableOpCode::Mult, {z, z});
147 c.declareOutputVariable(w);
148 std::vector<std::vector<double>> output(1, std::vector<double>(n));
149 c.finalizeCalculation(output);
150 for (auto const& v : output.front()) {
151 BOOST_CHECK_CLOSE(v, (dblPrecNumber + dblPrecNumber) * (dblPrecNumber + dblPrecNumber), 1.0E-15);
152 }
153
154 BOOST_TEST_MESSAGE(" do second calc using same kernel");
155
156 c.initiateCalculation(n, id, 0, settings);
157 std::vector<double> rx2(n, dblPrecNumber);
158 c.createInputVariable(&rx2[0]);
159 c.createInputVariable(dblPrecNumber);
160 std::vector<std::vector<double>> output2(1, std::vector<double>(n));
161 c.finalizeCalculation(output2);
162 for (auto const& v : output2.front()) {
163 BOOST_CHECK_CLOSE(v, (dblPrecNumber + dblPrecNumber) * (dblPrecNumber + dblPrecNumber), 1.0E-15);
164 }
165 }
166}
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [4/8]

BOOST_AUTO_TEST_CASE ( testLargeCalc  )

Definition at line 168 of file computeenvironment.cpp.

168 {
169 ComputeEnvironmentFixture fixture;
170
171 const std::size_t n = 65536;
172 const std::size_t m = 1024;
173
174 std::vector<double> results;
175 for (auto const& d : ComputeEnvironment::instance().getAvailableDevices()) {
176 BOOST_TEST_MESSAGE("testing large calc on device '" << d << "'.");
177 ComputeEnvironment::instance().selectContext(d);
178 auto& c = ComputeEnvironment::instance().context();
179 std::vector<std::size_t> values(m);
180 std::vector<double> data(n, 0.9f);
181 std::vector<std::vector<double>> output(1, std::vector<double>(n));
182
183 // first calc
184
186 settings.debug = true;
187 auto [id, _] = c.initiateCalculation(n, 0, 0, settings);
188 values[0] = c.createInputVariable(&data[0]);
189 std::size_t val = values[0];
190 for (std::size_t i = 0; i < m; ++i) {
191 std::size_t val2 = c.applyOperation(RandomVariableOpCode::Add, {val, values[0]});
192 std::size_t val3 = c.applyOperation(RandomVariableOpCode::Mult, {val2, values[0]});
193 // c.freeVariable(val);
194 // c.freeVariable(val2);
195 val = val3;
196 }
197 c.declareOutputVariable(val);
198 c.finalizeCalculation(output);
199 BOOST_TEST_MESSAGE(" first calculation result = " << output.front()[0]);
200 results.push_back(output.front()[0]);
201
202 // second calculation
203
204 c.initiateCalculation(n, id, 0);
205 values[0] = c.createInputVariable(&data[0]);
206 c.finalizeCalculation(output);
207 BOOST_TEST_MESSAGE(" second calculation result = " << output.front()[0]);
208 results.push_back(output.front()[0]);
209
210 outputTimings(c);
211 }
212
213 std::vector<RandomVariable> values(m);
214 for (std::size_t i = 0; i < m; ++i) {
215 values[i] = RandomVariable(n, 0.9);
216 values[i].expand();
217 }
218 RandomVariable res = values[0];
219 boost::timer::nanosecond_type t1;
220 boost::timer::cpu_timer timer;
221 for (std::size_t i = 0; i < m; ++i) {
222 res += values[0];
223 res *= values[0];
224 }
225 t1 = timer.elapsed().wall;
226 BOOST_TEST_MESSAGE(" testing large calc locally (benchmark)");
227 BOOST_TEST_MESSAGE(" result = " << res.at(0));
228 BOOST_TEST_MESSAGE(" " << 2.0 * (double)m * (double)n / (double)(t1) * 1.0E3 << " MFlops");
229
230 for (auto const& r : results) {
231 BOOST_CHECK_CLOSE(res.at(0), r, 1E-3);
232 }
233}
Real at(const Size i) const
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [5/8]

BOOST_AUTO_TEST_CASE ( testRngGeneration  )

Definition at line 252 of file computeenvironment.cpp.

252 {
253 ComputeEnvironmentFixture fixture;
254 const std::size_t n = 65536;
255 for (auto const& d : ComputeEnvironment::instance().getAvailableDevices()) {
256 BOOST_TEST_MESSAGE("testing rng generation on device '" << d << "'.");
257 ComputeEnvironment::instance().selectContext(d);
258 auto& c = ComputeEnvironment::instance().context();
259 auto [id, _] = c.initiateCalculation(n, 0, 0);
260 auto vs = c.createInputVariates(3, 2);
261 for (auto const& d : vs) {
262 for (auto const& r : d) {
263 c.declareOutputVariable(r);
264 }
265 }
266 std::vector<std::vector<double>> output(6, std::vector<double>(n));
267 c.finalizeCalculation(output);
268 outputTimings(c);
269 checkRngOutput(output);
270
271 BOOST_TEST_MESSAGE("test to replay same calc");
272 auto [id2, newCalc2] = c.initiateCalculation(n, id, 0);
273 BOOST_CHECK(!newCalc2);
274 BOOST_CHECK_EQUAL(id, id2);
275 c.finalizeCalculation(output);
276 outputTimings(c);
277 checkRngOutput(output);
278 }
279}
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [6/8]

BOOST_AUTO_TEST_CASE ( testReplayFlowError  )

Definition at line 281 of file computeenvironment.cpp.

281 {
282 ComputeEnvironmentFixture fixture;
283 const std::size_t n = 42;
284 std::vector<std::vector<double>> output;
285 for (auto const& d : ComputeEnvironment::instance().getAvailableDevices()) {
286 BOOST_TEST_MESSAGE("testing replay flow error on device '" << d << "'.");
287 ComputeEnvironment::instance().selectContext(d);
288 auto& c = ComputeEnvironment::instance().context();
289 auto [id, newCalc] = c.initiateCalculation(n, 0, 0);
290 BOOST_CHECK(newCalc);
291 BOOST_CHECK(id > 0);
292 auto v1 = c.createInputVariable(1.0);
293 auto v2 = c.createInputVariable(1.0);
294 c.finalizeCalculation(output);
295 auto [id2, newCalc2] = c.initiateCalculation(n, id, 0);
296 BOOST_CHECK(!newCalc2);
297 BOOST_CHECK_EQUAL(id, id2);
298 c.createInputVariable(1.0);
299 c.createInputVariable(1.0);
300 BOOST_CHECK_THROW(c.createInputVariates(1, 1), std::exception);
301 BOOST_CHECK_THROW(c.applyOperation(RandomVariableOpCode::Add, {v1, v2}), std::exception);
302 BOOST_CHECK_THROW(c.freeVariable(v1), std::exception);
303 BOOST_CHECK_THROW(c.declareOutputVariable(v1), std::exception);
304 BOOST_CHECK_NO_THROW(c.finalizeCalculation(output));
305 }
306}
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [7/8]

BOOST_AUTO_TEST_CASE ( testRngGenerationMt19937  )

Definition at line 308 of file computeenvironment.cpp.

308 {
309 ComputeEnvironmentFixture fixture;
310 const std::size_t n = 1500;
311 for (auto const& d : ComputeEnvironment::instance().getAvailableDevices()) {
312 BOOST_TEST_MESSAGE("testing rng generation mt19937 against QL on device '" << d << "'.");
313 ComputeEnvironment::instance().selectContext(d);
314 auto& c = ComputeEnvironment::instance().context();
317 settings.useDoublePrecision = c.supportsDoublePrecision();
318 BOOST_TEST_MESSAGE("using double precision = " << std::boolalpha << settings.useDoublePrecision);
319 c.initiateCalculation(n, 0, 0, settings);
320 auto vs = c.createInputVariates(1, 1);
321 auto vs2 = c.createInputVariates(1, 1);
322 for (auto const& d : vs) {
323 for (auto const& r : d) {
324 c.declareOutputVariable(r);
325 }
326 }
327 for (auto const& d : vs2) {
328 for (auto const& r : d) {
329 c.declareOutputVariable(r);
330 }
331 }
332 std::vector<std::vector<double>> output(2, std::vector<double>(n));
333 c.finalizeCalculation(output);
334
335 auto sg = GenericPseudoRandom<MersenneTwisterUniformRng, InverseCumulativeNormal>::make_sequence_generator(
336 1, settings.rngSeed);
337 MersenneTwisterUniformRng mt(settings.rngSeed);
338
339 double tol = settings.useDoublePrecision ? 1E-12 : 1E-4;
340
341 Size noErrors = 0, errorThreshold = 10;
342 for (Size j = 0; j < 2; ++j) {
343 for (Size i = 0; i < n; ++i) {
344 Real ref = sg.nextSequence().value[0];
345 Real err = std::abs(output[j][i] - ref);
346 if (std::abs(ref) > 1E-10)
347 err /= std::abs(ref);
348 if (err > tol && noErrors < errorThreshold) {
349 BOOST_ERROR("gpu value (" << output[j][i] << ") at j=" << j << ", i=" << i
350 << " does not match cpu value (" << ref << "), error " << err << ", tol "
351 << tol);
352 noErrors++;
353 }
354 }
355 }
356 }
357 BOOST_CHECK(true);
358}
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [8/8]

BOOST_AUTO_TEST_CASE ( testConditionalExpectation  )

Definition at line 360 of file computeenvironment.cpp.

360 {
361 ComputeEnvironmentFixture fixture;
362 const std::size_t n = 100;
363 for (auto const& d : ComputeEnvironment::instance().getAvailableDevices()) {
364 BOOST_TEST_MESSAGE("testing conditional expectation on device '" << d << "'.");
365 ComputeEnvironment::instance().selectContext(d);
366 auto& c = ComputeEnvironment::instance().context();
368 settings.useDoublePrecision = c.supportsDoublePrecision();
369 BOOST_TEST_MESSAGE("using double precision = " << std::boolalpha << settings.useDoublePrecision);
370
371 c.initiateCalculation(n, 0, 0, settings);
372
373 auto one = c.createInputVariable(1.0);
374 auto vs = c.createInputVariates(1, 2);
375 auto ce = c.applyOperation(RandomVariableOpCode::ConditionalExpectation, {vs[0][0], one, vs[0][1]});
376
377 for (auto const& d : vs) {
378 for (auto const& r : d) {
379 c.declareOutputVariable(r);
380 }
381 }
382 c.declareOutputVariable(ce);
383
384 std::vector<std::vector<double>> output(3, std::vector<double>(n));
385 c.finalizeCalculation(output);
386
387 RandomVariable y(output[0]);
388 RandomVariable x(output[1]);
390 y, {&x}, multiPathBasisSystem(1, settings.regressionOrder, QuantLib::LsmBasisSystem::Monomial, x.size()));
391
392 double tol = settings.useDoublePrecision ? 1E-12 : 1E-4;
393 Size noErrors = 0, errorThreshold = 10;
394
395 for (Size i = 0; i < n; ++i) {
396 Real err = std::abs(output[2][i] - z[i]);
397 if (std::abs(z[i]) > 1E-10)
398 err /= std::abs(z[i]);
399 if (err > tol && noErrors < errorThreshold) {
400 BOOST_ERROR("gpu value (" << output[2][i] << ") at i=" << i << " does not match reference cpu value ("
401 << z[i] << "), error " << err << ", tol " << tol);
402 noErrors++;
403 }
404 }
405 }
406 BOOST_CHECK(true);
407}
std::vector< std::function< RandomVariable(const std::vector< const RandomVariable * > &)> > multiPathBasisSystem(Size dim, Size order, QuantLib::LsmBasisSystem::PolynomialType type, Size basisSystemSizeBound)
RandomVariable conditionalExpectation(const std::vector< const RandomVariable * > &regressor, const std::vector< std::function< RandomVariable(const std::vector< const RandomVariable * > &)> > &basisFn, const Array &coefficients)
static constexpr std::size_t ConditionalExpectation
+ Here is the call graph for this function: