Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Тест производительности: CRITICAL_SECTION и SRWLOCK / 25 сообщений из 30, страница 1 из 2
20.01.2018, 19:36
    #39587594
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Вычитал у Рихтера что SRWLOCK работает быстрее чем CRITICAL_SECTION. Решил проверить.

Затестил на своей библиотеке акторов. Результат в млн. попугаев, т.е. млн. сообщений/сек.
Процессор Потоков CSx32 SRWx32 CSx64 SRWx64i7 3770K (4 ядра + HT) DDR3 8 39.5 38.7 39.9 42.2i7 6700K (4 ядра без HT) DDR4 4 30.7 31.2 29.5 29.6
x32/x64 - битность при компиляции.

Почти всегда SRWLOCK не хуже.

Если кто хочет позапускать Исходники . Компилировать stress_test.
Менять:
#define CPU_MAX 8 // Количество потоков
#define LT_WIN_XP // Вариант с CRITICAL_SECTION

Результат смотреть в строке msg_send/sec
...
Рейтинг: 0 / 0
21.01.2018, 20:04
    #39587916
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Мы должны упомянуть в топике о справедливости распределения ресурса между потоками.
Очередь и т.п. Иначе у читателя может сложится впечатление что SRWLOCK - панацея.
...
Рейтинг: 0 / 0
22.01.2018, 06:39
    #39588025
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
maytonМы должны упомянуть в топике о справедливости распределения ресурса между потоками.
Очередь и т.п. Иначе у читателя может сложится впечатление что SRWLOCK - панацея.
В этом плане CRITICAL_SECTION тоже не панацея.
https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms682530(v=vs.85).aspx There is no guarantee about the order in which waiting threads will acquire ownership of the critical section.

PS Попробовал SRWLOCK использовать по полной, т.е. сначала блокировка только на чтение, далее при необходимости блокировка на запись. В моем случае не помогло, т.к. при записи надо снять блокировку на чтение, поставить блокировку на запись, перепроверить что не было изменений между снятием и постановкой блокировки. Все эти манипуляции съедают всю экономию от параллельного чтения.
...
Рейтинг: 0 / 0
22.01.2018, 10:43
    #39588142
rdb_dev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Dima T, ну, ясен пень - быстрее! В CRITICAL_SECTION до ч0рта лишнего, вплоть до специальной секции с отладочной информацией.
Код: 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.
typedef
struct _RTL_CRITICAL_SECTION_DEBUG
{
  WORD Type;
  WORD CreatorBackTraceIndex;
  struct _RTL_CRITICAL_SECTION *CriticalSection;
  LIST_ENTRY ProcessLocksList;
  DWORD EntryCount;
  DWORD ContentionCount;
  DWORD Flags;
  WORD CreatorBackTraceIndexHigh;
  WORD SpareWORD;
}
RTL_CRITICAL_SECTION_DEBUG,
*PRTL_CRITICAL_SECTION_DEBUG,
RTL_RESOURCE_DEBUG,
*PRTL_RESOURCE_DEBUG;

typedef
struct _RTL_CRITICAL_SECTION
{
  PRTL_CRITICAL_SECTION_DEBUG DebugInfo;
  LONG LockCount;
  LONG RecursionCount;
  HANDLE OwningThread;
  HANDLE LockSemaphore;
  ULONG_PTR SpinCount;
}
RTL_CRITICAL_SECTION,
*PRTL_CRITICAL_SECTION;



для сравнения:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
typedef
struct _RTL_SRWLOCK
{
  PVOID Ptr;
}
RTL_SRWLOCK,
*PRTL_SRWLOCK;


В некоторых случаях можно применять inline функции с ассемблерной вставкой lock cmpxchg, будет еще быстрее. :)
...
Рейтинг: 0 / 0
22.01.2018, 11:55
    #39588185
