Fast way to iterate in python

I never had to worry about this problem, but now I need to use a number of vertices that need to be buffered by PyOpenGL and it seems like iteration in python is a bottleneck. Here is the situation. I have an array of three-dimensional vertices , and at each step I have to calculate a 4D array of colors for each vertex. So far my approach is:

 upper_border = len(self.vertices) / 3 #Only generate at first step, otherwise use old one and replace values if self.color_array is None: self.color_array = numpy.empty(4 * upper_border) for i in range(upper_border): #Obtain a color between a start->end color diff_activity = (activity[i] - self.min) / abs_diff clr_idx = i * 4 self.color_array[clr_idx] = start_colors[0] + diff_activity * end_colors[0] self.color_array[clr_idx + 1] = start_colors[1] + diff_activity * end_colors[1] self.color_array[clr_idx + 2] = start_colors[2] + diff_activity * end_colors[2] self.color_array[clr_idx + 3] = 1 

Now I donโ€™t think that there is anything else that I can do to exclude operations from each step of the loop, but I suppose there should be a more optimal way to execute this loop. I say this because, for example, in javascript, the same calculus creates 9FPS, and in Python I get only 2-3 FPS.

Regards, Bogdan

+4
source share
2 answers

To quickly make this code, you need to "vectorize" it: replace all explicit Python loops with implicit loops using the NumPy boradcasting rules. I can try and give a vector version of your loop:

 if self.color_array is None: self.color_array = numpy.empty((len(activity), 4)) diff_activity = (activity - self.min) / abs_diff self.color_array[:, :3] = (start_colors + diff_activity[:, numpy.newaxis] + end_colors) self.color_array[:, 3] = 1 

Please note that I had to guess a lot, since I'm not sure what all your variables are and what the code should do, so I cannot guarantee this code. I have turned color_array into a two-dimensional array as this seems more appropriate. This probably needs changes in other parts of the code (or you need to flatten the array again).

I assume that self.min and abs_diff are scalars, and all other names refer to NumPy arrays of the following forms:

 activity.shape == (len(vertices) // 3,) start_colors.shape == (3,) end_colors.shape == (3,) 

It also looks like vertices is a one-dimensional array and should be a two-dimensional array.

+12
source
  • First of all: your code profile with cProfile
  • You should use xrange instead of range
  • You should avoid calling self.color_array 4 times in each loop, try to create a local variable before the loop, and use it in the loop: local_array = self.color_array
  • try precomputing start_colors[N] and end_colors[N] : start_color_0 = start_colors[0]
  • try using list.extend () to cut lines in a loop:

     local_array.extend([ start_colors_0 + diff_activity * end_colors_0, start_colors_1 + diff_activity * end_colors_1, start_colors_2 + diff_activity * end_colors_2, 1 ]) 
+6
source

Source: https://habr.com/ru/post/1385902/


All Articles