科学计算, 生活

不同大小的矩阵的内存占用和计算时间

这是之前的一篇:矩阵一些运算的时间复杂度,说明了矩阵乘积、矩阵求逆、矩阵的特征值计算和矩阵维度的大致关系。本篇记录不同大小的矩阵的内存占用和计算时间,以 Python 程序为例。其中,时间测试包括了:矩阵创建、for 循环赋值、numba for 循环赋值,以及矩阵的迹、矩阵转置、矩阵加法、矩阵行列式、​矩阵乘法、矩阵求逆、矩阵的秩、矩阵的特征值、矩阵的特征值和特征向量。

内存占用的主要结论:

  • 如果程序中存在多个大矩阵,那么程序的预期内存占用大概是 4~10 倍的单个矩阵的内存占用。
  • 当矩阵维度为 7000,单个矩阵的内存占用会接近 400M,内存大于 2G~4G 的设备可以计算。
  • 当矩阵维度为 10000,单个矩阵的内存占用会接近 1GB,内存大于 4G~10G 的设备可以计算。
  • 当矩阵维度为 20000,单个矩阵的内存占用会超过 3GB,内存大于 12G~30G 的设备可以计算。
  • 当矩阵维度为 30000,单个矩阵的内存占用会接近 7GB,内存大于 28G~70G 的设备可以计算。

计算时间的主要结论:

  • 当矩阵维度为 20000,对于矩阵乘法、矩阵求逆、矩阵的秩、矩阵的特征值和特征向量等运算,计算时间就显得稍长了。一般来说,矩阵维度控制在 10000 以下或左右,计算起来会轻松一些。
  • 大矩阵的计算时间的大概排序为:矩阵的迹 < 矩阵转置 < 矩阵加法 < numba for 循环赋值 < 矩阵创建 < for 循环赋值 < 矩阵行列式 < 矩阵乘法 < 矩阵求逆 < 矩阵的秩 < 矩阵的特征值 < 矩阵的特征值和特征向量。
  • numba for 循环赋值比直接的 for 循环赋值快很多,因此当涉及比较多的 for 循环时,可以考虑用 numba 进行优化,参考:Numba加速Python的时间测试
  • 对于矩阵乘法、矩阵求逆、矩阵的秩、矩阵的特征值和特征向量等运算,多核计算比单核计算有明显的并行加速,参考:不同CPU核数对矩阵运算的加速效果

测试代码如下:

"""
This code is supported by the website: https://www.guanjihuan.com
The newest version of this code is on the web page: https://www.guanjihuan.com/archives/45275
"""

import numpy as np
import time
import sys
from numba import jit

n_array = np.concatenate((np.arange(1000, 10000, 1000), np.arange(10000, 40000, 10000)))
print(f'n_array={n_array}\n')

@jit
def numba_test(C, n):
    for i0 in range(n):
        for j0 in range(n):
            C[i0, j0] = np.random.rand()
    return C

