python — диагностика и улучшение скорости вычислений

У меня есть скрипт, который импортирует модуль geometryи этот модуль замедляет мой сценарий до крайнего уровня. Мой скрипт генерирует растровое изображение и для 16 миллионов пикселей это заняло бы 100+ часов

вот проблемный модуль:

'''
Created on 2 fevr. 2014

@author: gary
'''
#module name is: geometry.py

import numpy as np
import numpy.linalg as la
import tetgen

def barycentric_coords(vertices, point):
T = (np.array(vertices[:-1])-vertices[-1]).T
v = np.dot(la.inv(T), np.array(point)-vertices[-1])
v.resize(len(vertices))
v[-1] = 1-v.sum()
#print vertices
return v

def tetgen_of_hull(points):
tg_all = tetgen.TetGen(points)

hull_i = set().union(*tg_all.hull)
hull_points = [points[i] for i in hull_i]

tg_hull = tetgen.TetGen(hull_points)
return tg_hull, hull_i

def containing_tet(tg, point):
for tet in tg.tets:
verts = [tg.points[j] for j in tet]
bcoords = barycentric_coords(verts, point)
if (bcoords >= 0).all():
return bcoords
return None, None

это статистика, которую cProfile дает в моем скрипте, который использует функции, описанные выше, очевидно, именно на это и ушло время:

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
1291716   45.576    0.000  171.672    0.000 geometry.py:10(barycentric_coords)

6460649   31.617    0.000   31.617    0.000 {numpy.core.multiarray.array}
2583432   15.979    0.000   15.979    0.000 {method 'reduce' of 'numpy.ufunc'
objects}
2031   12.032    0.006  193.333    0.095 geometry.py:26(containing_tet)
1291716   10.944    0.000   58.323    0.000 linalg.py:244(solve)
1291716    7.075    0.000    7.075    0.000 {numpy.linalg.lapack_lite.dgesv}
1291716    5.750    0.000    9.865    0.000 linalg.py:99(_commonType)
2583432    5.659    0.000    5.659    0.000 {numpy.core.multiarray._fastCopyAn
dTranspose}
1291716    5.526    0.000    7.299    0.000 twodim_base.py:169(eye)
1291716    5.492    0.000   12.791    0.000 numeric.py:1884(identity)

Итак, вот мой вопрос:

numpy кажется, довольно медленно обрабатывает вычисление барицентрических координат, стоит ли это делать в c++? Или есть ли способ оптимизировать это по-другому (в Python)?

1

Решение

Источником реального времени, вероятно, будет инверсия матрицы, которую вы делаете в barycentric_coords:

    v = np.dot(la.inv(T), np.array(point)-vertices[-1])

Помните, что почти во всех случаях: Не инвертируйте эту матрицу!

Вы можете заменить эту строку на:

v = np.linalg.lstsq(T, np.array(point)-vertices[-1])[0]

Чтобы получить тот же результат с гораздо более быстрым решением наименьших квадратов.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]