You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Numpy对两层嵌套for循环进行向量化优化以缩短运行时长

优化方案

核心优化点

  • 移除所有i、j层显式循环,全部用numpy广播和矩阵运算实现,速度提升至少2个数量级
  • 预计算所有和hexind绑定的波矢分量,避免循环内重复计算
  • 利用delta项仅依赖k、i的特性,不需要在j维度重复计算
  • 特征向量内积直接用矩阵乘法批量计算,替代逐元素dot

完整实现代码

预计算全局依赖(仅需执行1次)

import numpy as np
epsilon = 0.15
im = complex(0,1)

def delta(x):
    # 洛伦兹型δ函数
    return (1/np.pi)*(epsilon)/(epsilon**2+x**2)

# 按你给出的最小示例定义基础变量
G1 = np.random.rand(1,2)
G2 = np.random.rand(1,2)
index = np.array([[ 0,  0],
       [ 1,  1],
       [ 1,  0],
       [ 0, -1],
       [-1, -1],
       [-1,  0],
       [ 0,  1]])
hexind2 = np.repeat(index,2, axis=0)
hexind = np.tile(hexind2,(2,1))
n = len(hexind)

# 预计算每个i对应的波矢分量,仅计算一次,后续不用循环重复算
G_mat = np.vstack([G2, G1])  # shape (2,2)
k_vecs = hexind @ G_mat  # shape (n, 2)
kx = k_vecs[:, 0].reshape(-1,1,1,1)  # 调整形状方便后续广播运算
ky = k_vecs[:, 1].reshape(-1,1,1,1)

优化后的主函数

def quantity_abs_squared_vec(Vecs, Egrid, Eigen, Rx, Ry):
    kdots = Vecs.shape[0]
    # 1. 预计算指数相位矩阵,shape (n,n,M,M),M为Rx/Ry的网格边长
    dkx = kx - kx.reshape(1,n,1,1)
    dky = ky - ky.reshape(1,n,1,1)
    phase = im * (dkx * Rx + dky * Ry)
    exp_mat = np.exp(phase)
    
    # 2. 预计算delta项,仅和k、i有关,shape (kdots, n, 1, 1)
    delta_vals = delta(Egrid - Eigen).reshape(kdots, n, 1, 1)
    
    holder = 0
    # 仅保留k层循环,1575次循环在numpy矩阵运算加持下速度极快
    for k in range(kdots):
        # 单次矩阵乘法直接得到所有i、j组合的特征向量内积,shape (n,n)
        vec_k = Vecs[k]
        coeff_mat = vec_k.T @ vec_k.conj()
        # 广播乘指数矩阵后求和i、j维度
        term = (coeff_mat[..., np.newaxis, np.newaxis] * exp_mat).sum(axis=(0,1))
        # 乘delta项后求和i维度,加入总结果
        holder += (delta_vals[k] * term).sum(axis=0)
    
    return 4 * holder / kdots

调用示例

kdots = 100
n = 28
# 生成测试用特征值、特征向量
E = np.random.rand(kdots, n)
vec = np.random.rand(kdots,n,n) + 1j*np.random.rand(kdots,n,n)

# 生成网格
rx = np.linspace(-20, 20)
ry = np.linspace(-20, 20)
Rx,Ry = np.meshgrid(rx,ry)

# 调用优化后的函数
Eval = 300
result = quantity_abs_squared_vec(vec, Eval, E, Rx,Ry)

性能说明

原代码n=244时,每个k点要执行244*244≈6万次python层循环,1575个k点累计近1亿次循环,耗时自然很长。优化后所有i、j维度的运算都交给numpy底层C实现,原10分钟的计算任务优化后仅需几秒到几十秒即可完成。如果内存不足可以将exp_mat的计算拆到k循环内,或者用numba对k层循环做JIT编译进一步提速。

内容的提问来源于stack exchange,提问作者Madlad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 17:57:02