I've been actively using QuantLib for structured product pricing using Monte Carlo. Due to the fact that at a great deal of paths are often needed and one needs to speed up the calculation and all that, I find myself having to think about ways to multithread the pricing. By profiling the code I obviously noted that the biggest bottleneck is not the product construction but running the Monte Carlo simulation.

Therefore let's suppose that if I needed 300k paths to somewhat accurately price the product, can I just spawn 10 threads, build the product in each one of them and make each thread calculate the NPV of the product with 30k paths all whilst using different seeds and then average the 10 different NPVs together?


Yes, it can work. However, keep in mind that:

  • you'll be safer if you don't share any objects between threads; see my answer here, in particular the last point;
  • even if you use different seeds, there's no guarantee that the generated sequences won't overlap. If you're willing to change the engine code so that you can pass the relevant parameters, a safer option would be to use a low-discrepancy generator such as Sobol, which has the ability to skip ahead in the sequence. This way, you could tell each generator to start at the correct place in the sequence of $2^N-1$ samples you'll use.
  • $\begingroup$ what you mention for the sobol' sequence is not the correct way to do it - you should apply a random 32 bit integer as a mask (OR mask) to the uniform integers created by the sobol' sequence. This is also how you measure the variance of calculated variables using sobl' sequences - just taking the variance of your output and dividing by the number of paths does not work here like it does for (pseudo) random numbers. $\endgroup$ – will Dec 26 '17 at 17:57
  • $\begingroup$ @will, I agree with you that Sobol doesn't give you a variance, but I'm not sure how skipping ahead to partition the target set of samples is not correct. May you elaborate? $\endgroup$ – Luigi Ballabio Dec 26 '17 at 18:33
  • $\begingroup$ when you use sobol sequences, you should take a power of two points to ensure you sample the space uniformly without any bias. If you decide to skip ahead a bunch of points, then you should align with a power of two and also end with a power of two. If you arbitrarily jump ahead the distribution will not neccesarily meet the various prng conditions required for MC simulation (i.e. moments). $\endgroup$ – will Dec 26 '17 at 18:59
  • $\begingroup$ Sure, I mentioned a sequence of 2^N-1 samples (a bit cryptically, maybe). But if you group the statistics at the end so that you reconstruct the full set, it doesn't matter who did what part of the sequence. This said, your method also gives the variance, so it's better. (In fact, you might post it as an answer to make it more visible.) $\endgroup$ – Luigi Ballabio Dec 26 '17 at 20:25

Adding to Luigi's answer, second point: The issue of overlapping Mersenne Twister sequences can be addressed with dynamically created Mersenne Twister Generators, cf. http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/DC/dc.html. I created a wrapper for the dcmt library so that it fits more easily into the QuantLib library, see https://github.com/pcaspers/QuantLib/blob/mtmc/ql/experimental/math/dynamiccreator.hpp. There are precomputed instances for parallel use in 8 threads.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.