Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Аналог windows event в с++ / 24 сообщений из 24, страница 1 из 1
17.04.2015, 07:50
    #38938765
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Надо пробуждать поток по мере необходимиости. С event все просто: ожидающий висит на WaitForSingleObject(), тот кому он потребовался вызывает SetEvent(), пример:
Код: 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.
#include <windows.h>
#include <thread>

HANDLE event = NULL;

void test_thread()
{
	int cnt = 0;
	while(cnt < 5) {
		WaitForSingleObject(event, INFINITE); // ожидаем задание
		printf("cnt = %d\n", cnt++); // обрабатываем задание
	}
}

int main(int argc, char* argv[])
{
	event = CreateEvent(NULL, FALSE, FALSE, NULL);
	std::thread th(test_thread);
	for(int i = 0; i < 5; i++) {
		Sleep(1000); // готовим задание
		printf("i = %d\n", i);
		SetEvent(event); // пробуждаем поток для обработки задания
	}
	th.join();
	CloseHandle(event);
	system("pause");
}


В линуксе подобное можно сделать семафорами.

Как сделать подобное средствами С++ ? <mutex> не подходит, т.к. unlock() может выполнить только тот поток который вызывал lock().
...
Рейтинг: 0 / 0
17.04.2015, 08:00
    #38938768
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Dima T,

там же есть condition variables
...
Рейтинг: 0 / 0
17.04.2015, 08:13
    #38938774
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
MasterZivтам же есть condition variables
Я читал про них, но так и не понял как их в такую конструкцию вписать. Еще почитаю
...
Рейтинг: 0 / 0
17.04.2015, 08:49
    #38938792
locked
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Dima T,

15105667
...
Рейтинг: 0 / 0
17.04.2015, 09:44
    #38938834
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Немного разобрался с condition_variable
Непонятно зачем перед командой на пробуждение (notify_one()) надо unique_lock. Во всех примерах так .
Код: 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.
#include <thread>
#include <condition_variable>

std::condition_variable cv;
std::mutex mtx;

void test_thread()
{
	int cnt = 0;
	while(cnt < 5) {
		std::unique_lock<std::mutex> lck(mtx);
		cv.wait(lck); // ожидаем задание
		printf("%5d: work %d\n", clock(), cnt); // обрабатываем задание
	}
}

int main(int argc, char* argv[])
{
	std::thread th(test_thread);
	for(int i = 0; i < 5; i++) {
		Sleep(1000); // готовим задание
		printf("%5d: task %d\n", clock(), i);
		std::unique_lock<std::mutex> lck(mtx); // зачем ???
		cv.notify_one(); // пробуждаем поток для обработки задания
	}
	th.join();
	system("pause");
}
...
Рейтинг: 0 / 0
17.04.2015, 10:14
    #38938870
locked
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Dima T,

потому что notify_ разблокирует его.
...
Рейтинг: 0 / 0
17.04.2015, 10:31
    #38938891
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
lockedDima T,

потому что notify_ разблокирует его.
Если строчку unique_lock убрать - работает точно также.

Думаю она нужна чтобы одновременно два notify_ не вызвать с двух разных потоков. Но не уверен что правильно понимаю. Где бы поподробнее почитать как <condition_variable> устроены, желательно по-русски.
...
Рейтинг: 0 / 0
17.04.2015, 11:10
    #38938942
locked
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Dima TlockedDima T,

потому что notify_ разблокирует его.
Если строчку unique_lock убрать - работает точно также.

Думаю она нужна чтобы одновременно два notify_ не вызвать с двух разных потоков. Но не уверен что правильно понимаю. Где бы поподробнее почитать как <condition_variable> устроены, желательно по-русски.

немного подзабыл. захват мютекса перед вызовом notify нужен только для монопольного доступа к ресурсам. например добавление задания в очередь для запускаемой thread. мютекс нужно освободить. т.к. пробуждаемая thread его захватывает внутри wait. по выходу из wait мютекс захвачен. thread может взять задание из очереди и _должна_ освободить мютекс.

типа такого

Код: 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.
#include <thread>
#include <condition_variable>

std::condition_variable cv;
std::mutex mtx;