kealon(Ruslan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Dima T,

не понял какая польза от него для очереди, чтения то у тебя по сути нет, только запись (доставание из очереди тоже запись, так как меняет очередь)

как то тестили мы раличные реализации RW-локов, там тоже всё не так однозначно, то что хорошо пашет на 10-ке например, тупит на 7-ке, и наоборот
...
Рейтинг: 0 / 0
22.01.2018, 12:38
    #39588223
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
kealon(Ruslan)Dima T,

не понял какая польза от него для очереди, чтения то у тебя по сути нет, только запись (доставание из очереди тоже запись, так как меняет очередь)
Польза в том что SRWLOCK быстрее работает, разве что на более свежем проце в x32 немного отстал.
Я использовал только блокировку на запись, т.е. по сути точно так же как CRITICAL_SECTION.

Блокировку на чтение попробовал использовать в переборе на поиск свободного необработанного (метод lite_actor_t::find_ready()), но стало чуть медленнее.
kealon(Ruslan)как то тестили мы раличные реализации RW-локов, там тоже всё не так однозначно, то что хорошо пашет на 10-ке например, тупит на 7-ке, и наоборот
Тестил оба на 10-ке. 7-ок не осталось.

Но если в целом смотреть, то SRWLOCK выгоднее: функционал CRITICAL_SECTION повторяет (кроме вложенных вызовов внутри потока) и плюсом можно блокировку для чтения задействовать при необходимости.
...
Рейтинг: 0 / 0
22.01.2018, 12:56
    #39588246
kealon(Ruslan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Dima T,

тогда, я бы на твоём месте удивился почему оно быстрее CS или спинлоков (на CAS реализация) тех же, ибо функционал реализованный в SRWLOCK несколько избыточный, например, по сравнению со спинлоком

Кроме того основное применение у SRWLOCK - это когда операций чтения значительно больше операций записи.
...
Рейтинг: 0 / 0
22.01.2018, 13:22
    #39588281
Вася Уткин
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Dima TPS Попробовал SRWLOCK использовать по полной, т.е. сначала блокировка только на чтение, далее при необходимости блокировка на запись. В моем случае не помогло, т.к. при записи надо снять блокировку на чтение, поставить блокировку на запись , перепроверить что не было изменений между снятием и постановкой блокировки. Все эти манипуляции съедают всю экономию от параллельного чтения.
Выделенное - это известная особенность в СУБД, т.к. повышение блокировки с разделяемой до эксклюзивной очень сильно повышает вероятность deadlock. Именно по этой причине в стандарте std::shared_mutex не сделали возможность повышения блокировки shared_lock до lock, хотя в boost::shared_mutex эта возможность была.

Dima TВычитал у Рихтера что SRWLOCK работает быстрее чем CRITICAL_SECTION. Решил проверить.

Затестил на своей библиотеке акторов. Результат в млн. попугаев, т.е. млн. сообщений/сек.
Процессор Потоков CSx32 SRWx32 CSx64 SRWx64i7 3770K (4 ядра + HT) DDR3 8 39.5 38.7 39.9 42.2i7 6700K (4 ядра без HT) DDR4 4 30.7 31.2 29.5 29.6
x32/x64 - битность при компиляции.

Почти всегда SRWLOCK не хуже.

Если кто хочет позапускать Исходники . Компилировать stress_test.
Менять:
#define CPU_MAX 8 // Количество потоков
#define LT_WIN_XP // Вариант с CRITICAL_SECTION

Результат смотреть в строке msg_send/sec

А какие результаты дают std::mutex C++11 (вместо CRITICAL_SECTION) и std::shared_mutex C++17 (вместо SRWLOCK)?
Если нет C++17, то можно использовать shared_timed_mutex C++14 (вместо SRWLOCK).
...
Рейтинг: 0 / 0
22.01.2018, 13:25
    #39588287
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
kealon(Ruslan)Dima T,

тогда, я бы на твоём месте удивился почему оно быстрее CS или спинлоков (на CAS реализация) тех же, ибо функционал реализованный в SRWLOCK несколько избыточный, например, по сравнению со спинлоком
Спинлоки не рассматриваем, они быстрее только при небольших нагрузках. Я же с них перешел на CS, т.к. спинлок тормозить начал.

CS и SRWLOCK хороши тем что после некоторого количества циклов спинлока уходят на ожидание встроенного Event`a, т.е. в режим ядра.
CS тоже избыточный, т.к. там возможны вложенные блокировки в пределах одного потока, т.е. он отслеживает поток, который блокировку накладывает, а SRWLOCK - нет. Может с этим связано.

Кроме того блокировка чтения-записи достаточно просто реализуется: уменьшить счетчик читающих на 1 если он был 0. Если удалось - блокировка на запись установлена.

PS Я бы может тоже удивился, но вычитал я это у Рихтера , он тоже мерил, поэтому решил просто проверить.
...
Рейтинг: 0 / 0
22.01.2018, 14:29
    #39588362
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Вася УткинА какие результаты дают std::mutex C++11 (вместо CRITICAL_SECTION) и std::shared_mutex C++17 (вместо SRWLOCK)?
Если нет C++17, то можно использовать shared_timed_mutex C++14 (вместо SRWLOCK).
Дополнил результат
Процессор Потоков CSx32 SRWx32 CSx64 SRWx64std::mutex x32std::mutex x64std::shared_mutex x32std::shared_mutex x64i7 3770K (4 ядра + HT) DDR3 8 39.5 38.7 39.9 42.2 25.5 28.8 37.7 43.0
Компилятор MSVC 2015. Второй комп пока под нагрузкой, не могу на нем потестить.

std::shared_mutex на x64 оказался быстрее SRWLOCK. Есть над чем подумать.
...
Рейтинг: 0 / 0
22.01.2018, 14:48
    #39588395
cfree
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Dima TВася УткинА какие результаты дают std::mutex C++11 (вместо CRITICAL_SECTION) и std::shared_mutex C++17 (вместо SRWLOCK)?
Если нет C++17, то можно использовать shared_timed_mutex C++14 (вместо SRWLOCK).
Дополнил результат
Процессор Потоков CSx32 SRWx32 CSx64 SRWx64std::mutex x32std::mutex x64std::shared_mutex x32std::shared_mutex x64i7 3770K (4 ядра + HT) DDR3 8 39.5 38.7 39.9 42.2 25.5 28.8 37.7 43.0
Компилятор MSVC 2015. Второй комп пока под нагрузкой, не могу на нем потестить.

std::shared_mutex на x64 оказался быстрее SRWLOCK. Есть над чем подумать.

Попробуйте скачать этот файл: https://raw.githubusercontent.com/AlexeyAB/object_threadsafe/master/safe_ptr.h
Сделать #include "safe_ptr.h"
И использовать default_contention_free_shared_mutex вместо std::shared_mutex, какая производительность будет?
...
Рейтинг: 0 / 0
22.01.2018, 14:59
    #39588418
kealon(Ruslan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Dima T,

посоветовал бы ещё спин-лок с разгрукой поюзать, 40 лямов/c на i7 он должен выжимать

std::shared_mutex x64 - 43.0, выглядит довольно подозрительно (затормаживает отдельные потоки??? посмотри нагруку на проц)
...
Рейтинг: 0 / 0
22.01.2018, 15:15
    #39588437
Вася Уткин
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Dima TВася УткинА какие результаты дают std::mutex C++11 (вместо CRITICAL_SECTION) и std::shared_mutex C++17 (вместо SRWLOCK)?
Если нет C++17, то можно использовать shared_timed_mutex C++14 (вместо SRWLOCK).
Дополнил результат
Процессор Потоков CSx32 SRWx32 CSx64 SRWx64std::mutex x32std::mutex x64std::shared_mutex x32std::shared_mutex x64i7 3770K (4 ядра + HT) DDR3 8 39.5 38.7 39.9 42.2 25.5 28.8 37.7 43.0
Компилятор MSVC 2015. Второй комп пока под нагрузкой, не могу на нем потестить.

std::shared_mutex на x64 оказался быстрее SRWLOCK. Есть над чем подумать.
Делаете только lock() или shared_lock() тоже в std::shared_mutex?
...
Рейтинг: 0 / 0
22.01.2018, 15:18
    #39588441
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Вася УткинДелаете только lock() или shared_lock() тоже в std::shared_mutex?
только lock(), т.е. везде монопольная блокировка (как для записи).
...
Рейтинг: 0 / 0
22.01.2018, 15:41
    #39588471
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
kealon(Ruslan)Dima T,

посоветовал бы ещё спин-лок с разгрукой поюзать, 40 лямов/c на i7 он должен выжимать
Это как? Знаю просто спинлок как сделать.
kealon(Ruslan)std::shared_mutex x64 - 43.0, выглядит довольно подозрительно (затормаживает отдельные потоки??? посмотри нагруку на проц)
У меня в тесте ограничение на количество потоков по числу ядер. Загрузка 100% на все 10 сек теста.

Я вот что подумал: из-за этого у меня ожидания долгого не происходит. Попробую затестить с количеством потоков больше чем ядер. Например 12 потоков на 8 ядрах.
...
Рейтинг: 0 / 0
22.01.2018, 16:01
    #39588499
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
cfreeПопробуйте скачать этот файл: https://raw.githubusercontent.com/AlexeyAB/object_threadsafe/master/safe_ptr.h
Сделать #include "safe_ptr.h"
И использовать default_contention_free_shared_mutex вместо std::shared_mutex, какая производительность будет?
Написал так
Код: plaintext
1.
2.
#include "safe_ptr.h"
typedef default_contention_free_shared_mutex lite_mutex_t;


Ошибка на второй строке
Код: plaintext
1.
identifier "default_contention_free_shared_mutex" is undefined
...
Рейтинг: 0 / 0
22.01.2018, 16:50
    #39588571
cfree
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Dima TcfreeПопробуйте скачать этот файл: https://raw.githubusercontent.com/AlexeyAB/object_threadsafe/master/safe_ptr.h
Сделать #include "safe_ptr.h"
И использовать default_contention_free_shared_mutex вместо std::shared_mutex, какая производительность будет?
Написал так
Код: plaintext
1.
2.
#include "safe_ptr.h"
typedef default_contention_free_shared_mutex lite_mutex_t;


Ошибка на второй строке
Код: plaintext
1.
identifier "default_contention_free_shared_mutex" is undefined


Попробуйте так
Код: plaintext
1.
2.
3.
4.
5.
#include "safe_ptr.h"
using namespace sf;

typedef default_contention_free_shared_mutex lite_mutex_t;
// typedef spinlock_t lite_mutex_t;  // а потом этот вариант
...
Рейтинг: 0 / 0
22.01.2018, 16:58
    #39588578
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Затестил на 12 потоках (8 логических ядер i7 3770K)
Блокировка 8 потоков 12 потоков 16 потоковSpin-lock 51.6 34.7 24.6std::shared_mutex 43.0 41.0 40.2SRWLOCK 42.2 40.4CRITICAL_SECTION 39.9 38.3std::mutex 28.9 27.6
Spin-lock исходник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
// Взято тут http://en.cppreference.com/w/cpp/atomic/atomic_flag

class lite_mutex_t {
	std::atomic_flag _lock = ATOMIC_FLAG_INIT;

public:
	void lock() noexcept {
		while (_lock.test_and_set(std::memory_order_acquire));
	}

	void unlock() noexcept {
		_lock.clear(std::memory_order_release);
	}
};


Spin-lock быстрый, но как только ядра свободные кончаются - все грустно становится.

PS Позже затестю std::shared_mutex на втором компе.
...
Рейтинг: 0 / 0
22.01.2018, 17:09
    #39588584
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
cfreeПопробуйте так
Код: plaintext
1.
2.
3.
4.
#include "safe_ptr.h"
using namespace sf;

typedef default_contention_free_shared_mutex lite_mutex_t;


Так получилось. Скорость не очень. Стенд тот же 21127862

Блокировка 8 потоков 12 потоков 16 потоковSpin-lock 51.6 34.7 24.6std::shared_mutex 43.0 41.0 40.2default_contention_free_shared_mutex 17.1 11.4 10.4
...
Рейтинг: 0 / 0
22.01.2018, 18:34
    #39588613
Вася Уткин
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Процессор Потоков CSx32 SRWx32 CSx64 SRWx64std::mutex x32std::mutex x64std::shared_mutex x32std::shared_mutex x64i7 3770K (4 ядра + HT) DDR3 8 39.5 38.7 39.9 42.2 25.5 28.8 37.7 43.0
Dima TВася УткинДелаете только lock() или shared_lock() тоже в std::shared_mutex?
только lock(), т.е. везде монопольная блокировка (как для записи).
Вообще странно, что на эксклюзивных блокировках std::shared_mutex быстрее, чем std::mutex. Судя по всему большинство времени один и тот же поток каждый раз захватывает блокировку и только изредка отдаёт её другому потоку - большую часть времени фактически получается однопоточное исполнение.
...
Рейтинг: 0 / 0
22.01.2018, 18:43
    #39588619
kealon(Ruslan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Dima T,
как-то так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
	void lock() noexcept {
                for ( ; ; )
                {
                        // пытаемся забить, количество попыток можно увеличить            
        		if (!_lock.test_and_set(std::memory_order_acquire)) return; 
        		if (!_lock.test_and_set(std::memory_order_acquire)) return;
                        // разгрузка  (под Linux можно usleep(20));
                        Sleep(0);  
                } 
	}

};



PS: с Sleep(1) тоже неплохо работает обычно, но как всегда есть ньюансы....
...
Рейтинг: 0 / 0
22.01.2018, 18:48
    #39588623
kealon(Ruslan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Вася УткинВообще странно, что на эксклюзивных блокировках std::shared_mutex быстрее, чем std::mutex. Судя по всему большинство времени один и тот же поток каждый раз захватывает блокировку и только изредка отдаёт её другому потоку - большую часть времени фактически получается однопоточное исполнение. во ..., это объясняет почему больше предела выходит
...
Рейтинг: 0 / 0
22.01.2018, 18:59
    #39588632
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Результат второго компа: в x32 shared_mutex самый медленный, в x64 самый быстрый
Процессор Потоков CSx32 SRWx32std::shared_mutex x32 SRWx64 CSx64std::shared_mutex x64i7 3770K (4 ядра + HT) DDR3 8 39.5 38.7 37.7 39.9 42.2 43.0i7 6700K (4 ядра без HT) DDR4 4 30.7 31.2 29.7 29.5 29.6 30.2
...
Рейтинг: 0 / 0
22.01.2018, 19:12
    #39588639
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
kealon(Ruslan)Вася УткинВообще странно, что на эксклюзивных блокировках std::shared_mutex быстрее, чем std::mutex. Судя по всему большинство времени один и тот же поток каждый раз захватывает блокировку и только изредка отдаёт её другому потоку - большую часть времени фактически получается однопоточное исполнение. во ..., это объясняет почему больше предела выходит
Чем тогда объясните 100% загрузки проца в диспетчере? Все восемь ядер под завязку. Я уже писал об этом 21127347
Задача искусственная, можно запросто хоть 100 ядер загрузить, суть в начале описана .
Если кто дальше не верит - исходники открыты, могу написать что подправить для запуска с использованием std::shared_mutex

PS Спинлок со Sleep() позже испытаю. Для подобных целей есть спец. функция в WinAPI, которая в отличии от слипа отдает остатки неизрасходованного времени другому потоку своего же процесса. Как называется - забыл, у Рихтера было, сейчас полистаю.
...
Рейтинг: 0 / 0
22.01.2018, 19:18
    #39588643
kealon(Ruslan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест производительности: CRITICAL_SECTION и SRWLOCK
Dima Tkealon(Ruslan)пропущено...
во ..., это объясняет почему больше предела выходит
Чем тогда объясните 100% загрузки проца в диспетчере? Все восемь ядер под завязку. Я уже писал об этом 21127347
Задача искусственная, можно запросто хоть 100 ядер загрузить, суть в начале описана .
Если кто дальше не верит - исходники открыты, могу написать что подправить для запуска с использованием std::shared_mutex

PS Спинлок со Sleep() позже испытаю. Для подобных целей есть спец. функция в WinAPI, которая в отличии от слипа отдает остатки неизрасходованного времени другому потоку своего же процесса. Как называется - забыл, у Рихтера было, сейчас полистаю.
наверное пытаются занять спин-лок

SwitchToThread
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Тест производительности: CRITICAL_SECTION и SRWLOCK / 25 сообщений из 30, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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