2

注意我很清楚我在问什么,我不可能在正常情况下需要使用这样的函数,但它被用作因子实验研究生项目的研究因素进行。

我有以下要使用 PLINQ(不是 TPL)运行的函数。我知道 PLINQ 运行在 TPL 之上,但是这部分的实验。此外,除非我不知道使用 PLINQ 的另一种方法,否则我相信我将不得不在某种程度上“破解”阶乘方法以使用带有递归的 for 循环。

由于 Parallel 类只提供 For、ForEach 和 Invoke,它没有提供我需要的东西,比如 TPL 做什么,我需要它返回,而 Invoke 不这样做,所以我将不得不使用 For 并做一个 for 循环每个递归调用从 0,1 开始(是的,我知道这看起来很荒谬)。

我想做如下的事情:

public ulong RecursivePLINQ(ulong factor)
    {
        if (factor > 1)
        {
            Parallel.For<ulong>(0, 1, () => factor, (j, loop, factorial) =>
            {
                Thread.Sleep(1);    /*Simulate Moderate Operation*/
                return factorial * RecursivePLINQ(--factorial);
            }, (i) => { });
        }


        return 1;

    }

目前,发生的事情是它似乎正在工作,但在最终调用它返回 1,递归调用的结果是 1,而不是递归更改的值。我似乎无法发现有什么问题。我有此处显示的备用 TPL 实现(再次用于研究),它正在工作。

public ulong RecursiveTPL(ulong factor)
    {
        if (factor > 1)
        {
            Task<ulong> task = new Task<ulong>((f) =>
            {
                Thread.Sleep(1);    /*Simulate Moderate Operation*/
                ulong val = (ulong)f;
                return factor * RecursiveTPL(--val);
            }, factor);
            task.Start();
            task.Wait();
            return task.Result;
        }
            return 1;


    }

***再次请不要因为我的要求而抨击我,这是为了一个非常具体的研究目的* ****

编辑我在 MSDN 文档上看到了一个示例,该示例显示了线程局部变量的使用,所以我尝试了类似的方法,但我的头开始有点旋转......不要注意铸造,它只是看看我是否可以让它工作...

public ulong RecursivePLINQ(ulong factor)
    {
        long total = 0;
        if (factor > 1)
        {
            Parallel.For<ulong>(0, 1, () => factor, (j, loop, factorial) =>
            {
                Thread.Sleep(1);    /*Simulate Moderate Operation*/
                return factorial * RecursivePLINQ(--factorial);
            }, (i) =>  Interlocked.Add(ref total,(long)i)
            );
        }


        return (ulong)total;

    }
4

2 回答 2

2

它不漂亮,我真的不确定这是否对我的目的有效,但它确实给了我正确的阶乘。我得到了这个解决方案,但我必须对总参数进行校正才能使其工作,不知道我会怎么称呼它,或者是否有更好的方法来做到这一点,但现在必须这样做。 ..

public long RecursivePLINQ(long factor,long total)
    {

        if(total == 0)
        {
            total = 1;
        }
        if (factor > 1)
        {
            Parallel.For<long>(0, 1, () => factor, (j, loop, factorial) =>
            {
                Thread.Sleep(1);    /*Simulate Moderate Operation*/
                total = factorial * RecursivePLINQ(--factorial, total);
                return total;
            }, (i) =>  {return;});
        }
        return total;
    }
于 2012-12-02T04:36:55.327 回答
1

无耻地抄袭Dobbs 博士的这篇文章,您可以使用聚合扩展方法来计算阶乘:

int value=5; 
var factorial=Enumerable.Range(1, value).AsParallel()
             .Aggregate(1, (result, number)=>      
                           result*number, result=>result);

您可以争辩说 Aggregate 执行您将手动执行的递归,或者您可以编写递归调用自身来计算阶乘的代码。

不过,和其他人一样,我看不到你会完成什么。您的代码将由 PLINQ 的设置和拆卸主导,您获得的任何数字都将毫无意义。

如果有的话,PLINQ 用于用一系列可以并行执行的运算符替换循环代码,而程序员不必指定如何发生。

于 2012-12-04T14:25:33.460 回答