Я пытаюсь создать 2D-массив в PHP размером 2000×2000 (4 миллиона записей). Кажется, мне здесь не хватает памяти, но способ появления ошибки сбивает меня с толку.
Когда я определяю массив и заполняю его изначально с помощью команды array_fill, и инициализирую каждую позицию в массиве (матрице) с 0, проблем не возникает.
Однако, если я попробую перебрать массив и заполнить каждую позицию 0, ему не хватит памяти.
Я бы предположил, что после запуска array_fill он выделяет память в этой точке, и он не должен исчерпать память в цикле.
Конечно, это просто упрощенная версия кода. В моем реальном приложении я буду использовать X & Y координирует поиск значения из другой таблицы, обрабатывает его, а затем сохраняет его в моей матрице. Это будут значения с плавающей запятой.
Может ли кто-нибудь помочь через этот свет, пожалуйста? Есть ли какой-то другой способ, которым я должен делать это?
Спасибо!
<?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>");
?>
Я бы предположил, что после запуска array_fill он выделяет память в этой точке, и он не должен исчерпать память в цикле.
И да и нет. Выделение памяти и выполнение программного кода — это два разных способа (обычно).
Память, выделенная для программы / процесса, обычно делится на две части — куча и стек. Когда вы «выделяете память» (в значении, которое вы использовали в своем вопросе), это происходит в куче. Когда вы выполняете программный код, также используется стек. Оба не разделены полностью, так как вы можете помещать и / или вставлять ссылки (указатели на кучу) в стек и / или из него.
Дело в том, что куча и стек разделяют часть памяти (выделенную этому процессу), и обычно одна увеличивается (заполняется) от старших адресов к младшим, а другая — от младших адресов к старшим, и так что у вас есть «плавающая» граница между ними. Как только обе части достигают этой «границы», вам «не хватает памяти».
Итак, в вашем случае, когда вы создаете и заполняете свой массив (матрицу), вы используете память для 2001 x 2001 целых чисел. Если целое число требует 32 бита или 4 байта, то 2001 x 2001 x 4 байта = 4004001 x 4 байта = 16016004 байта ~ 16 МБ.
При выполнении кода стек заполняется (локальными) переменными — переменной условия цикла, счетчиком цикла и всеми другими переменными.
Вы также не должны забывать, что код PHP (библиотека) также должен быть загружен в память, поэтому в зависимости от значения, которое вы установили как memory_limit
в вашей конфигурации вы можете быстро исчерпать память.
Других решений пока нет …