是否有可能在核心之间划分工作?

时间:2013-04-28 12:16:03

标签: c# .net parallel-processing task-parallel-library

我有这个简单的(虚拟)代码:(重计算:在我的机器中30秒)

BigInteger number = BigInteger.Pow(Int64.MaxValue, 300000);
Console.WriteLine(number);

Plinq将自动完成工作分工。 (将工作分成线程)。但它将在Ienumerable(后跟AsParallel)

上工作

这里我没有Ienumerable对象。我只有一个命令。

如何在可用内核之间划分我的命令

目前(正如你所看到的)只有1个核心正在努力工作:

enter image description here

编辑:

将其置于Task之下将不会在所有核心之间进行划分:

Task<BigInteger> t=Task.Factory.StartNew(()=>BigInteger.Pow(Int64.MaxValue, 300000));

Console.WriteLine(t.Result);
Console.ReadLine();

enter image description here

5 个答案:

答案 0 :(得分:4)

我没有使用BigInteger,但我在MSDN documentation中没有看到任何可以让我认为该方法可以分发到多个线程的内容。似乎该方法是作为单个同步过程编写的,如果不是自己重新实现它,就不可能分成多个线程。

编辑:如果您查看Mono source code或其他open source implementation,您可以将其Pow方法重写为多线程。

public static BigInteger Pow (BigInteger value, int exponent)
{
    if (exponent < 0)
        throw new ArgumentOutOfRangeException("exponent", "exp must be >= 0");
    if (exponent == 0)
        return One;
    if (exponent == 1)
        return value;

    BigInteger result = One;
    while (exponent != 0) 
    {
        if ((exponent & 1) != 0)
            result = result * value;
        if (exponent == 1)
            break;

        value = value * value;
        exponent >>= 1;
    }

    return result;
}

虽然查看了它的进程及其对前一个循环的构建/依赖(它改变/更新exponentvalueresult),但它可能很难完全编写一个新的例程,可以打破这个工作并将其分发给多个线程。

答案 1 :(得分:1)

@royi,

如果你在TaskParallelLibrary中保留一些逻辑,你就可以完成任务。 Bydefault我不认为.Net大整数支持并行性。试试下面的

    pubilic BigInteger ParallelBigPow(Int64 value, int expo)
    {
        int procCount = Environment.ProcessorCount;
        BigInteger result = 1;
        Parallel.For(0, procCount, (index) => result = result * BigInteger.Pow(value, expo / procCount));
        return result;
    }

如果你的指数可以被procCount整除,那么现在这种方法非常有效。你需要调整逻辑很少与任何指数一起工作:-)如果你遇到任何困难,请告诉我。

答案 2 :(得分:1)

这是一个很好的问题,并且意识到这是一个旧问题。

我相信TPL(parallel.for / foreach)依赖于操作系统将工作分配给各种核心上的线程,因此您无法明确地采用锅炉板,标准方法。我不认为TPL是为此而设计的。但是,可以通过使用ProcessThread.ProcessorAffinity属性将任务或委托方法分配给线程应该运行的特定处理器来实现此目的。

答案 3 :(得分:-1)

如果可以接受,您可以将您的工作委托给BackgroundWorker进程,框架会自动将工作负载分配到您的8个核心。

此对象还允许您启动进程异步(通过RunWorkerAsync

通过BW使用“多核”线程非常容易。

答案 4 :(得分:-2)

这似乎在Win 8和.Net 4.0上运行良好。 “箭头”显示我开始调试的位置。负载不是对称的,但正在使用所有核心。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            BigInteger number = BigInteger.Pow(Int64.MaxValue, 300000);
            Console.WriteLine(number);
        }
    }
}

enter image description here