void test_thread()
{
	int cnt = 0;
	while(cnt < 5) {
          { // область действия мютекса
		std::unique_lock<std::mutex> lck(mtx);
		cv.wait(lck); // ожидаем задание
// читаем задание для thread
          } // освобождаем мютекс
		printf("%5d: work %d\n", clock(), cnt); // обрабатываем задание
	}
}

int main(int argc, char* argv[])
{
	std::thread th(test_thread);
	for(int i = 0; i < 5; i++) {
		Sleep(1000); // готовим задание
		printf("%5d: task %d\n", clock(), i);
		std::unique_lock<std::mutex> lck(mtx); // зачем ???
// добавляем задание для thread в очередь
		cv.notify_one(); // пробуждаем поток для обработки задания
	}
	th.join();
	system("pause");
}
...
Рейтинг: 0 / 0
17.04.2015, 12:19
    #38939041
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
lockedнемного подзабыл. захват мютекса перед вызовом notify нужен только для монопольного доступа к ресурсам. например добавление задания в очередь для запускаемой thread. мютекс нужно освободить. т.к. пробуждаемая thread его захватывает внутри wait. по выходу из wait мютекс захвачен. thread может взять задание из очереди и _должна_ освободить мютекс.
...
Спасибо. Теперь понял.
...
Рейтинг: 0 / 0
17.04.2015, 12:57
    #38939116
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Dima T,

ну кстати я тоже не понимаю, почему бы аналог виндовых event не сделать в xnix.
мне они кажутся более понятными , чем cond var.
...
Рейтинг: 0 / 0
17.04.2015, 13:47
    #38939199
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
MasterZivну кстати я тоже не понимаю, почему бы аналог виндовых event не сделать в xnix.
Семафоры почти аналог. http://pubs.opengroup.org/onlinepubs/009695399/basedefs/semaphore.h.html
...
Рейтинг: 0 / 0
17.04.2015, 14:26
    #38939271
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
MasterZivну кстати я тоже не понимаю, почему бы аналог виндовых event не сделать в xnix.
мне они кажутся более понятными , чем cond var.
Самое смешное, что виндовый event это внутри и есть мьютекс + условная переменная ))
...
Рейтинг: 0 / 0
17.04.2015, 15:14
    #38939337
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Anatoly MoskovskyСамое смешное, что виндовый event это внутри и есть мьютекс + условная переменная ))
Тогда почему event быстрее?
Код: plaintext
1.
2.
3.
Mutex 1510 msec 1000001 count
Event 1420 msec 1000001 count
STD::Mutex 180 msec 1000001 count
CS 50 msec 1000001 count

Код теста
Код: 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.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>  
#include <string.h>
#include <time.h> 
#include <mutex> 

#define TEST 1000000 // до скольки считать

HANDLE event = NULL;
HANDLE mutex = NULL;
CRITICAL_SECTION cs;
std::mutex stdmtx;

int cnt_event = 0;
int cnt_mutex = 0;
int cnt_cs = 0;
int cnt_stdmtx = 0;

DWORD WINAPI test_event(LPVOID p)
{
	while(cnt_event < TEST) {
		WaitForSingleObject(event, INFINITE);
		cnt_event++;
		SetEvent(event);
	}
	return 0;
}

DWORD WINAPI test_mutex(LPVOID p)
{
	while(cnt_mutex < TEST) {
		WaitForSingleObject(mutex, INFINITE); 
		cnt_mutex++;
		ReleaseMutex(mutex);
	}
	return 0;
}

DWORD WINAPI test_cs(LPVOID p)
{
	while(cnt_cs < TEST) {
		EnterCriticalSection(&cs);
		cnt_cs++;
		LeaveCriticalSection(&cs);
	}
	return 0;
}

DWORD WINAPI test_stdmtx(LPVOID p)
{
	while(cnt_stdmtx < TEST) {
		stdmtx.lock();
		cnt_stdmtx++;
		stdmtx.unlock();
	}
	return 0;
}

