Royi Namir
Royi Namir

Reputation: 148524

Is it possible to divide work between cores?

I have this simple (dummy) code : (heavy computed : 30 sec in my machine)

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

Plinq will do the job division automatically . (divide work to threads). but it will work on Ienumerable (followed by AsParallel)

Here I don't have Ienumerable object. I just have 1 command.

How can I divide my command among the available cores ?

currently (as you can see) only 1 core is doing the hard work :

enter image description here

Edit :

Putting it under Task will not divide it among all cores :

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

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

enter image description here

Upvotes: 3

Views: 2130

Answers (5)

Terry C
Terry C

Reputation: 99

This is a great question and realize it is an old one.

I believe TPL (parallel.for/foreach) relies on the OS to distribute work to threads on various cores, so you would not be able to do this explicitly suing the boiler-plate, standard approaches. I do not think TPL was designed for that. But there may be a way to accomplish this by assigning a Task or delegate method to a particular processor that a thread should run on by using the ProcessThread.ProcessorAffinity property.

Upvotes: 1

Joy George Kunjikkuru
Joy George Kunjikkuru

Reputation: 1528

@royi,

If you keep some logic along with TaskParallelLibrary you can achieve the task. Bydefault I don't think .Net big integer supports parallelism. Try the below

    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;
    }

Now this works perfectly if your exponent is divisible by the procCount. You need to tweak the logic little to work with any exponent :-) If you face any difficult, let me know.

Upvotes: 1

Chris Sinclair
Chris Sinclair

Reputation: 23208

I haven't worked with BigInteger, but I don't see anything in the MSDN documentation that would lend me to think that the method can be distributed to multiple threads. It appears as though the method is written as a single, synchronous process which would be impossible to break into multiple threads short of re-implementing it yourself.

EDIT: If you look at the Mono source code, or another open source implementation, you may be able to rewrite their Pow methods to be muiti-threaded.

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;
}

Though looking at its process and its build-up/dependency on the previous loop (it alters/updates exponent, value, and result) it may be difficult non-trivial to write a new routine altogether that can break this work up and distribute it to multiple threads.

Upvotes: 4

Daro
Daro

Reputation: 2010

That seem to work fine on Win 8 and .Net 4.0. The "arrow" Shows where I started Debugging. The load is not symetric, but all cores are being used.

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

Upvotes: -2

Fusor
Fusor

Reputation: 31

if it is acceptable, you could delegate your work to a BackgroundWorker process, the framework will automatically dispatch the workload onto your 8 cores.

This object also permit you to start the process async (via the RunWorkerAsync)

It is very easy to use "multicore" threads through BW.

Upvotes: -1

Related Questions