Уведомления

Группа в Telegram: @pythonsu

#1 Июль 16, 2009 14:05:49

luckmaster
От:
Зарегистрирован: 2009-07-15
Сообщения: 16
Репутация: +  0  -
Профиль   Отправить e-mail  

Как эффективно использовать pyode?

В общем я использую pyode для расчета физики в 2D.
Все мне в нем нравится, но вот есть небольшая проблема - както медленно он работает. Например если свалить в кучу 30 объектов, то получаю около 15-30 fps, а если 40 объектов в кучу, то уже около 5-10 fps. Если разложить эти 40 объектов так чтобы они НЕ соприкасались друг с другом, то скорость значительно возрастает, но ведь мне то нужно чтобы они сталкивались :) Программу запускаю на машине - Athlon X2 2.2 GHz, RAM 2 GB.

И вот мне интиресно:
-такая сорость - это нормально для pyode?
-на сколько быстрее ode чем pyode?
-может надо знать какието премудрости чтобы эффективнее использовать pyode?


Вот привожу некоторые фрагменты кода, которые касаются pyode:

world = ode.World()
world.setGravity((0, -9.81, 0))
space = ode.Space()
#Вот таким образом создаю объекты
body = ode.Body(world)
m = ode.Mass()
m.setBox(density, lengths[0], lengths[1], lengths[2])
body.setMass(m)
geom = ode.GeomBox(space, (lengths[0], lengths[1], lengths[2]))
geom.setBody(body)
body.setPosition((x, y, 0))

#Это чтобы тело двигалось только в 2D
join2d = ode.Plane2DJoint(world)
join2d.attach(body, ode.environment)
#Эту функцию взял из туториала по pyode
def near_callback(args, geom1, geom2):
'''Callback function for the collide() method.

This function checks if the given geoms do collide and
creates contact joints if they do.
'''

# Check if the objects do collide
contacts = ode.collide(geom1, geom2)

# Create contact joints
world,contactgroup = args
for c in contacts:
c.setBounce(0.2)
c.setMu(5000)
j = ode.ContactJoint(world, contactgroup, c)
j.attach(geom1.getBody(), geom2.getBody())
#Этот блок каждый раз вызывается в главном цикле программы
contactgroup = ode.JointGroup()
n = 2
for i in range(n):
space.collide((world, contactgroup), near_callback)
world.step(dt / n)
contactgroup.empty()



Офлайн

#2 Июль 18, 2009 02:59:45

$m1t
От:
Зарегистрирован: 2006-12-31
Сообщения: 104
Репутация: +  0  -
Профиль   Отправить e-mail  

Как эффективно использовать pyode?

а там ни где нельзя например точность расчетов загрубить или шаг по времени при просчете физики крупнее сделать?



Офлайн

#3 Июль 18, 2009 05:24:07

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Как эффективно использовать pyode?

Там - нельзя.
pyode хорош “на попробовать”.
Но в живую callback на столкновение при приемлимой производительности можно писать только на C/C++
Питон все же долго считает элементарную математику - а еще дольше переводит ее между самим питоном и С.

Впрочем, можно попробовать такое:
- ставим Cython (PyRex тоже подойдет, но Cython не в пример лучше). Нужен вдобавок C compiler. На линухе gcc должна быть, на винде VC 7.1 для python 2.5 и VC 9 для 2.6 - и выше.
- пишем критический код на нем
- компилируем и смотрим на производительность

Будет хуже, чем на чистом ode. Но, быть может, подойдет.



Офлайн

#4 Июль 21, 2009 02:00:08

luckmaster
От:
Зарегистрирован: 2009-07-15
Сообщения: 16
Репутация: +  0  -
Профиль   Отправить e-mail  

Как эффективно использовать pyode?

$m1t
а там ни где нельзя например точность расчетов загрубить или шаг по времени при просчете физики крупнее сделать?
Ну вобще можно вот здесь увеличить dt и уменьшить n
#Этот блок каждый раз вызывается в главном цикле программы
contactgroup = ode.JointGroup()
n = 2
for i in range(n):
space.collide((world, contactgroup), near_callback)
world.step(dt / n)
contactgroup.empty()
Но я сейчас использую
dt = 1.0 / 30.0
n = 2
И всеравно так довольно медленно работает. А если еще больше упростить, то качество расчетов будет совсем уж низкое.

Андрей Светлов
Впрочем, можно попробовать такое:
- ставим Cython (PyRex тоже подойдет, но Cython не в пример лучше). Нужен вдобавок C compiler. На линухе gcc должна быть, на винде VC 7.1 для python 2.5 и VC 9 для 2.6 - и выше.
- пишем критический код на нем
- компилируем и смотрим на производительность
Спасибо, буду пробовать. Я правда впервые слышу о Cython и PyRex, но буду разбираться :)



