Skip to content

Commit 67f99f5

Browse files
author
jenkins
committed
git subrepo pull (merge) ore
subrepo: subdir: "ore" merged: "3b09ab42ed" upstream: origin: "git@gitlab.acadiasoft.net:qs/ore.git" branch: "master" commit: "95d7cf31b5" git-subrepo: version: "0.4.6" origin: "https://github.com/ingydotnet/git-subrepo" commit: "73a0129"
2 parents 21d71ca + 95d7cf3 commit 67f99f5

11 files changed

Lines changed: 336 additions & 352 deletions

File tree

Docs/ComputeEnvironment/computeenvironment.tex

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ \section*{Document History}
8989
Date & Author & Comment \\
9090
\hline
9191
19 June 2023 & Acadia & initial release\\
92+
15 April 2024 & Acadia & refactor context settings, add supportsDoublePrecision()\\
9293
\hline
9394
\end{supertabular}
9495
\end{flushleft}
@@ -222,7 +223,7 @@ \subsection{Implementation of the ComputeFramework interface}\label{implComputeF
222223
Notice that the same device can appear under several frameworks, e.g. a GPU could be accessed both via an OpenCL
223224
driver or via a CUDA driver.
224225
\item \verb+getContext()+ should return a raw pointer to a \verb+ComputeContext+ implementation for a given device label
225-
or throw an erro if the device label is not valid. See \ref{implComputeContext} for more details.
226+
or throw an error if the device label is not valid. See \ref{implComputeContext} for more details.
226227
\item \verb+Destructor+ The destructor of \verb+ComputeFramework+ is virtual and has an empty default implementation. It
227228
can be override in implementations to free ressources. For example, the \verb+OpenClFramework+ implementation stores
228229
raw pointers for each compute contexts that need to be deleted on destruction of the \verb+OpenClFramework+ instance.
@@ -251,9 +252,19 @@ \subsection{Implementation of the ComputeContext interface}\label{implComputeCon
251252
previous calculation. In this case only the input variables and random variates (see below) need to be set to
252253
retrieve the results of the calculation calling \verb+finalizeCalculation()+. If \verb+id+ is \verb+0+ on the other
253254
hand, a new calculation \verb+id+ will be generated and returned.
254-
\item \verb+version+: The version of a calculation.
255-
\item \verb+debug+: A flag indicating whether debug information on the number of performed operations and timings for
256-
data copying, kernel building and calculations should be collected.
255+
\item \verb+version+: The version of a calculation. This is a freely choosable integer, which is only used to identify
256+
different versions. Usually the first version of a calculation will be $0$, then next $1$, etc.
257+
\item \verb+Settings+: A struct summarizing settings for the compute environment:
258+
\begin{itemize}
259+
\item debug: a flag indicating whether debug information on the number of performed operations and timings for
260+
data copying, kernel building and calculations should be collected. Defaults to false.
261+
\item useDoublePrecision: a flag indicating whether double precision should be used for calculations. Defaults to
262+
false.
263+
\item rngSequenceType: the sequence type for random number generation. One of MersenneTwister,
264+
MersenneTwisterAntithetic, Sobol, Burley2020Sobol, SobolBrownianBridge, Burley2020SobolBrownianBridge
265+
\item seed: the seed for the random number generator
266+
\item regressionOrder: the regression order to be used within regression models
267+
\end{itemize}
257268
\end{itemize}
258269
The output parameter is a pair consisting of
259270
\begin{itemize}
@@ -268,8 +279,6 @@ \subsection{Implementation of the ComputeContext interface}\label{implComputeCon
268279
\begin{itemize}
269280
\item \verb+dim+ the dimension (typically the number of assets in a MC simulation)
270281
\item \verb+steps+ the number of steps (typically the number of time steps in a MC simulation)
271-
\item \verb+seed+ the seed of the random number generation, equal seeds must generate identical variates, different
272-
seeds might or might not generate different variates
273282
\end{itemize}
274283
The output parameter is a vector of a vector of ids for the generated variates. The inner vector loops of the steps,
275284
the outer vector over the dimensions.
@@ -281,6 +290,8 @@ \subsection{Implementation of the ComputeContext interface}\label{implComputeCon
281290
\item \verb+finalizeCalculation()+: execute the calculation and populate the given vector of vector of floats with the
282291
result. The inner vector is given as a raw pointer and must have the size of the calculation. The outer vector matches
283292
the output variables in the order they were declared before.
293+
\item \verb+deviceInfo()+: provide key-value pairs that describes the device, only used for information purposes
294+
\item \verb+supportsDoublePreicions()+: should return true if doule precision is supported, otherwise false
284295
\item \verb+debugInfo()+: provide info on the number of elementary operations and timings on data copying, program build
285296
and calculations. This info is collected if a new calculation is started with flag debug set to true
286297
\end{itemize}
@@ -428,7 +439,7 @@ \subsection{Populating the input variates}
428439
if (useExternalComputeFramework_ && newExternalCalc) {
429440
auto gen =
430441
ComputeEnvironment::instance().context().
431-
createInputVariates(rv.size(), rv.front().size(), 42);
442+
createInputVariates(rv.size(), rv.front().size());
432443
for (Size k = 0; k < rv.size(); ++k) {
433444
for (Size j = 0; j < rv.front().size(); ++j)
434445
valuesExternal[rv[k][j]] = ExternalRandomVariable(gen[k][j]);

Docs/ScriptedTrade/docs/models.tex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ \subsection{Pricing Engine Configuration}\label{pricingengine_config}
152152
UseExternalComputingDevice is true, this implies that UseCG is true irrespective of how it is configured.
153153
\item UseExternalComputingDevice: If true and RunType is not NPV (generating additional results) and AD sensitivities
154154
are {\em not} used, an external compute device is used for the calculations.
155+
\item UseDoublePrecisionForExternalCalculation: Use double precision for external computations. Defaults to false.
155156
\item ExternalComputeDevice: The external compute device to use if UseExternalComputingDevice is effective.
156157
\end{itemize}
157158

OREData/ored/portfolio/builders/scriptedtrade.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ ScriptedTradeEngineBuilder::engine(const std::string& id, const ScriptedTrade& s
264264
DLOG("useCg = " << std::boolalpha << useCg_);
265265
DLOG("useAd = " << std::boolalpha << useAd_);
266266
DLOG("useExternalDevice = " << std::boolalpha << useExternalComputeDevice_);
267+
DLOG("useDblPrecExtCalc = " << std::boolalpha << useDoublePrecisionForExternalCalculation_);
267268
DLOG("externalDevice = " << (useExternalComputeDevice_ ? externalComputeDevice_ : "na"));
268269
DLOG("calibration = " << calibration_);
269270
DLOG("base ccy = " << baseCcy_);
@@ -327,7 +328,8 @@ ScriptedTradeEngineBuilder::engine(const std::string& id, const ScriptedTrade& s
327328
bool useExternalDev = useExternalComputeDevice_ && !generateAdditionalResults && !useCachedSensis;
328329
engine = QuantLib::ext::make_shared<ScriptedInstrumentPricingEngineCG>(
329330
script.npv(), script.results(), modelCG_, ast_, context, mcParams_, script.code(), interactive_,
330-
generateAdditionalResults, includePastCashflows_, useCachedSensis, useExternalDev);
331+
generateAdditionalResults, includePastCashflows_, useCachedSensis, useExternalDev,
332+
useDoublePrecisionForExternalCalculation_);
331333
if (useExternalDev) {
332334
ComputeEnvironment::instance().selectContext(externalComputeDevice_);
333335
}
@@ -484,6 +486,8 @@ void ScriptedTradeEngineBuilder::populateModelParameters() {
484486
useAd_ = parseBool(engineParameter("UseAD", {resolvedProductTag_}, false, "false"));
485487
useExternalComputeDevice_ =
486488
parseBool(engineParameter("UseExternalComputeDevice", {resolvedProductTag_}, false, "false"));
489+
useDoublePrecisionForExternalCalculation_ =
490+
parseBool(engineParameter("UseDoublePrecisionForExternalCalculation", {resolvedProductTag_}, false, "false"));
487491
externalComputeDevice_ = engineParameter("ExternalComputeDevice", {}, false, "");
488492
includePastCashflows_ = parseBool(engineParameter("IncludePastCashflows", {resolvedProductTag_}, false, "false"));
489493

OREData/ored/portfolio/builders/scriptedtrade.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ class ScriptedTradeEngineBuilder : public EngineBuilder {
160160
bool useCg_;
161161
bool useAd_;
162162
bool useExternalComputeDevice_;
163+
bool useDoublePrecisionForExternalCalculation_;
163164
std::string externalComputeDevice_;
164165
bool includePastCashflows_;
165166
};

OREData/ored/scripting/engines/scriptedinstrumentpricingenginecg.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,16 @@ double externalAverage(const std::vector<double>& v) {
6666

6767
ScriptedInstrumentPricingEngineCG::ScriptedInstrumentPricingEngineCG(
6868
const std::string& npv, const std::vector<std::pair<std::string, std::string>>& additionalResults,
69-
const QuantLib::ext::shared_ptr<ModelCG>& model, const ASTNodePtr ast, const QuantLib::ext::shared_ptr<Context>& context,
70-
const Model::McParams& mcParams, const std::string& script, const bool interactive,
71-
const bool generateAdditionalResults, const bool includePastCashflows, const bool useCachedSensis,
72-
const bool useExternalComputeFramework)
69+
const QuantLib::ext::shared_ptr<ModelCG>& model, const ASTNodePtr ast,
70+
const QuantLib::ext::shared_ptr<Context>& context, const Model::McParams& mcParams, const std::string& script,
71+
const bool interactive, const bool generateAdditionalResults, const bool includePastCashflows,
72+
const bool useCachedSensis, const bool useExternalComputeFramework,
73+
const bool useDoublePrecisionForExternalCalculation)
7374
: npv_(npv), additionalResults_(additionalResults), model_(model), ast_(ast), context_(context),
7475
mcParams_(mcParams), script_(script), interactive_(interactive),
7576
generateAdditionalResults_(generateAdditionalResults), includePastCashflows_(includePastCashflows),
76-
useCachedSensis_(useCachedSensis), useExternalComputeFramework_(useExternalComputeFramework) {
77+
useCachedSensis_(useCachedSensis), useExternalComputeFramework_(useExternalComputeFramework),
78+
useDoublePrecisionForExternalCalculation_(useDoublePrecisionForExternalCalculation) {
7779

7880
// register with model
7981

@@ -180,9 +182,15 @@ void ScriptedInstrumentPricingEngineCG::calculate() const {
180182
if (useExternalComputeFramework_) {
181183
QL_REQUIRE(ComputeEnvironment::instance().hasContext(),
182184
"ScriptedInstrumentPricingEngineCG::calculate(): no compute enviroment context selected.");
185+
ComputeContext::Settings settings;
186+
settings.debug = false;
187+
settings.useDoublePrecision = useDoublePrecisionForExternalCalculation_;
188+
settings.rngSequenceType = mcParams_.sequenceType;
189+
settings.seed = mcParams_.seed;
190+
settings.regressionOrder = mcParams_.regressionOrder;
183191
std::tie(externalCalculationId_, newExternalCalc) =
184192
ComputeEnvironment::instance().context().initiateCalculation(model_->size(), externalCalculationId_,
185-
cgVersion_);
193+
cgVersion_, settings);
186194
DLOG("initiated external calculation id " << externalCalculationId_ << ", version " << cgVersion_);
187195
}
188196

@@ -224,7 +232,7 @@ void ScriptedInstrumentPricingEngineCG::calculate() const {
224232
if (useExternalComputeFramework_) {
225233
if (newExternalCalc) {
226234
auto gen =
227-
ComputeEnvironment::instance().context().createInputVariates(rv.size(), rv.front().size(), 42);
235+
ComputeEnvironment::instance().context().createInputVariates(rv.size(), rv.front().size());
228236
for (Size k = 0; k < rv.size(); ++k) {
229237
for (Size j = 0; j < rv.front().size(); ++j)
230238
valuesExternal[rv[k][j]] = ExternalRandomVariable(gen[k][j]);
@@ -296,8 +304,7 @@ void ScriptedInstrumentPricingEngineCG::calculate() const {
296304
// extract npv result and set it
297305

298306
if (useExternalComputeFramework_) {
299-
ComputeEnvironment::instance().context().finalizeCalculation(externalOutputPtr_,
300-
{mcParams_.regressionOrder});
307+
ComputeEnvironment::instance().context().finalizeCalculation(externalOutputPtr_);
301308
baseNpv_ = results_.value = externalAverage(externalOutput_[0]);
302309
} else {
303310
baseNpv_ = results_.value = model_->extractT0Result(values[baseNpvNode]);

OREData/ored/scripting/engines/scriptedinstrumentpricingenginecg.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,12 @@ class ScriptedInstrumentPricingEngineCG : public QuantExt::ScriptedInstrument::e
4242
ScriptedInstrumentPricingEngineCG(const std::string& npv,
4343
const std::vector<std::pair<std::string, std::string>>& additionalResults,
4444
const QuantLib::ext::shared_ptr<ModelCG>& model, const ASTNodePtr ast,
45-
const QuantLib::ext::shared_ptr<Context>& context, const Model::McParams& mcParams,
46-
const std::string& script = "", const bool interactive = false,
47-
const bool generateAdditionalResults = false,
45+
const QuantLib::ext::shared_ptr<Context>& context,
46+
const Model::McParams& mcParams, const std::string& script = "",
47+
const bool interactive = false, const bool generateAdditionalResults = false,
4848
const bool includePastCashflows = false, const bool useCachedSensis = false,
49-
const bool useExternalComputeFramework = false);
49+
const bool useExternalComputeFramework = false,
50+
const bool useDoublePrecisionForExternalCalculation = false);
5051

5152
bool lastCalculationWasValid() const { return lastCalculationWasValid_; }
5253
const std::string& npvName() const { return npv_; }
@@ -110,6 +111,7 @@ class ScriptedInstrumentPricingEngineCG : public QuantExt::ScriptedInstrument::e
110111
const bool includePastCashflows_;
111112
const bool useCachedSensis_;
112113
const bool useExternalComputeFramework_;
114+
const bool useDoublePrecisionForExternalCalculation_;
113115
};
114116

115117
} // namespace data

QuantExt/qle/math/basiccpuenvironment.cpp

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,18 @@ class BasicCpuContext : public ComputeContext {
4141

4242
std::pair<std::size_t, bool> initiateCalculation(const std::size_t n, const std::size_t id = 0,
4343
const std::size_t version = 0,
44-
const bool debug = false) override final;
44+
const Settings settings = {}) override final;
4545
std::size_t createInputVariable(double v) override final;
4646
std::size_t createInputVariable(double* v) override final;
47-
std::vector<std::vector<std::size_t>> createInputVariates(const std::size_t dim, const std::size_t steps,
48-
const std::uint32_t seed) override final;
47+
std::vector<std::vector<std::size_t>> createInputVariates(const std::size_t dim,
48+
const std::size_t steps) override final;
4949
std::size_t applyOperation(const std::size_t randomVariableOpCode,
5050
const std::vector<std::size_t>& args) override final;
5151
void freeVariable(const std::size_t id) override final;
5252
void declareOutputVariable(const std::size_t id) override final;
53-
void finalizeCalculation(std::vector<double*>& output, const Settings& settings = Settings()) override final;
53+
void finalizeCalculation(std::vector<double*>& output) override final;
54+
55+
bool supportsDoublePrecision() const override { return true; }
5456

5557
const DebugInfo& debugInfo() const override final;
5658

@@ -100,7 +102,7 @@ class BasicCpuContext : public ComputeContext {
100102

101103
std::size_t currentId_ = 0;
102104
ComputeState currentState_ = ComputeState::idle;
103-
bool debug_;
105+
Settings settings_;
104106
bool newCalc_;
105107

106108
std::vector<RandomVariable> values_;
@@ -140,12 +142,12 @@ void BasicCpuContext::init() {
140142
}
141143

142144
std::pair<std::size_t, bool> BasicCpuContext::initiateCalculation(const std::size_t n, const std::size_t id,
143-
const std::size_t version, const bool debug) {
145+
const std::size_t version, const Settings settings) {
144146

145147
QL_REQUIRE(n > 0, "BasicCpuContext::initiateCalculation(): n must not be zero");
146148

147149
newCalc_ = false;
148-
debug_ = debug;
150+
settings_ = settings;
149151

150152
if (id == 0) {
151153

@@ -220,18 +222,21 @@ std::size_t BasicCpuContext::createInputVariable(double* v) {
220222
return numberOfInputVars_[currentId_ - 1]++;
221223
}
222224

223-
std::vector<std::vector<std::size_t>>
224-
BasicCpuContext::createInputVariates(const std::size_t dim, const std::size_t steps, const std::uint32_t seed) {
225+
std::vector<std::vector<std::size_t>> BasicCpuContext::createInputVariates(const std::size_t dim,
226+
const std::size_t steps) {
225227
QL_REQUIRE(currentState_ == ComputeState::createInput || currentState_ == ComputeState::createVariates,
226-
"BasicCpuContext::createInputVariable(): not in state createInput or createVariates ("
228+
"BasicCpuContext::createInputVariates(): not in state createInput or createVariates ("
227229
<< static_cast<int>(currentState_) << ")");
228230
QL_REQUIRE(currentId_ > 0, "BasicCpuContext::freeVariable(): current id is not set");
229231
QL_REQUIRE(newCalc_, "BasicCpuContext::createInputVariates(): id (" << currentId_ << ") in version "
230232
<< version_[currentId_ - 1] << " is replayed.");
231233
currentState_ = ComputeState::createVariates;
232234

233235
if (rng_ == nullptr) {
234-
rng_ = std::make_unique<MersenneTwisterUniformRng>(seed);
236+
QL_REQUIRE(settings_.rngSequenceType == QuantExt::SequenceType::MersenneTwister,
237+
"BasiCpuContext::createInputVariates(): sequence type "
238+
<< settings_.rngSequenceType << " not supported, expected 'MersenneTwister'");
239+
rng_ = std::make_unique<MersenneTwisterUniformRng>(settings_.seed);
235240
}
236241

237242
if (variates_.size() < dim * steps) {
@@ -282,7 +287,7 @@ std::size_t BasicCpuContext::applyOperation(const std::size_t randomVariableOpCo
282287

283288
// update num of ops in debug info
284289

285-
if (debug_)
290+
if (settings_.debug)
286291
debugInfo_.numberOfOperations += 1 * size_[currentId_ - 1];
287292

288293
// return result id
@@ -314,7 +319,7 @@ void BasicCpuContext::declareOutputVariable(const std::size_t id) {
314319
outputVars_[currentId_ - 1].push_back(id);
315320
}
316321

317-
void BasicCpuContext::finalizeCalculation(std::vector<double*>& output, const Settings& settings) {
322+
void BasicCpuContext::finalizeCalculation(std::vector<double*>& output) {
318323
struct exitGuard {
319324
exitGuard() {}
320325
~exitGuard() { *currentState = ComputeState::idle; }
@@ -331,7 +336,7 @@ void BasicCpuContext::finalizeCalculation(std::vector<double*>& output, const Se
331336

332337
const auto& p = program_[currentId_ - 1];
333338

334-
auto ops = getRandomVariableOps(size_[currentId_ - 1], settings.regressionOrder);
339+
auto ops = getRandomVariableOps(size_[currentId_ - 1], settings_.regressionOrder);
335340

336341
// resize values vector to required size
337342

QuantExt/qle/math/computeenvironment.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ void ComputeEnvironment::selectContext(const std::string& deviceName) {
7070

7171
ComputeContext& ComputeEnvironment::context() { return *currentContext_; }
7272

73-
void ComputeContext::finalizeCalculation(std::vector<std::vector<double>>& output, const Settings& settings) {
73+
void ComputeContext::finalizeCalculation(std::vector<std::vector<double>>& output) {
7474
std::vector<double*> outputPtr(output.size());
7575
std::transform(output.begin(), output.end(), outputPtr.begin(),
7676
[](std::vector<double>& v) -> double* { return &v[0]; });
77-
finalizeCalculation(outputPtr, settings);
77+
finalizeCalculation(outputPtr);
7878
}
7979

8080
void ComputeFrameworkRegistry::add(const std::string& name, std::function<ComputeFramework*(void)> creator,

0 commit comments

Comments
 (0)