for n in n_array:
    print(f'n={n}')

    A = np.random.rand(n, n)
    B = np.random.rand(n, n)
    C = np.random.rand(n, n)

    # 矩阵占用内存
    size = sys.getsizeof(C)
    print(f'矩阵占用内存: {size/(1024*1024):.2f} MB')

    # 矩阵的迹
    start_time = time.time()
    trace_A = np.trace(A)
    trace_time = time.time() - start_time
    print(f"矩阵的迹时间: {trace_time:.3f} 秒")

    # 矩阵转置
    start_time = time.time()
    A_T = A.T
    transpose_time = time.time() - start_time
    print(f"矩阵转置时间: {transpose_time:.3f} 秒")

    # 矩阵加法
    start_time = time.time()
    C = A + B
    add_time = time.time() - start_time
    print(f"矩阵加法时间: {add_time:.3f} 秒")

    # numba for 循环赋值
    start_time = time.time()
    numba_test(C, n)
    create_time = time.time() - start_time
    print(f"numba for 循环赋值时间: {create_time:.3f} 秒")

    # 矩阵创建
    start_time = time.time()
    C = np.random.rand(n, n)
    create_time = time.time() - start_time
    print(f"矩阵创建时间: {create_time:.3f} 秒")

    # for 循环赋值
    start_time = time.time()
    for i0 in range(n):
        for j0 in range(n):
            C[i0, j0] = np.random.rand()
    create_time = time.time() - start_time
    print(f"for 循环赋值时间: {create_time:.3f} 秒")

    # 矩阵行列式
    start_time = time.time()
    det_A = np.linalg.det(A)
    det_time = time.time() - start_time
    print(f"矩阵行列式时间: {det_time:.3f} 秒")

    # 矩阵乘法
    start_time = time.time()
    C = np.dot(A, B)
    multiply_time = time.time() - start_time
    print(f"矩阵乘法时间: {multiply_time:.3f} 秒")

    # 矩阵求逆
    start_time = time.time()
    inv_A = np.linalg.inv(A)
    inv_time = time.time() - start_time
    print(f"矩阵求逆时间: {inv_time:.3f} 秒")

    # 矩阵的秩
    start_time = time.time()
    rank_A = np.linalg.matrix_rank(A)
    rank_time = time.time() - start_time
    print(f"矩阵的秩时间: {rank_time:.3f} 秒")

    # 矩阵的特征值
    start_time = time.time()
    eigenvalues_A = np.linalg.eigvals(A)
    eigen_time = time.time() - start_time
    print(f"矩阵特征值时间: {eigen_time:.3f} 秒")

    # 矩阵的特征值和特征向量
    start_time = time.time()
    eigenvalues_A, eigenvector_A = np.linalg.eig(A)
    eigen_time = time.time() - start_time
    print(f"矩阵特征值和特征向量时间: {eigen_time:.3f} 秒")

    print()

运行结果(单核):

n_array=[ 1000  2000  3000  4000  5000  6000  7000  8000  9000 10000 20000 30000
 40000 50000]
 
n=1000 
矩阵占用内存: 7.63 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.000 秒 
矩阵加法时间: 0.006 秒 
numba for 循环赋值时间: 1.597 秒 
矩阵创建时间: 0.009 秒 
for 循环赋值时间: 0.446 秒 
矩阵行列式时间: 0.054 秒 
矩阵乘法时间: 0.095 秒 
矩阵求逆时间: 0.119 秒 
矩阵的秩时间: 0.281 秒 
矩阵特征值时间: 0.628 秒 
矩阵特征值和特征向量时间: 0.886 秒 

n=2000 
矩阵占用内存: 30.52 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.000 秒 
矩阵加法时间: 0.015 秒 
numba for 循环赋值时间: 0.020 秒 
矩阵创建时间: 0.026 秒 
for 循环赋值时间: 1.773 秒 
矩阵行列式时间: 0.186 秒 
矩阵乘法时间: 0.336 秒 
矩阵求逆时间: 0.537 秒 
矩阵的秩时间: 2.037 秒 
矩阵特征值时间: 2.895 秒 
矩阵特征值和特征向量时间: 4.975 秒 

n=3000 
矩阵占用内存: 68.66 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.000 秒 
矩阵加法时间: 0.035 秒 
numba for 循环赋值时间: 0.044 秒 
矩阵创建时间: 0.075 秒 
for 循环赋值时间: 4.004 秒 
矩阵行列式时间: 0.546 秒 
矩阵乘法时间: 1.128 秒 
矩阵求逆时间: 1.701 秒 
矩阵的秩时间: 3.218 秒 
矩阵特征值时间: 9.864 秒 
矩阵特征值和特征向量时间: 15.712 秒 

n=4000 
矩阵占用内存: 122.07 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.000 秒 
矩阵加法时间: 0.062 秒 
numba for 循环赋值时间: 0.078 秒 
矩阵创建时间: 0.132 秒 
for 循环赋值时间: 7.124 秒 
矩阵行列式时间: 1.257 秒 
矩阵乘法时间: 2.645 秒 
矩阵求逆时间: 3.971 秒 
矩阵的秩时间: 7.724 秒 
矩阵特征值时间: 23.538 秒 
矩阵特征值和特征向量时间: 37.521 秒 

