Различное сходство потоков в Parallel.For Iterations

Мне нужна итерация параллельного цикла for для использования 7 ядер (или держаться подальше от 1 ядра), но еще одна итерация для использования 8 (всех) ядер и попытка ниже кода:

Parallel.For(0,2,i=>{
  if(i=0)
     Process.GetCurrentProcess().ProcessorAffinity = (System.IntPtr)(255);

  if(i==1)
     Process.GetCurrentProcess().ProcessorAffinity = (System.IntPtr)(254);
  Thread.Sleep(25);// to make sure  both set their affinities
  Console.WriteLine(Process.GetCurrentProcess().ProcessorAffinity);
});

это выводит 255 для обеих итераций. Таким образом, либо цикл parallel.for использует для них один поток, либо один параметр также устанавливает сходство для других итераций. Другая проблема заключается в том, что это приложение, чувствительное к задержке, и все эти настройки привязки добавляют задержку от 1 до 15 миллисекунд.

Нужно ли явно использовать потоки и устанавливать привязки только один раз?

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

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


person huseyin tugrul buyukisik    schedule 16.09.2016    source источник
comment
Я недостаточно знаю, чтобы помочь, но Parallel.For использует потоки или пул задач? Потому что я видел, как он создает и уничтожает степени параллелизма в зависимости от требований пула задач. Я почти уверен, что потоки этого не делают. Я установил maxDegree на 26 операционных 3,2 миллиарда сравнений, и количество активных потоков колебалось от 5 до 26 в течение шести дней, которые потребовались для завершения. Так что, хотя я не могу помочь, я определенно заинтересован в вашем вопросе.   -  person Shannon Holsinger    schedule 16.09.2016
comment
Я не смог найти для этого ничего похожего на minParallelismDegree, но сейчас я пробую чистые потоки, используя делегат анонимной функции и обработчик событий.   -  person huseyin tugrul buyukisik    schedule 16.09.2016
comment
Это параметр, который вы устанавливаете в Parallel.For -- msdn.microsoft.com/en-us/library/, как я уже сказал, я невежественен, но это может помочь вам понять, что скрывается под капотом.   -  person Shannon Holsinger    schedule 16.09.2016
comment
Обратите внимание, что MSDN упоминает, когда эвристика пула потоков не может определить правильное количество потоков для использования и может привести к внедрению слишком большого количества потоков. Например, в длительных итерациях тела цикла пул потоков может быть не в состоянии определить разницу между разумным прогрессом, динамической блокировкой или тупиковой блокировкой, а также может быть не в состоянии восстановить потоки, которые были добавлены для повышения производительности. В этом случае вы можете установить это свойство, чтобы гарантировать, что вы не используете более разумного количества потоков, поэтому это звучит так, как будто потоки управляются, а не назначаются специально.   -  person Shannon Holsinger    schedule 16.09.2016
comment
@ShannonHolsinger только что попробовал темы, то же самое. Думаю, это касается всего процесса. Но MSDN говорит, что это для потока. Задает процессоры, на которых может работать связанный поток.   -  person huseyin tugrul buyukisik    schedule 16.09.2016
comment
Сейчас я читаю сходство потоков ОС, что кажется более сложным.   -  person huseyin tugrul buyukisik    schedule 16.09.2016
comment
Не вмешивайтесь в потоки из пула. Ваше первоначальное требование ... использовать 7 ядер (или держаться подальше от 1 ядра) весьма подозрительно в том, что оно дезинформировано, но когда вам это действительно нужно: забудьте о Parallel, Tasks и пуле.   -  person Henk Holterman    schedule 16.09.2016
comment
@HenkHolterman даже в той же теме, секундомер перестал работать, словарь начал дублировать .add и выдал ошибку. Может быть, поток больше не является одним потоком, и мне нужны блокировки вокруг всего? Мне просто нужно параллельное управление устройствами. Запустил параллельно, без проблем. Может быть, анонимная функция вызывает это? Я установил его на Func‹› и использовал в качестве делегата для 2 потоков.   -  person huseyin tugrul buyukisik    schedule 16.09.2016
comment
Звучит как много связанных, но разных проблем... Убедитесь, что вы знаете основы многопоточности и безопасности потоков.   -  person Henk Holterman    schedule 16.09.2016
comment
Кажется ли parallel.for более безопасным, чем потоки, потому что в фоновом режиме он может использовать только 1 поток (может быть, основной поток?) всего за 2 итерации?   -  person huseyin tugrul buyukisik    schedule 16.09.2016
comment
Вы цитируете MSDN, но затем используете в своем коде совершенно другое свойство (в процессе). msdn.microsoft.com /en-us/библиотека/   -  person Ian Mercer    schedule 16.09.2016
comment
@huseyintugrulbuyukisik - я думаю, что ключевое слово здесь может использовать только 1 поток - может использовать более одного. Все это было очень интересно. Всем спасибо!   -  person Shannon Holsinger    schedule 16.09.2016


Ответы (1)


Различное сходство потоков в Parallel.For Iterations

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

Для Parallel API вы можете установить максимальную степень параллелизма следующим образом:

ParallelOptions parallelOption = new ParallelOptions();

parallelOption.MaxDegreeOfParallelism = Environment.ProcessorCount;

