国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

高性能計算的矩陣乘法優(yōu)化 - Python + OpenMP實現

這篇具有很好參考價值的文章主要介紹了高性能計算的矩陣乘法優(yōu)化 - Python + OpenMP實現。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

關于上一節(jié)讀者某些疑問:為什么你用進程并行不是線程并行?

回答:由于Python解釋器有GIL(全局解釋器鎖),在單進程的解釋器上有線程安全鎖,也就是說每次只能一個線程訪問解釋器,因此Python在語法上的多線程(multithreads)實現是不會提高并行性能的。
這一點和C\C++上的編譯級別的并行是不一樣的,Python能做到的極限是多進程的解釋級別并行。(上一節(jié)我實現的是多進程并行,和老師課上MPI的多線程是不一樣的?。。?/p>

0. 引言

OpenMP是一種C/C++的并行編譯標準方案,嚴謹地說,在Python上使用OpenMP是不可能的,因為本來Python是一門解釋語言。

但如果在某個解釋流程實現并行優(yōu)化是可行的,也有一些方案。

如下所示C和Python在實現OpenMP接口的可能性對比:

openmp python,python,矩陣,numpy

如上兩個地方可以實現mp的優(yōu)化,分別為:在可交互級別的轉化,在解釋階段級別的轉化。

  • 在可交互級別的轉化:一些第三方包pymp,pyopenmp,使用fork脫離GIL

  • 在解釋階段級別的轉化:使用Cython直接編寫C code,這樣寫出來的module在解釋的時候會被解釋器做并行優(yōu)化。

早期Cython是不支持openmp的,但如今已支持了,我們可以非常方便地使用Cython語法編寫支持openmp并行優(yōu)化編譯的代碼。

因此,本文通過第一種實現方式對上一節(jié)的矩陣乘法優(yōu)化做探究。

生成示例矩陣向量、計算代碼都使用上一節(jié)內容。

鏈接:高性能計算的矩陣乘法優(yōu)化 - Python +MPI的實現

import numpy as np
from functools import wraps
import time

def generate_example_matrix(h, w):
    _vs = (-1, 2, -1)
    _i = -1  # shift bits
    example_data = np.zeros([h, w], dtype=np.int32)
    for i in range(3):
        example_data_eye_mask = np.eye(h, w, _i + i,
                                       dtype=np.bool_)  # build eyes and shift
        example_data[example_data_eye_mask == True] = _vs[i]
    return example_data


def generate_example_vector(w):
    _rest_dict = {
        1: [1],
        2: [1, 2],
        3: [1, 2, 3],
    }
    rest_bits = int(w % 3)
    repeat_times = int(w // 3)
    example_vector = np.repeat([[1, 2, 3]], repeat_times, axis=0).ravel()

    if rest_bits > 0:
        tail_vec = _rest_dict[rest_bits]
        tail_vec = np.array(tail_vec, dtype=np.int32)
        example_vector = np.concatenate([example_vector, tail_vec], axis=0)
    return example_vector
    

計算的naive code如下:

def naive_method(example_matrix, example_vector):
    result = []
    h, w = example_matrix.shape
    for hi in range(h):
        colv = example_matrix[hi, :]
        temp = 0
        for wi in range(w):
            temp += colv[wi] * example_vector[wi]
        result.append(temp)
    return np.array(result)

單進程單線程執(zhí)行:

from utils import generate_example_matrix, generate_example_vector
import pymp
import time
import numpy as np

def naive_method(example_matrix, example_vector):
    result = []
    h, w = example_matrix.shape
    for hi in range(h):
        colv = example_matrix[hi, :]
        temp = 0
        for wi in range(w):
            temp += colv[wi] * example_vector[wi]
        result.append(temp)
    return np.array(result)

def main():
    start_time = time.perf_counter()
    h = 5000
    w = 5000
    print('--- Current matrix scale is: {} x {} ---'.format(h,w))
    example_matrix = generate_example_matrix(h, w)
    example_vector = generate_example_vector(w)
    result = naive_method(example_matrix, example_vector)
    end_time = time.perf_counter()
    print('single method used time is: {:.2f}s\n'.format(end_time - start_time))

if __name__ == '__main__':
    main()

1. 在可交互級別的轉化

一個實現上是openmp stye的第三方庫:pymp-pypi.

注意,該方法不能在Windows上實現,因為他使用fork來繞過GIL的。

操作系統的fork方法可以繞過GIL(全局解釋器鎖),從而實現多線程,這比Python原生的multithreads會更加并行高效。

題外話:當然還有一堆其他類似的第三方庫,看看別人的教程也可以輕松實現。我這里只挑一個

安裝pip install pymp-pypi

基本用法

優(yōu)化前:

ex_array = np.zeros((100,), dtype='uint8')

for index in range(0, 100):
    ex_array[index] = 1
    print('Yay! {} done!'.format(index))
    

優(yōu)化后:

import pymp

ex_array = pymp.shared.array((100,), dtype='uint8')

with pymp.Parallel(4) as p:
    for index in p.range(0, 100):
        ex_array[index] = 1
        # The parallel print function takes care of asynchronous output.
        p.print('Yay! {} done!'.format(index))

1.1 OpenMP Style的改寫

將該用法改寫到我們原來的運算代碼中:

優(yōu)化后:

from utils import generate_example_matrix, generate_example_vector
import pymp
import time
import numpy as np

def naive_multi_method(example_matrix, example_vector, threads):
    # result = pymp.shared.list()
    result = []
    h, w = example_matrix.shape
    with pymp.Parallel(num_threads = threads) as p:
        for hi in p.range(0, h):
            colv = example_matrix[hi, :]
            temp = 0
            for wi in p.range(0, w):
                temp += colv[wi] * example_vector[wi]
            result.append(temp)

def main():
    start_time = time.perf_counter()
    h = 50000
    w = 50000
    threads_num = 200 # 250, 200, 100, 50, 25, 16, 8
    print('--- Current matrix scale is: {} x {} ---'.format(h,w))
    print('<- Threads num is: {} ->'.format(threads_num))
    example_matrix = generate_example_matrix(h, w)
    example_vector = generate_example_vector(w)
    result = naive_multi_method(example_matrix, example_vector, threads = threads_num)
    end_time = time.perf_counter()
    print('multi-thread method used time is: {:.2f}s\n'.format(end_time - start_time))
    return np.array(result)
if __name__ == '__main__':
    main()

2.2 實驗對比:

相較于上一次的實驗,我換了一臺設備,CPU配置如下:

11th Gen Intel? Core? i5-11600K @ 3.90GHz,此外,我超頻到了4.5GHz

這一次直接測試50000規(guī)模的運算。

單線程運行:

--- Current matrix scale is: 50000 x 50000 ---
single method used time is: 475.64s

Baseline:475秒

多線程優(yōu)化之后

8線程

--- Current matrix scale is: 50000 x 50000 ---
<- Threads num is: 8 ->
multi-thread method used time is: 19.46s

T8:19秒

16線程:13秒

--- Current matrix scale is: 50000 x 50000 ---
<- Threads num is: 16 ->
multi-thread method used time is: 13.28s

T16:13秒

25線程

--- Current matrix scale is: 50000 x 50000 ---
<- Threads num is: 25 ->
multi-thread method used time is: 11.12s

T25:11秒

50線程

--- Current matrix scale is: 50000 x 50000 ---
<- Threads num is: 50 ->
multi-thread method used time is: 9.18s

T50:9.18秒

100線程

--- Current matrix scale is: 50000 x 50000 ---
<- Threads num is: 100 ->
multi-thread method used time is: 8.27s

T100:8.27秒

200線程

--- Current matrix scale is: 50000 x 50000 ---
<- Threads num is: 200 ->
multi-thread method used time is: 8.23s

T200:8.23秒

250線程

--- Current matrix scale is: 50000 x 50000 ---
<- Threads num is: 250 ->
multi-thread method used time is: 8.47s

T250:8.47秒

從以上數據可見,線程瓶頸數在200到250之間,接下來可以使用二分查找測試出最佳的線程數文章來源地址http://www.zghlxwxcb.cn/news/detail-553868.html

到了這里,關于高性能計算的矩陣乘法優(yōu)化 - Python + OpenMP實現的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 高性能MySQL實戰(zhàn)(三):性能優(yōu)化

    大家好,我是 方圓 。這篇主要介紹對慢 SQL 優(yōu)化的一些手段,而在講解具體的優(yōu)化措施之前,我想先對 EXPLAIN 進行介紹,它是我們在分析查詢時必要的操作,理解了它輸出結果的內容更有利于我們優(yōu)化 SQL。為了方便大家的閱讀,在下文中規(guī)定類似 key1 的表示二級索引,key_

    2024年02月11日
    瀏覽(97)
  • C++高性能優(yōu)化編程之如何測量性能(一)

    C++高性能優(yōu)化編程系列 深入理解設計原則系列 深入理解設計模式系列 高級C++并發(fā)線程編程 不好的編程習慣,不重視程序性能測量分析讓代碼跑的更快,會導致 浪費大量的CPU周期、程序響應時間慢以及卡頓,用戶滿意度下降,進而浪費大量的時間返工去重構本應該一開始就

    2024年02月06日
    瀏覽(26)
  • MySQL高性能優(yōu)化規(guī)范建議

    數據庫命令規(guī)范 數據庫基本設計規(guī)范 1. 所有表必須使用 Innodb 存儲引擎 2. 數據庫和表的字符集統一使用 UTF8 3. 所有表和字段都需要添加注釋 4. 盡量控制單表數據量的大小,建議控制在 500 萬以內。 5. 謹慎使用 MySQL 分區(qū)表 6.盡量做到冷熱數據分離,減小表的寬度 7. 禁止在表中建

    2024年02月12日
    瀏覽(24)
  • 如何評估和優(yōu)化系統的高性能

    如何評估和優(yōu)化系統的高性能

    系統的關鍵性能指標:吞吐量,延遲和TP。 吞吐量:反應單位時間內處理請求的能力。 延遲:從客戶端發(fā)送請求到接收響應的時間。 延遲和吞吐量的曲線如下圖所示: 總體來看,隨著壓力增大,系統單位時間內被訪問的次數增加。結合延遲和吞吐量觀察的話,系統優(yōu)化性能

    2024年02月22日
    瀏覽(23)
  • Kafka高性能集群部署與優(yōu)化

    Kafka 是由Apache Software Foundation開發(fā)的一個分布式流處理平臺,源代碼以Scala編寫。Kafka最初是由LinkedIn公司開發(fā)的,于2011年成為Apache的頂級項目之一。它是一種高吞吐量、可擴展的發(fā)布訂閱消息系統,具有以下特點: 高吞吐量:Kafka每秒可以處理數百萬條消息。 持久化:數據存

    2024年02月13日
    瀏覽(36)
  • 數據庫——MySQL高性能優(yōu)化規(guī)范

    所有數據庫對象名稱必須使用小寫字母并用下劃線分割 所有數據庫對象名稱禁止使用 MySQL 保留(如果表名中包含查詢時,需要將其用單引號括起來) 數據庫對象的命名要能做到見名識意,并且最后不要超過 32 個字符 臨時庫表必須以 tmp_為前綴并以日期為后綴,

    2024年02月11日
    瀏覽(50)
  • 讀高性能MySQL(第4版)筆記10_查詢性能優(yōu)化(上)

    讀高性能MySQL(第4版)筆記10_查詢性能優(yōu)化(上)

    4.11.1.1.?在存儲引擎層完成的 4.11.2.1.?直接從索引中過濾不需要的記錄并返回命中的結 4.11.2.2.?在MySQL服務器層完成的,但無須再回表查詢記錄 4.11.3.1.?在MySQL服務器層完成 4.11.3.2.?需要先從數據表中讀出記錄然后過濾 4.13.2.1.?使用單獨的匯總表 5.5.1.1.?定期清除大量數據時,

    2024年02月08日
    瀏覽(33)
  • 讀高性能MySQL(第4版)筆記11_查詢性能優(yōu)化(中)
  • 讀高性能MySQL(第4版)筆記12_查詢性能優(yōu)化(下)

    讀高性能MySQL(第4版)筆記12_查詢性能優(yōu)化(下)

    2.3.1.1.?讀取行指針和需要排序的字段,對其進行排序,然后再根據排序結果讀取所需要的數據行 2.3.1.2.?即需要從數據表中讀取兩次數據,第二次讀取數據的時候,因為是讀取排序列進行排序后的所有記錄,這會產生大量的隨機I/O,所以兩次傳輸排序的成本非常高 2.3.2.1.?先

    2024年02月08日
    瀏覽(22)
  • 企業(yè)如何構建高性能計算云?

    企業(yè)如何構建高性能計算云?

    HPC是推動科學和工程應用發(fā)展的重要組成部分。除了將處理器向Exascale邁進之外,工作負載的性質也在不斷變化—從傳統的模擬和建模到混合工作負載,包括企業(yè)內部和云應用,還需要整合、吸收和分析來自無數物聯網傳感器的數據。同時,隨著HPC基礎設施上的人工智能工作

    2024年02月03日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包