powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
20 сообщений из 20, страница 1 из 1
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38259123
aspi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.

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

В первом приближении архитектура такова: 1 провайдер - N получателей.

По опыту изучения проблемы уже испробовал и lock-free очереди, и синхронизация по атомик переменным, по conditional переменным, мьютексы, spin-lock и т.д. Но в каждом варианте все равно фиксирую неприемлимые либо задержки в передаче данных, либо серьезное деградировании и конкуренцию ресурсов машины.

Какие требования я перед собой ставлю:
1. максимальное быстрое получение данных подписчиком с момента получения даннх провайдером. счет на микросекунды (>10мкс уже провал)
2. малое потребление ресурсов машины
3. пока windows

Был бы признателен если кто пожелает поделиться опытом, поскольку я в некотором тупике.

Спасибо.
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38259149
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Эээээ... Пункт номер три ставит крест на пункте номер один.
Если есть нужда в IPC рассчитанном на микросекунды, то дорога только одна: RTOS.
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38259230
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aspi,

1) Попробуйте накапливать сообщения в генерирующем потоке и передавать их группами.
Тогда требования к синхронизации снизятся.

2) А вы уверены что задержка именно в синхронизации? Может получатель медленно обрабатывает сообщения и поэтому следующие к нему доходят с задержкой?

3) На многопроцессорных системах часто скорость доступа к памяти гораздо выше в том процессоре, который данный блок памяти выделил. Поэтому если у вас память под все очереди выделяется в одном потоке, а работа с очередями происходит в других потоках, то возможно имеет смысл перенести выделение в рабочий поток непосредственно работающий с очередью.
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38259242
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
4) Если активных потоков больше чем ядер, тогда ОС вынуждена переключаться между потоками выделяя им по очереди кванты времени для выполнения на данном ядре. При этом остальные потоки, запланированные для выполнения на том же ядре, усыпляются.
Насколько я помню эти кванты времени достаточно большие, чтото вроде 1 мс (но могу ошибаться).
Это может быть причиной того что сообщения доставляются с задержкой.
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38259503
Bred eFeM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aspi,

счет на микросекунды ???
ну а тест на время, без данных и синхронизации Вас устраивает?
(1мкс на 4ГГц = 4000 тактов, а это очень немного даже для RTOS)

может ошибочка, и там миллисекунды, а если нет, то для каких еще задач бережете ресурсы?

Можно покрутить как-то так:
N получателей = X ядер - 1 (провайдер) - 1 (для системы?)
Провайдер-менеджер поддерживает N (получатели между собой не конкурируют) очередей ( без realloc'a )

P.S.
А без потоков, никак? :)
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38259542
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovskyaspi,

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

Тут только надо в рассуждении потоки заменить процессорами, на которых они выполняются. Потому что NUMA относится к ядрам и физическим блокам памяти, а не к логическим потокам управления.
Потоки же в SMP могут кочевать с одного ядра на другое, если не задавать affinity.
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38260156
aspi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovskyaspi,

1) Попробуйте накапливать сообщения в генерирующем потоке и передавать их группами.
Тогда требования к синхронизации снизятся.

2) А вы уверены что задержка именно в синхронизации? Может получатель медленно обрабатывает сообщения и поэтому следующие к нему доходят с задержкой?

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

4) Если активных потоков больше чем ядер, тогда ОС вынуждена переключаться между потоками выделяя им по очереди кванты времени для выполнения на данном ядре. При этом остальные потоки, запланированные для выполнения на том же ядре, усыпляются.
Насколько я помню эти кванты времени достаточно большие, чтото вроде 1 мс (но могу ошибаться).
Это может быть причиной того что сообщения доставляются с задержкой.


Анатолий,
1. Именно так я и делаю. Провайдер получает извне данные, накапливая в буфер. Затем этот буфер нужно отдать получателям.
2. Задержка именно в синхронизации, то есть время с момента получения всех данных провайдером и временем как эти данные получил подписчик.
3. Насколько я понял, Вы предлагаете строго назначать поток-ядро
4. сейчас работающих потоков точно меньше чем ядер.


Bred eFeMaspi,

счет на микросекунды ???
ну а тест на время, без данных и синхронизации Вас устраивает?
(1мкс на 4ГГц = 4000 тактов, а это очень немного даже для RTOS)

может ошибочка, и там миллисекунды, а если нет, то для каких еще задач бережете ресурсы?

Можно покрутить как-то так:
N получателей = X ядер - 1 (провайдер) - 1 (для системы?)
Провайдер-менеджер поддерживает N (получатели между собой не конкурируют) очередей ( без realloc'a )

P.S.
А без потоков, никак? :)


