Dave
Dave

Reputation: 2994

Parallel loop returns a sum of floats

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.

Upvotes: 3

Views: 3377

Answers (1)

Magnus
Magnus

Reputation: 46977

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();

Upvotes: 5

Related Questions