Офлайн

#5 Июль 21, 2009 02:17:39

luckmaster
От:
Зарегистрирован: 2009-07-15
Сообщения: 16
Репутация: +  0  -
Профиль   Отправить e-mail  

Как эффективно использовать pyode?

Еще такой вопрос: а может можно както заставить pyode делать расчеты в 2-х измерениях?

Потому что в моем случае, хоть тела и движутся по плоскости, но ведь pyode всеравно приходится делать вычисления в 3D

#Это чтобы тело двигалось только в 2D
join2d = ode.Plane2DJoint(world)
join2d.attach(body, ode.environment)
А если откинуть одно измерение, то расчеты должны сильно упроститься и сорость возрастет…

Или может посоветуете какой-нибудь другой движек - более подходящий именно для 2D.



Офлайн

#6 Июль 23, 2009 01:09:54

$m1t
От:
Зарегистрирован: 2006-12-31
Сообщения: 104
Репутация: +  0  -
Профиль   Отправить e-mail  

Как эффективно использовать pyode?

luckmaster
еще можно не для всех объектов считать столкновения. Например только что столкнувшиеся, при низкой концентрации имеют малую вероятность столкнуться опять, их можно на некоторое время исключить.

Можно попробовать для каждого объекта хранить расстояние l до ближайшего соседа, которое обновлять каждые l/(2*v_средн) секунд, где v_средн средняя скорость объектов. Вместе с обновлением расстояния l можно пытаться просчитать для объекта столкновение.

Понятно, что этот метод будет давать ошибку, но интуитивно понятно, что энергия со временем должна равномерно распределиться между всеми объектами и можно будет пользоваться средними.

p.s. если у вас в задаче механика просчитывается решением диффуров, то можно использовать какой-нить продвинутый или сильно приближенный метод для их решения.



Отредактировано (Июль 23, 2009 01:15:59)

Офлайн

#7 Июль 23, 2009 14:24:37

luckmaster
От:
Зарегистрирован: 2009-07-15
Сообщения: 16
Репутация: +  0  -
Профиль   Отправить e-mail  

Как эффективно использовать pyode?

$m1t
Спасибо за хорошие идеи!
Мне правда было както лениво делать подобные расчеты самостоятельно, и я полез в документацию pyode в надежде найти там чтото подобное. И нашел у класса World 2 полезные функции :)

quickStep(stepsize)
Step the world.

setAutoDisableFlag(flag)
Set the default auto-disable flag for newly created bodies.

В общем получил увеличение скорости примерно на 700%, при том что качество симуляции практически не пострадало…



Офлайн

#8 Июль 23, 2009 14:28:24

Griffon
От: Ukrain, Zaporozhie
Зарегистрирован: 2009-03-04
Сообщения: 324
Репутация: +  11  -
Профиль   Отправить e-mail  

Как эффективно использовать pyode?

Построить сетку и контролировать наличие обьектов в одном квадрате и смежных. И соответственно запускать расчёт столкновения вручную для конкретных обьектов.
Плюс контроль критического расстояния, о чём говорилось выше.



Офлайн

#9 Июль 24, 2009 01:16:05

luckmaster
От:
Зарегистрирован: 2009-07-15
Сообщения: 16
Репутация: +  0  -
Профиль   Отправить e-mail  

Как эффективно использовать pyode?

Griffon
Построить сетку и контролировать наличие обьектов в одном квадрате и смежных. И соответственно запускать расчёт столкновения вручную для конкретных обьектов.
Еще немного порылся в документации pyode и нашел похожий алгоритм, он уже реализован в самом движке, его просто надо было включить :)

Type SpaceBase

This Space class can be used for both, a SimpleSpace and a HashSpace (see ODE documentation).
>>> space = Space(type=0) # Create a SimpleSpace
>>> space = Space(type=1) # Create a HashSpace
HashSpace - это оно.

P.S. Я вобще документацию к ode посмотрел, и почти на все свои вопросы там ответ нашел…



Отредактировано (Июль 24, 2009 01:18:36)

Офлайн

#10 Июль 29, 2009 09:04:28

Striver
От:
Зарегистрирован: 2006-10-26
Сообщения: 247
Репутация: +  22  -
Профиль   Отправить e-mail  

Как эффективно использовать pyode?

luckmaster: Если не сложно, напиши, что получилось после всех оптимизаций, какая скорость?

Тоже думал разобраться с pyode, хотелось бы знать, стоит ли…



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version