Member 11856456 Ответов: 2

Как мне использовать параллельный файл.foreach?


Я пытаюсь использовать параллель.foreach. Однако я заметил, что когда я установил счетчик, чтобы увидеть итерацию, я заметил, что количество раз, которое она повторяет, меньше, чем фактическое количество итераций.

Вот мой код:

Parallel.ForEach(dt.AsEnumerable,
       Sub(f)
           countI += 1
       End Sub)


количество dt = 154563
количество параллельных.по каждому элементу = 154510

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

Что я уже пробовал:

Попытался изменить его на параллельный, но вместо этого сделал счет 1/3, что еще хуже.

2 Ответов

Рейтинг:
19

OriginalGriff

Проблема в том, что когда вы пытаетесь распараллелить "базовый код", вы должны быть осторожны в том, что вы делаете.

x += 1
это "синтаксический сахар", на самом деле это так:
x = x + 1
Что в "машинных терминах" представляет собой короткую последовательность дискретных операций:
1) Load "x" into a register.
2) Add one to the register.
3) Load the register into "x".
Когда вы распараллеливаете эту последовательность, вы получаете несколько задач, выполняющих ее как можно ближе одновременно, и поскольку у вас нет 154 563 отдельных ядер в вашем процессоре, это означает, что все они не выполняют одни и те же шаги одновременно. Таким образом, если у вас есть одно ядро, которое только что загрузило "x" в регистр, и второе ядро, которое как раз собирается загрузить в него новое значение, то первая задача собирается перезаписать пересмотренное значение второй задачи своим новым значением - но поскольку они оба загрузили одно и то же значение, новое значение увеличивается только один раз!

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


Member 11856456

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

OriginalGriff

Если ваш код не имеет "значительного размера" - а этот код далек от этого, - то не пытайтесь распараллелить или многопоточить его, вы добавите больше накладных расходов, чем сэкономите, и если у вас нет достаточного количества ядер, чтобы было минимальное "ожидание", вы не испытаете значительного улучшения и вполне можете замедлить процесс.
Конечно, попытка использовать 154 563 отдельных потока для чего-либо обречена на провал!

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

В данном случае? Просто забудьте об этом - это не та задача, которая подходит для параллельной работы!

Рейтинг:
1

RickZeeland

Как заметил Грифф параллельно.по каждому элементу может получиться очень проблематично.
Альтернативой, которая хорошо работает (по моему опыту), является использование Задачи, который также рекомендуется корпорацией Майкрософт, см. пример здесь: Метод TaskFactory.StartNew (System.Нарезание резьбы.Задачи) | Microsoft Docs[^]