Parallel.For(0, 20, parallelOption, i =>

Но это никогда не гарантирует количество потоков, которые будут вызываться для параллельной обработки, поскольку потоки используются из ThreadPool, а CLR решает во время выполнения в зависимости от объема обрабатываемой работы, требуется ли для обработки больше one thread.

В том же цикле Parallel вы можете попробовать следующее: напечатайте Thread.Current.ManageThreadId, это даст четкое представление о количестве потоков, вызываемых в цикле Parallel.

Нужно ли явно использовать потоки и устанавливать привязки только один раз?

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

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

Thread[] threadArray = new Thread[2];
threadArray[0] = new Thread(<ThreadDelegate>);
threadArray[1] = new Thread(<ThreadDelegate>);
threadArray[0]. ProcessorAffinity = <Set Processor Affinity>
threadArray[1]. ProcessorAffinity = <Set Processor Affinity>

Предполагая, что вы правильно назначили сходство, вы можете распечатать их и найти разные значения, проверьте следующее ProcessThread.ProcessorAffinity.

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

ИЗМЕНИТЬ:

Попробуйте следующее редактирование вашей программы (на основе того факта, что два идентификатора потока распечатываются), теперь, когда оба потока находятся на картинке, они оба получают одинаковое значение variable i, им нужно local variable, чтобы избежать проблемы с закрытием

Parallel.For(0,2,i=>{
  int local = i;
  if(local=0)
     Process.GetCurrentProcess().ProcessorAffinity = (System.IntPtr)(255);

  if(local==1)
     Process.GetCurrentProcess().ProcessorAffinity = (System.IntPtr)(254);
  Thread.Sleep(25);// to make sure  both set their affinities
  Console.WriteLine(Process.GetCurrentProcess().ProcessorAffinity);
});

РЕДАКТИРОВАТЬ 2: (чаще всего не работает, так как оба потока могут увеличиваться до фактического выполнения логики)

 int local = -1;
  Parallel.For(0,2,i=>{
  Interlocked.Increment(ref local);
  if(local=0)
     Process.GetCurrentProcess().ProcessorAffinity = (System.IntPtr)(255);

  if(local==1)
     Process.GetCurrentProcess().ProcessorAffinity = (System.IntPtr)(254);
  Thread.Sleep(25);// to make sure  both set their affinities
  Console.WriteLine(Process.GetCurrentProcess().ProcessorAffinity);
});
person Mrinal Kamboj    schedule 16.09.2016
comment
Для первой части требуется от 20 до 200 миллисекунд на итерацию, которая является балансировщиком нагрузки и балансирует работу для всех устройств и делает их равной задержкой. - person huseyin tugrul buyukisik; 16.09.2016
comment
--------------- Thread.Current.ManageThreadId 10 Thread.Current.ManageThreadId 16 --------------- похоже на это, но меняется только второй - person huseyin tugrul buyukisik; 16.09.2016
comment
Проверьте редактирование, если это происходит, то в основном это проблема с закрытием, так как к тому времени, когда оба потока появляются на картинке, value of i is 0 для них обоих - person Mrinal Kamboj; 16.09.2016
comment
Я использую i в замке или использую параллельную строку i и консольную строку записи 0 и 1 - person huseyin tugrul buyukisik; 16.09.2016
comment
i in a lock означает, пожалуйста, предоставьте код, это очень распространенная проблема со значениями многопоточных переменных. - person Mrinal Kamboj; 16.09.2016
comment
Вместо этого вы можете попробовать Interlocked.Increment для общей переменной, что гарантирует, что два потока будут увеличивать ее один раз, и вы можете проверить логику - person Mrinal Kamboj; 16.09.2016
comment
Проверьте Edit 2, чтобы добиться того же - person Mrinal Kamboj; 16.09.2016
comment
Это был lock(obj){i++;} и инициализировал его с -1, поэтому первая итерация делает i = 0, а вторая итерация делает i=1 - person huseyin tugrul buyukisik; 16.09.2016
comment
Хорошо, это также неверно, как и моя версия Interlocked.Increment, что происходит, прежде чем вы сможете добраться до if statement, оба потока уже прошли через блокировку, и все еще существует только одно значение, лучшим решением является Изменить 1, так как это решает проблему закрытия в подлинном смысле. Хотя использование Interlocked.Increment или Lock может привести к неоднозначным результатам. - person Mrinal Kamboj; 16.09.2016
comment
Также еще один момент, касающийся вашего кода, вы, кажется, устанавливаете affinity for complete Process не только Thread, а Process affinity повлияет на все потоки в процессе. - person Mrinal Kamboj; 16.09.2016
comment
Я перешел на threadpool и использовал вашу локальную переменную. Это так же быстро, как parallel.for, и теперь я уверен, что нет ошибки, связанной с потоком. Но чистые потоки медленнее, и это плохо, поскольку только чистая версия потока может быть сделана потоком ОС и потоком. - person huseyin tugrul buyukisik; 16.09.2016
comment
С другой стороны, пожалуйста, не лучше с привязкой к процессору, ОС знает это лучше всего, ваша настройка/приоритизация может привести к голоданию нескольких потоков. Также Closure является очень распространенной проблемой в многопоточных приложениях. - person Mrinal Kamboj; 16.09.2016
comment
Это закрытие странно, как будто оно получает ссылку на i вместо значения. - person huseyin tugrul buyukisik; 16.09.2016