n=5000 
矩阵占用内存: 190.73 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.000 秒 
矩阵加法时间: 0.097 秒 
numba for 循环赋值时间: 0.123 秒 
矩阵创建时间: 0.205 秒 
for 循环赋值时间: 11.185 秒 
矩阵行列式时间: 2.321 秒 
矩阵乘法时间: 5.168 秒 
矩阵求逆时间: 7.605 秒 
矩阵的秩时间: 13.565 秒 
矩阵特征值时间: 45.365 秒 
矩阵特征值和特征向量时间: 80.265 秒 

n=6000 
矩阵占用内存: 274.66 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.001 秒 
矩阵加法时间: 0.141 秒 
numba for 循环赋值时间: 0.211 秒 
矩阵创建时间: 0.329 秒 
for 循环赋值时间: 19.439 秒 
矩阵行列式时间: 3.900 秒 
矩阵乘法时间: 9.506 秒 
矩阵求逆时间: 14.469 秒 
矩阵的秩时间: 23.906 秒 
矩阵特征值时间: 89.140 秒 
矩阵特征值和特征向量时间: 136.497 秒 

n=7000 
矩阵占用内存: 373.84 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.001 秒 
矩阵加法时间: 0.199 秒 
numba for 循环赋值时间: 0.290 秒 
矩阵创建时间: 0.472 秒 
for 循环赋值时间: 25.998 秒 
矩阵行列式时间: 6.091 秒 
矩阵乘法时间: 15.412 秒 
矩阵求逆时间: 22.411 秒 
矩阵的秩时间: 38.326 秒 
矩阵特征值时间: 124.900 秒 
矩阵特征值和特征向量时间: 210.791 秒 

n=8000 
矩阵占用内存: 488.28 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.001 秒 
矩阵加法时间: 0.244 秒 
numba for 循环赋值时间: 0.344 秒 
矩阵创建时间: 0.521 秒 
for 循环赋值时间: 29.591 秒 
矩阵行列式时间: 8.753 秒 
矩阵乘法时间: 20.965 秒 
矩阵求逆时间: 30.456 秒 
矩阵的秩时间: 52.435 秒 
矩阵特征值时间: 195.694 秒 
矩阵特征值和特征向量时间: 294.924 秒 

n=9000 
矩阵占用内存: 617.98 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.001 秒 
矩阵加法时间: 0.311 秒 
numba for 循环赋值时间: 0.456 秒 
矩阵创建时间: 0.752 秒 
for 循环赋值时间: 41.978 秒 
矩阵行列式时间: 12.345 秒 
矩阵乘法时间: 31.079 秒 
矩阵求逆时间: 45.033 秒 
矩阵的秩时间: 79.933 秒 
矩阵特征值时间: 289.316 秒 
矩阵特征值和特征向量时间: 407.273 秒 

n=10000 
矩阵占用内存: 762.94 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.002 秒 
矩阵加法时间: 0.391 秒 
numba for 循环赋值时间: 0.575 秒 
矩阵创建时间: 0.944 秒 
for 循环赋值时间: 51.109 秒 
矩阵行列式时间: 17.626 秒 
矩阵乘法时间: 42.732 秒 
矩阵求逆时间: 60.364 秒 
矩阵的秩时间: 106.439 秒 
矩阵特征值时间: 380.776 秒 
矩阵特征值和特征向量时间: 611.635 秒 

n=20000 
矩阵占用内存: 3051.76 MB 
矩阵的迹时间: 0.001 秒 
矩阵转置时间: 0.003 秒 
矩阵加法时间: 1.640 秒 
numba for 循环赋值时间: 2.291 秒 
矩阵创建时间: 3.738 秒 
for 循环赋值时间: 212.194 秒 
矩阵行列式时间: 137.455 秒 
矩阵乘法时间: 341.421 秒 
矩阵求逆时间: 482.127 秒 
矩阵的秩时间: 766.457 秒 
矩阵特征值时间: 2775.898 秒 
矩阵特征值和特征向量时间: 4807.064 秒 

