Вызывают ли статические классы проблемы с производительностью в многоядерных системах?

на днях мой коллега заявил, что использование статических классов может вызвать проблемы с производительностью в многоядерных системах, потому что статический экземпляр не может быть разделен между кэшами процессора. Это правильно? Есть ли какие-то критерии для проверки этого утверждения? Это заявление было сделано в контексте обсуждения, связанного с разработкой .Net (с C #), но для меня это звучит как независимая от языка и среды проблема.

Спасибо за ваши комментарии.

12.12.2008 12:39:25
8 ОТВЕТОВ
РЕШЕНИЕ

Я бы попросил вашего коллегу предоставить данные или хотя бы ссылки.

Дело в том, что если у вас есть общие данные, у вас есть общие данные. Будь то через статические классы, синглтон, что угодно, не очень важно. Если вам не нужны общие данные, я думаю, у вас не будет статического класса.

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

Как всегда, сначала пишите наиболее разумный, читаемый и поддерживаемый код, а затем работайте, если у вас есть узкое место в производительности, и действуйте соответствующим образом.

14
12.12.2008 12:42:33

Если вы не используете какие-либо блокировки или синхронизацию, то static-vs.-non-static не повлияет на вашу производительность.

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

2
12.12.2008 12:42:01

«[a] статический экземпляр не может быть разделен между кешами процессора. Это верно?»

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

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

Интересно, говорил ли ваш коллега не о производительности, а о необходимости применять правильную блокировку, если несколько потоков читают / записывают одни и те же данные?

3
12.12.2008 12:58:46
Имеет много смысла для меня. Он действительно говорил о производительности.
Prensen 12.12.2008 13:02:56
Так что вы думаете он имел в виду? :) Что значит разделять экземпляр между кешами?
Daniel Earwicker 12.12.2008 13:29:10
Ну, он имел в виду - если я правильно его понял - что статический экземпляр этого класса может одновременно находиться только в одном кеше процессора. Но это не имеет смысла для меня.
Prensen 12.12.2008 13:32:44

На любом языке, контролируемом «виртуальной машиной» (.NET, Java и т. Д.), Этот элемент управления, скорее всего, делегируется базовой ОС и, вероятно, далее - BIOS и другим элементам управления расписанием. Тем не менее, в двух основных направлениях, .NET и Java, статическое и нестатическое является проблемой памяти , а не процессора.

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

Проблема с управлением кэшем ЦП не ограничивается только статическими методами. Только один процессор может обновлять любой адрес памяти одновременно. Объект в вашей виртуальной машине, и в частности поле в вашем объекте, является указателем на указанный адрес памяти. Таким образом, даже если у меня есть изменяемый объект Foo, вызов setBar(true)Foo будет разрешен только для одного процессора за раз.

Все это, как говорится, суть .NET и Java в том, что вы не должны тратить свое время на то, чтобы потеть на этих проблемах, пока не докажете, что у вас есть проблема, и я сомневаюсь, что вы это сделаете.

2
12.12.2008 13:00:41
если вы считаете, что BIOS участвует в планировании и управлении кэшем, вам придется много перечитывать ...
Javier 12.12.2008 14:23:17
Да, BIOS здесь не имеет ничего общего. Как только ОС загружена, она полностью контролируется и является единственным действующим процессом, который работает, все остальное - просто абстракция, которая существует в ее границах.
ApplePieIsGood 14.12.2008 04:26:14

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

0
12.12.2008 13:21:20

Если несколько потоков записывают в эти данные, вы будете иметь перегрузку кеша (запись в кеш одного ЦП аннулирует кеши других ЦП). Ваш друг технически прав, но есть большая вероятность, что это не ваше основное узкое место, так что это не имеет значения.

Если данные прочитаны несколькими потоками , ваш друг ошибается.

3
12.12.2008 13:23:50
Да. Очень верно. И, как отметил Джон Скит: с какой стати вы беспокоитесь об этом? Лучше быть уверенным, что ваш код не просто связан с процессором, а связан с этим эффектом кэширования в процессоре, прежде чем вы решите исключить полезный статический класс. И тогда, в этот момент, вы можете использовать C.
PeterAllenWebb 12.12.2008 14:52:51
Почему бы C облегчить проблему? Проблема будет связана с архитектурой памяти, язык, используемый для представления разделяемой памяти, не будет иметь значения к тому времени, когда она преобразуется из ISA в микрокод.
ApplePieIsGood 14.12.2008 04:28:02
C дает вам явный контроль над всей вашей моделью памяти, включая вопросы выравнивания и заполнения для очистки кеша. Это абсолютно не гарантирует, что вы добьетесь большего успеха с решением на C, но увеличит потолок производительности, если вы сможете работать лучше, чем VM / JIT.
Tom 14.12.2008 18:09:21
  1. если вы разделяете изменяемые данные между потоками, вам нужен либо алгоритм блокировки, либо алгоритм без блокировки (редко доступен, а иногда, к сожалению, труден в использовании).
    • Имея несколько широко используемых ресурсов с блокировкой и арбитражем, вы можете оказаться в узких местах.
    • статические данные похожи на ресурс одного экземпляра.

следовательно:

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

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

1
12.12.2008 14:29:19
Также учтите, что с ростом количества потоков увеличивается стоимость переключений контекста, и это в какой-то момент будет угрожать перевесом неэффективной очистки кеша подсистемой ЦП / памяти. Просто слишком субъективно спекулировать без более конкретного понимания приложения.
ApplePieIsGood 14.12.2008 04:32:29
планировщик O (1) не должен заботиться о количестве потоков. я думаю, что большинство * nix систем в наши дни соответствуют требованиям
Javier 14.12.2008 23:41:57

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

1
12.12.2008 15:06:01