使用 numpy 矩阵加速计算
我有两个矩阵。两者都充满了零和一。一个是大的(3000 x 2000 个元素),另一个是较小的(20 x 20)元素。我正在做类似的事情:
newMatrix = (size of bigMatrix), filled with zeros
l = (a constant)
for y in xrange(0, len(bigMatrix[0])):
for x in xrange(0, len(bigMatrix)):
for b in xrange(0, len(smallMatrix[0])):
for a in xrange(0, len(smallMatrix)):
if (bigMatrix[x, y] == smallMatrix[x + a - l, y + b - l]):
newMatrix[x, y] = 1
这非常缓慢。我做错了什么吗?有没有一种聪明的方法可以让这项工作更快?
编辑:基本上我是,对于大矩阵中的每个(x,y),检查大矩阵和(x,y)周围小矩阵的所有像素,看看它们是否为1。如果它们是1,那么我在 newMatrix 上设置该值。我正在做一种碰撞检测。
I have two matrices. Both are filled with zeros and ones. One is a big one (3000 x 2000 elements), and the other is smaller ( 20 x 20 ) elements. I am doing something like:
newMatrix = (size of bigMatrix), filled with zeros
l = (a constant)
for y in xrange(0, len(bigMatrix[0])):
for x in xrange(0, len(bigMatrix)):
for b in xrange(0, len(smallMatrix[0])):
for a in xrange(0, len(smallMatrix)):
if (bigMatrix[x, y] == smallMatrix[x + a - l, y + b - l]):
newMatrix[x, y] = 1
Which is being painfully slow. Am I doing anything wrong? Is there a smart way to make this work faster?
edit: Basically I am, for each (x,y) in the big matrix, checking all the pixels of both big matrix and the small matrix around (x,y) to see if they are 1. If they are 1, then I set that value on newMatrix. I am doing a sort of collision detection.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我可以想到一些优化 -
当你使用 4 个嵌套的 python “for” 语句时,你的速度会尽可能慢。
我无法确切地弄清楚你在寻找什么 -
但一方面,如果你的大矩阵“1”的密度很低,你当然可以在 bigMtarix 的切片上使用 python 的“any”函数来快速检查那里是否有任何集合元素 - 你可以获得数倍的速度提升那里:
此时,如果仍然需要在每个元素上进行交互,您可以执行另一对索引来遍历步骤内的每个位置 - 但我认为您已经明白了。
除了使用像“任何”用法这样的内部数字操作之外,您当然可以添加一些控制流代码来在找到第一个匹配像素时中断 (b,a) 循环。
(就像,在最后一个“if”中插入一个“break”语句,并在“b”循环中插入另一个 if..break 对。
我真的无法准确地弄清楚你的意图是什么 - 所以我不能给你更多具体代码。
I can think of a couple of optimisations there -
As you are using 4 nested python "for" statements, you are about as slow as you can be.
I can't figure out exactly what you are looking for -
but for one thing, if your big matrix "1"s density is low, you can certainly use python's "any" function on bigMtarix's slices to quickly check if there are any set elements there -- you could get a several-fold speed increase there:
At this point, if still need to interact on each element, you do another pair of indexes to walk each position inside the step - but I think you got the idea.
Apart from using inner Numeric operations like this "any" usage, you could certainly add some control flow code to break-off the (b,a) loop when the first matching pixel is found.
(Like, inserting a "break" statement inside your last "if" and another if..break pair for the "b" loop.
I really can't figure out exactly what your intent is - so I can't give you more specifc code.
您的示例代码没有任何意义,但问题的描述听起来像是您正在尝试对大位数组进行小位数组的二维卷积。 scipy.signal 包中有一个 convolve2d 函数可以完成此任务。只需执行 convolve2d(bigMatrix,smallMatrix) 即可获得结果。不幸的是,scipy 实现没有布尔数组的特殊情况,因此完整的卷积相当慢。下面的函数利用了数组只包含 1 和 0 的事实:
在我的机器上,它运行 3000x2000 x 20x20 卷积的时间不到 9 秒。运行时间取决于较小数组中的 1 数量,每个非零元素为 20 毫秒。
Your example code makes no sense, but the description of your problem sounds like you are trying to do a 2d convolution of a small bitarray over the big bitarray. There's a convolve2d function in scipy.signal package that does exactly this. Just do
convolve2d(bigMatrix, smallMatrix)
to get the result. Unfortunately the scipy implementation doesn't have a special case for boolean arrays so the full convolution is rather slow. Here's a function that takes advantage of the fact that the arrays contain only ones and zeroes:On my machine it runs in less than 9 seconds for a 3000x2000 by 20x20 convolution. The running time depends on the number of ones in the smaller array, being 20ms per each nonzero element.
如果你的位确实被打包为每个字节 8 个/每个整数 32 个,
你可以将你的smallMatrix减少到20x16,
然后尝试以下操作,此处针对单行。
(
newMatrix[x, y] = 1
,当 x,y 周围 20x16 的任何位为 1 时?你真正在寻找什么?)
If your bits are really packed 8 per byte / 32 per int,
and you can reduce your smallMatrix to 20x16,
then try the following, here for a single row.
(
newMatrix[x, y] = 1
when any bit of the 20x16 around x,y is 1 ??What are you really looking for ?)