Parallel.ForEach и Parallel.For, похоже, ставят элементы в очередь в отдельных потоках. ⇐ C#
Parallel.ForEach и Parallel.For, похоже, ставят элементы в очередь в отдельных потоках.
Рассмотрим следующий код:
var items = Enumerable.Range(0, 200); Parallel.ForEach(элементы, элемент => Console.WriteLine(элемент)); Элементы в консоли располагаются в случайном порядке. Я не уверен, как перечисляет Parallel.ForEach, но похоже, что он заранее разделяет настройку на очереди, а затем назначает очередь каждому потоку. Я хочу, чтобы все шло по порядку. Мне не нужно завершение по порядку, я хочу, чтобы элементы, взятые из перечисляемого, были в порядке. Если один поток быстрее, это нормально. Но 8 потоков должны работать всегда и получать элемент только тогда, когда это необходимо.
А теперь попробуем следующее:
var items = Enumerable.Range(0, 200).ToArray(); Parallel.For(0, items.Length, item => Console.WriteLine(item)); Тот же результат, полная случайность. Хорошо, а как насчет этого:
var locker = новый объект(); var items = Enumerable.Range(0, 200).ToArray(); индекс вар = 0; Parallel.For(0, items.Length, _ => { // Выбрасываем индекс, который дал нам параллельный цикл, захватываем // фактический следующий элемент для обработки потокобезопасным способом интервал indexToPull; замок (шкафчик) { indexToPull = индекс++; } Console.WriteLine(пункты[indexToPull]); }); Опять же, случайно. В моем тесте первыми были 0 и 1, но номер 2 находился более чем в середине списка. Теперь я понимаю, что мой пример не идеален, потому что Console.WriteLine на самом деле является результатом завершения параллельного потока. Я просто пытаюсь проиллюстрировать свою точку зрения.
Почему это важно? Для меня обработка элементов занимает от 0,001 секунды до 2+ часов. Я сталкиваюсь с ситуацией, когда я запускаю 8 потоков, используя ParallelOptions, но к концу перечисления количество активных потоков падает и падает. В конце концов, остается 1 поток, но остаются 1-2 необработанных элемента. Таким образом, загрузка процессора снижается и снижается. В самом конце элемент n-2 обрабатывается в единственном оставшемся потоке, но у меня еще есть n-1 и n.
Чего я хочу: я хочу разместить элементы в более или менее порядке сложности и запускать их параллельно. Я хочу, чтобы каждый поток захватывал по одному элементу за раз и всегда получал следующий в списке. Опять же, когда этот поток завершится, не имеет значения. Это должно гарантировать, что 8 потоков все еще выполняются при перечислении последнего элемента. На этом этапе потоки завершатся, и количество запущенных потоков упадет, но элементов не останется, поэтому время, которое я трачу на выполнение менее 8 потоков, сведено к минимуму.
Рассмотрим следующий код:
var items = Enumerable.Range(0, 200); Parallel.ForEach(элементы, элемент => Console.WriteLine(элемент)); Элементы в консоли располагаются в случайном порядке. Я не уверен, как перечисляет Parallel.ForEach, но похоже, что он заранее разделяет настройку на очереди, а затем назначает очередь каждому потоку. Я хочу, чтобы все шло по порядку. Мне не нужно завершение по порядку, я хочу, чтобы элементы, взятые из перечисляемого, были в порядке. Если один поток быстрее, это нормально. Но 8 потоков должны работать всегда и получать элемент только тогда, когда это необходимо.
А теперь попробуем следующее:
var items = Enumerable.Range(0, 200).ToArray(); Parallel.For(0, items.Length, item => Console.WriteLine(item)); Тот же результат, полная случайность. Хорошо, а как насчет этого:
var locker = новый объект(); var items = Enumerable.Range(0, 200).ToArray(); индекс вар = 0; Parallel.For(0, items.Length, _ => { // Выбрасываем индекс, который дал нам параллельный цикл, захватываем // фактический следующий элемент для обработки потокобезопасным способом интервал indexToPull; замок (шкафчик) { indexToPull = индекс++; } Console.WriteLine(пункты[indexToPull]); }); Опять же, случайно. В моем тесте первыми были 0 и 1, но номер 2 находился более чем в середине списка. Теперь я понимаю, что мой пример не идеален, потому что Console.WriteLine на самом деле является результатом завершения параллельного потока. Я просто пытаюсь проиллюстрировать свою точку зрения.
Почему это важно? Для меня обработка элементов занимает от 0,001 секунды до 2+ часов. Я сталкиваюсь с ситуацией, когда я запускаю 8 потоков, используя ParallelOptions, но к концу перечисления количество активных потоков падает и падает. В конце концов, остается 1 поток, но остаются 1-2 необработанных элемента. Таким образом, загрузка процессора снижается и снижается. В самом конце элемент n-2 обрабатывается в единственном оставшемся потоке, но у меня еще есть n-1 и n.
Чего я хочу: я хочу разместить элементы в более или менее порядке сложности и запускать их параллельно. Я хочу, чтобы каждый поток захватывал по одному элементу за раз и всегда получал следующий в списке. Опять же, когда этот поток завершится, не имеет значения. Это должно гарантировать, что 8 потоков все еще выполняются при перечислении последнего элемента. На этом этапе потоки завершатся, и количество запущенных потоков упадет, но элементов не останется, поэтому время, которое я трачу на выполнение менее 8 потоков, сведено к минимуму.
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Как текущая очередь, очередь отправки и целевая очередь взаимодействуют друг с другом в GCD?
Anonymous » » в форуме IOS - 0 Ответы
- 102 Просмотры
-
Последнее сообщение Anonymous
-