3

I want to convert this simple for loop into a parallel one. It loops over an array of strings (floats read from a text file) and computes the sum.

for (int i = 0; i < parts.Length; i++)
{
    float tmp;

    if (float.TryParse(parts[i], out tmp) || float.TryParse(parts[i].Replace('.', ','), out tmp))
        total += tmp;
}

this is my try :

Parallel.For(0, parts.Length, i =>
{
    float tmp;

    if (float.TryParse(parts[i], out tmp) || float.TryParse(parts[i].Replace('.', ','), out tmp))
        total += tmp;
});

It returns a float but the value is wrong.

I also tryed this one.

Parallel.For<float>(0, parts.Count, () => 0, (i, loop, subtotal) =>
    {
        total += result[i];
        return subtotal;
    },
    (x) => Interlocked.Add(ref sum, x)
);

Couldn't get the syntax down.

Also I know it sounds ridiculous but most examples are with integers and eventually they use a method Add that only accepts int parameters, which I can't use obviously.

Dave
  • 2,774
  • 4
  • 36
  • 52
  • Keep in mind that for simple operations like computing a sum, the overhead involved with threading will almost certainly outweigh the benefits of parallel computation. – Daniel Mann Oct 20 '14 at 21:37
  • @DanielMann In this case there is some parsing going on also. – Magnus Oct 20 '14 at 22:03

1 Answers1

5

To make it easy use the following:

var total = 
    parts.AsParallel().Sum(x => 
    {
        float tmp;
        if (float.TryParse(x, out tmp) || float.TryParse(x.Replace('.', ','), out tmp))
            return tmp;
        return 0;
    });

Or using Parallel.For

var bag = new ConcurrentBag<float>(); //Will hold the sub total for each thread.

Parallel.For<float>(0, parts.Count, () => 0, (i, state, subtotal) =>
{
    float tmp;
    if (float.TryParse(parts[i], out tmp) || float.TryParse(parts[i].Replace('.', ','), out tmp))
        subtotal += tmp;
    return subtotal;
},
(x) => bag.Add(x));

var total = bag.Sum();
Magnus
  • 45,362
  • 8
  • 80
  • 118
  • Yeah I read your link on Parallel.For, but couldn't get the syntax down. Your answer is fantastic, it's simple and it works. Out of curiosity, does the Parallel.For and the AsParallel() give similar performances ? is there a case where one is better than the other ? – Dave Oct 20 '14 at 20:59
  • 1
    They should have similar performances. As always when using linq it will give a little overhead. But for easy of use and code maintainability I would go with the linq `Sum` solution. – Magnus Oct 20 '14 at 21:08
  • @Dave I've updated the answer with a `Parallel.For` implementation also. – Magnus Oct 20 '14 at 21:23