Эффективный сбор больших объемов данных

У меня есть программа, которая создает солнечную систему, интегрируется до тех пор, пока не произойдет близкое столкновение между соседними планетами (или до 10e+9 лет), а затем записывает две точки данных в файл. Попытки и исключения действуют как флаг, когда планеты подходят слишком близко. Этот процесс повторяется 16 000 раз. Все это делается путем импорта модуля REBOUND, который представляет собой программный пакет, интегрирующий движение частиц под действием силы тяжести.

for i in range(0,16000):
    def P_dist(p1, p2):
        x = sim.particles[p1].x - sim.particles[p2].x
        y = sim.particles[p1].y - sim.particles[p2].y
        z = sim.particles[p1].z - sim.particles[p2].z
        dist = np.sqrt(x**2 + y**2 + z**2)
        return dist

    init_periods = [sim.particles[1].P,sim.particles[2].P,sim.particles[3].P,sim.particles[4].P,sim.particles[5].P]

    try:
        sim.integrate(10e+9*2*np.pi)
    except rebound.Encounter as error:
        print(error)
        print(sim.t)

    for j in range(len(init_periods)-1):
        distance = P_dist(j, j+1)
        print(j,":",j+1, '=', distance)
        if distance <= .01: #returns the period ratio of the two planets that had the close enecounter and the inner orbital period between the two
            p_r = init_periods[j+1]/init_periods[j]
            with open('good.txt', 'a') as data: #opens a file writing the x & y values for the graph
                data.write(str(math.log10(sim.t/init_periods[j])))
                data.write('\n')
                data.write(str(p_r))
                data.write('\n')

Близкое столкновение или нет, зависит в основном от случайного значения, которое я назначил, и это случайное значение также определяет, как долго может работать симуляция. Например, я выбрал случайным значением максимальное значение 9,99, а близкое столкновение произошло примерно через 11e+8 лет (примерно 14 часов). Случайные значения варьируются от 2 до 10, а близкие встречи чаще случаются на нижней стороне. На каждой итерации, если произойдет близкое столкновение, мой код будет записывать в файл, который, как я полагаю, может занимать много времени моделирования. Поскольку большую часть моего времени моделирования занимает попытка найти близкие контакты, я хотел бы сэкономить время, найдя способ собрать необходимые данные без необходимости добавлять в файл каждую итерацию.

Поскольку я пытаюсь отобразить данные, собранные в ходе этой симуляции, не будет ли создание двух массивов и вывод данных в них быстрее? Или есть способ записать в файл только один раз, когда все 16000 итераций завершены?

sim — это переменная, содержащая всю информацию о Солнечной системе.

Это не полный код, я пропустил ту часть, где создал солнечную систему.

count = 0
data = open('good.txt', 'a+')
....
     if distance <= .01:
         count+=1
         while(count<=4570)
             data.write(~~~~~~~)
....
data.close()

person dlsj    schedule 02.08.2017    source источник
comment
Ваша мысль верна, но логика неверна. Этот цикл while бесконечен: count равно 1, когда вы входите в цикл, и он никогда не меняется. У вас есть только один цикл, но два пути выхода: j >= len(periods) или count > 4570. Либо закодируйте оба условия в заголовок цикла, либо используйте второе условие для break из цикла.   -  person Prune    schedule 03.08.2017


Ответы (1)


Проблема не в том, что вы пишете каждый раз, когда обнаруживаете близкую встречу. Это то, что для каждой встречи вы открываете файл, записываете одну выходную запись и закрываете файл. Все открытие и добавление происходит медленно. Вместо этого попробуйте следующее: откройте файл один раз и выполните только одну запись для каждой записи.

# Near the top of the program
data = open('good.txt', 'a')
...
    if distance <= .01: #returns the period ratio of the two planets that had the close enecounter and the inner orbital period between the two
        # Write one output record
        p_r = init_periods[j+1]/init_periods[j]
        data.write(str(math.log10(sim.t/init_periods[j])) + '\n' +
                   str(p_r) + '\n')
...
data.close()

Это должно работать хорошо, так как запись будет буферизоваться и часто будет выполняться параллельно со следующим вычислением.

person Prune    schedule 02.08.2017
comment
Отлично, еще один вопрос. Я решил уменьшить размер выборки до 4570 близких встреч. Так как близкие встречи не происходят каждую итерацию, я придумал способ поддерживать работу программы до тех пор, пока не будет встречено 4570 близких встреч. - person dlsj; 03.08.2017
comment
Это утверждение, а не вопрос. Возможно, пропущено слово или два? - person Prune; 03.08.2017
comment
В своем последнем редактировании сообщения я загрузил блок кода, похожий на ваш. Является ли это эффективным способом получения необходимого объема данных? - person dlsj; 03.08.2017
comment
Ах ... тогда эти комментарии должны быть к вопросу, а не к этому ответу. - person Prune; 03.08.2017