Я пытаюсь реализовать модифицированный алгоритм параллельного поиска в глубину в Erlang (назовем его * dfs_mod *) .
Все, что я хочу получить, это все «тупиковые пути», которые в основном представляют собой пути, которые возвращаются, когда * dfs_mod * посещает вершину без соседей или вершину с соседями, которые уже были посещены. Я сохраняю каждый путь в ets_table1
, если моя пользовательская функция fun1 (Path)
возвращает true
и в ets_table2
if fun1 (Path )
возвращает false
(мне нужно отфильтровать результирующие «тупиковые» пути с помощью некоторого фильтра клиентов).
Я реализовал последовательную версию этого алгоритма, и по какой-то странной причине он работает лучше, чем параллельный.
Идея параллельной реализации проста:
вершину
из [Vertex | Other_vertices] = Unvisited_neighbours
, вершину
] к текущему пути; {self (), wait}
процессу «сборщик»; Unvisited_neighbours
текущего ] Вершина
в новом процессе ; Other_vertices
); {self (), done}
процессу-сборщику и завершите его; Итак, в основном каждый раз, когда я посещаю вершину с непосещенными соседями, я порождаю новый процесс поиска в глубину, а затем продолжить с другими вершинами.
Сразу после создания первого процесса * dfs_mod * я начинаю собирать все сообщения {Pid, wait}
и {Pid, done}
( wait
сообщение состоит в том, чтобы заставить сборщик ждать всех сообщений done
). Через N миллисекунд после ожидания функция-сборщик возвращает ok
.
По какой-то причине эта параллельная реализация работает от 8 до 160 секунд, а последовательная версия - всего 4 секунды (тестирование проводилось на полностью подключенном орграфе с 5 вершинами на машине с процессором Intel i5).
Вот мои мысли о такой низкой производительности:
Graph
каждому новому процессу, который запускает * dfs_mod *.Может быть, выполнение орграфа: out_neighbours (Graph)
против одного орграфа из многих процессов вызывает эту медлительность? ([bag, public, {write_concurrency, true})
, но, может быть, я делаю что-то не так? fun1 ()
(она в основном проверяет, есть ли в пути вершины, помеченные буквой «n», встречающиеся перед вершинами с «m», и возвращает true / false
в зависимости от результат). Может быть, этот fun1 ()
замедляет работу? done
и wait
, но htop
показывает большую активность Erlang в течение довольно долгого времени после того, как * dfs_mod * возвращает ok
в оболочке, поэтому я не думаю, что активная передача сообщений замедляет работу. Как я могу заставить мой параллельный dfs_mod работать быстрее, чем его последовательный аналог?
Edit : когда я запускаю параллельный * dfs_mod *, pman
не показывает никаких процессов вообще, хотя ] htop
показывает, что все 4 потока ЦП заняты.