int main(int argc, char* argv[])
{
	{
		mutex = CreateMutex(NULL, TRUE, NULL);
		HANDLE th1 = CreateThread(NULL, 0, &test_mutex, NULL, 0, NULL);
		HANDLE th2 = CreateThread(NULL, 0, &test_mutex, NULL, 0, NULL);
		clock_t start = clock();
		ReleaseMutex(mutex);
		WaitForSingleObject(th1, INFINITE);
		WaitForSingleObject(th2, INFINITE);
		printf("Mutex %d msec %d count\n", clock() - start, cnt_mutex);
		CloseHandle(mutex);
		CloseHandle(th1);
		CloseHandle(th2);
	}
	{
		event = CreateEvent(NULL, FALSE, FALSE, NULL);
		HANDLE th1 = CreateThread(NULL, 0, &test_event, NULL, 0, NULL);
		HANDLE th2 = CreateThread(NULL, 0, &test_event, NULL, 0, NULL);
		clock_t start = clock();
		SetEvent(event);
		WaitForSingleObject(th1, INFINITE);
		WaitForSingleObject(th2, INFINITE);
		printf("Event %d msec %d count\n", clock() - start, cnt_event);
		CloseHandle(event);
		CloseHandle(th1);
		CloseHandle(th2);
	}
	{
		stdmtx.lock();
		HANDLE th1 = CreateThread(NULL, 0, &test_stdmtx, NULL, 0, NULL);
		HANDLE th2 = CreateThread(NULL, 0, &test_stdmtx, NULL, 0, NULL);
		clock_t start = clock();
		stdmtx.unlock();
		WaitForSingleObject(th1, INFINITE);
		WaitForSingleObject(th2, INFINITE);
		printf("STD::Mutex %d msec %d count\n", clock() - start, cnt_stdmtx);
		CloseHandle(th1);
		CloseHandle(th2);
	}
	{
		InitializeCriticalSectionAndSpinCount(&cs, 4000);
		EnterCriticalSection(&cs);
		HANDLE th1 = CreateThread(NULL, 0, &test_cs, NULL, 0, NULL);
		HANDLE th2 = CreateThread(NULL, 0, &test_cs, NULL, 0, NULL);
		clock_t start = clock();
		LeaveCriticalSection(&cs);
		WaitForSingleObject(th1, INFINITE);
		WaitForSingleObject(th2, INFINITE);
		printf("CS %d msec %d count\n", clock() - start, cnt_cs);
		DeleteCriticalSection(&cs);
		CloseHandle(th1);
		CloseHandle(th2);
	}
	system("pause");
}


Интересные результаты. Похоже <mutex> не использует виндовый mutex. Ну и CRITICAL_SECTION самый быстрый способ. Интересно стало. Вечером линуксовый mutex потестю, нет под рукой многоядерного линукса.
...
Рейтинг: 0 / 0
17.04.2015, 15:25
    #38939349
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Dima TТогда почему event быстрее?
Потому что код внутри разный?
...
Рейтинг: 0 / 0
17.04.2015, 15:33
    #38939367
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Dima T, я глубоко не погружался в тему крит-секций. Но в погоне за скоростью
ты не забыл что есть еще и критерий "справедливости" выдачи маркера для ожидающих
потоков?

Ну ... по крайней мере тема справедливости поднималась в альтернативных (отличных от С++)
систем разработки и ЯП.
...
Рейтинг: 0 / 0
17.04.2015, 16:18
    #38939471
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
maytonDima T, я глубоко не погружался в тему крит-секций. Но в погоне за скоростью
ты не забыл что есть еще и критерий "справедливости" выдачи маркера для ожидающих
потоков?
Сходу не смог придумать задачу где важно равномерное распределение пробуждения.

Если все-таки важно, организуй идеальное распределение внутри CS счетчиком.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
DWORD WINAPI test_cs(LPVOID p)
{
	static int th_count = 0;
	int my_num = th_count;
	th_count++;
	int cnt = 0;
	while(cnt_cs < TEST) {
		EnterCriticalSection(&cs);
		if(cnt_cs % th_count == my_num) {
			cnt_cs++;
			cnt++;
		}
		LeaveCriticalSection(&cs);
	}
	EnterCriticalSection(&cs);
	printf("local %d count\n", cnt);
	LeaveCriticalSection(&cs);

	return 0;
}


