2013-09-30 2 views
0

Я работаю над имитацией сетчатой ​​сети с большим количеством узлов. Узлы передают данные между различными ведущими узлами по всей сети.Многопоточность с очень большим количеством потоков

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

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

Что такое хороший подход к обработке потоков, поэтому каждый узел действует так, как будто он работает в своей собственной нити?

В случае, если это имеет значение, я строю симуляцию в python 2.7, но я открыт для изменения чего-то еще, если это имеет смысл.

+0

Вы должны рассмотреть возможность осуществления какой-либо (потоковой) очереди или, по крайней мере, диспетчера для управления потоком информации. Однако трудно сказать, не зная, чего вы хотите добиться. – tamasgal

+0

Запуск 1600 потоков, конечно, приведет к плохой производительности на обычном компьютере. Вам может потребоваться рассмотреть высокопроизводительный компьютер, или вы можете попытаться использовать свой GPU для большей вычислительной мощности. GPU хорош для многопоточности. – justhalf

+0

@justhalf Конечно, это будет плохо. Каждый поток активен только в течение нескольких миллисекунд в секунду и спящий остаток времени, поэтому я думаю, что проблема заключается не в ресурсах центрального процессора, а в том, что количество ядер или просто простое существование многих потоков и контекст переключает их требуют. Вместо 1600 я должен сказать даже 10 000. Я ищу хорошее решение для аппроксимации этих узлов, работающих параллельно, чтобы максимизировать количество узлов, которые я могу запустить. Я не думаю, что переезд на GPU действительно поможет здесь. – Liron

ответ

1

Во-первых, вы используете обычные потоки Python по умолчанию, доступные в интерпретаторе Python 2.7 (CPython) по умолчанию, и все это ваш код в Python? Если это так, вы, вероятно, фактически не используете несколько ядер процессора из-за блокировки глобального интерпретатора CPython (см. https://wiki.python.org/moin/GlobalInterpreterLock). Возможно, вы можете попробовать запустить свой код под Jython, просто чтобы проверить, будет ли производительность лучше.

Возможно, вы должны пересмотреть свою архитектуру приложений и переключиться на ручное планирование событий вместо использования потоков или, возможно, попробовать использовать что-то вроде зеленых (https://stackoverflow.com/a/15596277/1488821), но это, вероятно, означает менее точные тайминги из-за отсутствия параллелизма.

+0

Я использую python, который поставляется с Canopy (enthought). Я предполагаю, что это обычный CPython. – Liron

+1

С небольшим количеством Googling это похоже на то, что есть. Но, как и другие, вы также решили, что вашу проблему лучше решить, используя другая архитектура приложения. –

+0

Я переключил архитектуру на использование gevents, причем каждый узел работает на своей собственной озелене. Для моего приложения это действительно работает очень хорошо, потому что мне не нужны фактические параллельные функции, и параллелизма достаточно. (В принципе Мастель мастера просто устанавливает флаг для того, когда Мастер активно получает соединения, а запрос ведомых - это значение непосредственно на Master.) Спасибо за идею. – Liron

1

Для меня 1600 потоков звучат много, но не чрезмерно, учитывая, что это симуляция. Если бы это было производственное приложение, это, вероятно, не было бы достойным производства.

Стандартная машина не должна иметь проблем с обработкой 1600 потоков. Что касается ОС this article, вы можете получить некоторые сведения.

Когда речь идет о вашем коде, сценарий Python не является родным приложением, а интерпретируемым скриптом и, как таковой, потребует больше ресурсов ЦП для выполнения.

Я предлагаю вам попробовать реализовать симуляцию на C или C++ вместо этого, которая будет создавать собственное приложение, которое должно выполняться более эффективно.

+0

C#, возможно, тоже стоит посмотреть. Он правильно выполняет потоки (в отличие от Python) и менее шокирован для тех, которые используются для удобства Python; C/C++ может оказаться слишком спартанским для удобства. – bazza

1

Не используйте для этого резьбу. Если придерживаться Python, пусть узлы выполняют свои действия один за другим. Если производительность, которую вы делаете, в порядке, вам не придется использовать C/C++. Если действия, выполняемые каждым узлом, просты, это может сработать. Во всяком случае, нет причин использовать потоки в Python вообще. Потоки Python используются в основном для блокировки ввода-вывода, чтобы не блокировать вашу программу, а не для использования нескольких ядер процессора.

Если вы хотите действительно использовать параллельную обработку и писать свои узлы, как если бы они были действительно разделены и обменивались только сообщениями, вы можете использовать Erlang (http://www.erlang.org/). Это функциональный язык, очень хорошо подходящий для выполнения параллельных процессов и обмена ими сообщений. Процессы Erlang не сопоставляются с потоками ОС, и вы можете создать тысячи из них. Тем не менее, Erlang является чисто функциональным языком и может показаться крайне странным, если вы никогда не использовали такие языки. И это также не очень быстро, поэтому, как и Python, вряд ли будет обрабатывать 1600 действий каждые 5 мс, если действия не будут достаточно простыми.

И, наконец, если вы не получите желаемую производительность с помощью Python или Erlang, вы можете перейти на C или C++. Однако до сих пор не используют потоки 1600.Фактически, использование потоков для повышения производительности является разумным только в том случае, если число потоков существенно не превышает число ядер процессора. В этом случае вам может понадобиться шаблон реактора (с несколькими реакторными резьбами) (http://en.wikipedia.org/wiki/Reactor_pattern). Существует превосходная реализация шаблона реактора в библиотеке boost.asio. Это объясняется здесь: http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio/

+0

Моя цель здесь не в увеличении пропускной способности с несколькими потоками, а в том, чтобы имитировать inter -node-коммуникация. На каждом узле очень мало обработки. Я взгляну на erlang и посмотрю, как это выглядит. – Liron

0

Некоторые случайные мысли здесь:

я довольно хорошо с несколькими сотнями нитей, работающих, как это в Java; это можно сделать с помощью правильного языка. (Но я не пробовал это в Python.)

На любом языке вы могли бы запустить код главного узла в одном потоке; просто продолжайте цикл, запуская код для каждого мастера в каждом цикле. Тем не менее, вы потеряете преимущества нескольких ядер. С другой стороны, вы также потеряете проблемы многопоточности. (Вы могли бы сказать, скажем, 4 таких нити, используя ядра, но получая многопоточную головную боль назад. Это также будет препятствовать потоку вниз, но тогда есть блокировка ...)

Одна большая проблема, с которой я столкнулся были потоки, блокирующие друг друга. Включение 100 потоков для одновременного вызова одного и того же метода на одном и том же объекте, не ожидая друг друга, требует немного размышлений и даже исследований. Я обнаружил, что моя многопоточная программа сначала часто использовала только 25% четырехъядерного процессора даже при запуске. Это может быть одна из причин, по которой вы работаете медленно.

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

Плата за то, что у него больше потоков, чем ядер. Когда у вас есть два потока, они могут блокировать друг друга (и будут, если они будут делиться любыми данными). Если у вас есть код для запуска, который не будет блокироваться, вы хотите запустить его в своем собственном потоке, чтобы он не ожидал, что код блокируется, чтобы разблокировать и завершить. Я нашел один раз, когда у меня было несколько потоков, они начали размножаться как сумасшедшие - отсюда моя программа сотнями нитей. Даже когда 100 нитей блокируются в одном месте, несмотря на весь мой блеск, есть много других потоков, чтобы поддерживать ядро!

Смежные вопросы