Читаем Системное программирование в среде Windows полностью

VOID SetCriticalSectionSpinCount(LPCRITICAL_SECTION lpCriticalSection, DWORD dwCount) 

В документации Microsoft говорится о том, что рекомендуемым для управления кучей значением спин-счетчика является 4000. Однако оптимальное значение зависит от свойств приложения, и поэтому спин-счетчики должны настраиваться индивидуально для каждого приложения, выполняющегося в реалистическом SMP-окружении. Наилучшее значение будет различным в зависимости от количества процессоров, характера приложения и тому подобного.

На Web-сайте книги находится программа TimedMutualExclusionSC. Эта программа представляет собой видоизмененный вариант уже знакомой вам программы TimedMutualExclusion, в котором значение спин-счетчика указания в качестве параметра командной строки. Вы можете запустить эту программу на своей машине для приблизительной оценки того, какое значение спин-счетчика будет наиболее приемлемым для выполнения того или иного из вариантов тестовых программ на доступных вам SMP-системах, что и предлагается сделать в упражнении 9.2. 

<p>Дросселирование семафора для уменьшения состязательности между потоками</p>

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

Если ни один из этих методов не дает желаемого улучшения, то могло бы показаться, что нет иного выхода, кроме как уменьшить количество потоков, но при этом вы будете вынуждены заставлять одиночные потоки мультиплексировать те операции, которые естественнее было бы распределить между несколькими потоками. Выход из этой ситуации обеспечивают семафоры, которые дают возможность сохранить естественную многопоточную модель, но вместе с тем свести к минимуму количество активных потоков, конкурирующих между собой. Такое решение является концептуально простым, и его можно без труда включить в любую существующую прикладную программу, например TimedMutualExclusion. В системе "хозяин/рабочий" решение, носящее название "дросселя" семафора (semaphore throttle), использует следующую методику:

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

• Каждый рабочий поток ожидает перехода семафора в сигнальное состояние, прежде чем войти в критический участок кода. Ожидание семафора может непосредственно предшествовать ожиданию мьютекса или объекта CS.

• Если максимальное значение счетчика семафора равно 1, то использование мьютекса становится излишним. Подобное решение нередко является наилучшим для SMP-систем. 

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

Счетчик семафора просто представляет число потоков, которые могут быть активными в любой момент времени, и ограничивает количество потоков, соревнующихся между собой за право владения мьютексом, объектом CS или иным ресурсом. Главный поток даже может регулировать, или, как говорят, "дросселировать" (throttle) выполнение рабочих потоков и динамически настраивать работу приложения, ожидая, пока не уменьшится значение счетчика, если он решает, что уровень состязательности слишком высок, или увеличивая значение счетчика с помощью функции ReleaseSemaphore, чтобы дать возможность выполняться большему количеству потоков. Заметьте, однако, что максимальное значение счетчика семафора устанавливается при его создании, и изменить его впоследствии невозможно.

В приведенном ниже фрагменте кода представлен видоизмененный рабочий цикл, выполняющий две операции с семафором.

while (TRUE) { // Рабочий цикл

 WaitForSingleObject(hThrottleSem, INFINITE);

Перейти на страницу:

Похожие книги

C++: базовый курс
C++: базовый курс

В этой книге описаны все основные средства языка С++ - от элементарных понятий до супервозможностей. После рассмотрения основ программирования на C++ (переменных, операторов, инструкций управления, функций, классов и объектов) читатель освоит такие более сложные средства языка, как механизм обработки исключительных ситуаций (исключений), шаблоны, пространства имен, динамическая идентификация типов, стандартная библиотека шаблонов (STL), а также познакомится с расширенным набором ключевых слов, используемым в .NET-программировании. Автор справочника - общепризнанный авторитет в области программирования на языках C и C++, Java и C# - включил в текст своей книги и советы программистам, которые позволят повысить эффективность их работы. Книга рассчитана на широкий круг читателей, желающих изучить язык программирования С++.

Герберт Шилдт

Программирование, программы, базы данных
Programming with POSIX® Threads
Programming with POSIX® Threads

With this practical book, you will attain a solid understanding of threads and will discover how to put this powerful mode of programming to work in real-world applications. The primary advantage of threaded programming is that it enables your applications to accomplish more than one task at the same time by using the number-crunching power of multiprocessor parallelism and by automatically exploiting I/O concurrency in your code, even on a single processor machine. The result: applications that are faster, more responsive to users, and often easier to maintain. Threaded programming is particularly well suited to network programming where it helps alleviate the bottleneck of slow network I/O. This book offers an in-depth description of the IEEE operating system interface standard, POSIX (Portable Operating System Interface) threads, commonly called Pthreads. Written for experienced C programmers, but assuming no previous knowledge of threads, the book explains basic concepts such as asynchronous programming, the lifecycle of a thread, and synchronization. You then move to more advanced topics such as attributes objects, thread-specific data, and realtime scheduling. An entire chapter is devoted to "real code," with a look at barriers, read/write locks, the work queue manager, and how to utilize existing libraries. In addition, the book tackles one of the thorniest problems faced by thread programmers-debugging-with valuable suggestions on how to avoid code errors and performance problems from the outset. Numerous annotated examples are used to illustrate real-world concepts. A Pthreads mini-reference and a look at future standardization are also included.

David Butenhof

Программирование, программы, базы данных