|
From: Peter C. <pca...@gm...> - 2014-05-25 18:34:57
|
Hi,
I am currently trying to parallelize some computations in some pricing
engines (using the OpenMP API). There is a complication due to calls
to a lazy object model_ within a loop like this
#pragma omp parallel for default(shared) firstprivate(p) if(expiry0>settlement)
for (Size k = 0; k < (expiry0 > settlement ? npv0.size() : 1);
k++) {
[...]
model_->zerobond(arguments_.fixedPayDates[l],
expiry0, z[k], discountCurve_);
The problem is that the first call triggers performCalculations() in
model_ and before it has finished a call from another thread might
occur, in which model_ is considered to be computed already, because
in LazyObject the calculated_ flag is set to true right before the
actual computation has started
inline void LazyObject::calculate() const {
if (!calculated_ && !frozen_) {
calculated_ = true; // prevent infinite recursion in
// case of bootstrapping
try {
performCalculations();
} catch (...) {
calculated_ = false;
throw;
}
}
}
Of course it would not be desirable to trigger performCalculations()
from two threads either. We'd rather need a mechanism which makes all
threads wait until the first thread which triggered
performCalculations() has finished (I guess). Also the check of the
calculated_ flag and assignments to this variable would have to be
made thread safe.
I worked around this problem just by ensuring that model_ is
calculated before the parallelized loop by a dummy call (at low
additional cost)
#ifdef _OPENMP
if(expiry0>settlement)
model_->numeraire(QL_EPSILON);
#endif
I wonder however if someone has a more general and neater solution for this ?
I am not interested in general multithreading ability at the moment,
but more in this kind of "local" parallelizations, which seem quite
attractive (the bermudan swaption engine above is already faster by a
factor of 5 (on 8 cores), which is ok imo given the small effort to
adapt the code).
Thanks
Peter
|