【发布时间】:2017-11-24 07:18:56
【问题描述】:
我在单个天体坐标对象中包含大量坐标。我想对每个坐标并行应用一个函数,并生成一个相同形状的输出数组——但这很慢。
(在我的例子中,该函数是一个模型,它采用星系中心坐标并输出与空间中该点相关的“亮度”。)
插图:
In [339]: type(data)
Out[339]: astropy.coordinates.builtin_frames.galactocentric.Galactocentric
In [340]: data.shape, data.size # Not that big, really
Out[340]: ((21, 21, 31), 13671)
In [341]: data[0,0,0] # An example of a single coordinate
Out[341]:
<Galactocentric Coordinate (galcen_distance=8.3 kpc, galcen_ra=266d24m18.36s, galcen_dec=-28d56m10.23s, z_sun=27.0 pc, roll=0.0 deg): (rho, phi, z) in (kpc, deg, kpc)
( 8.29995608, 180., 0.027)>
In [342]: func = vectorize(lambda coord: 0) # Dummy function
In [343]: %time func(data).shape
CPU times: user 33.2 s, sys: 88.1 ms, total: 33.3 s
Wall time: 33.4 s
Out[343]: (21, 21, 31)
我怀疑这很慢,因为在每次迭代中,都会初始化一个新的坐标对象,然后再将其传递给矢量化函数 (discussion)。
解决方案可能是在应用函数之前将坐标对象转换为普通的 numpy 数组,丢弃单元信息和元数据(因为单元是同质的)。
但是,我找不到这样做的方法。
我应该如何处理这个问题?如果转换为 vanilla numpy 数据类型是最好的解决方案,那是如何实现的?
谢谢!
最小的工作示例:
from numpy import *
from astropy import units as u
from astropy.coordinates import Galactocentric
# Generate lots of coordinates
x = linspace(0, 1, 1e3)*u.pc
data = Galactocentric(x=x, y=0*u.pc, z=0*u.pc)
@vectorize
def func(coord):
'''ultimately in terms of coord.x, coord.y, coord.z...'''
return 0
# timeit
func(data)
【问题讨论】:
-
我通常会通过
data.si.value删除单位。 -
在我的例子中,
data.data(哎呀——不幸的命名)是一个无量纲的<CartesianRepresentation … >对象,它位于不同的坐标系中。我的data对象具有(rho, phi, z)坐标,这是我的模型所需要的。 -
在我喜欢使用
%timeit。np.vectorize不会产生快速编译的代码;阅读其速度免责声明。如果没有有关您的功能的信息,我们将无能为力。 -
问题不在于我的功能。即使是带有返回零的函数的简单示例仍然很慢。问题在于我如何迭代坐标。用我的复杂函数迭代一个普通的 numpy 数组确实非常快。
-
请参阅github.com/astropy/astropy/issues/3323 了解有关此问题的一些长期讨论。认识到这是一个真正的问题,与初始化坐标对象有关。也许
fastiter()解决方案对您有用,如果您同意,请在 github 上投票。