如何使用 numpy einsum_path 结果?
How to use numpy einsum_path result?
我正在使用 numpy einsum 对一些 3 维和 4 维张量执行相当复杂的操作。
我的实际代码是
np.einsum('oij,imj,mjkn,lnk,plk->op',phi,B,Suu,B,phi)
这就是我想要的。
使用einsum_path,结果是:
>>> path = np.einsum_path('oij,imj,mjkn,lnk,plk->op',phi,B,Suu,B,phi)
>>> print(path[0])
['einsum_path', (0, 1), (0, 3), (0, 1), (0, 1)]
>>> print(path[1])
Complete contraction: oij,imj,mjkn,lnk,plk->op
Naive scaling: 8
Optimized scaling: 5
Naive FLOP count: 2.668e+07
Optimized FLOP count: 1.340e+05
Theoretical speedup: 199.136
Largest intermediate: 7.700e+02 elements
--------------------------------------------------------------------------
scaling current remaining
--------------------------------------------------------------------------
4 imj,oij->moj mjkn,lnk,plk,moj->op
5 moj,mjkn->nok lnk,plk,nok->op
4 plk,lnk->npk nok,npk->op
4 npk,nok->op op->op
这表明理论上的加速约为 200 倍。
我如何使用这个结果来加速我的代码?我如何 "implement" einsum_path 告诉我什么?
Theoretical Speedup = speedup = naive_cost / opt_cost
naive_cost = _flop_count(idx_contract, idx_removed, len(input_sets), idx_dict)
因此,据此判断,要加快进程,您需要降低 FLOPS (Floating Point Operations Per Second)。由于原始成本是未优化表达式的成本,因此您需要以这样一种方式重写表达式,即删除与表达式关联的任何 "junk",同时在不更改表达式的基础结构的情况下离开。
根据您的问题判断您正在做一些复杂的表达式,这可能是不可能的。但是要回答您的问题,请尝试重写您的表达式是一种更紧凑的方式,以获得较低的理论加速。
您可以尝试使用不同的路径来降低 FLOPS。
做一些时间测试
path = np.einsum_path('oij,imj,mjkn,lnk,plk->op',phi,B,Suu,B,phi)
np.einsum('oij,imj,mjkn,lnk,plk->op',phi,B,Suu,B,phi, optimize=False)
np.einsum('oij,imj,mjkn,lnk,plk->op',phi,B,Suu,B,phi, optimize=True)
np.einsum('oij,imj,mjkn,lnk,plk->op',phi,B,Suu,B,phi, optimize=path[0])
在我测试第二个 运行 时速度相同。对于小问题 optimize=False
更快,大概是因为分析和重新排列需要时间。对于较大的问题,如果理论加速比较大,True
的实际加速比可能会大于理论。据推测,内存管理正在减慢 False
案例。
theoretical speedup
只是基于 FLOPS 计数的估计。只有在 FLOPS 主导计算的情况下才会如此。
您还可以为 path
计算计时。问题的大小将决定它的时间是总时间的一小部分还是大部分。
我正在使用 numpy einsum 对一些 3 维和 4 维张量执行相当复杂的操作。
我的实际代码是
np.einsum('oij,imj,mjkn,lnk,plk->op',phi,B,Suu,B,phi)
这就是我想要的。
使用einsum_path,结果是:
>>> path = np.einsum_path('oij,imj,mjkn,lnk,plk->op',phi,B,Suu,B,phi)
>>> print(path[0])
['einsum_path', (0, 1), (0, 3), (0, 1), (0, 1)]
>>> print(path[1])
Complete contraction: oij,imj,mjkn,lnk,plk->op
Naive scaling: 8
Optimized scaling: 5
Naive FLOP count: 2.668e+07
Optimized FLOP count: 1.340e+05
Theoretical speedup: 199.136
Largest intermediate: 7.700e+02 elements
--------------------------------------------------------------------------
scaling current remaining
--------------------------------------------------------------------------
4 imj,oij->moj mjkn,lnk,plk,moj->op
5 moj,mjkn->nok lnk,plk,nok->op
4 plk,lnk->npk nok,npk->op
4 npk,nok->op op->op
这表明理论上的加速约为 200 倍。
我如何使用这个结果来加速我的代码?我如何 "implement" einsum_path 告诉我什么?
Theoretical Speedup = speedup = naive_cost / opt_cost
naive_cost = _flop_count(idx_contract, idx_removed, len(input_sets), idx_dict)
因此,据此判断,要加快进程,您需要降低 FLOPS (Floating Point Operations Per Second)。由于原始成本是未优化表达式的成本,因此您需要以这样一种方式重写表达式,即删除与表达式关联的任何 "junk",同时在不更改表达式的基础结构的情况下离开。
根据您的问题判断您正在做一些复杂的表达式,这可能是不可能的。但是要回答您的问题,请尝试重写您的表达式是一种更紧凑的方式,以获得较低的理论加速。
您可以尝试使用不同的路径来降低 FLOPS。
做一些时间测试
path = np.einsum_path('oij,imj,mjkn,lnk,plk->op',phi,B,Suu,B,phi)
np.einsum('oij,imj,mjkn,lnk,plk->op',phi,B,Suu,B,phi, optimize=False)
np.einsum('oij,imj,mjkn,lnk,plk->op',phi,B,Suu,B,phi, optimize=True)
np.einsum('oij,imj,mjkn,lnk,plk->op',phi,B,Suu,B,phi, optimize=path[0])
在我测试第二个 运行 时速度相同。对于小问题 optimize=False
更快,大概是因为分析和重新排列需要时间。对于较大的问题,如果理论加速比较大,True
的实际加速比可能会大于理论。据推测,内存管理正在减慢 False
案例。
theoretical speedup
只是基于 FLOPS 计数的估计。只有在 FLOPS 主导计算的情况下才会如此。
您还可以为 path
计算计时。问题的大小将决定它的时间是总时间的一小部分还是大部分。