python中大数组的计算

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:

我有一个关于在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:
                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