高性能计算的矩阵乘法优化 - Python + OpenMP实现

这篇具有很好参考价值的文章主要介绍了高性能计算的矩阵乘法优化 - Python + OpenMP实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

关于上一节读者某些疑问:为什么你用进程并行不是线程并行?

回答:由于Python解释器有GIL(全局解释器锁),在单进程的解释器上有线程安全锁,也就是说每次只能一个线程访问解释器,因此Python在语法上的多线程(multithreads)实现是不会提高并行性能的。
这一点和C\C++上的编译级别的并行是不一样的,Python能做到的极限是多进程的解释级别并行。(上一节我实现的是多进程并行,和老师课上MPI的多线程是不一样的!!)

0. 引言

OpenMP是一种C/C++的并行编译标准方案,严谨地说,在Python上使用OpenMP是不可能的,因为本来Python是一门解释语言。

但如果在某个解释流程实现并行优化是可行的,也有一些方案。

如下所示C和Python在实现OpenMP接口的可能性对比:

openmp python,python,矩阵,numpy

如上两个地方可以实现mp的优化,分别为:在可交互级别的转化在解释阶段级别的转化

  • 在可交互级别的转化:一些第三方包pymp,pyopenmp,使用fork脱离GIL

  • 在解释阶段级别的转化:使用Cython直接编写C code,这样写出来的module在解释的时候会被解释器做并行优化。

早期Cython是不支持openmp的,但如今已支持了,我们可以非常方便地使用Cython语法编写支持openmp并行优化编译的代码。

因此,本文通过第一种实现方式对上一节的矩阵乘法优化做探究。

生成示例矩阵向量、计算代码都使用上一节内容。

链接:高性能计算的矩阵乘法优化 - 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)

单进程单线程执行:

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

基本用法

优化前:

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

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

优化后:

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的改写

将该用法改写到我们原来的运算代码中:

优化后:

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规模的运算。

单线程运行:

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

Baseline:475秒

多线程优化之后

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之间,接下来可以使用二分查找测试出最佳的线程数文章来源地址https://www.toymoban.com/news/detail-553868.html

到了这里,关于高性能计算的矩阵乘法优化 - Python + OpenMP实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 高性能MySQL实战(三):性能优化

    大家好,我是 方圆 。这篇主要介绍对慢 SQL 优化的一些手段,而在讲解具体的优化措施之前,我想先对 EXPLAIN 进行介绍,它是我们在分析查询时必要的操作,理解了它输出结果的内容更有利于我们优化 SQL。为了方便大家的阅读,在下文中规定类似 key1 的表示二级索引,key_

    2024年02月11日
    浏览(50)
  • C++高性能优化编程之如何测量性能(一)

    C++高性能优化编程系列 深入理解设计原则系列 深入理解设计模式系列 高级C++并发线程编程 不好的编程习惯,不重视程序性能测量分析让代码跑的更快,会导致 浪费大量的CPU周期、程序响应时间慢以及卡顿,用户满意度下降,进而浪费大量的时间返工去重构本应该一开始就

    2024年02月06日
    浏览(54)
  • MySQL高性能优化规范建议

    数据库命令规范 数据库基本设计规范 1. 所有表必须使用 Innodb 存储引擎 2. 数据库和表的字符集统一使用 UTF8 3. 所有表和字段都需要添加注释 4. 尽量控制单表数据量的大小,建议控制在 500 万以内。 5. 谨慎使用 MySQL 分区表 6.尽量做到冷热数据分离,减小表的宽度 7. 禁止在表中建

    2024年02月12日
    浏览(43)
  • 如何评估和优化系统的高性能

    系统的关键性能指标:吞吐量,延迟和TP。 吞吐量:反应单位时间内处理请求的能力。 延迟:从客户端发送请求到接收响应的时间。 延迟和吞吐量的曲线如下图所示: 总体来看,随着压力增大,系统单位时间内被访问的次数增加。结合延迟和吞吐量观察的话,系统优化性能

    2024年02月22日
    浏览(46)
  • Kafka高性能集群部署与优化

    Kafka 是由Apache Software Foundation开发的一个分布式流处理平台,源代码以Scala编写。Kafka最初是由LinkedIn公司开发的,于2011年成为Apache的顶级项目之一。它是一种高吞吐量、可扩展的发布订阅消息系统,具有以下特点: 高吞吐量:Kafka每秒可以处理数百万条消息。 持久化:数据存

    2024年02月13日
    浏览(54)
  • 数据库——MySQL高性能优化规范

    所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用 MySQL 保留(如果表名中包含查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过 32 个字符 临时库表必须以 tmp_为前缀并以日期为后缀,

    2024年02月11日
    浏览(95)
  • 读高性能MySQL(第4版)笔记10_查询性能优化(上)

    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日
    浏览(49)
  • 读高性能MySQL(第4版)笔记12_查询性能优化(下)

    2.3.1.1. 读取行指针和需要排序的字段,对其进行排序,然后再根据排序结果读取所需要的数据行 2.3.1.2. 即需要从数据表中读取两次数据,第二次读取数据的时候,因为是读取排序列进行排序后的所有记录,这会产生大量的随机I/O,所以两次传输排序的成本非常高 2.3.2.1. 先

    2024年02月08日
    浏览(41)
  • 企业如何构建高性能计算云?

    HPC是推动科学和工程应用发展的重要组成部分。除了将处理器向Exascale迈进之外,工作负载的性质也在不断变化—从传统的模拟和建模到混合工作负载,包括企业内部和云应用,还需要整合、吸收和分析来自无数物联网传感器的数据。同时,随着HPC基础设施上的人工智能工作

    2024年02月03日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包