first question asked in StackOverflow, so tips on how to 'ask' better are most welcome.
Basic Goal of this part of the code: A number of balls (no_balls) move in random directions.
I am trying to move from python lists to numpy arrays for better performance. Here is the reduced code.
Basic Problem: My iterator gives me objects of type ndarray not vpy.sphere , therefore calling sphere.pos on the objects I am iterating over fails. Or is this not possible, since Numpy is build for numbers?? Alternatives for performance?
import vpython as vpy
import numpy as np
#Create and Fill numpy array with random size balls
balls = np.empty([no_ball], dtype=vpy.sphere)
with np.nditer(balls, flags=['refs_ok'], op_flags=['readwrite']) as b_it:
debug_msg(len(b_it))
for b in b_it:
b[...] = (vpy.sphere( radius=random_in_range(ball_min_r,ball_max_r),
opacity=0.8,
color=random_RGB(),
pos=vpy.vector(0,0,0),))
debug_msg('populated balls list')
#Main Loop
debug_msg('Starting Main Loop')
while True:
vpy.rate(30)
with np.nditer(balls, flags=['refs_ok'], op_flags=['readwrite']) as b_it:
#Main Loop
debug_msg('Starting Main Loop')
while True:
vpy.rate(30)
#The actual loop manipulates the position but the problem is that I can't access the position of the sphere objects. Type returns nd.array for b
for b in b_it:
debug_msg(type(b[...]))
debug_msg(b[...].pos)
#Above outputs
<class 'numpy.ndarray'>
Traceback (most recent call last):
File "path", line 93, in <module>
debug_msg(b[...].pos)
AttributeError: 'numpy.ndarray' object has no attribute 'pos'
How do I call methods and members of objects in the array. And on a sidenote, why do I need to call b[...] instead of b, seems obsolete.
A simple class:
A list of such objects:
An equivalent object dtype array:
Fetching the attribute from the list:
and from the array (slower):
Using
nditer
- you studied the docs enough to get the flags right, but didn't grasp thatb
is an array, not aFoo
:Fetching a list of the attribute:
And a poor timing:
One of the cleaner ways of performing an action on elements of an object array is with
frompyfunc
:Still slower than the iteration, though if we want an array instead of just a list, it is better than:
The
nditer
docs need a stronger performance disclaimer.nditer
when used inc
orcython
code is useful and fast, but when accessed via Python code it is inferior to more obvious alternatives. It's extra bells-n-whistles may be useful in some cases, but mostly I see it as a bridge to properly compiled code, not as an end of itself.At the heart of the performance issue is that
Foo
is a Python class. So accessing thei
attribute has to use the full Python referencing system. It can't make use of any of the fast compilednumpy
numeric methods.