2014-11-18 12 views
5

Próbuję utworzyć tablicę 2D w PHP o rozmiarze 2000x2000 (4 miliony wpisów). Wygląda na to, że zabrakło mi tu pamięci, ale sposób, w jaki pojawia się błąd, jest mylący.Błąd pamięci PHP z dużą tablicą

Po zdefiniowaniu tablicy i wypełnieniu jej początkowo za pomocą komendy array_fill i zainicjowaniu każdej pozycji w tablicy (macierzy) za pomocą 0 nie ma problemu.

Jednak jeśli spróbuję iterować po tablicy i wypełnić każdą pozycję wartością 0, zabraknie jej pamięci.

Założę się, że po uruchomieniu array_fill przydzieli pamięć w tym miejscu i nie powinno zabraknąć pamięci w pętli.

Oczywiście jest to tylko uproszczona wersja kodu. W mojej aktualnej aplikacji będę używał współrzędnych Y X &, aby sprawdzić wartość z innej tabeli, przetworzyć ją, a następnie zapisać w mojej macierzy. Będą to wartości zmiennoprzecinkowe.

Czy ktoś może pomóc w tym świetle? Czy jest jakiś inny sposób, w jaki powinienem to robić?

Dziękujemy!

<?php 

// Set error reporting. 
error_reporting(E_ALL); 
ini_set('display_errors', TRUE); 
ini_set('display_startup_errors', TRUE); 

// Define Matrix dimensions. 
define("MATRIX_WIDTH", 2000+1); 
define("MATRIX_HEIGHT", 2000+1); 


// Setup array for matrix and initialize it. 
$matrix = array_fill(0,MATRIX_HEIGHT,array_fill(0,MATRIX_WIDTH,0)); 

// Populate each matrix point with calculated value. 
for($y_cood=0;$y_cood<MATRIX_HEIGHT;$y_cood++) { 

    // Debugging statement to see where the script stops running. 
    if(($y_cood % 100) == 0) {print("Y=$y_cood<br>"); flush();} 

    for($x_cood=0;$x_cood<MATRIX_WIDTH;$x_cood++) { 
     $fill_value = 0; 
     $matrix[$y_cood][$x_cood]=$fill_value; 
    } 
} 

print("Matrix width: ".count($matrix)."<br>"); 
print("Matrix height: ".count($matrix[0])."<br>"); 

?> 
+0

Spróbuj zwiększyć rozmiar pamięci PHP 'memory_limit = 128M; Maksymalna ilość pamięci, którą może zużyć skrypt (128 MB) '. Osobiście nie radzę uwierzyć w wyniki spowodowane niestabilnym zachowaniem skryptu. –

+0

Dzięki. Czy to w końcu. –

Odpowiedz

4

Przypuszczam, że gdy uruchamiam array_fill przydziela pamięć w tym punkcie, i nie powinno zabraknąć pamięci w pętli.

Tak ... i nie. Przydzielanie pamięci i wykonywanie kodu programu to dwa różne buty (zwykle).
Pamięć przydzielona do programu/procesu jest zwykle podzielona na dwie sterty i stos. Kiedy "przydzielisz pamięć" (w znaczeniu użytym w pytaniu), pojawi się to w stercie. Po uruchomieniu kodu programu używany jest również stos. Oba nie są całkowicie rozdzielone, ponieważ możesz wciskać i/lub wstawiać odniesienia (wskaźniki do sterty) na i/lub ze stosu.

Chodzi o to, że sterty i stosy współdzielą część pamięci (przydzieloną do tego procesu) i zazwyczaj ta jedna rośnie (jest wypełniana) z wyższych adresów do najniższych, a druga - z niskich adresów do wyższy, a więc masz "pływającą" granicę między oboma. Jak tylko obie części osiągną tę "granicę", jesteś "bez pamięci".
enter image description here

Tak więc, w twoim przypadku, gdy tworzysz i wypełniasz tablicę (macierz), wykorzystałeś pamięć na liczby całkowite 2001 x 2001. Jeśli liczba całkowita wymaga 32 bitów lub 4 bajty, to są 2001 x 2001 x 4 bajty = 4004001 x 4 bajty = 16016004 bajty ~ 16 MB.
Podczas wykonywania kodu stos jest wypełniany zmiennymi (lokalnymi) - zmienna warunku pętli, licznik pętli i wszystkie pozostałe zmienne.
Należy również pamiętać, że kod PHP (biblioteki) również powinien być załadowany do pamięci, dlatego w zależności od wartości ustawionej jako memory_limit w konfiguracji może szybko zabraknąć pamięci.

+1

Dzięki za wyjaśnienie! –