I have compiled part of boost - the ibeta_inv function - into a .Net 64 bit assembly and it worked great until I started calling it from multiple threads. Then it occationally return wrong results.
I complied it using this code (C++/CLI):
// Boost.h
#pragma once
#include <boost/math/special_functions/beta.hpp>
using namespace boost::math;
namespace Boost {
public ref class BoostMath
{
public:
double static InverseIncompleteBeta( double a, double b, double x )
{
return ibeta_inv(a,b,x);
}
};
}
Has anyone tried this before?
I have NOT tried this outside .Net, so I don't know if this is the cause, but I really don't see why, since it works great single threaded.
Usage (C#):
private void calcBoost(List<Val> vals)
{
//gives WRONG results (sometimes):
vals.AsParallel().ForAll(v => v.BoostResult = BoostMath.InverseIncompleteBeta(v.A, v.B, v.X));
//gives CORRECT results:
vals.ForEach(v => v.BoostResult = BoostMath.InverseIncompleteBeta(v.A, v.B, v.X));
}
UPDATE: As can be seen in my comments below - I'm not sure at all anymore that this is a Boost problem. Maybe it is some weird PLinq to C++/CLI bug??? I'm blaffed and will return with more facts later.
The reason for the latter limitation is the need to initialise symbolic constants using constructs ... as in this case there is a need for T's constructors to be run, leading to potential race conditions.
I openly wonder if your code exposes this race condition unexpectedly, and I wholeheartedly back stanwise on reporting this as a bug. – BuonaparteVal
class. Or try it at least with an immutableVal
class. – Mattias