C# Parallel.For

Need help with an engine or coding not on the list? Need help with a game or the website and forums here? Direct all questions here.
Post Reply
User avatar
Xaos
Posts: 946
Joined: Wed Jan 11, 2012 4:01 am

C# Parallel.For

Post by Xaos »

Hey guys. I decided to use Parallel.For for one of my for loops to make it faster, but for some reason once I hook up the Parallel.For, I get a System.ArgumentException error cast and it says the Source array was not long enough, even though it works perfectly fine for a normal for loop. None of that code changed.
User avatar
a_bertrand
Posts: 1537
Joined: Mon Feb 25, 2013 1:46 pm

Re: C# Parallel.For

Post by a_bertrand »

You should provide us the code to try to help you. Just like that it's impossible to say what's going on.
Creator of Dot World Maker
Mad programmer and annoying composer
User avatar
Xaos
Posts: 946
Joined: Wed Jan 11, 2012 4:01 am

Re: C# Parallel.For

Post by Xaos »

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace EconomicSimulator
{
    class Citizen
    {
        public static int Population;
        public static List<long> citizenList = new List<long>();

        public static void Populate()
        {
            long income;
            Random rnd = new Random();
            Population = rnd.Next(17800000, 47800000); //Creating the population, some # between those numbers

            Parallel.For(0, Population, i => //Loop through the population
            {
                double incomeChance = (rnd.Next(0, 1200000)); //Figure out which income bracket said 'person' is in
                if (incomeChance <= 1)
                {
                    income = Math.Abs(10000000 * rnd.Next(10000, 80000));
                    citizenList.Add(income);
                    // Over $10,000,000
                }
                else if (incomeChance <= 2)
                {
                    income = Math.Abs(1000 * rnd.Next(5000, 10000));
                    citizenList.Add(income);
                    // $5,000,000 to $10,000,000
                }
                else if (incomeChance > 3 && incomeChance <= 7)
                {
                    income = Math.Abs(1000 * rnd.Next(1500, 2000));
                    citizenList.Add(income);
                    // $1,500,000 to $2,000,000
                }
                else if (incomeChance > 7 && incomeChance <= 30)
                {
                    income = Math.Abs(1000 * rnd.Next(2000, 5000));
                    citizenList.Add(income);
                    // $2,000,000 to $5,000,000
                }
                else if (incomeChance > 30 && incomeChance <= 86)
                {
                    income = Math.Abs(1000 * rnd.Next(1000, 1500));
                    citizenList.Add(income);
                    // $1,000,000 to $1,500,000
                }
                else if (incomeChance > 86 && incomeChance <= 136)
                {
                    income = Math.Abs(100 * rnd.Next(5000, 10000));
                    citizenList.Add(income);
                    // $500,000 to $1,000,000
                }
                else if (incomeChance > 136 && incomeChance <= 256)
                {
                    income = Math.Abs(100 * rnd.Next(2000, 5000));
                    citizenList.Add(income);
                    // $200,000 to $500,000
                }
                else if (incomeChance > 256 && incomeChance <= 10606)
                {
                    income = Math.Abs(10 * rnd.Next(2500, 3000));
                    citizenList.Add(income);
                    // $25,000 to $30,000
                }
                else if (incomeChance > 10606 && incomeChance <= 50606)
                {
                    income = Math.Abs(10 * rnd.Next(2000, 2500));
                    citizenList.Add(income);
                    // $20,000 to $25,000
                }
                else if (incomeChance > 50606 && incomeChance <= 100606)
                {
                    income = Math.Abs(rnd.Next(1, 5000));
                    citizenList.Add(income);
                    // $1 to $5,000
                }
                else if (incomeChance > 100606 && incomeChance <= 280606)
                {
                    income = Math.Abs(10 * rnd.Next(4000, 5000));
                    citizenList.Add(income);
                    // $40,000 to $50,000
                }
                else if (incomeChance > 280606 && incomeChance <= 345606)
                {
                    income = Math.Abs(10 * rnd.Next(7500, 10000));
                    citizenList.Add(income);
                    // $75,000 to $100,000
                }
                else if (incomeChance > 345606 && incomeChance <= 426606)
                {
                    income = Math.Abs(10 * rnd.Next(1500, 2000));
                    citizenList.Add(income);
                    // $15,000 to $20,000
                }
                else if (incomeChance > 426006 && incomeChance <= 621006)
                {
                    income = Math.Abs(rnd.Next(5000, 10000));
                    citizenList.Add(income);
                    // $5,000 to $10,000
                }
                else if (incomeChance > 621006 && incomeChance <= 710006)
                {
                    income = Math.Abs(10 * rnd.Next(1000, 1500));
                    citizenList.Add(income);
                    // $10,000 to $15,000
                }
                else if (incomeChance > 710006 && incomeChance <= 780006)
                {
                    income = Math.Abs(10 * rnd.Next(3000, 4000));
                    citizenList.Add(income);
                    // $30,000 to $40,000
                }
                else if (incomeChance > 780006 && incomeChance <= 800006)
                {
                    income = Math.Abs(100 * rnd.Next(1000, 2000));
                    citizenList.Add(income);
                    // $100,000 to $200,000
                }
                else if (incomeChance > 800006)
                {
                    income = Math.Abs(10 * rnd.Next(5000, 7500));
                    citizenList.Add(income);
                    // $50,000 to $75,000
                }
            });
        }
    }
}
Here you go, thought maybe the above would be enough and this is a common err or something. But I have the Parallel.For, and it throws the exception. With a normal for loop it doesn't.
User avatar
Jackolantern
Posts: 10893
Joined: Wed Jul 01, 2009 11:00 pm