n=30000 
矩阵占用内存: 6866.46 MB 
矩阵的迹时间: 0.001 秒 
矩阵转置时间: 0.007 秒 
矩阵加法时间: 6.090 秒 
numba for 循环赋值时间: 5.195 秒 
矩阵创建时间: 8.435 秒 
for 循环赋值时间: 477.623 秒 
矩阵行列式时间: 430.537 秒 
矩阵乘法时间: 1168.907 秒 
矩阵求逆时间: 1614.139 秒 
矩阵的秩时间: 2272.073 秒 
矩阵特征值时间: 9281.661 秒 
矩阵特征值和特征向量时间: 15251.770 秒 

运行结果(四核):

n_array=[ 1000  2000  3000  4000  5000  6000  7000  8000  9000 10000 20000 30000
 40000 50000]
 
n=1000 
矩阵占用内存: 7.63 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.000 秒 
矩阵加法时间: 0.005 秒 
numba for 循环赋值时间: 1.153 秒 
矩阵创建时间: 0.014 秒 
for 循环赋值时间: 0.541 秒 
矩阵行列式时间: 0.208 秒 
矩阵乘法时间: 0.068 秒 
矩阵求逆时间: 0.080 秒 
矩阵的秩时间: 0.145 秒 
矩阵特征值时间: 0.555 秒 
矩阵特征值和特征向量时间: 0.790 秒 

n=2000 
矩阵占用内存: 30.52 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.000 秒 
矩阵加法时间: 0.016 秒 
numba for 循环赋值时间: 0.023 秒 
矩阵创建时间: 0.030 秒 
for 循环赋值时间: 2.066 秒 
矩阵行列式时间: 0.075 秒 
矩阵乘法时间: 0.106 秒 
矩阵求逆时间: 0.221 秒 
矩阵的秩时间: 0.969 秒 
矩阵特征值时间: 2.053 秒 
矩阵特征值和特征向量时间: 3.304 秒 

n=3000 
矩阵占用内存: 68.66 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.000 秒 
矩阵加法时间: 0.026 秒 
numba for 循环赋值时间: 0.050 秒 
矩阵创建时间: 0.083 秒 
for 循环赋值时间: 4.545 秒 
矩阵行列式时间: 0.223 秒 
矩阵乘法时间: 0.332 秒 
矩阵求逆时间: 0.622 秒 
矩阵的秩时间: 1.657 秒 
矩阵特征值时间: 6.039 秒 
矩阵特征值和特征向量时间: 10.583 秒 

n=4000 
矩阵占用内存: 122.07 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.000 秒 
矩阵加法时间: 0.065 秒 
numba for 循环赋值时间: 0.090 秒 
矩阵创建时间: 0.147 秒 
for 循环赋值时间: 8.224 秒 
矩阵行列式时间: 0.483 秒 
矩阵乘法时间: 0.781 秒 
矩阵求逆时间: 1.441 秒 
矩阵的秩时间: 3.980 秒 
矩阵特征值时间: 13.757 秒 
矩阵特征值和特征向量时间: 21.800 秒 

n=5000 
矩阵占用内存: 190.73 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.000 秒 
矩阵加法时间: 0.099 秒 
numba for 循环赋值时间: 0.139 秒 
矩阵创建时间: 0.228 秒 
for 循环赋值时间: 12.640 秒 
矩阵行列式时间: 0.726 秒 
矩阵乘法时间: 1.483 秒 
矩阵求逆时间: 3.393 秒 
矩阵的秩时间: 6.026 秒 
矩阵特征值时间: 21.143 秒 
矩阵特征值和特征向量时间: 41.571 秒 

n=6000 
矩阵占用内存: 274.66 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.001 秒 
矩阵加法时间: 0.146 秒 
numba for 循环赋值时间: 0.201 秒 
矩阵创建时间: 0.330 秒 
for 循环赋值时间: 18.506 秒 
矩阵行列式时间: 1.481 秒 
矩阵乘法时间: 2.536 秒 
矩阵求逆时间: 3.998 秒 
矩阵的秩时间: 9.744 秒 
矩阵特征值时间: 42.314 秒 
矩阵特征值和特征向量时间: 74.825 秒 

