Функция многопроцессорного пула появляется быстрее, но время Unix говорит об обратном - PullRequest
0 голосов
/ 20 марта 2019

Я хотел ускорить свою функцию в классе с именем translate_dirac_delta. Я использовал многопроцессорность для заполнения массива разделяемым массивом в соответствии с этой демонстрацией https://jonasteuwen.github.io/numpy/python/multiprocessing/2017/01/07/multiprocessing-numpy-array.html. Я рассчитал t1-t0 для вызова функции, которая оказалась вдвое быстрее, чем 4 ядра. Однако, когда я использовал функцию времени Unix, она на самом деле в два раза медленнее. Я знаю, что будет несколько подслушано использование многопроцессорных, но я не ожидал, что это будет так много. Модуль, который я использую ssht, является оберткой для Cython, которая не является общедоступной, поэтому не может сделать полный MWE.

Функция синхронизации / вызова

import pyssht as ssht # cython wrapper

def translation(self, flm, pix_i, pix_j):
    t0 = time.time()
    glm = self.translate_dirac_delta(flm, pix_i, pix_j)
    t1 = time.time()
    print(t1 - t0)

    return glm

def calc_pixel_value(self, ind, pix_i, pix_j):
    # create Ylm corresponding to index
    ylm_harmonic = np.zeros((self.L * self.L), dtype=complex)
    ylm_harmonic[ind] = 1

    # convert Ylm from pixel to harmonic space
    ylm_pixel = ssht.inverse(ylm_harmonic, self.L, Method=self.method)

    # get value at pixel (i, j)
    ylm_omega = np.conj(ylm_pixel[pix_i, pix_j])

    return ylm_omega

Оригинал

  • t1 - t0 = 16,4 с
  • реальный 0m16,8
  • пользователь 0m22.2s
  • sys 0m1.5s

    def translate_dirac_delta(self, flm, pix_i, pix_j):
        flm_trans = self.complex_translation(flm)
    
        return flm_trans
    
    def complex_translation(self, flm):
        for ell in range(self.L):
            for m in range(-ell, ell + 1):
                ind = ssht.elm2ind(ell, m)
                conj_pixel_val = self.calc_pixel_value(ind)
                flm[ind] = conj_pixel_val
        return flm
    

Параллельное

  • t1 - t0 = 8,0 с
  • реальный 0m19,5
  • пользователь 0m31.9s
  • sys 0m1.5s

    def translate_dirac_delta(self, flm, pix_i, pix_j):
        # create arrays to store final and intermediate steps
        result_r = np.ctypeslib.as_ctypes(np.zeros(flm.shape))
        result_i = np.ctypeslib.as_ctypes(np.zeros(flm.shape))
        shared_array_r = multiprocessing.sharedctypes.RawArray(
                         result_r._type_, result_r)
        shared_array_i = multiprocessing.sharedctypes.RawArray(
                         result_i._type_, result_i)
    
        # ensure function declared before multiprocessing pool
        global complex_func
    
        def complex_func(ell):
            # store real and imag parts separately
            tmp_r = np.ctypeslib.as_array(shared_array_r)
            tmp_i = np.ctypeslib.as_array(shared_array_i)
            # perform translation
            for m in range(-ell, ell + 1):
                ind = ssht.elm2ind(ell, m)
                conj_pixel_val = self.calc_pixel_value(
                    ind, pix_i, pix_j)
                tmp_r[ind] = conj_pixel_val.real
                tmp_i[ind] = conj_pixel_val.imag
    
        # initialise pool and apply function
        with multiprocessing.Pool() as p:
            p.map(complex_func, range(self.L))
    
        # retrieve real and imag components
        result_r = np.ctypeslib.as_array(shared_array_r)
        result_i = np.ctypeslib.as_array(shared_array_i)
    
        # combine results
        return result_r + 1j * result_i
    

1 Ответ

2 голосов
/ 20 марта 2019

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

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

https://en.wikipedia.org/wiki/Time_%28Unix%29

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