У меня есть 3 модуля ocaml, последний из которых выполняет фактические вычисления и использует функции, определенные в двух других.
Основная идея программы состоит в том, чтобы иметь порт в качестве начального состояния, который содержит лодки, и перемещать эти лодки до тех пор, пока мы не достигнем выигрышной ситуации или больше не будет возможных ходов. Фактический код здесь не проблема. Это, вероятно, не очень эффективно, но находит решение... за исключением случаев, когда это не так.
В то время как программе требуется несколько секунд для сложных ситуаций, в некоторых случаях, когда я добавляю немного сложности, поиск решений занимает целую вечность.
Когда я запускаю программу следующим образом:
$ ocamlc -o test.exe port.ml moves.ml solver.ml
$ ./test.exe > file
Полученный файл действительно огромен, но его размер через некоторое время перестает увеличиваться. Мне кажется, что через некоторое время программа перестает работать, но без завершения, не выдается ошибка Stackoverflow или нехватка памяти. Программа просто не продолжает выполнение. Другими словами, команда
$ ./test.exe > file
все еще выполняется, но в файл больше не добавляются новые строки. Если я захожу в саму оболочку, а не в файл, я получаю тот же результат: через некоторое время новые строки не добавляются.
Что бы это могло быть?
Основная функция (отвечающая за поиск решения) использует алгоритм поиска в глубину и содержит много операций со списком, таких как List.fold, List.map, List.iter, List.partition, List.filter. Я думал, что, возможно, у этих функций есть проблемы с обработкой огромных списков сложных типов в какой-то момент, но опять же, никакой ошибки не выдается, выполнение просто останавливается.
Я объяснил это очень расплывчато, но я действительно не понимаю проблемы здесь. Я не знаю, связана ли проблема с моей оболочкой (подсистема Ubuntu в Windows) с нехваткой памяти или с ограничениями функций списка ocaml в какой-то момент... Если у вас есть какие-либо предложения, не стесняйтесь комментировать
Спасибо. Я посмотрю, смогу ли я предоставить код.
Обновление: я не обновлял ответ кодом, так как это, вероятно, не привело бы к решению. Решение, вероятно, заключается в том, что код все еще работал в фоновом режиме, а мой алгоритм настолько медленный, что кажется, что он завис.
Для отладки таких случаев следует использовать диагностические утилиты, предоставляемые вашей операционной системой и самой инфраструктурой OCaml.
Прежде всего, вы должны изучить состояние вашего процесса. Вы можете использовать утилиты top
или htop
, если вы используете машину Unix. В противном случае вы можете использовать диспетчер задач.
Если процессу не хватает физической памяти, он может быть заменен операционной системой. В этом случае все операции с памятью превратятся в чтение и запись жесткого диска. Поэтому сбор мусора из кучи, хранящейся на жестком диске, займет некоторое время. Если это так, то вы можете использовать профилировщик памяти, чтобы определить суть проблемы.
Если процесс постоянно выполняется без изменения объема памяти, то, похоже, либо вы наткнулись на ошибку в своем коде, т. е. бесконечный цикл, либо некоторые из ваших алгоритмов имеют экспоненциальную сложность, как упомянул Константин в комментарий. Используйте выходные данные отладки или трассировку, чтобы определить место, где программа остановилась.
Наконец, если ваша программа находится в спящем состоянии, это может привести к взаимоблокировке. Например, если вы читаете и пишете в один и тот же файл, это может привести к гонке. В общем, если ваша программа многопоточная или работает с несколькими процессами, существует множество возможностей вызвать состояние гонки.
Вы должны указать код, иначе это выглядит как гадание. Одной из причин, по которой ваш код перестает выдавать какой-либо вывод, может быть экспоненциальный рост времени некоторых вычислений — он все еще работает внутри, но с точки зрения внешнего наблюдателя он выглядит застрявшим, потому что для расчета следующего шага требуется слишком много времени. и т.д. Но гадать нет смысла...