n=7000 
矩阵占用内存: 373.84 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.001 秒 
矩阵加法时间: 0.192 秒 
numba for 循环赋值时间: 0.268 秒 
矩阵创建时间: 0.442 秒 
for 循环赋值时间: 24.707 秒 
矩阵行列式时间: 2.349 秒 
矩阵乘法时间: 3.933 秒 
矩阵求逆时间: 5.928 秒 
矩阵的秩时间: 13.863 秒 
矩阵特征值时间: 58.228 秒 
矩阵特征值和特征向量时间: 112.797 秒 

n=8000 
矩阵占用内存: 488.28 MB 
矩阵的迹时间: 0.001 秒 
矩阵转置时间: 0.001 秒 
矩阵加法时间: 0.245 秒 
numba for 循环赋值时间: 0.313 秒 
矩阵创建时间: 0.521 秒 
for 循环赋值时间: 28.609 秒 
矩阵行列式时间: 3.166 秒 
矩阵乘法时间: 7.573 秒 
矩阵求逆时间: 10.245 秒 
矩阵的秩时间: 22.854 秒 
矩阵特征值时间: 98.880 秒 
矩阵特征值和特征向量时间: 175.645 秒 

n=9000 
矩阵占用内存: 617.98 MB 
矩阵的迹时间: 0.000 秒 
矩阵转置时间: 0.001 秒 
矩阵加法时间: 0.310 秒 
numba for 循环赋值时间: 0.396 秒 
矩阵创建时间: 0.659 秒 
for 循环赋值时间: 36.487 秒 
矩阵行列式时间: 4.417 秒 
矩阵乘法时间: 10.234 秒 
矩阵求逆时间: 15.217 秒 
矩阵的秩时间: 30.049 秒 
矩阵特征值时间: 138.918 秒 
矩阵特征值和特征向量时间: 244.765 秒 

n=10000 
矩阵占用内存: 762.94 MB 
矩阵的迹时间: 0.254 秒 
矩阵转置时间: 0.002 秒 
矩阵加法时间: 0.380 秒 
numba for 循环赋值时间: 0.490 秒 
矩阵创建时间: 0.813 秒 
for 循环赋值时间: 45.182 秒 
矩阵行列式时间: 5.552 秒 
矩阵乘法时间: 13.261 秒 
矩阵求逆时间: 18.668 秒 
矩阵的秩时间: 40.731 秒 
矩阵特征值时间: 176.486 秒 
矩阵特征值和特征向量时间: 306.722 秒 

n=20000 
矩阵占用内存: 3051.76 MB 
矩阵的迹时间: 0.002 秒 
矩阵转置时间: 0.002 秒 
矩阵加法时间: 1.526 秒 
numba for 循环赋值时间: 1.953 秒 
矩阵创建时间: 3.255 秒 
for 循环赋值时间: 180.067 秒 
矩阵行列式时间: 36.621 秒 
矩阵乘法时间: 104.103 秒 
矩阵求逆时间: 145.663 秒 
矩阵的秩时间: 276.173 秒 
矩阵特征值时间: 1243.477 秒 
矩阵特征值和特征向量时间: 2490.158 秒 

n=30000 
矩阵占用内存: 6866.46 MB 
矩阵的迹时间: 0.001 秒 
矩阵转置时间: 0.007 秒 
矩阵加法时间: 3.416 秒 
numba for 循环赋值时间: 4.389 秒 
矩阵创建时间: 7.314 秒 
for 循环赋值时间: 402.068 秒 
矩阵行列式时间: 138.942 秒 
矩阵乘法时间: 340.128 秒 
矩阵求逆时间: 464.236 秒 
矩阵的秩时间: 844.484 秒 
矩阵特征值时间: 3988.969 秒 
矩阵特征值和特征向量时间: 8426.078 秒 
10 次浏览

【说明:本站主要是个人的一些笔记和代码分享,内容可能会不定期修改。为了使全网显示的始终是最新版本,这里的文章未经同意请勿转载。引用请注明出处:https://www.guanjihuan.com

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

Captcha Code