многопоточность — Какой самый быстрый способ отправки данных из одного потока в другой в C ++?

Я попытался провести эксперимент, в котором я создал простую программу «Производитель / Потребитель». Они запускаются в отдельных потоках. Производитель генерирует некоторые данные, а потребитель собирает их в другом потоке. Задержка обмена сообщениями, которую я достиг, составляет приблизительно 100 наносекунд. Кто-нибудь может сказать мне, если это разумно или есть значительно более быстрые реализации там?

Я не использую замки … просто счетчики памяти. Мой эксперимент описан здесь:

http://tradexoft.wordpress.com/2012/10/22/how-to-move-data-between-threads-in-100-nanoseconds/

Обычно потребитель ожидает увеличения счетчика, а затем вызывает функцию-обработчик. Так что на самом деле не так много кода. Тем не менее я был удивлен, что это заняло 100 нс.

Потребитель выглядит так:

 void operator()()
{
while (true)
{
while (w_cnt==r_cnt) {};
auto rc=process_data(data);
r_cnt++;
if (!rc)
break;
}
}

Производитель просто увеличивает w_cnt, когда у него есть доступные данные.

Есть ли более быстрый способ?

6

Решение

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

Однако вы можете перемещать больше данных одновременно, используя кольцевой буфер. Если один поток пишет, а другой поток читает, вы можете реализовать кольцевой буфер без блокировок. По сути это был бы тот же подход спин-блокировки (ожидание до tailidx != headidx), но производитель может закачать более одного значения в буфер, прежде чем оно будет передано потребителю. Это должно улучшить общее время ожидания (но не однозначное время ожидания).

6

Другие решения

Если ваши потоки выполняются на разных ядрах, самый быстрый способ «отправить сообщение» из одного потока в другой — барьер записи.

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

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

3

По вопросам рекламы [email protected]