【並行計算】經典的積分求解示例

1.前言

  積分求解是講並行計算是非常常用的一個經典例子,一方面因爲其確實是一個並行運算能夠發揮更好性能的例子,另一方面也比較簡單,並不需要很深的數學基礎,下面我們就一起來看看吧!
  比如下面這條y = x^2的曲線,我們想計算其在0-10這一段的積分值,當然我們可以採用求原函數的方法,但是有很多時候,當函數比較複雜時,原函數往往是求不出來的,這時,我們就可以採用數值逼近的方法,比如將其積分面積劃分爲很多個小梯形,分別求小梯形的面積,然後來求和。
  而當我們需要非常高的精度時,我們一般就會將梯形劃分的很窄,梯形的數量就會非常多,可能甚至成千上萬,這取決於我們希望的精度。而這,可能是一個很耗費時間的計算過程,因爲計算是串行的,而如果我們採用並行計算的方式,將有可能以指數增加的效率來完成計算。
在這裏插入圖片描述

2. Talking is Cheap, Show me the Code!

將下面的代碼保存爲calculate_parallel.py

import numpy as np
import sys
from mpi4py import MPI
from mpi4py.MPI import ANY_SOURCE

comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()

integral = np.zeros(1)
receive_buff = np.zeros(1)

# get parameters from command-line
start = float(sys.argv[1])
end = float(sys.argv[2])
piece = int(sys.argv[3])


# objective function
def f(x):
    return x**2


# integral calculate in a small range
def integrate_range(start, end, piece):
    integral = -(f(start) + f(end))/2.0
    for x in np.linspace(start, end, piece + 1):
        integral += f(x)
    integral = integral * (end - start)/piece
    return integral


# divide the integral into pieces for processes
width = (end - start) / piece
local_piece = piece/size        # pieces of a process
local_start = start + rank*local_piece*width
local_end = local_start + local_piece*width

integral[0] = integrate_range(local_start, local_end, local_piece)

# process 0 collects all results and sum
if rank == 0:
    integral_sum = integral[0]
    for i in range(1, size):
        comm.Recv(receive_buff, ANY_SOURCE)
        integral_sum += receive_buff[0]
else:
    comm.Send(integral, dest=0)

if rank == 0:
    print('With %d pieces, the estimation the integral of function y = x^2 from x = %f to x = %f is: %f.'
          % (piece, start, end, integral_sum))

3.運行效果:

在命令行輸入:

mpiexec -n 4 python calculate_parallel.py 0 10 16

輸出爲:

(base) C:\Users\44375\Documents\python_proj>mpiexec -n 4 python calculate_parallel.py 0 10 16
With 16 pieces, the estimation the integral of function y = x^2 from x = 0.000000 to x = 10.000000 is: 333.984375.

4.該如何改進?

  細心的朋友可能已經發現,上面的代碼中,實際上我們在最後求和的過程中也是串行的,這對我們提升計算速度而言是不利的,那麼有沒有其他的方案呢?
  下面給出一點思路供大家參考:
在這裏插入圖片描述
  通過上圖,大家可以看到在A中,也就是我們上面代碼中採用的思路,A需要串行的去加2.3.4的結果,而在B中,則將A的計算過程轉移了一部分到3中,使A僅需要進行兩次計算,這看起來僅僅少了一次,但是當進程數成百上千時,這個時間利用效率是呈指數增加的。

參考

1.Point-to-Point Communication with Python and mpi4py (lecture 4/5)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章