0

I have an genetic algorithym code to solve a problem. It works slowly when the problem size gets bigger. So I have an idea to make it faster using multithreads running the same GA procedure.

But when I used 4 threads, it stopped to find best values too early. I think this is because of working on the same variables at the same time in the threads. But I don't know how to solve this.

So I want to ask what is the right way to call the same method that contains global variables in different threads?

My cropped code to help:

public void Start()
    {
        CreateInitialPopulation();
        Task th1 = new Task(() =>
        {
            Procedure();
        });
        Task th2 = new Task(() =>
        {
            Procedure();
        }); 
        Task th3 = new Task(() =>
        {
            Procedure();
        }); 
        Task th4 = new Task(() =>
        {
            Procedure();
        });
        th1.Start();
        th2.Start();
        th3.Start();
        th4.Start();
    }
    #endregion

    void Procedure()
    {

        stopped = false;
        while (produced < 10000000)
        {
            int[] nums = doSelection();

            Schedule mother = population[nums[0]];
            Schedule father = population[nums[1]];

            Schedule child1 = doCrossover(mother, father);
            Schedule child2 = doCrossover(father, mother);

            doMutation(child1);
            doMutation(child2);

            population[nums[nums.Length - 1]] = child1;
            population[nums[nums.Length - 2]] = child2;

            checkBestValueChanged(child1);
            checkBestValueChanged(child2);

            produced++;
            nothingFound++;
            if (nothingFound > 300000 && refresh)
            {
                addNewChromosomes(popSize / 10);
                nothingFound = 0;
            }

            Progress = double.Parse((produced * 100d / 10000000).ToString("0.00"));

            if (stopped)
                break;
        }
    }

UPDATE: In addition, when I used lock for the whole block the algorithym works good but at that time it works like using one thread, at normal speed.

Ali Tor
  • 2,772
  • 2
  • 27
  • 58
  • The variables are global. What effect were you going for? You'd at the least need to make their access thread-safe. – Nikki9696 Jun 27 '16 at 18:30
  • Also, threads are hard. Are you sure this is the way you want to solve this problem? – Nikki9696 Jun 27 '16 at 18:31
  • @Nikki9696, e.g. there are one `best` variable and in the loop this variable can be changed if a better is found. – Ali Tor Jun 27 '16 at 18:36
  • You should still be using classes and proper access so you can do things like locking when you need. Global variables are nearly always a code smell in an OOP language. I assume you do mean global in the traditional sense, not a static property somewhere or a property of the class (e.g. this.Stopped). – Nikki9696 Jun 27 '16 at 18:37
  • 1
    This is something I'd expect for a map/reduce scenario https://www.researchgate.net/publication/258858471_Parallelization_of_genetic_algorithms_using_Hadoop_MapReduce – Nikki9696 Jun 27 '16 at 18:40
  • No, in my code, nearly all global variables exists as its property like you said (e.g. this.Stopped) – Ali Tor Jun 27 '16 at 18:42
  • 1
    Check out this, (and do some googling on thread safety because there are fun gotchas) http://stackoverflow.com/questions/9848067/what-makes-a-method-thread-safe-what-are-the-rules – Nikki9696 Jun 27 '16 at 18:49

1 Answers1

1

Well, first of all you should understand, that more threads will give you really more speed only if you have several CPUs.

For your programm you could use Parallel.For method, but remember, it works fine only for great massives of data, cycles with very large number of iterations an so on.

If you use different locks (for example ReaderWriterLockSlim), try to use them for as little part of your code as you can, to lock threads for less time.

And of course, try to write you programs without global vars if it's real

Daniil Vlasenko
  • 457
  • 3
  • 11
  • The threads works to speed up the progress. But it doesn't reports `best` variables, so the progress is just a number. – Ali Tor Jun 27 '16 at 18:40
  • @Ali Tor, Yep, this was not a moral, just advice. Try paraller.for, i think it'll help – Daniil Vlasenko Jun 27 '16 at 18:43
  • 2
    Parallel.For still needs everything to be thread safe though, so check those functions you're calling. They also need thread safe variables if they get passed in or use globals. – Nikki9696 Jun 27 '16 at 18:51