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

このDrDobbsの記事から恥知らずにコピーすると、階乗の計算にAggregate拡張メソッドを使用できます。

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 に答える