2017-02-20 32 views
4

Я начал возиться с параллельным программированием и Cython/OpenMP, и у меня есть простая программа, которая суммирует по массиву с помощью Прейндж:Локальные параллельные вычисления для операции суммирования

import numpy as np 
from cython.parallel import prange 
from cython import boundscheck, wraparound 

@boundscheck(False) 
@wraparound(False) 

def parallel_summation(double[:] vec): 

    cdef int n = vec.shape[0] 
    cdef double total 
    cdef int i 

    for i in prange(n, nogil=True): 
     total += vec[i] 

    return total 

Это похоже на работу ОК с файлом setup.py. Тем не менее, мне было интересно, можно ли настроить эту функцию и немного больше контролировать, что делают процессоры.

Предположим, у меня есть 4 процессора: я хочу разбить вектор, который будет суммирован на 4 части, а затем каждый процессор локально добавит элементы внутри. Затем, в конце, я могу комбинировать результаты от каждого процессора, чтобы получить общую сумму. Из документации cython я не смог понять, возможно ли что-то подобное или нет (документация немного разрежена).

Я был бы признателен, если бы кто-нибудь мог объяснить, если/как что-то подобное делается с помощью cython/openmp, или, может быть, поможет найти подходящие примеры (его было неожиданно трудно найти в Интернете).

ответ

1

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

Это именно то, что здесь уже происходит. Cython выдает из вашей операции inplace, что вы хотите сделать сокращение. OpenMP реализует параллельный цикл с частными (нулевыми инициализированными) копиями переменной total и добавляет их все в total в конце цикла.

В сгенерированном C, это выглядит следующим образом:

#pragma omp parallel 
{ 
    #pragma omp for firstprivate(__pyx_v_i) lastprivate(__pyx_v_i) reduction(+:__pyx_v_total) 
    for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_3; __pyx_t_2++){ 
     { 
      __pyx_v_i = (int)(0 + 1 * __pyx_t_2); 
      __pyx_t_4 = __pyx_v_i; 
      __pyx_v_total = (__pyx_v_total + (*((double *) (/* dim=0 */ (__pyx_v_vec.data + __pyx_t_4 * __pyx_v_vec.strides[0]))))); 
     } 
    } 
} 

Вам просто нужно включить OpenMP as described here.

Единственное, что вы должны изменить в своем коде, это инициализировать total = 0, иначе это просто унифицированная переменная C, которая может содержать мусор.

 Смежные вопросы

  • Нет связанных вопросов^_^