aharbick wrote: November 29th, 2025, 1:06 am
If anyone has ideas for further performance improvements OR if you want to donate your 5090 cycles hit me up
An idea that seems to have some potential (with many possible variants) is to use the fact that Life is not reversible, meaning that the set of patterns that can arise after one generation is much smaller than the set of all patterns.
Take this partial pattern, where blue cells are set as off, the green cell is on and red cells are unset.
Code:
Select all
x = 8, y = 8, rule = LifeHistory:P8,8
A2B5D$3B5D$2B6D$8D$8D$8D$8D$8D!
Whatever you put in the red zone, after one generation it will be the same as if you had started with this pattern :
Code:
Select all
x = 8, y = 8, rule = LifeHistory:P8,8
3B5D$3B5D$2B6D$8D$8D$8D$8D$8D!
This can work anytime the state of a cell is irrelevant to the rest of the evolution of the pattern. Solely with the case above, you can save about 1/64th of the total computing time. It might be worthwhile to make an exhaustive search for similar cases for cells in the corners or on the borders, where there are less constraints.
By the way, up in this thread apg mentionned a 56B soups/s performance. Why this discrepancy? Was it on a multi-GPU machine?
There have been discussions on a similar subject but for tori instead of planes last year : see this thread
viewtopic.php?f=2&t=6506. In particular, in
this post of mine I presented some exhaustive searches, which I conducted on one CPU in about 12 hours (if I remember correcly) but for a 6x6 torus. I was searching at about 1M patterns/s with a very naive algorithm, nowhere near the performance of your optimised GPU algorithm. I you can give it a try, I would be very interested in knowing the maximum lifespan on a 7x7 torus, or even on an 8x8 one. It seems more tractable to run exhaustive searches on tori since they have translation symmetries which vastly reduce the search space.
Edit:
I wrote a quick script to generalise my idea on all 3x3 squares in the upper left corner. The same trick works for 18 of 256 (barring bugs) possible arrangements.
Code: Select all
o..
...
...
o..
o..
...
o..
...
o..
oo.
...
...
o..
.o.
...
oo.
oo.
...
o..
...
.o.
oo.
oo.
oo.
o.o
...
...
o..
..o
...
ooo
ooo
...
ooo
ooo
oo.
o..
...
..o
o..
o..
ooo
oo.
oo.
ooo
ooo
..o
..o
ooo
ooo
..o
ooo
ooo
ooo
That's 512-18 = 494 corners to be searched. Without taking symmetries into account, if this reduction is applied on every corner the size of the search space is reduced by a factor of (512/494)^4 = 1.15 (probably less interesting with symmetries, but still worth considering).
Edit 2:
Testing this idea with the 3x8 upper box, looking at changes of the top line which do not affect the first generation there are (barring bugs) only 11,510,370 patterns which produce a distinct output among all 16,777,216 = 2^24, a reduction of the search space by a factor of 1.46, or 2.12 if applied on top and bottom (again, without symmetries).
Edit 3:
I think that I found a variant of the above idea which could reduce the search space by a factor of 14. The splitting that I will present is probably not as well suited for GPUs as apg's design, but perhaps it can be refined.
The first level of iteration is over the middle 4x4 block. After symmetry deduplication, there should be about 2^13 such blocks.
Then iterate over the side 2x4 blocks, again removing symmetrics if needed. This should produce about 2^29 middle 8x4 blocks.
Code:
Select all
x = 8, y = 8, rule = LifeHistory:P8,8
8B$8B$8D$8D$8D$8D$8B$8B!
For each 8x4 block, compute separatedly the possible missing 2x8 blocks. Specifically, we want every possible 2-generations outcome for the upper rows to occur exactly once, which requires running each of 2^16 patterns for 2 generations and comparing the 4 top rows for equality. This way we are ensured to iterate over all unique patterns after 2 generations, since there is no interaction with the bottom rows until generation 3. The 4 rows obtained can be kept in two lists, one for the top and one for the bottom, which can then be recombine to form all licit 2-generations pattern. According to statistics that I collected over 10000 starting blocks, only one in 3.8 (or about 17000) of all possibilities are expected to produce a different 2-generations upper-half, or 17000^2 ~ 300M possibilities in total for each block. This makes a total of about 1.6*10^17 patterns to try.
At 10B soups/s, this would reduce the search time to about 185 days. Can someone confirm my logic?