Introduction Generally speaking, Python is not a high-performance language, in a sense, this statement is true. However, with the development of the ecosystem to Numpy centered math and science software package, to achieve a reasonable performance is not too difficult. When performance becomes a problem, the running time is usually determined Ladies Nike Blazers High Tops Leopard Print YellowB Air Jordan Outlet by several functions. Rewrite these functions using C, usually can greatly improve performance. In the first part of this series, we look at how to write a Python extension of the C language using NumPy C 378037 010 Original?CBlack-True Red-White Air Jordan 11 Retro Nike Kids Sneakers Factory Outlet API, in order Nike Basketball to improve the performance of the model. In a future article, we will be here to present our solutions to further improve its performance. Files involved in this article is available on Github. As the starting point of the simulation exercise, we will be under the influence of gravity as a force to be considered for the N-body simulation of 2D N body. The following is used to store the state of our world, as well as some temporary variables category. # Lib / sim.py class World (object): \u0026 quot; \u0026 quot; \u0026 quot; World is a structure that holds the state of N bodies and additional variables threads:.. (Int) The number of threads to use for multithreaded implementations STATE OF THE WORLD: N: (int) The number of bodies in the simulation m:. (1D ndarray) The mass of each body r:. (2D ndarray) The position of each body v:. (2D ndarray) The velocity of each body F:. (2D ndarray) Nike Air Jordan 5 Women The force on each body TEMPORARY VARIABLES:. Ft: (3D ndarray) A 2D force array for each thread's local storage s:. (2D ndarray) The vectors from one body to all others s3.: (1D ndarray) The norm of each s vector Lebron Slide 2 Elite NOTE: Ft is used by parallel algorithms for thread-local storage s and s3 are only used by the Python implementation \u0026 quot; \u0026 quot; \u0026 quot; def __init __ (self, N, threads... = 1, m_min = 1, m_max = Nike Basketball 30.0, r_max = 50.0, v_max = 4.0, dt = 1e-3): self.threads = threads self.N = N self.m = np.random.uniform (m_min, m_max, N) self.r = np.random.uniform (-r_max, r_max, (N, 2)) self.v = np.random.uniform (-v_max, v_max, (N, 2)) self.F = np. zeros_like (self.r) self.Ft = np.zeros ((threads, N, 2)) self.s = np.zeros_like (self.r) self.s3 = np.zeros_like (self.m) self.dt = dt at the start of simulation, N body were randomly assigned to mass m, the position r and velocity v. For each time step, the next calculation are: force F, force each body on another body in accordance with the calculation of all. Velocity v, due to the force of the speed of each body is changed. Position R, due to the position and speed of each body is changed. The first step is to calculate the force F, which will be our bottleneck. Due to other objects, the force on the existence of a single object in the world is the sum of all forces. This leads to a complexity of O (N ^ 2). Velocity v r update location and complexity are O (N). If you are interested in this Wikipedia article describes some approximation method can accelerate the computing power. Pure Python in pure Python, using NumPy array is a function of the time evolution of an implementation, it provides a starting point for the optimization and involves testing other implementations. # Lib / sim.py def compute_F (w): \u0026 quot; \u0026 quot; \u0026 quot; Compute the force on each body in the world, w \u0026 quot; \u0026 quot; \u0026 quot; for i in xrange (wN):. Ws [:] = wr - wr [i] w.s3 [:] = (ws [:, Nike Air Max 0] ** 2 + ws [:, 1] ** 2) ** 1.5 w.s3 [i] = 1.0 # This makes the self- .. force zero wF [i] = (wm [i] * wm [:, None] * ws / w.s3 [:, None]) sum (0) def evolve (w, steps): \u0026 quot; \u0026 quot; \u0026 2015 Nike Free 5.0 quot ; Evolve the world, w, through the given number of steps \u0026 quot; \u0026 quot; \u0026 quot; for _ in xrange (steps):. compute_F (w) wv + = wF * w.dt / wm [:, None] wr + = wv * w.dt force computational complexity of the phenomenon array notation O (N ^ 2) is NumPy masked. Each array operating through the array elements. Here are seven visual object evolution from random initial state of the road map: In order to achieve this benchmark performance, we created under the project directory with a script that contains the following: import lib Ladies Nike Blazers High Tops Leopard Print YellowB w = lib.World (101) lib.evolve ( w, 4096) we use cProfile module test measures the script. python -m few lines before cProfile -scum bench.py tell us, compute_F really is our bottleneck, it accounts for over 99% of the time. 428710 function calls (428521 primitive calls) in 16.836 seconds Ordered by: cumulative time ncalls tottime percall cumtime percall filename: lineno (function) 1 0.000 0.000 16.837 16.837 bench.py:2(\u0026lt;module\u0026gt;) 1 0.062 0.062 16.756 16.756 sim. py: 60 (evolve) 4096 15.551 0.004 16.693 0.004 sim.py:51(compute_F) 413696 1.142 0.000 1.142 0.000 {method 'sum' ... 3 0.002 0.001 0.115 0.038 Nike Blazers __init__.py:1(\u0026lt;module\u0026gt;) .. On the desktop Intel i5 101 body, this implementation can be through 257 time steps per second evolution of the world. Simple C extensions 1 In this section, we will see an evolution of C extension module function. When reading this section, which may help us to obtain a copy of a C file. File src / simple1.c, available on GitHub. Other documents on NumPy C API, see NumPy reference. Detailed documentation Python's C API here. Template file the first thing is to declare evolution functions. This method will be used directly in the list below. static PyObject * evolve (PyObject * self, PyObject * args); followed by Nike Air Max 2011 Men a list of methods. {}, {NULL, NULL, 0, NULL} / * Sentinel * / {\u0026 quot; evolve \u0026 quot ;, evolve, METH_VARARGS, \u0026 quot;.; Doc string \u0026 quot}; this is an export extension module static PyMethodDef methods [] = list of methods. This is only one method named evolve. The last part of the model is to initialize the module. PyMODINIT_FUNC initsimple1 (void) {(void) Py_InitModule (\u0026 quot; simple1 \u0026 quot ;, methods); import_array ();} Also, as shown here, initsimple1 the name must match Py_InitModule the first parameter. For each use NumPy API extensions, the call import_array is necessary. Array access macro array access macros can be used to correctly index in the array, regardless of how arrays are remodeling or slice. These macros can also use the following Mens Nike Free 3.0 V2 Shoes Black Blue code so that Lebron Slide 2 Elite they have a higher readability. #define m (x0) (* (npy_float64 *) ((PyArray_DATA (py_m) + \\ (x0) * PyArray_STRIDES (py_m) [0]))) # define m_shape (i) (py_m- \u0026 gt; dimensions [(i) ]) # define r (x0, x1) (* (npy_float64 *) ((PyArray_DATA (py_r) + \\ (x0) * PyArray_STRIDES (py_r) [0] + \\ (x1) * PyArray_STRIDES (py_r) [1])) ) #define r_shape (i) (py_r- \u0026 gt; dimensions [(i)]) Here we see the access macros one-dimensional and two-dimensional arrays. Having a higher dimensional array can be accessed in a similar manner. In these macros help, we can use the following code loops r: for (i = 0; i \u0026 lt; r_shape (0); ++ i) {for (j = 0; j \u0026 lt; r_shape (1); + + j) {r (i, j) = 0;. // Zero all elements}} name tag definition above macro, only matching NumPy array of objects define the correct name if valid. In the above code, the array is named py_m and py_r. In order to use the same name of the macro, NumPy arrays in a different approach needs to be consistent. Computing power especially with the above five elements compared to Python code, the method of computing power arrays have become quite cumbersome. static inline void compute_F (npy_int64 N, PyArrayObject * py_m, PyArrayObject * py_r, PyArrayObject * py_F) {npy_int64 i, j; npy_float64 sx, sy, Fx, Fy, s3, tmp;. // Set all forces to zero for (i = 0; Nike Air Max 2011 Men i \u0026 lt; N; ++ i) {F (i, 0) = F (i, 1) = 0;} // Compute forces between pairs of bodies for (i = 0;. i \u0026 lt; N; ++ i) {for (j = i + 1; j \u0026 lt; N; ++ j) {sx = r (j, 0) - r (i, 0); sy = r (j, 1) - r ( i, 1); s3 = sqrt (sx * sx + sy * sy); s3 * = s3 * s3; tmp = m (i) * m (j) / s3; Fx = tmp * sx; Fy = tmp * sy ; F (i, 0) + = Fx; F (i, 1) + = Fy; F (j, 0) - = Fx; F (j, 1) - = Fy;}}} Note that we use Newton Third Law (pairs of force equal in magnitude and opposite in direction) to reduce the inner range. Unfortunately, its complexity is still O (N ^ 2). Evolutionary function in this file is the last function evolution method export. static PyObject * evolve (PyObject * self, PyObject * args) {// Declare variables npy_int64 N, threads, steps, step, i;. npy_float64 dt; PyArrayObject * py_m, * py_r, * py_v, * py_F; // Parse arguments .! if (PyArg_ParseTuple (args, \u0026 quot; ldllO O O O \u0026 quot ;, \u0026 amp;!!!! threads, \u0026 amp; dt, \u0026 amp; steps, \u0026 amp; N, \u0026 amp; PyArray_Type, \u0026 amp; py_m, \u0026 amp; PyArray_Type, \u0026 amp ; py_r, \u0026 amp; PyArray_Type, \u0026 amp; py_v, \u0026 amp; PyArray_Type, \u0026 amp; py_F)) {return NULL;} // Evolve the world for (step = 0;. step \u0026 lt; steps; ++ step) {compute_F (N, py_m, py_r, py_F); for (i = 0; i \u0026 lt; N; ++ i) {v (i, 0) + = F (i, 0) * dt / m (i); v (i, 1 ) + = F (i, 1) * dt / m (i); r (i, 0) + = v (i, 0) * dt; r (i, 1) + = v (i, 1) * dt ;}} Py_RETURN_NONE;} Here, we see how the Python arguments are parsed. In the time step of the function at the bottom of the cycle, we have seen the speed and position of the vectors x and y components of the explicit calculation. Performance C version Python version faster than evolution method, this should not surprising. In the same i5 desktop mentioned above, the evolution of the method implemented in C can be achieved per 17 972 time steps. Compared Python implementation, in this respect, 70 fold increase. Observation note, C code is kept as simple as possible. Input parameters and output matrix can type checking, and assign a Python function decorator. Remove distribution, not only to speed up processing, and eliminates the Python object caused an incorrect reference counting memory leaks (or worse). The next section in the next part of this series of articles, our strengths NumPy matrix adjacent to enhance the performance of this implementation to play through C-. After that, we'll look at using Intel's SIMD instructions and OpenMP be further promoted. If you have any questions, comments, suggestions or corrections, please let me know via the contact link.performance Python extensions (1)