Der eigentliche Grund ist aber, dass Speicherzugriffe nicht immer gleich lange dauern.
Um den Zugriff auf den Hauptspeicher zu beschleunigen, verfügen Prozessoren über Caches, kleine Zwischenspeicher. Davon kann es auch mehrere Stufen geben, und ganz am Ende stehen Daten in den Registern des Prozessors, wo der Zugriff am schnellsten ist.
Da es wenig Sinn macht, jedes Datum einzeln in den Cache zu laden, und da man beobachtet, dass Daten die im Speicher eng zusammen liegen, auch meistens in ihrer Benutzung eng zusammen liegen, schreibt man sie sozusagen schon auf verdacht in den Cache.
Iterierst du also so über die Daten, wie sie im Speicher liegen, hast du die optimale Performance. Benutzt du einen eher wahlfreien zugriff (so sieht es zumindest aus, wenn du in umgekehrter Reihenfolge iterierst), musst du andauernd andere Daten in den Cache laden, was langsamer ist. Das Stichwort wäre Cache-Miss. Mehr dazu hier:
https://de.wikipedia.org/wiki/Cache
Der einzige Grund, weshalb ich [y][x] geschrieben habe, ist übrigens der, dass mein Proxy-Objekt eben so herum funktionierte. Wer aber das Prinzip verstanden hat, kann den Code natürlich umschreiben, so dass man am Ende [x][y] benutzten kann. Zu beachten ist, dass sich dadurch das Speicherlayout nicht ändert, da einfach nur die Position anders berechnet wird.