-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Port from mathutils.Vector to numpy ndarray #10
Comments
I have committed a first running version of the library, which uses a simple, not yet very optimized, port to numpy. Surprizingly, it is much slower than the previous version using mathutils.Vector. I am not yet sure if this port is a good idea. In the following I highlight some issues that explain the reasons just by numbers. numpy is slow to compute the magnitude of a vectorThe magnitude is quite often computed in the library. I define a 2D vector in both systems: A_mu = mathutils.Vector((1.543,5.497))
A_np = np.array((1.543,5.497)) Then I measured the execution time, even using a square root is faster than numpy.linalg.norm: print( 'mathutils:',timeit.timeit("a = A_mu.magnitude", number=1000000, globals=globals()) )
print( 'numpy 1: ',timeit.timeit("a = np.linalg.norm(A_np)", number=1000000, globals=globals()) )
print( 'numpy 2: ',timeit.timeit("a = np.sqrt(A_np[0]**2+A_np[1]**2)", number=1000000, globals=globals()) )
> mathutils: 0.1049282
> numpy 1: 13.433569
> numpy 2: 2.1385508 numpy is slow to normalize to a unit vector:print( 'mathutils:',timeit.timeit("a = A_mu.normalized()", number=1000000, globals=globals()) )
print( 'numpy 1: ',timeit.timeit("a = A_np / np.linalg.norm(A_np)", number=1000000, globals=globals()) )
print( 'numpy 2: ',timeit.timeit("a = A_np / np.sqrt(A_np[0]**2+A_np[1]**2)", number=1000000, globals=globals()) )
> mathutils: 0.1791930
> numpy 1: 15.281904
> numpy 2: 3.3529117 numpy has no equality operator for vectorsprint( 'mathutils:',timeit.timeit("a = A_mu == B_mu", number=1000000, globals=globals()) )
print( 'numpy: ',timeit.timeit("a = (A_np == B_np).all(0)", number=1000000, globals=globals()) )
> mathutils: 0.1171712
> numpy: 4.8632144 therefore, checking the presence in a list is slowT_mu is a mthutils.Vector and L_mu is a list of such vectors. T_np is a numpy vectorr and L_np is a list of such vectors. B_np is an array (a block) with numpy vectors a rows. print( 'mathutils : ',timeit.timeit("a = T_mu in L_mu", number=1000000, globals=globals()) )
print( 'numpy list : ',timeit.timeit("a = any((np.array(L_np)[:]==T_np).all(1))", number=1000000, globals=globals()) )
print( 'numpy block: ',timeit.timeit("a = any((B_np[:]==T_np).all(1))", number=1000000, globals=globals()) )
> mathutils : 0.18083845
> numpy list : 16.5957837
> numpy block: 5.24514710 Other issueIn contrast to a list, a numpy array is constructed as a contiguous memory block and can't be used to append or extend elements, as it is possible for a list. The function vstack() allows to append rows, but the result is in a new memory block and gets copied from the old. verts = np.vstack((verts,skeleton_nodes3D)) Therefore, the argument verts in the argument list of polygonize() does not get appended by the source vertices of the skeleton. For this experiment I just returned it as a function result (see also in demo.py). Attached here my test code discussed above: test_numpy_speed.py.zip |
Yes, I doesn't seem to be a good idea. I reproduced your results in Blender's Python. I got the same results for the dot and cross products: print( 'mathutils:', timeit.timeit("a = A_mu.dot(B_mu)", number=1000000, globals=globals()) )
print( 'numpy:', timeit.timeit("a = np.dot(A_np, B_np)", number=1000000, globals=globals()) )
print( 'mathutils:', timeit.timeit("a = A_mu.cross(B_mu)", number=1000000, globals=globals()) )
print( 'numpy:', timeit.timeit("a = np.cross(A_np, B_np)", number=1000000, globals=globals()) ) |
I got the same execution time for mathutils and numpy for the dot product of two vectors with 10.000 elements. |
The conversion to numpy wasn't certainly a good idea. |
Plain Python is better than either |
For consistency, the library shall use numpy arrays instead of mathutils.Vector. The development is moved to the branch dev_numpy.
The text was updated successfully, but these errors were encountered: