2009-12-17 2 views
2

Я пишу PHP-функцию, которая должна будет перебирать массив указателей и для каждого элемента, извлекать эти данные (будь то из базы данных MySQL или плоского файла). У кого-нибудь есть идеи оптимизировать это, поскольку потенциально могут быть тысячи и тысячи итераций?PHP Loop Performance Optimization

Моя первая идея состояла в том, чтобы иметь статический массив кэшированных данных, над которыми я работаю, и любые изменения просто изменят этот кешированный массив, а затем в конце я могу сбросить его на диск. Однако в цикле из более 1000 элементов это было бы бесполезно, если бы я содержал только около 30 в массиве. Каждый элемент не слишком большой, но 1000+ из них в памяти слишком много, следовательно, потребность в дисковой памяти.

Данные - это просто сериализованные объекты. В настоящее время я использую базу данных для хранения данных, но думаю, что плоские файлы будут быстрее (меня не волнуют проблемы параллелизма, и мне не нужно их анализировать, просто разархивируйте и несериализуйте). У меня уже есть пользовательский итератор, который будет вытягивать по 5 элементов за раз (чтобы сократить соединения БД) и сохранить их в этом кеше. Но опять же, использование кеша в 30, когда мне нужно перебирать тысячи, довольно бесполезно.

В принципе, мне просто нужно быстро перебрать эти предметы.

+0

Я попытаюсь объяснить себя яснее ... Я пишу сеть нейронов, поэтому мне нужно перебирать некоторые объекты нейрона, чтобы повлиять на некоторые из их данных, а затем сохранить их, перейти к следующей и т.д. 1000+ нейронов позже. Затем мне нужно снова повторить обратное (обратное распространение). Я думаю, что лучшим решением является поиск носителя между памятью и доступом к IO. Если я загружаю по 100 объектов за раз, это означает меньше IO, но больше памяти. – Louis

ответ

1

Ну, вы не дали многого для продолжения. Вы не описываете свои данные, и вы не описываете, что делают ваши данные, или когда вам нужен один объект, а не другой, и как эти объекты освобождаются временно и при каких обстоятельствах вам это нужно, и ..

Так что все, что угодно, говорит, что это будет полный выстрел в темноте.

... так что вдоль этих линий, вот выстрел в темноте.

Если вы только удобно держите х элементов в памяти в любое время, отложите пространство для предметов x. Затем, каждый раз, когда вы обращаетесь к объекту, обратите внимание на время (это может не означать тактовое время, так как это может означать порядок, в котором вы обращаетесь к ним). Храните каждый элемент в списке (он может быть не реализован в списке, а скорее как кучная структура), так что самые последние используемые элементы появляются раньше в списке. Когда вам нужно поместить новый в память, вы заменяете тот, который использовался дольше всего, а затем переместите этот элемент в начало списка. Возможно, вам потребуется сохранить еще один индекс элементов, чтобы вы знали, где именно они находятся в списке, когда вам это нужно. То, что вы делаете, это искать, где находится элемент, связать его родительский и дочерний указатели, а затем переместить его в начало списка. Вероятно, есть и другие способы оптимизации времени поиска.

Это называется LRU algroithm. Это схема замены страниц для виртуальной памяти. Что он делает, это задерживает ваше узкое место (дисковый ввод-вывод), пока его, вероятно, не избежать. Стоит отметить, что этот алгоритм не гарантирует оптимальную замену, но он все же неплохо работает.

Помимо этого, я бы рекомендовал распараллеливать ваш код в большой степени (если возможно), чтобы, когда один элемент должен был ударить по жесткому диску для загрузки или сброса, вы можете заставить этот процессор заняться реальной работой.

< Редактировать> Основываясь на вашем комментарии, вы работаете над нейронной сетью. В случае вашей исходной федерации данных (до этапа коррекции) или когда вы активно используете ее для классификации, я не вижу, как алгоритм является плохой идеей, если только нет возможности для соответствия наиболее часто используемые узлы в памяти.

На этапе коррекции (возможно, back-prop?) Должно быть очевидно, какие узлы вы ДОЛЖНЫ хранить в памяти ... потому что вы уже навещали их!

Если ваша сеть большая, вам не удастся избежать ввода/вывода диска. Трюк заключается в том, чтобы найти способ минимизировать его. </edit>

+0

Да, жаль, что это трудно объяснить. Данные представляют собой сериализованный объект, поэтому, когда я его неэтериализую, он будет в памяти. Это то, что я делаю в данный момент. Но проблема кроется в том, что когда мне нужно повторять все, те, которые в кеше будут использоваться последним, когда другая функция запускает новую итерацию, все те, что в кеше, не будут нужны до конца. Для записи я работаю над сетями нейронов, отсюда это безумие;) – Louis

+0

Вы правы. Проблема в том, что касается обучения. Я должен запустить сеть вперед с некоторыми входами, что означает повторение над нейронами в одном слое, затем нейроны в следующем и т. Д. И т. Д. Затем запустите его назад, вычислив ошибку в недавно запущенной сети. Я стараюсь оптимизировать это, так что происходит только одна итерация, но я не думаю, что это возможно. Да, в любом случае будет нужен диск IO, но, возможно, привлечение многих за раз - это ответ. В конце концов, память дешевая. – Louis

0

Очевидно, что хранение его в памяти происходит быстрее, чем что-либо еще. Насколько велик каждый предмет? Даже если они составляют 1 тыс. Каждый, десять тысяч из них составляют только 10 М.

+0

Если это изображения или что-то подобное, вы можете видеть порядка десятков мегабайт или более в зависимости от уровня сжатия. Если у вас есть 100 объектов изображения размером в 15 мегабайт, вы только что использовали ~ 1,5 гигабайта памяти! –

+0

Каждый элемент, вероятно, составляет около 1-5k, но затем, говоря 100 одновременных пользователей, который быстро растет. – Louis

0

вы всегда можете вырваться из цикла после получения необходимых данных. так что он не будет продолжать цикл. если это плоский файл, который вы храните. на вашем сервере будет страдать тысячи или миллионы файлов с разным размером файла. Но если вы говорите о полном фактическом файле, хранящемся в БД. то лучше сохранить его в папке и просто сохранить путь к этому файлу в БД. И попробуйте поместить вытащенные элементы в XML. так что доступ к ним намного проще, и он может содержать много атрибутов для деталей предмета, набранного, например (имя, дата и т. д.).

0

Вы можете использовать memcached для хранения объектов при первом чтении, а затем использовать кешированную версию в последующих вызовах. Memcached использует ОЗУ для хранения объектов, поэтому, если у вас достаточно памяти, у вас будет отличное ускорение. Существует php api to memcached