Проведение эксперимента с различными параметрами, эффективное сохранение результатов - PullRequest
0 голосов
/ 05 июля 2018

Моя задача:

  • У меня есть программа, написанная на Python, которая принимает набор переменных (A, B, C) в качестве входных данных и выводит два числа (X, Y).
  • Я хочу запустить эту программу на большом диапазоне входов (A, B, C)
    • Я буду называть запуск программы с заданным набором переменных «проведением эксперимента»
  • Я использую кластер для этого (я отправляю свои работы в SLURM)
  • Затем я хочу сохранить результаты экспериментов в одном файле, например, фрейм данных со столбцами [A | B | C | X | Y], где каждая строка является выходом другого эксперимента.

Моя текущая ситуация:

  • Я написал свою программу в следующей форме:

    import io
    from optparse import OptionParser
    
    parser = OptionParser()
    
     parser.add_option("-f", "--file",action="store", type="string", dest="filename")
     parser.add_option("-a", "--input_a",type="int", dest="a")
     parser.add_option("-b", "--input_b",type="int", dest="b")
     parser.add_option("-c", "--input_c",type="int", dest="c")
    (options, args) = parser.parse_args()
    
     def F(a,b,c):
         return((a+b, b+c))
    
     Alice = options.input_a
     Bob = options.input_b
     Carol = options.input_c
    
      with io.open("results_a_{0}_b_{1}_c_{2}.txt".format(Alice, Bob, Carol), "a") as f:
         (x,y) = F(Alice, Bob, Carol)
         f.write(u"first output = {0}, second output = {1}".format(x,y))
    
  • Это позволяет мне запустить программу один раз и сохранить результаты в одном файле.

  • В принципе, я мог бы затем отправить это задание для диапазона (A, B, C), получить большое количество текстовых файлов с результатами и затем попытаться объединить их в один файл.
  • Тем не менее, я полагаю, что это не самый лучший способ действовать.

Я бы хотел знать:

  • Есть ли для меня более естественный способ запустить эти эксперименты и сохранить результаты в одном файле, и если да, то что это?
  • Как мне отправить мою коллекцию заданий на SLURM для этого?
    • В настоящее время я отправляю (эффективно) приведенный ниже скрипт, который на самом деле не работает:

...

      for a in 1 2 3; do
      for b in 10 20 30; do
      for c in 100 200 300; do
      python toy_experiment.py -a $a -b $b -c $c &
      done
      done
      done
      wait

[Я опасаюсь, что, возможно, во многих других местах я ошибаюсь - я открыт для использования чего-то другого, кроме optparse, для передачи аргументов в мою программу, для сохранения результатов по-другому и т. Д. - мой главный цель - найти рабочее решение.]

1 Ответ

0 голосов
/ 06 июля 2018

TL; DR

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

Вы также должны отправить свой сценарий, назначить массив заданий и разрешить каждому заданию в массиве запускать один эксперимент.


Здесь много чего происходит.

Один важный вопрос: сколько времени обычно занимает F () для вычисления? Я предполагаю, что вы только что написали пример, но это необходимо, чтобы решить, как лучше всего решить проблему.

Если промежуток времени для каждого вычисления невелик, возможно, вы можете запустить несколько пакетов, объединяя в одном скрипте несколько вычислений: в примере 3 пакета (для == 1, == 2 и == 3) каждый из них вычисляет все возможные эксперименты для b и c и генерирует 3 файла, которые должны быть объединены в конце.

Если временной интервал длинный, то перегрузка создания нескольких тысяч маленьких файлов не имеет большого значения. И объединить их потом будет легко.

Другое дело: при одновременном запуске всех заданий в фоновом режиме вы, вероятно, перегружаете одну машину. Я не знаю, как вы запрашиваете у SLURM ресурсы, но наверняка вы будете использовать только один узел. И злоупотребляя этим. Если там есть другие пользователи, они, вероятно, разозлятся. Вы должны контролировать количество одновременных заданий, запущенных на узле, чтобы быть числом процессоров, предоставленных на этом узле. Вероятно, поможет запуск ваших расчетов с помощью srun.

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

Наконец, перейдем к вашему основному вопросу: как лучше всего сохранить всю эту информацию на диске.

Создание тысяч файлов легко и возможно, но не лучшим способом для файловой системы. Возможно, у вас есть доступ к некоторому RAM-диску в общем узле. Запись небольшого файла в локальное хранилище вычислительного узла и копирование этого файла на общий диск в памяти было бы намного более эффективным. И когда все эксперименты выполнены, вы можете легко объединить результаты. Недостатком является то, что пространство обычно очень ограничено (я действительно не знаю реального размера ваших данных), и это будет диск в памяти: он может быть потерян в случае сбоя питания.

Лучше всего использовать один файл, но, как отметил Дмитрий Чубаров, вы должны использовать механизмы блокировки файлов. В противном случае вы рискуете получить смешанные результаты.

Наконец, подход, который я считаю наиболее подходящим для вашей проблемы, заключается в использовании какого-то решения, подобного базе данных. Если у вас есть доступ к реляционной БД, которая поддерживает транзакции, просто создайте таблицу с необходимыми полями и позвольте вашему коду подключиться и вставить результаты. Извлечение их в конце будет бризом. БД может быть клиент-серверной (MySQL, PostgreSQL, Oracle ...) или встроенной (HSQLDB). Другой вариант - использовать какой-либо формат файла, например NetCDF, который точно предназначен для такого рода научных данных и имеет некоторую поддержку параллельного доступа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...