提升数学(ibeta_inv函数)不是线程安全吗?

Dan*_*röm 8 .net c# boost c++-cli plinq

我已经将boost的一部分 - ibeta_inv函数 - 编译成.Net 64位程序集,并且它工作得很好,直到我开始从多个线程调用它.然后它在某种程度上会返回错误的结果.

我使用此代码(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);
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

有人曾尝试过这个吗?

我没有在.Net之外尝试过这个,所以我不知道这是不是原因,但我真的不明白为什么,因为它的单线程很好.

用法(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));
}
Run Code Online (Sandbox Code Playgroud)

更新:从我在下面的评论中可以看出 - 我完全不确定这是一个Boost问题.也许这是一些奇怪的PLinq到C++/CLI的bug?我被废除了,以后会回来更多的事实.

Zoo*_*ine 2

我碰巧将 boost 的一部分封装在 C++/CLI 64 位项目中,并像您一样从 C# 中使用它。

因此,我将您的 C++ 类放入我自己的 Boost 包装器中,并将以下代码添加到 C# 项目中:

    private class Val
    {
        public double A;
        public double B;
        public double X;
        public double ParallellResult;
    }

    private static void findParallelError()
    {
        var r = new Random();

        while (true)
        {
            var vals = new List<Val>();
            for (var i = 0; i < 1000*1000; i++)
            {
                var val = new Val();
                val.A = r.NextDouble()*100;
                val.B = val.A + r.NextDouble()*1000;
                val.X = r.NextDouble();
                vals.Add(val);
            }

            // parallel calculation
            vals.AsParallel().ForAll(v => v.ParallellResult = Boost.BoostMath.InverseIncompleteBeta(v.A, v.B, v.X));

            /sequential verification
            var error = vals.Exists(v => v.ParallellResult != Boost.BoostMath.InverseIncompleteBeta(v.A, v.B, v.X));
            if (error)
                return;
        }
    }
Run Code Online (Sandbox Code Playgroud)

它只是“永远”执行。并行结果始终等于顺序结果。这里没有线程不安全...

我可以建议您下载 Boost 的新副本并将其包含在一个全新的项目中并尝试一下吗?

我还注意到您将结果称为“BoostResult”...并在评论中提到了有关“我们当前的实现”的内容。您到底在比较什么结果?你对“正确”的定义是什么?