1

I have a grid of 300x300 cells. I am checking each cell individually which means I am checking 90000 cells atleast every second. Now, I know, one second is pretty fast considering the cpu is going through 300^2 different cells. But this stuff just isn't fast enough. I watched a guy on youtube who got his simulation to update every 20 ms. And he was running 512^2 cells. How is this possible? Optimizations? Is my computer a potato? I'll show my code if anyone wants to see exactly what i'm doing.

for (int y = GY; y >= 0; y--)
    for (int x = 0; x < GX; x++) {
        cell* cell_pointer = &grid[x][y];
        if (grid[x][y].CellT == type::SAND) {
            if (grid[x][y+1].CellT == type::AIR) {
                if (y+1 > GY-1) {
                    continue;
                }
                cell* cell_below = &grid[x][y+1];

                cell_below->Color ={ 255,0,0 };
                cell_below->CellT = type::SAND;

                cell_pointer->Color ={ 0,0,0 };
                cell_pointer->CellT = type::AIR;
            }
            else if (grid[x+1][y+1].CellT == type::AIR) {
                cell* cell_below = &grid[x+1][y+1];

                cell_below->Color ={ 255,0,0 };
                cell_below->CellT = type::SAND;

                cell_pointer->Color ={ 0,0,0 };
                cell_pointer->CellT = type::AIR;
            }
            else if (grid[x-1][y+1].CellT == type::AIR) {
                cell* cell_below = &grid[x-1][y+1];

                cell_below->Color ={ 255,0,0 };
                cell_below->CellT = type::SAND;

                cell_pointer->Color ={ 0,0,0 };
                cell_pointer->CellT = type::AIR;
            }
        }
    }

The code above is my update function. I am updating the cells bottom to top, left to right. It's a sand simulation which is why we're checking the bottom left, bottom right as well as the bottom neighboring cells.

//Square//
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
SDL_RenderClear(renderer);

//////////

int X = floor(mousePos.x/r.w);
int Y = floor(mousePos.y/r.h);

if (left) {
        grid[X][Y].CellT = type::SAND;
        grid[X][Y].Color ={ 255,0,0 };
}
if (right) {
        grid[X][Y].CellT = type::WALL;
        grid[X][Y].Color ={ 0,255,0 };
}

for (int y = 0; y < GY; y++)
for (int x = 0; x < GX; x++) {
        cell* cell_pointer = &grid[x][y];
        SDL_SetRenderDrawColor(renderer, cell_pointer->Color.r, cell_pointer->Color.g, cell_pointer->Color.b, 255);
        r.x = cell_pointer->PosG.x;
        r.y = cell_pointer->PosG.y;

        SDL_RenderFillRect(renderer, &r);
}

SDL_RenderPresent(renderer);

SDL_UpdateWindowSurface(window);

The code above is my draw function. I am using SDL as my graphics API. I am getting the mouse position relative to the grids so that when I click left or right mouse buttons I can draw a sand cell or a wall cell. So I am checking each cell individually top to bottom and left to right and then drawing a square individually where the cell's position is.

genpfault
  • 51,148
  • 11
  • 85
  • 139
Idiot Boy
  • 51
  • 5
  • 1
    Depending on the data layout, flipping the `for` loops for `x` and `y` can sometimes cause miracles. – Mooing Duck Jul 21 '20 at 22:52
  • 3
    Did you profile the code to determine that the update is slow? Or is the slow part SDL_RenderFillRect? – Mooing Duck Jul 21 '20 at 22:52
  • I think you read from `y-1` before your `if (y+1 > GY-1)` check, in which case you're reading out of bounds. – Mooing Duck Jul 21 '20 at 22:54
  • The inner parts of the `if` blocks are identical in code and only vary in values, which means you have 3x as much code as needed in your instruction cache, which could theoretically slow performance. In practice, this is unlikely to affect anything noticable. – Mooing Duck Jul 21 '20 at 22:55
  • 2
    Compiler's optimizer should already know this trick, but consider using a reference instead of a pointer at `cell* cell_below = &grid[x][y+1];` and friends. Speaking of, don't waste your time considering the speed of the the program if you don't have medium to high optimization turned on. – user4581301 Jul 21 '20 at 22:56
  • 1
    One tidbit is that you're updating all 90k cells per update. If you only update cells adjecent to updates from the previous frame, you can (sometimes) get _way_ faster performance, depending on how much of the screen is updated each frame. – Mooing Duck Jul 21 '20 at 22:57
  • Now that I've read teh code, I'm 95% sure the problem is `SDL_RenderClear(renderer)` followed by 90k `SDL_RenderFillRect` calls. That's a _ton_ of data to try to funnel to the video card every frame. – Mooing Duck Jul 21 '20 at 22:58
  • @MooingDuck So how do I fix this problem? I'm very used to clear and then draw again. – Idiot Boy Jul 21 '20 at 23:07
  • something something [hashlife](https://en.wikipedia.org/wiki/Hashlife) :) – genpfault Jul 21 '20 at 23:10
  • @IdiotBoy: I don't know much about graphics (yet), but my money would be on not doing a clear and only painting changed cells. Or doing the algorithm entirely in the GPU where it's all parallelized, but I don't know how that works. – Mooing Duck Jul 21 '20 at 23:10
  • @genpfault I will take a look at that, thank you. – Idiot Boy Jul 21 '20 at 23:15
  • @IdiotBoy: Nah, I was being facetious, sorry. Mooing Duck has it with the "waaaay too many `SDL_RenderFillRect()` calls per frame". You're going to want to modify your CA state color array CPU-side, [upload it into a SDL_Texture](https://stackoverflow.com/questions/33304351/sdl2-fast-pixel-manipulation/33312056#33312056), and then draw that. That way you only have (essentially) only one GPU draw-call per frame. – genpfault Jul 21 '20 at 23:38
  • More generally RE: CA optimization, look into [stencil code](https://en.wikipedia.org/wiki/Stencil_code) frameworks, those can use templates & threads to automagically parallelize CA updates while still maintaining (relatively) normal-looking inner-loop rule code – genpfault Jul 21 '20 at 23:45
  • Also, edit in a [mcve], I'm interested in seeing what the overall effect is. – genpfault Jul 21 '20 at 23:46

0 Answers0