How to understand what is slowing down the code on many iterations?

edited May 2018 in Library Questions

I have a very big code with multiple classes which creates a simulation of artificial creatures. It contains an evolution algorithm which at the end of each generation saves several copies of the best individuals and then recreates an entirely new generation using their neural networks with added mutations. On the creation of a new generation, the old one is wiped. However, with each generation, it loads the next generation slower practically stopping on gen 4 or 5 (the number of agents doesn't change from generation to generation). At that point, it just basically freezes after I call the "evolveWorkers()" function. Is there any tool which I can use in order to find the function on which it gets stuck?

Thanks in advance to anyone who replies.

And in case you can help me, here are some bits of code which I think might be creating a problem, if you want a function of something in particular I am happy to share it too.:

void evolveWorkers() {
    int j = 0;
    ArrayList <Alien> elites = new ArrayList <Alien>(); //creating an array list where to store the best fit 
    elites = returnFit();

    for ( int i = 0; i< aliens.size(); i++) {
      if ( aliens.get(i) instanceof Worker) {
        aliens.get(i).dead = true; //marks the old aliens dead so they get removed
      }
    }

    for ( int i = 0; i< 20; i++) {
      aliens.add(new Worker(width/2, height/2, elites.get(j).net));
      j++;
      if (j >= elites.size()) {
        j = 0;
      }
    }
  }
}

ArrayList <Alien> returnFit() {
    ArrayList <Alien> workers; //array to pick the workers out of all aliens
    ArrayList <Alien> elites;
    elites = new ArrayList<Alien>();
    workers = new ArrayList <Alien>();
    for ( int i = 0; i < aliens.size(); i++) {
      Alien m = aliens.get(i);
      if ( m instanceof Worker) {
        workers.add(m);
      }
      Collections.sort(workers, new Sortbyfitness());
    }

    for (int i = workers.size()-1; i >= workers.size()-1 - int(workers.size()* elitesPercent/100); i --) {
      elites.add(workers.get(i));
    }
    return elites;
  }

 //remove the dead aliens
  void clearDead() {
    for (int i = 0; i< aliens.size(); i++) {
      Alien a = aliens.get(i);
      if (a.dead) {
        aliens.remove(a);
        a.removeObserver(tutorial); //important to remove the observers in order to preserve framerate
      }
    }
  }

I suspect that the agents are not really wiped at the new gen so the program somehow needs to go through all of them and the data gets accumulated somewhere... I am not sure.

Answers

  • edited May 2018

    When removing things from an ArrayList, usually you loop over the objects in the ArrayList in reverse order. I also worry that you are calling .remove() with an Alien (a), not the index of an alien (i)...

    Also I worry about this removeObserver() function. Why is whatever that is not just something inside your Alien class?

    It's super hard to tell more without seeing the full code. Can you trim it down to an example that shows the same slowdown?

  • Thank you for your help. I've been thinking about the problem for a while and I changed several things. Running this code on my Windows 10 laptop still leads to the problem that I've described above. However, I tried it on a Mac laptop and everything was running super smooth. It seems like my code might not be the main cause of the problem.

  • That is far more surprising, can you replicate this problem with any smaller code, like TF is asking you to? It could be quite useful to know what is causing this bug

  • edited May 2018

    My code is really monstrous in size, I tried shrinking it down by a lot, but without all the features and big class constructors that come with it, the problem doesn't seem to be present. I don't think I can post it here.

    Also, I tried in on one more laptop which runs windows 10 too. The problem was not present at all even after iterating through 20 or more generations...

    A question - why would one particular laptop have problems running it? Any ideas?

  • edited May 2018

    I was able to learn (with the strategical use of "println") that the code is slowing down when this loop is running:

     for ( int i = 0; i< 20; i++) {
          aliens.add(new Worker(width/2, height/2, elites.get(j).net));
          j++;
          if (j >= elites.size()) {
            j = 0;
          }
        }
    

    So somehow adding a new "Worker" is slow. Here is what the constructor looks like:

      public Worker(float _x, float _y, NeuralNetwork _net) {
    
    
        directionsPI = new float [] {0,QUARTER_PI, PI/2, PI/2 + QUARTER_PI, PI, PI + QUARTER_PI, PI + PI/2, PI*2 - QUARTER_PI, PI};
        directionalValues = new float [directionsPI.length];
        for ( int i = 0; i < directionalValues.length; i++){
          directionalValues [i] = 0;
        }
    
        _layers = new int[] {16, 30, 16, directionalValues.length};
        net = new NeuralNetwork ( _layers, _net);
        type = "Worker";
        diameter = worker_size;
        pos = new PVector (_x, _y);
        speed = worker_speed;
        cor = workerColor;
        hearing_distance = 100;
        controls = new String[] {"Evolve Fighter"};
        out = minim.getLineOut();
        // create a sine wave Oscil, set to 440 Hz, at 0.5 amplitude
        wave = new Oscil( 200, 0.5f, Waves.SINE );
        fftLinA = new FFT (out.bufferSize(), out.sampleRate());
        fftLinA.linAverages(30);
        this.registerObserver(tutorial);
        collidable = true;
        selectable = true;
        soundInterval = 10;
        fitness = 0;
    
         float ran = random(1);
            if ( ran > mutation_chance){
              net.Mutate();
            }
    
      }
    

    As you can see that it contains a constructor for the other class which is NeuralNetwork which is the constructor that creates a copy of an existing net which is one of the arguments for the Worker. It also runs a "Mutate()" command which makes random changes to the neural network.

  • it's creating these also

    wave = new Oscil( 200, 0.5f, Waves.SINE );
    fftLinA = new FFT (out.bufferSize(), out.sampleRate());
    

    plus, that first loop isn't creating a new Worker, it's creating twenty new Workers.

Sign In or Register to comment.