python中大数组的计算
我有一个关于在Ubuntu SO上用python(>=3.6.8)计算大型数组的问题。 我有一个大数组a,大约20000(或更多)点(每个点是一个三维坐标x,y,z)。 我想知道这些点中哪一点靠近给定的平面。我使用Symphy python库来表示点、平面和距离。 我有另一个平面数组T(作为sympy对象),特别是一个7或10个元素的数组。 例如,对于阵列的每个点p和每个t平面,我执行如下操作:python中大数组的计算,python,arrays,numpy,sympy,Python,Arrays,Numpy,Sympy,我有一个关于在Ubuntu SO上用python(>=3.6.8)计算大型数组的问题。 我有一个大数组a,大约20000(或更多)点(每个点是一个三维坐标x,y,z)。 我想知道这些点中哪一点靠近给定的平面。我使用Symphy python库来表示点、平面和距离。 我有另一个平面数组T(作为sympy对象),特别是一个7或10个元素的数组。 例如,对于阵列的每个点p和每个t平面,我执行如下操作: for p in A: for t in T:
for p in A:
for t in T:
if t.distance(p) <= Delta:
do something
对于A中的p:
对于t中的t:
如果t.distance(p)使用map
似乎非常快
这里是一个代码测试示例,它在4秒内获得了一百万分
在这种情况下,map
需要一个函数和两个iterable,
所以我们需要iterable点(一百万)和iterable平面(一百万,在这种情况下都是一样的)
一百万点平面距离计算的输出:
1000000 distances in 4.155193328857422 seconds
我认为20米距离计算需要4.15*20->83秒~
试试看,让我知道
这里是一个扩展示例,用于获取一个新列表,其中点的距离小于某个值,**在5秒内处理1M点**
import math
import numpy as np
import time
# Function to find point plane distance
def ppdist(p, plane ):
x1,y1,z1 = p
a,b,c,d = plane
d = abs((a * x1 + b * y1 + c * z1 + d))
e = (math.sqrt(a * a + b * b + c * c))
return d/e
# Function returns point if distance is less than value
def pdistmin(point , dist , val):
return point if dist < val else None
# num points
numpts = 1000000
#creating random 3d points
pts = np.random.randint(0,1234,size=(numpts,3))
#plane
a = 20
b = -20
c = 50
d = 80
plane=[a,b,c,d]
#creating a list of identical planes
planes = [ plane for n in range( numpts ) ]
# Function call
start_time = time.time()
res_dist = list(map( ppdist , pts , planes))
end_time = time.time()
elapsed = end_time-start_time
print(len(res_dist), " distances in ", elapsed, "seconds")
start_time = time.time()
less = [ 10 for n in range( numpts ) ]
xxx = list(map( pdistmin, pts, res_dist , less ))
end_time = time.time()
elapsed = end_time-start_time
print(len(xxx), " points or None computation in ", elapsed, "seconds")
start_time = time.time()
needed_points = [ p for p in xxx if p is not None ]
end_time = time.time()
elapsed = end_time-start_time
print(len(needed_points), " points in ", elapsed, "seconds")
所以不到5秒就可以获得1米的积分20米积分大概100秒Symphy是一个符号库。我们的想法是,您可以使用它来象征性地推导公式,然后使用更高效的数值库进行计算,例如:
In [20]: x, y, z = symbols('x, y, z')
In [21]: arbitrary_point = Point3D(x, y, z)
In [22]: delta = 2
In [23]: plane = Plane(Point3D(1, 1, 1), normal_vector=(1,4,7))
In [24]: condition = plane.distance(arbitrary_point) < delta
In [25]: condition
Out[25]:
│√66⋅(x - 1) 2⋅√66⋅(y - 1) 7⋅√66⋅(z - 1)│
│─────────── + ───────────── + ─────────────│ < 2
│ 66 33 66 │
In [26]: f = lambdify((x, y, z), condition)
In [27]: f(2, 3, 4)
Out[27]: False
In [28]: f(1, 1, 2)
Out[28]: True
现在,您可以将此函数用于x
、y
和z
值的numpy数组:
[33]中的:xvals=np.arange(0,10)
在[34]中:yvals=np.arange(0,10)
[35]:zvals=np.arange(0,10)
In[36]:f(xvals,yvals,zvals)
出[36]:
数组([真,真,真,假,假,假,假,假,假,
错误])
这将更有效地处理大型输入阵列,例如,可在1秒内处理2000万个点:
In [38]: xvals = yvals = zvals = np.arange(0, 20*10**6)
In [39]: %time ok = f(xvals, yvals, zvals)
CPU times: user 698 ms, sys: 553 ms, total: 1.25 s
Wall time: 1.26 s
你的数组是二维的吗?因为它包含20米x-y-z点。A是三维阵列。每个点有3个浮点值:x,y,zHi-Mario,谢谢您的建议。您的解决方案非常有效。我注意到,sympy转换(点对点3D,解决一些代数问题)需要很多时间。事实上,当我在Point3D类中使用您的代码时,我会在一小时后得到结果。。。这对我来说很奇怪。不管怎样,你的解决方案给了我一个快速计算距离的方法。非常感谢。拜拜。你好,马里奥,经过一些测试,我得到了以下结果:每个点有3个浮动坐标(x,y,z),我有大约400000个点。我用你们的例子来计算距离(我用ppdist作为我的类的方法)。在具有UBUNTU 18.04(8GB RAM和分配给VM的4个CPU)的虚拟机上,总时间为2106秒(35分钟)。可能我的代码有问题。请直接试用我的代码,就像在虚拟机上一样。如果执行时间太长,问题可能是虚拟机。在其他地方,你的课程进程很慢。让我们知道。我不知道为什么。。。如果我使用list(map)(在类外使用ppdist作为函数,性能是可以的(我在几秒钟内得到结果),但是如果我调用ppdist作为我的类方法处理最后几个小时。我认为因为ppdist作为类方法创建了该方法的一个新实例,所以创建400K实例会导致一个巨大的过程。
1000000 distances in 4.1579577922821045 seconds
1000000 points or None computation in 0.42284178733825684 seconds
9372 points found in 0.014847517013549805 seconds
In [20]: x, y, z = symbols('x, y, z')
In [21]: arbitrary_point = Point3D(x, y, z)
In [22]: delta = 2
In [23]: plane = Plane(Point3D(1, 1, 1), normal_vector=(1,4,7))
In [24]: condition = plane.distance(arbitrary_point) < delta
In [25]: condition
Out[25]:
│√66⋅(x - 1) 2⋅√66⋅(y - 1) 7⋅√66⋅(z - 1)│
│─────────── + ───────────── + ─────────────│ < 2
│ 66 33 66 │
In [26]: f = lambdify((x, y, z), condition)
In [27]: f(2, 3, 4)
Out[27]: False
In [28]: f(1, 1, 2)
Out[28]: True
In [29]: import inspect
In [31]: print(inspect.getsource(f))
def _lambdifygenerated(x, y, z):
return (less(abs((1/66)*sqrt(66)*(x - 1) + (2/33)*sqrt(66)*(y - 1) + (7/66)*sqrt(66)*(z - 1)), 2))
In [38]: xvals = yvals = zvals = np.arange(0, 20*10**6)
In [39]: %time ok = f(xvals, yvals, zvals)
CPU times: user 698 ms, sys: 553 ms, total: 1.25 s
Wall time: 1.26 s