Изменение инкрементного значения цикла C# Parallel.For

Я хочу преобразовать цикл for, который увеличивает итератор на 2 при каждом проходе, в цикл Parallel For с использованием TPL. Данные никоим образом не зависят от порядка или ограничений, но я хочу обрабатывать данные только в каждом другом элементе моего исходного массива (который является _Datalist в приведенном ниже коде), следовательно, необходимо увеличить на 2.

Мой цикл:

for (int i = 1; i < _DataList.Length - 1; i += 2)
{
     // Do work for _DataList[i]
}

Можно ли сказать параллельному циклу, что я хочу увеличить i на два вместо одного?

Вот параллельный цикл, но, очевидно, i увеличивается только на 1 на каждой итерации:

        Task.Factory.StartNew(() =>
            Parallel.For(1, _DataList.Length, i =>
            {
                // do work for _DataList[i]                    
            })
        );

Я мог бы сказать телу внутреннего цикла игнорировать нечетные значения i, но это кажется немного беспорядочным - есть ли способ сделать это каким-то образом при инициализации цикла?


person Gareth    schedule 20.10.2010    source источник
comment
Не просто игнорируйте нечетные значения; это создает в два раза больше задач, чем вам нужно, что добавляет много ненужных накладных расходов.   -  person Gabe    schedule 20.10.2010
comment
Да, я понимаю, что вы имеете в виду   -  person Gareth    schedule 20.10.2010


Ответы (4)


Как насчет:

var odds = Enumerable.Range(1, _DataList.Length).Where(i => i % 2 != 0);

Task.Factory.StartNew(() =>
    Parallel.ForEach(odds, i =>
    {
        // do work for _DataList[i]                    
    })
);
person Darin Dimitrov    schedule 20.10.2010

Вы можете вдвое уменьшить количество шагов и удвоить индексы:

Parallel.For(0, _DataList.Length / 2, i =>
{
    // do work for _DataList[2 * i]                    
});
person dtb    schedule 20.10.2010

ответ Дарина Димитрова показывает простой способ добиться этого.

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

person Reed Copsey    schedule 20.10.2010
comment
Отмечено для дальнейшего использования, но в случае, к которому я применяю этот цикл, порядок обработки элементов действительно не имеет значения. - person Gareth; 20.10.2010
comment
@Gareth: я просто упоминаю об этом, поскольку на самом деле было обсуждение (которое я не могу найти в банкомате) Стивена Тоуба, в котором конкретно упоминалось, почему Parallel.For не добавил эту функцию - и в основном это сводилось к тому, что это обычно проблематично для параллельного обработки, но вы всегда можете обойти это с помощью разделителя или parallel.foreach. - person Reed Copsey; 20.10.2010
comment
Я считаю, что этот вариант использования возникает очень естественно при работе с SIMD-инструкциями в .NET, поскольку они работают, создавая Vector<'T> для каждого n-го элемента массива, где N — ширина вектора. Вы не можете использовать Parallel.For для небольших векторизованных функций, потому что приемы перечисления или умножения сводят на нет преимущества производительности. - person jackmott; 26.07.2016

Просто пропустите четные значения.

Task.Factory.StartNew(() =>
                Parallel.For(1, _DataList.Length, i =>
                {
                    if(i % 2 == 0)
                    {
                        // do work for   
                    }   
                })
            );
person Junior    schedule 19.09.2015
comment
Можете ли вы объяснить больше о своем ответе? Обычно считается хорошей практикой давать некоторую информацию или пояснения к ответам, которые вы даете. Это может помочь будущим пользователям или OP больше. - person Bono; 19.09.2015
comment
Это не очень хорошая идея, поскольку вы создаете накладные расходы, и я пытался избежать этого - см. Первый комментарий к вопросу. К счастью, 5 лет назад были хорошие решения :) - person Gareth; 21.09.2015