Код: plaintext
1.
2.
3.
STD::Mutex 170 msec 1000001 count
local 500000 count
local 500001 count
CS 50 msec 1000001 count
Скорость не поменялась.

CS быстро работает пока одновременно несколько потоков не начинают ждать входа, в этом случае он event задействует и начинает подтормаживать. Вот тест на 3 потоках
Код: plaintext
1.
STD::Mutex 343 msec 1000002 count
CS 359 msec 1000002 count

Т.е. CS есть смысл использовать там где конкуренция маловероятна.
...
Рейтинг: 0 / 0
17.04.2015, 16:44
    #38939490
locked
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Dima TИнтересно стало. Вечером линуксовый mutex потестю, нет под рукой многоядерного линукса.

не забудь про pthread_spin_lock
.
...
Рейтинг: 0 / 0
17.04.2015, 16:48
    #38939496
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Со счетчиком для идеального распределения я фигню придумал, тормозит из-за холостых циклов.
Замерил распределение дополнительным счетчиком в потоке
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
DWORD WINAPI test_cs(LPVOID p)
{
	int cnt = 0;
	while(cnt_cs < TEST) {
		EnterCriticalSection(&cs);
		cnt_cs++;
		cnt++;
		LeaveCriticalSection(&cs);
	}
	EnterCriticalSection(&cs);
	printf("local %d count\n", cnt);
	LeaveCriticalSection(&cs);
	return 0;
}


local 334744 count
local 330466 count
local 334792 count
Mutex 1700 msec 1000002 count
local 335488 count
local 335494 count
local 329020 count
Event 1684 msec 1000002 count
local 333330 count
local 333322 count
local 333350 count
STD::Mutex 312 msec 1000002 count
local 316675 count
local 336532 count
local 346794 count
CS 125 msec 1000001 count

У CS похуже, но не намного. Отчасти из-за этого и скорость выше. Для идеального распределения надо чаще потоки переключать, что тоже доп. затраты времени.
...
Рейтинг: 0 / 0
17.04.2015, 19:22
    #38939634
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Затестил в линуксе
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
thread 2 count 1007663
thread 1 count 370236
thread 3 count 365356
No lock 4 msec 1000000 count
thread 2 count 497213
thread 1 count 251662
thread 3 count 251126
STD::Mutex 167 msec 1000001 count
thread 1 count 285231
thread 2 count 287346
thread 3 count 427424
Mutex 135 msec 1000001 count
thread 2 count 486152
thread 1 count 462504
thread 3 count 51346
Spinlock 105 msec 1000002 count
thread 3 count 400041
thread 1 count 300265
thread 2 count 299694
Semaphore 586 msec 1000000 count
Код: 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.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
#include <stdio.h>
#include <stdlib.h>  
#include <string.h>
#include <time.h> 
#include <mutex> 
#include <thread> 
#include <pthread.h>
#include <sys/time.h>
#include <semaphore.h>
#include <errno.h>
#include <stdint.h>

uint32_t now_msec()
{
	struct timeval tv_sec;
	gettimeofday(&tv_sec, NULL);
	return (uint32_t)(((tv_sec.tv_sec & 0x1FFFFF) * 1000 + (tv_sec.tv_usec / 1000)) & 0xFFFFFFFF);
}

void sleep(int msec)
{
    struct timespec t, ost;
    t.tv_sec  =  msec / 1000;
    t.tv_nsec = (msec % 1000) * 1000000;
    nanosleep (&t, NULL);
}

#define TEST 1000000
#define THREAD 3

std::mutex stdmtx;
pthread_mutex_t mutex;
pthread_spinlock_t spinlock;
sem_t sem;

volatile int cnt_nolock = -1;
int cnt_stdmtx = 0;
int cnt_mutex = 0;
int cnt_spinlock = 0;
int cnt_sem = 0;

void test_nolock(int id)
{
	while(cnt_nolock == -1);
	int cnt = 0;
	while(cnt_nolock < TEST) {
		cnt_nolock++;
		cnt++;
	}
	stdmtx.lock();
	printf("thread %d count %d\n", id, cnt);
	stdmtx.unlock();
}

