Как заставить Parallel.For последовательно ставить свои итерации в очередь - PullRequest
1 голос
/ 06 апреля 2019

У меня есть цикл.Параллельно для.И много итераций.Я хочу использовать все процессорные ядра, которые есть в среде.Но мне действительно нужно, чтобы итерации были поставлены в очередь последовательно.

Например, у меня есть 100 итераций для запуска Parallel.For и 4 доступных ядра.Похоже, что первые итерации, которые нужно запустить, это 0, 25, 50, 75.Я хочу, чтобы они были 1-го, 2-го, 3-го и 4-го, а когда один из них закончен, следующий должен быть 5-м, затем 6-м и т. Д.

Когда я связываюсь с «степеньюпараметр "параллелизм", он просто по-разному делит диапазон итераций, например, 0, 10, 20 и т. д.Единственный способ добиться последовательной очереди - это установить параллелизм равным полному числу итераций, чтобы они, по крайней мере, начинались последовательно.Но я предполагаю, что это не самый эффективный способ, так как избыточные процессы будут замедлять ранее запущенные.

Итак, как мне поставить в очередь Parallel.for, чтобы итерации запускались по порядку, но не больше, чем сразууказанное число?

Ответы [ 2 ]

0 голосов
/ 06 апреля 2019

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

Вы могли бы сначала разделить значения для работы, как:

public Dictionary<string, List<int>> CreateDictionary()
{
    var rtnValue = new Dictionary<string, List<int>>()
    {
        { "0", new List<int>() },
        { "1", new List<int>() },
        { "2", new List<int>() },
        { "3", new List<int>() }
    };


    var rando = new Random();
    for (int i = 0; i < 100; i++)
    {
        if (i < 25)
            rtnValue["0"].Add(rando.Next(-100, 100));

        if (i > 24 && i < 50)
            rtnValue["1"].Add(rando.Next(-100, 100));

        if (i > 49 && i < 75)
            rtnValue["2"].Add(rando.Next(-100, 100));

        if (i > 74 && i < 100)
            rtnValue["3"].Add(rando.Next(-100, 100));
    }

    return rtnValue;
}

Теперь у нас есть метод, который делает эту работу.

public static string processList(IList<int> param)
{
    return string.Join(", ", param);
}

И, наконец, выполняйте работу параллельно, как:

public void runInParallel()
{
    var DataToOperateOn = CreateDictionary();
    Parallel.For(0, DataToOperateOn.Count, i =>
    {
        processList(DataToOperateOn[i.ToString()]);
    });
}

В качестве альтернативы, вы можете выполнить то же самое с Parallel.Invoke, например:

public void runInParallel()
{
    var DataToOperateOn = CreateDictionary();
    Parallel.Invoke(
    () => { processList(DataToOperateOn["0"]); },
    () => { processList(DataToOperateOn["1"]); },
    () => { processList(DataToOperateOn["2"]); },
    () => { processList(DataToOperateOn["3"]); });
}
0 голосов
/ 06 апреля 2019

Если вам нужен специальный заказ, вы можете использовать Queue, чтобы обеспечить первоисточник:

public static void DoSomething(int x)
{
    Console.WriteLine("Starting " + x);
    Thread.Sleep((x%10) * 1000);
}

public static void Main(string[] args)
{

    Queue<int> myList = new Queue<int>();
    for (int i = 0; i < 100; i++)
        myList.Enqueue(i);

    // This would be random if we'd use a List
    //Parallel.ForEach(myList, new ParallelOptions() { MaxDegreeOfParallelism = 4 }, x => DoSomething(x));

    // This will get the right order. But 2 can still be faster than 1 if 2's thread is quicker. But generally you got your order.
    Parallel.For(
        0,  // We count from 0
        myList.Count,  // to max entries..
        new ParallelOptions() { MaxDegreeOfParallelism = 4 },  // don't forget this one ;)
        (x) => { lock (myList) { int y = myList.Dequeue(); Console.WriteLine(y); DoSomething(y); } });
}

Посмотрите на вывод. Если два потока начинаются параллельно, вы не знаете порядок. Но, как правило, следующий будет удален.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...