Re: C# Parallel.For

Post by Jackolantern »

I am not that familiar with the TPL in .NET, but does this require synchronization or some other type of thread-safety on the citizenList, Alan? If so, Xaos, you may want to consider switching to one of the ready-made thread-safe collections. Unchecked multithreading can cause all kinds of headaches with collections, such as doubling values, missing values, etc.

Also, Xaos, have you actually checked that this FOR loop is causing performance problems? I do realize it is running millions of times, but that may actually finish at a decent rate since little work is being done inside of it. It is generally a best practice to not start worrying about optimization until you are sure there is a problem. If it is completing in a half a second or so, I would see little point in investing it making it concurrent.
The indelible lord of tl;dr
User avatar
Xaos
Posts: 946
Joined: Wed Jan 11, 2012 4:01 am

Re: C# Parallel.For

Post by Xaos »

Well I was hoping that this would work so I could see if this could make it faster. But ill check into thoee you linker.
User avatar
a_bertrand
Posts: 1537
Joined: Mon Feb 25, 2013 1:46 pm

Re: C# Parallel.For

Post by a_bertrand »

Indeed, lists are not thread safe and here this code will access the list from multiple threads at the same time. Either lock every access of the list, or use a thread safe collection. You will not be 100% pleased by those collections however as they are not the same as the non thread safe one.
Creator of Dot World Maker
Mad programmer and annoying composer
User avatar
Jackolantern
Posts: 10893
Joined: Wed Jul 01, 2009 11:00 pm

Re: C# Parallel.For

Post by Jackolantern »

You will also notice quite a large step backwards in performance back towards the sequential access. Almost all of your code inside the parallel for loop would be considered critical, so a ton of that is going to end up becoming sequential to maintain locks.
The indelible lord of tl;dr
User avatar
Xaos
Posts: 946
Joined: Wed Jan 11, 2012 4:01 am

Re: C# Parallel.For

Post by Xaos »

Ohh, gotcha guys. How do you guys recommend optimizing? I'm basically running this for loop, finding the mean, finding the median, then taking a % of each value in an array (from the for loop) and taking a %, adding it to anohter value and changing it in the array.
User avatar
Jackolantern
Posts: 10893
Joined: Wed Jul 01, 2009 11:00 pm

Re: C# Parallel.For

Post by Jackolantern »

How long is it taking to complete as-is?
The indelible lord of tl;dr
User avatar
Xaos
Posts: 946
Joined: Wed Jan 11, 2012 4:01 am

Re: C# Parallel.For

Post by Xaos »

About 20-30 minutes for a simulation of 17.8 million - 47.8 million.
Post Reply

Return to “Advanced Help and Support”