void test_stdmtx(int id)
{
	int cnt = 0;
	while(cnt_stdmtx < TEST) {
		stdmtx.lock();
		cnt_stdmtx++;
		cnt++;
		stdmtx.unlock();
	}
	stdmtx.lock();
	printf("thread %d count %d\n", id, cnt);
	stdmtx.unlock();
}

void test_mutex(int id)
{
	int cnt = 0;
	while(cnt_mutex < TEST) {
		if(pthread_mutex_lock(&mutex) != 0) break;
		cnt_mutex++;
		cnt++;
		pthread_mutex_unlock(&mutex);
	}
	pthread_mutex_lock(&mutex);
	printf("thread %d count %d\n", id, cnt);
	pthread_mutex_unlock(&mutex);
}


void test_spinlock(int id)
{
	int cnt = 0;
	while(cnt_spinlock < TEST) {
		if(pthread_spin_lock(&spinlock) != 0) break;
		cnt_spinlock++;
		cnt++;
		pthread_spin_unlock(&spinlock);
	}
	pthread_spin_lock(&spinlock);
	printf("thread %d count %d\n", id, cnt);
	pthread_spin_unlock(&spinlock);
}

void test_sem(int id)
{
	int cnt = 0;
	while(cnt_sem < TEST) {
		if(sem_wait(&sem) != 0) break;
		cnt_sem++;
		cnt++;
		sem_post(&sem);
	}
	sem_wait(&sem);
	printf("thread %d count %d\n", id, cnt);
	sem_post(&sem);
}

int main(int argc, char* argv[])
{
	if(1){
		std::thread th[THREAD];
		for(int i = 0; i < THREAD; i++) th[i] = std::thread(test_nolock, i+1);
		sleep(100);
		int start = now_msec();
		cnt_nolock = 0;
		for(int i = 0; i < THREAD; i++) th[i].join();
		printf("No lock %d msec %d count\n", now_msec() - start, cnt_nolock);
	}
	if(1){
		stdmtx.lock();
		std::thread th[THREAD];
		for(int i = 0; i < THREAD; i++) th[i] = std::thread(test_stdmtx, i+1);
		sleep(1000);
		int start = now_msec();
		stdmtx.unlock();
		for(int i = 0; i < THREAD; i++) th[i].join();
		printf("STD::Mutex %d msec %d count\n", now_msec() - start, cnt_stdmtx);
	}
	if(1){
		pthread_mutex_init(&mutex, NULL);
		pthread_mutex_lock(&mutex);
		std::thread th[THREAD];
		for(int i = 0; i < THREAD; i++) th[i] = std::thread(test_mutex, i+1);
		sleep(1000);
		int start = now_msec();
		pthread_mutex_unlock(&mutex);
		for(int i = 0; i < THREAD; i++) th[i].join();
		printf("Mutex %d msec %d count\n", now_msec() - start, cnt_mutex);
		pthread_mutex_destroy(&mutex);
	}
	if(1){
		pthread_spin_init(&spinlock, PTHREAD_PROCESS_PRIVATE);
		pthread_spin_lock(&spinlock);
		std::thread th[THREAD];
		for(int i = 0; i < THREAD; i++) th[i] = std::thread(test_spinlock, i+1);
		sleep(1000);
		int start = now_msec();
		pthread_spin_unlock(&spinlock);
		for(int i = 0; i < THREAD; i++) th[i].join();
		printf("Spinlock %d msec %d count\n", now_msec() - start, cnt_spinlock);
		pthread_spin_destroy(&spinlock);
	}
	if(1){
		sem_init(&sem, 0, 1);
		sem_wait(&sem);
		std::thread th[THREAD];
		for(int i = 0; i < THREAD; i++) th[i] = std::thread(test_sem, i+1);
		sleep(1000);
		int start = now_msec();
		sem_post(&sem);
		for(int i = 0; i < THREAD; i++) th[i].join();
		printf("Semaphore %d msec %d count\n", now_msec() - start, cnt_sem);
		sem_destroy(&sem);
	}
}


Код: plaintext
1.
2.
3.
STD::Mutex 167 msec 1000001 count
Mutex 135 msec 1000001 count
Spinlock 105 msec 1000002 count
Semaphore 586 msec 1000000 count

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