Тест на время в архитектуре провайдер-подписчик без данных не устраивает. Проблема в данном случае не в колве данных, а в способе взимодействия между потоками. То есть если предположить, что один пишет другой читает, например лок-фри очередь, без принужительно ожидания (например слип), то жрется проц время, то в данном случает задержек в получении данных между провайдер-подписчик нет и это устраивает. Но проблема в том, что в таком случае каждый из этих потоков делает дикое колво холостых циклов, грузит процессор и это совсем не профессионально и глупо. Тем более, колво подписчиков в будущем мне надо увеличивать и они должны все быть в равных стартовых позициях относительно получения одного и тогоже куска данных от провайдера.
Без потоков никак.

MasterZiv Тут только надо в рассуждении потоки заменить процессорами, на которых они выполняются. Потому что NUMA относится к ядрам и физическим блокам памяти, а не к логическим потокам управления.
Потоки же в SMP могут кочевать с одного ядра на другое, если не задавать affinity.


Понял.


Попробую резюмировать Задачу:
1. Есть один провайдер-один подписчик.
2. Провайдер получает данные, складывает себе в буфер. Как только получил все данные (он об этом знает), буфер должен отдаться подписчику.
3. Подписчик ждет данные. как только буфер появился, он его должен прочитать и дальше обработать.

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


Спасибо.
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38260192
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aspiКак синхронизировать потоки таким образом, чтобы минимизировать время с момента
получение всех данных провайдером и получения этих данных подписчиком.
Для начала покажи как ты это делал с помощью Windows Events.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38260393
aspi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry SibiryakovaspiКак синхронизировать потоки таким образом, чтобы минимизировать время с момента
получение всех данных провайдером и получения этих данных подписчиком.
Для начала покажи как ты это делал с помощью Windows Events.



например вот так

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
// threads_pub_sub.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;

LARGE_INTEGER freq;
LARGE_INTEGER tp_sent;
LARGE_INTEGER tp_recv;

double d_sgl = 0;
double d_sum = 0;
double d_cnt = 0;

int c_events = 500;

DWORD WINAPI Tf ( LPVOID n )
{
	cout<<"Thread Instantiated........."<<endl;

	HANDLE hEvent = OpenEvent ( EVENT_ALL_ACCESS , false, L"MyEvent" );
	if ( !hEvent ) { return -1; }

	for ( int counter = 0; counter < c_events; counter ++ )
	{

		WaitForSingleObject ( hEvent, INFINITE );

		QueryPerformanceCounter(&tp_recv);

		d_sgl = (tp_recv.QuadPart - tp_sent.QuadPart) * 1000.0 / freq.QuadPart;
		d_sum += d_sgl;
		d_cnt++;
				
		cout << "# " << d_cnt << " in " << d_sgl << "ms" << endl;

	}
	CloseHandle(hEvent);
	cout<<"End of the Thread......"<<endl;
	return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int ch;

	QueryPerformanceFrequency(&freq);

	HANDLE     hEvent = CreateEvent ( NULL , false , false , L"MyEvent" );
	if ( !hEvent ) return -1;

	DWORD Id;
	HANDLE hThrd = CreateThread ( NULL, 0, (LPTHREAD_START_ROUTINE)Tf,0,0,&Id );
	if ( !hThrd ) { CloseHandle (hEvent); return -1; }

	Sleep ( 1000 );

	for ( int counter = 0; counter < c_events; counter ++ )
	{
		QueryPerformanceCounter(&tp_sent);

		// Signal the event		
		SetEvent ( hEvent );
		// wait for some time before giving another signal
		Sleep ( 50 );
	}

	WaitForSingleObject ( hThrd, INFINITE );

	CloseHandle ( hThrd );
	CloseHandle ( hEvent );

	cout<<"avg in " << d_sum/d_cnt << endl;
	cin >> ch;
	cout<<"End of Main ........"<<endl;
	return 0;

	return 0;
}
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38260427
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aspi
Код: sql
1.
2.
	// wait for some time before giving another signal
	Sleep (50  );


Эту цифру пробовал увеличить до 1000?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38260442
aspi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakovaspi
Код: sql
1.
2.
	// wait for some time before giving another signal
	Sleep (50  );


Эту цифру пробовал увеличить до 1000?


да, пробовал. в чем скрытый смысл?
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38260452
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aspiда, пробовал. в чем скрытый смысл?
Вывод на консоль довольно тормозной процесс. При малой задержке, SetEvent может вызываться
до того, как в потоке закончится вывод и вызовется WaitFor. Таким образом к задержке между
посылкой сигнала и его приёмом добавится время вывода на экран и ты получишь левые числа.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38260466
aspi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakovaspiда, пробовал. в чем скрытый смысл?
Вывод на консоль довольно тормозной процесс. При малой задержке, SetEvent может вызываться
до того, как в потоке закончится вывод и вызовется WaitFor. Таким образом к задержке между
посылкой сигнала и его приёмом добавится время вывода на экран и ты получишь левые числа.


