关于计算性能的若干重要事实

125 篇文章 0 订阅
124 篇文章 0 订阅

在算法课程中,我们往往使用时间复杂度(大 O 符号)作为衡量算法性能的重要指标。这种表示方法对于算法理论性能分析非常有效,但也可能给我们带来一种误解,即常数项的时间复杂度变化对实际的数值计算效率影响不大。事实上,在实际的数值计算中,有以下关于计算性能的重要事实。尽管它们带来的都是常数级的时间复杂度变化,但对计算性能的影响却相当显著。

  • 不同的程序设计语言由于设计机制和理念,以及编译器 / 解释器的实现方式不同,在数值计算的效率上有着巨大的区别。例如,Python 语言为了增强语言的动态性,而牺牲了大量计算效率。而 C/C++ 语言虽然复杂,但具有出色的计算效率。简而言之,对程序员友好的语言往往对计算机不友好,反之亦然。不同程序设计语言带来的性能差距可达 数量级以上。TensorFlow 等各种数值计算库的底层就是使用 C++ 开发的;
  • 对于矩阵运算,由于有内置的并行加速和硬件优化过程,数值计算库的内置方法(底层调用 BLAS)往往要远快于直接使用 For 循环,大规模计算下的性能差距可达 数量级以上;
  • 对于矩阵 / 张量运算,GPU 的并行架构(大量小的计算单元并行运算)使其相较于 CPU 具有明显优势,具体视 CPU 和 GPU 的性能而定。在 CPU 和 GPU 级别相当时,大规模张量计算的性能差距一般可达 以上。

 

以下示例程序使用了 Python 的三重 For 循环、Cython 的三重 For 循环、NumPy 的 dot 函数和 TensorFlow 的 matmul 函数,分别计算了两个 10000×10000 的随机矩阵 A 和 B 的乘积。程序运行平台为一台具备 Intel i9-9900K 处理器、NVIDIA GeForce RTX 2060 SUPER 显卡与 64GB 内存的个人电脑(后文亦同)。运行所需时间分别标注在了程序的注释中。

import tensorflow as tf
import numpy as np
import time
import pyximport; pyximport.install()
import matrix_cython

A = np.random.uniform(size=(10000, 10000))
B = np.random.uniform(size=(10000, 10000))

start_time = time.time()
C = np.zeros(shape=(10000, 10000))
for i in range(10000):
    for j in range(10000):
        for k in range(10000):
            C[i, j] += A[i, k] * B[k, j]
print('time consumed by Python for loop:', time.time() - start_time)    # ~700000s

start_time = time.time()
C = matrix_cython.matmul(A, B)      # Cython 代码为上述 Python 代码的 C 语言版本,此处省略
print('time consumed by Cython for loop:', time.time() - start_time)    # ~8400s

start_time = time.time()
C = np.dot(A, B)
print('time consumed by np.dot:', time.time() - start_time)     # 5.61s

A = tf.constant(A)
B = tf.constant(B)
start_time = time.time()
C = tf.matmul(A, B)
print('time consumed by tf.matmul:', time.time() - start_time)  # 0.77s

可见,同样是 O(n^3) 时间复杂度的矩阵乘法(具体而言10^2次浮点数乘法的计算量),使用 GPU 加速的 TensorFlow 竟然比直接使用原生 Python 循环快了近 100 万倍!这种极大幅度的优化来源于两个方面,一是使用更为高效的底层计算操作,避免了原生 Python 语言解释器的各种冗余检查等所带来的性能损失(例如,Python 中每从数组中取一次数都需要检查一次是否下标越界)。二是利用了矩阵相乘运算具有的充分的可并行性。在矩阵相乘 A * B 的计算中,矩阵 A 的每一行与矩阵 B 的每一列所进行的相乘操作都是可以同时进行的,而没有任何的依赖关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值