#python #python-2.7 #optimization #import #load
#python #python-2.7 #оптимизация #импорт #загрузить
Вопрос:
На это должен быть ответ, но я не могу его найти. Я использую довольно большой модуль python под названием quippy. С помощью этого модуля можно определить межмолекулярный потенциал для использования в качестве калькулятора в ASE следующим образом:
from quippy import *
from ase import atoms
pot=Potential("Potential xml_label=gap_h2o_2b_ccsdt_3b_ccsdt",param_filename="gp.xml")
some_structure.set_calculator(pot)
Это начало скрипта. Проблема в том, что это import
занимает около 3 секунд и pot=Potential...
занимает около 30 секунд при 100% загрузке процессора. (Я считаю, что это связано с анализом большого XML-файла ascii.) Если бы я печатал в интерактивном режиме, я мог бы сохранить импортированный модуль и определить потенциал, но при запуске скрипта это выполняется снова при каждом запуске.
Могу ли я сохранить модуль и потенциальный объект в памяти / на диске между запусками? Может быть, сохранить процесс python на холостом ходу и сохранить эти вещи в памяти? Или запустите эти строки в интерпретаторе и каким-то образом вызовите остальную часть скрипта оттуда?
Любой подход подходит, но некоторая помощь будет оценена!
Комментарии:
1. Как часто вы вызываете скрипт? Если у вас достаточно оперативной памяти, ваша ОС будет кэшировать файлы модулей, используемые во
import
время . Если вы хотите сохранитьpot
, просто запишите его в файл, например, используяpickle
.
Ответ №1:
Вы можете использовать необработанные файлы или такие модули, pickle
чтобы легко хранить данные.
import cPickle as pickle
from quippy import Potential
try: # try previously calculated value
with open('/tmp/pot_store.pkl') as store:
pot = pickle.load(store)
except OSError: # fall back to calculating it from scratch
pot = quippy.Potential("Potential xml_label=gap_h2o_2b_ccsdt_3b_ccsdt",param_filename="gp.xml")
with open('/tmp/pot_store.pkl', 'w') as store:
pot = pickle.dump(pot, store)
Для этого существуют различные способы оптимизации, например, проверка того, старше ли ваш файл pickle, чем файл, генерирующий его значение.
Комментарии:
1. Я собираюсь попробовать wthis с вашим кодом, но на самом деле я только что попробовал с cPickle, и у меня это не сработало. Но что вы имеете в виду под необработанными файлами? Я думаю, что сохранение его в виде двоичного файла помогло бы, но как?
2. Что вы подразумеваете под «не заставило его работать»? Это часть стандартной библиотеки py2.7. Необработанные файлы — это просто файлы, в которые вы записываете простые строки без какой-либо библиотеки сверху. Например, if
pot
— это число с плавающей точкой, вы могли бы сделатьstore.write(str(pot))
иfloat(store.readline().strip())
.3. Я не был хорошо сформулирован. cPickle не выдал ошибку ни при сбросе, ни при загрузке, но при попытке запустить загруженный потенциал я получил ошибку. И, глядя на файл, это было несколько байтов, а не размер реального объекта.
4. Какую ошибку вы получили? Какой объект вы храните?
5. Я не смог заставить ваш точный код работать, вместо этого я использовал полные выражения, начинающиеся с
with
, для сброса и загрузкиpot
. Я дамп, выхожу из интерпретатора, повторно ввожу интерпретатор и загружаю его (вместе с обычным импортом). Затем>>> type(pot)
правильно выдает<class 'quippy.potential.Potential'>
, но в первой строке использует потенциалobject.set_calculator(pot)
, который я получаюSegmentation fault
, и больше никакой информации. Я подозреваю, что этот объект нельзя мариновать.
Ответ №2:
Я нашел одно решение, но меня интересуют альтернативы. Вы можете разделить скрипт на две части:
start.py:
from quippy import Potential
from ase import atoms
pot=Potential(... etc...
body.py:
for i in range(max_int):
print "doing things"
# etc...
Затем введите интерпретатор python и запустите start-script только один раз, но тело столько, сколько необходимо:
me@laptop:~/dir$ python
>>> execfile('start.py')
>>> execfile('body.py')
>>> #(change code of "body.py" in editor)
>>> execfile('body.py') # again without reloading "start.py"
Таким образом, это означает, что терминал занят, и скрипт затронут, но он работает.