Параллельный поиск в глубину в Erlang медленнее, чем его последовательный аналог

Я пытаюсь реализовать модифицированный алгоритм параллельного поиска в глубину в Erlang (назовем его * dfs_mod *) .

Все, что я хочу получить, это все «тупиковые пути», которые в основном представляют собой пути, которые возвращаются, когда * dfs_mod * посещает вершину без соседей или вершину с соседями, которые уже были посещены. Я сохраняю каждый путь в ets_table1 , если моя пользовательская функция fun1 (Path) возвращает true и в ets_table2 if fun1 (Path ) возвращает false (мне нужно отфильтровать результирующие «тупиковые» пути с помощью некоторого фильтра клиентов).

Я реализовал последовательную версию этого алгоритма, и по какой-то странной причине он работает лучше, чем параллельный.

Идея параллельной реализации проста:

  • посетить вершину из [Vertex | Other_vertices] = Unvisited_neighbours ,
  • добавить эту вершину ] к текущему пути;
  • отправить {self (), wait} процессу «сборщик»;
  • запустить * dfs_mod * для Unvisited_neighbours текущего ] Вершина в новом процессе ;
  • продолжить выполнение * dfs_mod * с остальными предоставленными вершинами ( Other_vertices );
  • когда больше нет вершин to visit - отправьте {self (), done} процессу-сборщику и завершите его;

Итак, в основном каждый раз, когда я посещаю вершину с непосещенными соседями, я порождаю новый процесс поиска в глубину, а затем продолжить с другими вершинами.

Сразу после создания первого процесса * dfs_mod * я начинаю собирать все сообщения {Pid, wait} и {Pid, done} ( wait сообщение состоит в том, чтобы заставить сборщик ждать всех сообщений done ). Через N миллисекунд после ожидания функция-сборщик возвращает ok .


По какой-то причине эта параллельная реализация работает от 8 до 160 секунд, а последовательная версия - всего 4 секунды (тестирование проводилось на полностью подключенном орграфе с 5 вершинами на машине с процессором Intel i5).

Вот мои мысли о такой низкой производительности:

  • Я передаю орграф Graph каждому новому процессу, который запускает * dfs_mod *.Может быть, выполнение орграфа: out_neighbours (Graph) против одного орграфа из многих процессов вызывает эту медлительность?
  • Я накапливаю текущий путь в списке и передаю его каждому новому порожденному процессу * dfs_mod *, возможно, передавая так много списков - проблема?
  • Я использую таблицу ETS для сохранения пути каждый раз, когда я посещаю новую вершину и добавляю ее к пути. Свойства ETS: ([bag, public, {write_concurrency, true}) , но, может быть, я делаю что-то не так?
  • каждый раз, когда я посещаю новую вершину и добавляю ее к пути, я проверяю путь с пользовательской функцией fun1 () (она в основном проверяет, есть ли в пути вершины, помеченные буквой «n», встречающиеся перед вершинами с «m», и возвращает true / false в зависимости от результат). Может быть, этот fun1 () замедляет работу?
  • Я пытался запустить * dfs_mod * без сбора сообщений done и wait , но htop показывает большую активность Erlang в течение довольно долгого времени после того, как * dfs_mod * возвращает ok в оболочке, поэтому я не думаю, что активная передача сообщений замедляет работу.

Как я могу заставить мой параллельный dfs_mod работать быстрее, чем его последовательный аналог?

Edit : когда я запускаю параллельный * dfs_mod *, pman не показывает никаких процессов вообще, хотя ] htop показывает, что все 4 потока ЦП заняты.

7
задан skanatek 22 November 2011 в 13:30
поделиться