PS Время не сравнивайте с тестами выше, комп другой, послабже. Затестю потом этот код на том же компе что и в виндовсе. Но и так понятно что линукс быстрее переключается.
...
Рейтинг: 0 / 0
17.04.2015, 20:50
    #38939662
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Хм... интересно девки пляшут.

https://ru.wikipedia.org/wiki/Spinlock Кроме того, в той же Windows есть разновидности мьютексов (например, общеизвестная CRITICAL_SECTION, или же FAST_MUTEX в ядре), которые сначала работают как spinlock, используя опрос значения в памяти, и только потом, по истечении большого количества опросов, переходят в ядро к блокирующему ожиданию. Такие объекты сочетают лучшие качества спинлоков (минимальная цена захвата) и мьютексов (отсутствие растраты ресурса процессора на опрос).
...
Рейтинг: 0 / 0
17.04.2015, 21:24
    #38939679
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Интереснее это
https://ru.wikipedia.org/wiki/Spinlock Дело в том, что реализация атомарных операций с памятью происходит путем аппаратного блокирования системной шины процессором на время выполнения атомарной операции (которая включает чтение, модификацию и запись). Во время выполнения этих трёх операций выполнение каких-либо других операций на шине невозможно, что снижает производительность других процессоров в системе (если они разделяют общую шину), даже если они не имеют никакого отношения к данному спинлоку.
...
Рейтинг: 0 / 0
20.04.2015, 16:57
    #38940844
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Затестил в линуксе на том же компе где в виндовсе тестил
Код: 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.
thread 1 count 999743
thread 3 count 311464
thread 2 count 334119
No lock 2 msec 1000001 count

thread 1 count 308920
thread 2 count 299365
thread 3 count 391717
STD::Mutex 86 msec 1000002 count

thread 3 count 321740
thread 2 count 380536
thread 1 count 297725
Mutex 83 msec 1000001 count

thread 3 count 998849
thread 1 count 706
thread 2 count 447
Spinlock 79 msec 1000002 count

thread 1 count 288612
thread 2 count 460147
thread 3 count 251242
Semaphore 116 msec 1000001 count

Код: plaintext
1.
2.
3.
4.
STD::Mutex 86 msec 1000002 count
Mutex 83 msec 1000001 count
Spinlock 79 msec 1000002 count
Semaphore 116 msec 1000001 count

Вот как было в виндовсе в три потока:
Код: plaintext
1.
2.
3.
Mutex 1700 msec 1000002 count
Event 1684 msec 1000002 count
STD::Mutex 312 msec 1000002 count
CS 125 msec 1000001 count
...
Рейтинг: 0 / 0
21.04.2015, 08:37
    #38941231
locked
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
Dima T
Затестил в линуксе на том же компе где в виндовсе тестил
Код: 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.
thread 1 count 999743
thread 3 count 311464
thread 2 count 334119
No lock 2 msec 1000001 count

thread 1 count 308920
thread 2 count 299365
thread 3 count 391717
STD::Mutex 86 msec 1000002 count

thread 3 count 321740
thread 2 count 380536
thread 1 count 297725
Mutex 83 msec 1000001 count

thread 3 count 998849
thread 1 count 706
thread 2 count 447
Spinlock 79 msec 1000002 count

thread 1 count 288612
thread 2 count 460147
thread 3 count 251242
Semaphore 116 msec 1000001 count

Код: plaintext
1.
2.
3.
4.
STD::Mutex 86 msec 1000002 count
Mutex 83 msec 1000001 count
Spinlock 79 msec 1000002 count
Semaphore 116 msec 1000001 count

Интересные результаты. спинлок и мютэкс почти одинаковы. Какая версия ядра ? CPU ?
...
Рейтинг: 0 / 0
21.04.2015, 09:24
    #38941267
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Аналог windows event в с++
lockedКакая версия ядра ? CPU ?
Запускал с флэшки Debian 7.5 live c nonfree драйверами. Версию ядра не смотрел.
Проц i5-660 реально 2 ядра, для ОС - 4 (Hyper-threading не отключается)
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Аналог windows event в с++ / 24 сообщений из 24, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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