Параллелизм и массивы? количество вычислений во время выполнения определенной подгруппе элементов во время выполнения - PullRequest
0 голосов
/ 21 февраля 2020

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

Значения аргументов, количество позиций и инструкции списка (добавьте это к позициям, идущим от X к Y, вычтите это к позициям от P к Q)

Решение, которое у меня было было:

  1. Заполните List<long> Output нулями в соответствии с длиной, полученной аргументами;
  2. long output[] = Output.ToArray();
  3. Instructions.ForEach(op => DoOperations(op)); (где op имел, с какой позиции до какой позиции я должен делать, какие вычисления с какими числами)

  4. A for выполняет вычисления для каждой из отфильтрованных позиций output[].

    Теперь дело в том, что ограничение по времени делает все это нежизнеспособным, поэтому мне нужен асинхронный вызов / когда все в действии, но также мне нужно, чтобы все они разделяли output, чтобы они все могли работать с ним, не проблема, какая операция решается первой. И в Asyn нет параметров ref или out c.

Какой самый эффективный и чистый способ сделать это?

@ Изменить на показать, как работает параллель:

static long arrayManipulation(int n, int[][] queries) 
    {
        long[] operate;
        for(long i=0;i<n;i++) 
            lOperate.Add(0);

        operate = lOperate.ToArray();
        List<int[]> lQueries = new List<int[]>(queries.ToList<int[]>());    
        Parallel.ForEach(lQueries, op=>
        {
            Parallel.For(op[0]-1, op[1], i=> (operate[i]+= (long)op[2]));
        });
        return operate.Max();
    }

1 Ответ

1 голос
/ 27 февраля 2020

Без какой-либо информации о масштабе проблемы трудно попытаться решить проблему, но некоторые быстрые тесты показывают, что параллельное выполнение операций добавления не стоит. Существуют некоторые издержки при настройке Parallel.For и вызове лямбда-метода, и это затрачивает время только на использование базовых c for l oop и сложений.

OTOH с использованием вне Parallel.For для выполнения операций целесообразно (по крайней мере, на многоядерных процессорах) работать на моем компьютере в четыре раза быстрее. Развертывание внутренних циклов несколько раз для пакетных операций, кажется, не дает преимущества в 2х и 4х. Использование стандартного оператора LINQ Max составляет всего 0,2% от общего времени, поэтому попытка отследить максимальное значение во время операций не представляется целесообразной.

Поэтому мое предложение:

Parallel.For(0, operations.Length, j1 => {
    var op = operations[j1];
    for (int j2 = op[0]; j2 < op[1]; ++j2)
        operate[j2] += op[2];
});
var ans = operate.Max();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...