Является ли Core Affinity чем-то, что мы можем безопасно делать в .NET? - PullRequest
0 голосов
/ 05 июня 2018

Я посмотрел здесь, в StackOverflow, информацию о реализации Core Affinity для потока,
в .NET.

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

Вкл.С другой стороны, в других ответах упоминаются следующие свойства:
- ProcessThread.IdealProcessor ссылка
- ProcessThread.ProcessorAffinity ссылка

Как видноэти 2 свойства не являются свойствами класса Thread, а класса ProcessThread.

Поэтому я хотел бы спросить:
Если кто-то создает приложение .NET,
и хочет установить привязку к ядру для потоков своего приложения,
безопасно ли это поддерживается в управляемых потоках .NET?

(Если да, то мне интересно, почему эти 2 свойствавыставлены на ProcessThread класс
, а не на Thread класс?)

PS: я использую .NET Framework v3.5 и v2.0,
и не новееверсии Framework.

Ответы [ 2 ]

0 голосов
/ 06 июня 2018

Это более подробный ответ, который некоторые люди могут найти полезным.

Если вы хотите сделать это исключительно с использованием API существующего стандарта .NET, тогда ответ действительно «нет», и я объясню почему.Я также расскажу о том, как этого добиться, используя набор API-интерфейсов .NET Standard 2.0 и либо один API-интерфейс ОС, либо один API-интерфейс .NET Core 2.1.

Это правда, что, как правило, фиксированныйсопоставление «один к одному» между управляемыми потоками и собственными потоками не гарантируется на протяжении всего жизненного цикла управляемого приложения.Это основано на стандарте CLI Раздел I.12.3.1:

CLI управляет несколькими параллельными потоками управления (не обязательно такими же, как потоки, предоставляемые операционной системой хоста), несколькими управляемыми кучамии адресное пространство совместно используемой памяти.

Одна вещь, которая не очень четко сформулирована, состоит в том, содержится ли коллекция собственных потоков, используемых для запуска управляемых потоков, в одном и том же процессе или нескольких процессах.Но в стандарте CLI и документации .NET есть операторы, которые указывают, что все управляемое приложение живет в одном процессе ОС.Также мне неизвестно о какой-либо реализации, которая планирует управляемые потоки в нескольких процессах ОС.

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

В противном случае может бытьмножественные сходства.Собственный поток типа ProcessThread предлагает свойство только для записи ProcessorAffinity .Тип управляемого потока Thread не предлагает такого API.Тем не менее, он предлагает статический метод BeginThreadAffinity , который позволяет текущему управляемому потоку фиксировать свое сопоставление с любым собственным потоком, к которому он в данный момент сопоставлен, до тех пор, пока управляемый поток не вызовет EndThreadAffinity.Обратите внимание, что BeginThreadAffinity не является подсказкой для среды выполнения.Либо создается исключение, либо оно успешно возвращается с фиксированным отображением для текущего управляемого потока.Теперь, если мы можем получить текущий собственный поток, мы можем просто изменить его привязку к процессору, используя ProcessThread.ProcessorAffinity.К сожалению, в отличие от получения текущего управляемого потока, нет стандартного управляемого API, который возвращает ссылку или идентификатор текущего собственного потока.Как вы можете видеть, мы можем добиться фиксированного сопоставления, используя только API .NET Standard 2.0, но нет никакого способа выяснить, какой собственный поток сопоставлен с каким управляемым потоком. Я не думаю, что естьхорошая техническая причина, почему бы не иметь такого API.

Один из способов - вызвать некоторый OS-зависимый API для получения идентификатора текущего собственного потока.В Windows это GetCurrentThreadId из kernel32.dll.Текущий управляемый поток может вызывать этот API для получения идентификатора текущего собственного потока.Затем ссылку на соответствующий объект ProcessThread можно получить путем итерации по собственным потокам с использованием Process.GetCurrentProcess().Threads и поиска объекта с совпадающим идентификатором.После этого ProcessThread.ProcessorAffinity можно использовать для эффективной установки соответствия текущего управляемого потока.Обратите внимание, что, поскольку ProcessThread.ProcessorAffinity является свойством только для записи, отсутствует .NET Standard 2.0 API, позволяющий восстановить старую привязку.Я не знаю, почему это только для записи.

Другой, гораздо более сложный способ - использовать Thread.GetCurrentProcessorId , который в настоящее время существует только в .NET Core 2.1 (последняя версия),Вы можете установить привязку каждого собственного потока к определенному процессору и проверить, какой управляемый поток в данный момент работает на этом процессоре.В конце концов, вы можете определить, какой управляемый поток сопоставлен с каким собственным потоком.

Хотя возможно добиться фиксированного сопоставления, как обсуждалось выше, мне кажется, что BeginThreadAffinity не гарантирует, что каждый управляемый поток сопоставляется с уникальным собственным потоком.Таким образом, сопоставление один-к-одному не может быть достигнуто стандартным образом.

В .NET Core ProcessThread.ProcessorAffinity реализовано только в Windows.На других ОС выдает PlatformNotSupportedException.

0 голосов
/ 05 июня 2018

Нет.

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

Обратите внимание, что ProcessThread просто содержит информацию о запускепоток операционной системы в процессе.Это именно то, что вы получаете, когда спрашиваете, какие потоки имеет процесс - это часть ОС, а не .NET.Напротив, Thread - это примерно ваши потоки и только управляемые.

...