我有一个I*J大小的输入矩阵A
输出矩阵B的大小为N*M
还有一些预先计算好的地图,尺寸为N*M*2,它规定了B中的每个坐标,A中的坐标要取。地图没有我可以使用的特定规则或线性。只是一张看起来随机的地图。在
矩阵非常大(~5000*~3000),所以创建映射矩阵是不可能的(5000*3000*5000*3000)
我用了一个简单的地图和循环:
for i in range(N):
for j in range(M):
B[i, j] = A[mapping[i, j, 0], mapping[i, j, 1]]
我用索引法成功地做到了:
^{pr2}$这样做效果更好,但还是有点慢。在
我有无限的时间提前计算映射或任何其他效用计算。但在这些预先计算之后,这种映射应该尽快进行。在
目前,我看到的唯一的另一个选择就是在C或其他更快的地方重新实现它。。。在
(如果有人好奇,我会用其他形状和方向不同的图像,用一些编码来创建一个图像。但它的映射非常复杂,不是简单或线性的东西可以使用)
如果您有无限时间进行预计算,您可以通过使用平面索引来获得一点加速:
然后简单地做:
^{2}$请注意,这个加速是在我们从花式索引得到的大加速之上。例如:
如果我们与原始的循环代码相比,加速比将更接近40倍
最后,请注意,此解决方案不仅避免了额外的依赖性和潜在的安装噩梦,而且更简单、更短、更快:
代码:
对于这些类型的性能关键问题,一个非常好的解决方案是保持简单,并使用一个高性能包。最简单的可能是Numba,它提供了
jit
修饰符,它将数组和循环重代码编译为优化的LLVM。下面是一个完整的例子:这使用了您自己的循环解决方案,使用标准Python时它的速度本来就很慢,但是在使用Numba时它的速度与C一样快。在我的机器上,
normal
函数执行时间为0.270秒,而fast
函数的执行时间为0.00248秒。也就是说,Numba给了我们一个109x的加速(!)差不多是免费的。在注意,
fast
Numba函数被调用了两次,首先是用小的输入数组,然后才是实际数据。这是一个经常被忽视的关键步骤。如果没有它,您将发现性能的提高并不如第一次调用编译代码那样好。在这个初始调用中,输入数组的类型和维度应该相同,但是每个维度中的大小并不重要。在我在函数之外创建
B
,并将其作为参数传递(要“用值填充”)。您不妨在函数内部分配B
,Numba不在乎。在获得Numba最简单的方法是通过Anaconda分布正确地进行。在
一种选择是使用^{} ,这通常可以在这种简单的算法代码中提供实质性的改进。在
这给了我们匹配的结果:
^{2}$而且速度更快:
在第一次呼叫之后,当它必须执行jit工作时,速度更快:
增加两行代码可以提高30倍。在
相关问题 更多 >
编程相关推荐