Действительно ли спин-блокировки являются хорошим выбором для средства выделения памяти?

Я предложил специалистам по обслуживанию времени выполнения языка программирования D несколько раз, чтобы средство выделения/сборщик "мусора" памяти использовало спин-блокировки вместо регулярной ОС критические разделы. Это действительно не завоевало популярность. Вот причины, я думаю, что спин-блокировки были бы лучше:

  1. По крайней мере, в синтетических сравнительных тестах, которые я сделал, это несколько раз быстрее, чем ОС критические разделы, когда существует конкуренция для блокировки средства выделения/GC памяти.Править: Опытным путем использование спин-блокировок даже не имело измеримых издержек в одножильной среде, вероятно, потому что блокировки должны быть сохранены в течение такого короткого промежутка времени в средстве выделения памяти.
  2. Выделения памяти и подобные операции обычно берут небольшую часть интервала и даже небольшую часть времени, которое контекстное переключение занимает, делая ее глупой к контекстному переключению в случае конкуренции.
  3. Сборка "мусора" в рассматриваемой реализации останавливает мир во всяком случае. Во время набора не будет никакого вращения.

Разве там какие-либо серьезные основания не состоят в том, чтобы использовать спин-блокировки в реализации средства выделения/сборщика "мусора" памяти?

8
задан dsimcha 15 December 2009 в 21:53
поделиться

6 ответов

На Windows в любом случае, объекты критической секции уже имеют такую возможность (http://msdn.microsoft.com/en-us/library/ms682530.aspx):

Поток использует функцию InitializeCriticalSectionAndSpinCount или SetCriticalSectionSpinCount, чтобы задать счетчик вращений для объекта критической секции. Вращение означает, что когда поток пытается получить критическую секцию, которая заблокирована, он входит в цикл, проверяет, не снята ли блокировка, и если блокировка не снята, поток переходит в спящий режим. На однопроцессорных системах счетчик спинов игнорируется, а счетчик спинов критической секции устанавливается равным 0 (нулю). На многопроцессорных системах, если критическая секция недоступна, вызывающий поток спинирует dwSpinCount перед выполнением операции ожидания на семафоре, связанном с критической секцией. Если критическая секция становится свободной во время выполнения спиновой операции, то вызывающий поток избегает операции ожидания.

Надеюсь, что другие платформы последуют этому примеру, если они еще этого не сделали.

.
2
ответ дан 5 December 2019 в 19:00
поделиться

Есть ли веские причины не использовать спинблоки в реализации аллокатора памяти/коллектора мусора?

Когда одни потоки связаны с вычислениями (CPU), а другие - с выделением памяти, то использование спинблоков занимает циклы процессора, которые в противном случае могли бы использоваться либо связанными с вычислениями потоками, либо принадлежащими другим процессам.

.
2
ответ дан 5 December 2019 в 19:00
поделиться
  1. Очевидно, что наихудшее поведение спинблока - ужасное (планировщик ОС видит только 30 потоков, связанных с процессором, поэтому он пытается дать им всем некоторое процессорное время; 29 из них вращаются как сумасшедшие, в то время как поток, удерживающий блокировку, спит), так что вам следует избегать их, если вы можете это сделать. Многие люди умнее меня утверждают, что спинблоки имеют нет случаев использования пользовательского пространства из-за этого.

  2. Системные мьютексы должны немного крутиться перед тем, как перевести поток в спящий режим (или действительно сделать любой системный вызов), так что иногда они могут выполнять в точности то же самое, что и спинблоки, даже когда есть некоторое утверждение.

  3. Аллокатор часто может практически устранить утверждение о блокировке, используя блокировку только для того, чтобы выделить страницы для потоков. В этом случае каждый поток отвечает за разметку своих страниц. В конце концов, вы получаете блокировку только один раз при каждом N назначении, и вы можете настроить N на что угодно.

Я считаю, что 2 и 3 являются сильными аргументами, которые не могут быть эффективно противопоставлены синтетическим бенчмаркам. Вам нужно будет показать, что производительность реальной программы страдает

.
3
ответ дан 5 December 2019 в 19:00
поделиться

Спинлок абсолютно бесполезен на системах с одним процессором/ядром, или - в более общем плане - на системах с высокой контенцией (когда на блокировке ждет много потоков)

.
2
ответ дан 5 December 2019 в 19:00
поделиться

Не уверен, согласен ли я, так как выделение памяти CAN занимает очень много времени (единственный способ, если вы предварительно выделите всю память, а затем заново выпустите ее) ..Вам действительно нужно попробовать те же самые выделения и разделения с несколькими гигабайтными кучами с миллионами записей, со многими приложениями, попадающими в критическую секцию выделения (приложения заметок, а не потоки) и с "мусорным" диском/заменой с недостаточного количества памяти. Вы также можете столкнуться с проблемами подмены диска, когда выделение нецелесообразно, и делать блокировку вращения диска в ожидании запроса диска, конечно же, нецелесообразно.

И, как упоминал CyberShadow на однопоточном процессоре, в конечном итоге вы попадаете в обычную блокировку с накладными расходами. Теперь язык может работать на многих встроенных процессорах, которые являются однопоточными.

Также, если вы можете обойтись без блокировки обмена, это лучше всего (так как он без блокировки, хотя все равно останавливает процессор и поднимает LOCK# для многоядерной памяти), но большинство блокировок используют это в любом случае (но нужно сделать больше) . Однако структура кучи обычно означает, что заблокированного обмена недостаточно, и в конечном итоге вы создаете критическую секцию. Обратите внимание, что в ( Generational) Mark Sweep Nursery с ГХ можно делать распределения как блокированное сравнение и добавление указателя. Я делаю это для ГХ ОС Cosmos C# и это делает для распределения скорости стека.

0
ответ дан 5 December 2019 в 19:00
поделиться

Одна из ошибок в сборщике мусора Glasgow Haskell Compiler настолько раздражает, что носит название « последнее замедление ядра ». Это прямое следствие ненадлежащего использования спин-блокировок в их сборщиках мусора и исключается в Linux из-за его планировщика, но на самом деле эффект может наблюдаться всякий раз, когда другие программы конкурируют за процессорное время.

Эффект очевиден на втором графике здесь и его можно увидеть не только на последнем ядре здесь , где программа Haskell видит снижение производительности за пределами 5 ядер.

0
ответ дан 5 December 2019 в 19:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: