У меня есть PHP-скрипт, который выполняет часы (возможно, дни) для выполнения. Это довольно простое, но очень ресурсоемкий, большая часть времени исполнения тратится на (я могу сказать после того, как профилированный сценарий):увеличить производительность сценариев PHP с интенсивным использованием процессора
$array = explode(',', $a[$i]);
где$a[$i]
очень длинная строка, которая представляет собой вектор 30k элементов, разделенных запятойforeach($array as $key => $value)
петли; где для каждого цикла некоторые in_array() и сравнения и присваивания операции выполняются
$a
на самом деле очень большой и разреженная матрица (30k * 30k), но я не могу держать его в памяти (8 Гб, кажется, не хватает ОЗУ), поэтому я сохраняю просто «разреженное представление» (в основном каждая строка является строкой) и используйте explode()
в любое время, когда мне нужно работать в строке.
Я знаю, что переписывание всего на C (или других языках) улучшит производительность (сколько?), Но прежде чем делать это, я хотел бы знать, могу ли я что-либо сделать, чтобы улучшить время выполнения в PHP.
EDIT после ответов.
Я попробовал несколько из ваших советов и вот мой отчет:
1) str_getcsv в большинстве случае медленнее, чем взорваться
2) SPLFixedArray уменьшить память запрашиваемую хранить матрицу, но все еще, 8GB было недостаточно для матрицы 30k x 30k, поэтому я не думаю, что это может помочь; реальная проблема здесь заключается в отсутствии разреженного представления для матрицы в PHP. Я думаю, что
3) Я не могу сохранить все результаты операций взрыва, потому что, тем не менее, это означало бы сохранение всей матрицы в памяти (не достаточно ОЗУ)
4) Я пробовал подход к базе данных, даже если бы был уверен, что это было бы медленнее: я сохранил тройки (i, j, value) для представления каждого матричного элемента; даже удаляя менее важные значения (я могу пожертвовать значениями меньше порога и получить менее точный результат, но все же полезный) и хранения всего 18 миллионов кортежей, подход с mysql myisam намного медленнее, чем мой массив в памяти.
5) Я пробовал подход к базе данных, используя механизм MEMORY (таблицу mysql в ОЗУ) и сохраняя все элементы матрицы, кроме тех, которые имеют нулевое значение; имея на данный момент 42 миллиона записей ... это быстрее, а не на порядок, но в 2-4 раза быстрее ... Думаю, я смогу закончить работу за 5 дней вместо 15-20 ... это все равно слишком много (Я хотел бы закончить в течение 24 часов), если у вас есть какие-либо другие предложения, которые вы очень радушны
EDIT 2: Я объясняю проблему
Я дам некоторые подробности о проблеме, мне действительно нужно упростить все, иначе было бы слишком долго объяснять, но я думаю, что этого достаточно, чтобы лучше понять ситуацию.
У меня есть матрица, представляющая расстояния между узлами; расстояние в целое число и также может быть бесконечным.
У меня есть таблица памяти, представляющая каждое расстояние с тройками: node_1, node_2, distance (показаны только бесконечные расстояния).
У меня есть такой жадный алгоритм, который я не писал, и я должен его оптимизировать, чтобы выполнить его в допустимое время (допустим, менее одного дня) на ноутбуке с 8 ГБ ОЗУ.
алго основном получает во входных двух узлов и конструкций путь между начальным узлом и заканчивающийся шаг узла за шагом в соответствии со следующими двумя свойствами, которые должны быть проверены на каждом шаге:
- новый промежуточный продукт узел должен быть выбран из множества узлов, которые находятся ближе к концовкам относительно узла к текущему узлу
- среди этих узлов, тот, который ближе к текущему узлу выбран
Пожалуйста, обратите внимание, что 1) Неравномерность треугольника НЕ выполняется. 2) Это НЕ задача о кратчайшем пути
Вот некоторые псевдо код для функции я называю несколько раз, пока я достаточно близко к заканчивающегося узлом:
get_next_node($node_1, $node_2){
$dist = select distance from distances_table where node_2 = $node_2 and node_1 = $node_1
$candidates_ar = select node_1 from distances_table where node_2 = $node_2 and distance < $dist
$distances_ar = select distance from distances_table where node_1 = $node_1 and node_2 in ($candidates_ar) // e.g. $distances_ar[12] contains distance between node 12 and $node_1
$min = 1000;
foreach ($candidates_ar as $value){
if ($distances_ar[$value] < $min){
$min = $distances_ar[$value]
$next_node = $value
}
}
}
Я пропущенной много проверки и дополнительную сложность, но это основное, и именно здесь алго проводит большую часть времени.
Я предполагаю, что это может быть решено с помощью реализации A *, но я бы хотел избежать этого, если можно увеличить производительность, чтобы я мог выполнять его в часах (а не в днях).
Спасибо.
возможно попробовать использовать str_getcsv() вместо того, чтобы взорваться() –
, если я правильно понимаю, каждый раз, когда вам нужен ряд, вы взорваетесь. сделайте это только один раз и сохраните результаты. в отношении C: я уверен, что это значительно улучшит производительность ... –
использовать структуры данных индекса, например, в базе данных или даже лучше: использовать базу данных – hek2mgl