Как функция PLINQ AsParallel передает данные в функцию при вызове в той же области - PullRequest
0 голосов
/ 17 июня 2019

Используя IronPython, я вызываю некоторую функцию параллельно, которая находится внутри той же функции, в которой находятся распараллеленные данные, чтобы сохранить их в той же области видимости.

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

В случае PLINQ, как код выполняется параллельно? I.E.:

Есть ли еще один экземпляр ironpython, который запускается и все снова импортируется? Например, import myHugeLibrary будет запускаться каждый раз, когда из файла создается новый экземпляр python.

CalcParallel() принимает некоторые массивы данных и словарь. В этой области находится функция computation(), которая должна выполняться параллельно, и она вызывает другую функцию checkVals() в основном скрипте. Поскольку computation() находится в той же области, в которой вызывается AsParallel(), мне не нужно явно передавать ему данные, которые будут использоваться. Однако означает ли это, что данные копируются в каждый процесс / поток или хранятся в качестве ссылки, и это нормально, когда они только читаются (не записываются)? Если он копируется, копируется ли он каждый раз при вычислении элемента, то есть, если в списке 100 элементов и 10 потоков, будет ли он копировать данные 10 раз, поскольку он помещает 100 элементов в 10 блоков, или копирует 100 раз

Аналогично, пример данных C_dict модифицируется после вычисления некоторого количества данных и перед запуском следующего раунда данных (на основе результатов он добавляет больше вещей). Затем эти измененные данные копируются снова при запуске параллельного процесса?

Ниже приведен пример структуры кода, который мне интересен. Дело не в самом коде, но я написал это, чтобы проиллюстрировать вопрос, даже если это не совсем правильно.

# get LINQ dependencies
import clr
clr.AddReference("System.Core")
import System
clr.ImportExtensions(System.Linq)
from System.Threading.Tasks import *

#import some huge library that takes time
import myHugeLibrary

max_val = 4 #some global value used within the thread

def checkVals(itemToCheck,A_vals,B_vals):
    #check against some global value
    if itemToCheck < max_val:
        return 0
    #do something else with A_vals

def CalcParallel(todo_list,A_vals,B_vals,C_dict): 
    """
    take in some data that is used in the functions that will
    run in parallel.
    """

    total_list = []

    #make a function that will be run in parallel
    def computation(itemToCheck):
        checkedItems = checkVals(itemToCheck,A_vals,B_vals)
        results = []
        for item in checkedItems: 
                results.append(item)
        return results

    #in a loop keep sending something out for calculation in parallel until
    # all the combinations are done
    while len(todo_list) != 0:
            #use AsParallel on a list of items
            results = todo_list.AsParallel().SelectMany(
                            lambda itemToCheck: 
                                computation(itemToCheck) ).ToList()

            todo_list = []
            for item in results:
                if item not in total_list: 
                    total_list.append(item)

                    #do some modification to the dictionary that was passed in
                    C_dict[item] = None

    return total_list


def main():
    todo_list = [3,3,2,4,5,4,1,3,4,5,1]
    A_vals = [0,1,2,3,4,5,6]
    B_vals = [-1,-3,-5,-7,-9]
    C_dict = {0:-3,4:-7}

    newVals = CalcParallel(todo_list,A_vals,B_vals,C_dict)

    print(newVals)

main()

1 Ответ

1 голос
/ 19 июня 2019

PLINQ действует несколько похоже на TPL.Работа разбита на части / запланирована / отправлена ​​с использованием относительно легких конструкций.Никаких дополнительных процессов IronPython нет, и, скорее всего, работа запланирована в пуле рабочих потоков (с помощью задач), что означает, что накладные расходы должны быть довольно малыми.

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

Чтобы обеспечить эффективное выполнение, блоки работы должны быть разумного размера, чтобы избежать непредвиденных накладных расходов.

...