да, но, скорее всего, потерянный ивент будет если я сдедаю Sleep(1) в main.
Проблема пропадание евентов, за чет того, что ктото торомзит, тоже причина того, что я не могу положиться наних ибо моя задача отработать _все_ ивенты, что сгенерировались провайдером последовательно. Провайдер же может отдавать буферы с частотой до микросекунд. Тогдая если интервал у провайдера вдруг для какойто порции увеличится, то это значит, теоретически и даже фактически, мужду провайдером и потребителем будет зависший(ие) необработанные буферы...
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38260472
Фотография vromanov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чтобы уменьшить взаимоблокировки имеет смысл использовать мультиплексор. Т.е. один процесс выбирает данные извне или из очереди и раскладывает по N очередям. N воркеров разгребают каждый свою очередь.
В этом случае работа одного форкера не мешает второму.
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38260478
aspi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
vromanovЧтобы уменьшить взаимоблокировки имеет смысл использовать мультиплексор. Т.е. один процесс выбирает данные извне или из очереди и раскладывает по N очередям. N воркеров разгребают каждый свою очередь.
В этом случае работа одного форкера не мешает второму.

да, и с какой частотой воркер долджен выбирать данные из очереди?
мне нужно с максимальной. значит sleep(0) или безнего. но это отжер ресурсов и холостые циклы, что неприемлимо.
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38260518
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aspi,

Я читал топик, и на самом деле сознательно не вступал в диалог.
Дело в том, что "низколатентное взаимодействие между потоками" -- это утопия.
Синхронизация потоков всегда достаточно дорога.
Если у тебя задача на это завязана, то что-то не так у тебя в королевстве.
Скорость работы многопоточных приложений должна достигаться тем, что потоки должны получать независимые задачи и сравнительно ДОЛГО их выполнять, получать результаты и отдавать куда-то (или не получать результаты вообще).
Если твои потоки всё время тычаться в синхронизацию очереди, это просто неправильно. Т.е. это правильно, но ничего быстрого от такой архитектуры ожидать нельзя.

Как тут уже говорили, нужно например пачками накапливать задания и потом пачками их обрабатывать.
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38260614
Фотография vromanov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivСкорость работы многопоточных приложений должна достигаться тем, что потоки должны получать независимые задачи и сравнительно ДОЛГО их выполнять, получать результаты и отдавать куда-то (или не получать результаты вообще).

Осталось определиться, что считать "скоростью".
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38260802
aspi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
всем спасибо. буду думать над архитектурой.
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38260898
landy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. убрать из потоков обработки вывод на экран, вообще. Это непредсказуемые задержки
ввода-вывода, если нужен вывод - делать в отдельном потоке, например через общую память(или что там в виндовс) - т е потоки обработки пишут в общую память, а поток вывода неспешно печатает.
2. наплодить потоков-потребителей, которые спят(хз как это в виндовс, но суть думаю понятна)
3. поток производитель когда подготовил данные, посылает сигнал, что данные готовы - просыпается
первый попавшийся поток и начинает работать
4. время шедулирования зависит от тика системы и в виндовс он имхо достаточно большой
5. убрать sleep - это гарантированое время засыпания, которое не меньше заявленного значения(т е оно может быть больше, зависит от того, как система нагружена, сколько процессов, приоритеты и т п)
6. Приоритет у потоков потребителей должен быть выше потока производителя(иначе послав сигнал, поток производитель скорее всего опять сшедулируется к выполнению и вытеснит поток потребитель)
Ну почитать, например, вот это
http://www.google.ru/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CCoQFjAA&url=http://www3.msiu.ru/~vag4/rms.doc&ei=JO-UUY3DJKyQ4ASIh4HYBA&usg=AFQjCNFNa84iDywPe2lqiEFeh2CPqejj7g&sig2=FPim8d3ZdxDIJ6PR5_uCHQ&bvm=bv.46471029,d.bGE&cad=rjt
...
Рейтинг: 0 / 0
Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
    #38261014
Bred eFeM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aspi,
думаю Вам необходимо определиться с масштабом времени, так как тут ms
Код: plaintext
1.
2.
3.
4.
		d_sgl = (tp_recv.QuadPart - tp_sent.QuadPart) * 1000.0 / freq.QuadPart;
		d_sum += d_sgl;
		d_cnt++;
		cout << "# " << d_cnt << " in " << d_sgl << "ms" << endl;


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

Можно закладываться на крейсерский отклик потока на Event'e < 1 ms. Но нужно и знать, что делать, если какой-то отклик будет через 20-50мс
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Ultra LowLatency threads interaction (низколатентное взаимодействие между потоками)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]