Я читал эту тему: C# Thread safe fast(est) counter и реализовал эту функцию в своем параллельном коде. Насколько я вижу, все работает нормально, однако оно значительно увеличило время обработки, как и 10% или около того.Даже более быстрый недорогой потокобезопасный счетчик?
Это немного подслушивало меня, и я думаю, что проблема заключается в том, что я делаю огромное количество относительно дешевых (< 1 квантовых) задач на небольших фрагментах данных, которые хорошо дополняются и, вероятно, хорошо используют локализации кэша, таким образом, работающая оптимально. Мое лучшее предположение, основанное на том, что мало что известно о MESI, заключается в том, что префикс x86 LOCK
в Interlocked.Increment
выталкивает кешью в эксклюзивный режим и заставляет пропустить кеш на других ядрах и заставляет перезагружать кеш на каждом параллельном проходе только ради увеличения этого счетчика , С задержкой в 100 нс для промаха в кэше и моей рабочей нагрузкой он, похоже, складывается. (Опять же, я мог ошибаться)
Теперь я не вижу способа обойти это, но, возможно, мне не хватает чего-то очевидного. Я даже думал об использовании n счетчиков (соответствующих степени распараллеливания), а затем увеличивал каждый на конкретном ядре, однако он кажется неосуществимым (обнаружение того ядра, на котором я работаю, вероятно, будет более дорогостоящим, не говоря уже о разработке, если/then/else структуру и испортить конвейер выполнения). Любые идеи о том, как разбить этого зверя? :)
map-reduce, как правило, проще рассуждать о подходах, основанных на блокировке/кеше ... Если вы можете разделить данные, чем считать каждый раздел отдельно, а не комбинировать результаты ... –
Вы имеете в виду разделить пакет на n потоков и обрабатывать каждый поток на конкретном ядре с несколькими приращениями? Но у меня нет способа заставить сродство, нет? Это означает, что мои потоки теперь будут длиннее 1 кванта и будут по всем ядрам, снова заставляя промахи пропустить кеш на своем счетчике, нет? Даже если он не будет блокирован, он будет грязным и заставит читать запись. У меня было бы n-раз меньше промахов на счетчик, но в n раз больше счетчиков. – mmix
Разделенная модель используется Java [Striped64] (http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/7b4721e4edb4/src/share/classes/java/util/concurrent/atomic/Striped64. Ява). Быстрый путь (бесконтактный) дешевый, со сложностью динамического роста счетчиков при обнаружении конфликта. Я адаптировал его для выращивания массива кольцевых буферов, и на практике он работает очень хорошо. –