Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Python can be faster than C


May 29, 2021 Article blog



Python is a very versatile programming language with thousands of third-party libraries for a wide range of applications in artificial intelligence, machine learning, automation, and more.
 Python can be faster than C1
As we all know, Python is a dynamic language, with a global interpreter lock, slower than other static languages, and that's why you might turn to other languages such as Java, C, but wait a minute, share a technique today that will make Python faster than C.
Today's protagonist is Numba, an open source instant compiler (JIT compiler) that converts Python and NumPy codes into fast machine codes for faster operation. C an reach the speed of C or FORTRAN. I sn't it hard to use such a cow? N o, No, No, So easy, you don't need to replace the Python interpreter, you don't need to compile it separately, you don't even need to install the C/C? compiler. S imply place the decorator provided by Numba on top of the Python function and leave the rest to Numba for completion. To give a simple example:
from numba import jit
import random

@jit(nopython=True)
def monte_carlo_pi(nsamples):
    acc = 0
    for i in range(nsamples):
        x = random.random()
        y = random.random()
        if (x ** 2 + y ** 2) < 1.0:
            acc += 1
    return 4.0 * acc / nsamples
Numba is designed for scientific computing, and when used with NumPy, Numba generates specialized code for different array data types to optimize performance:
@numba.jit(nopython=True, parallel=True)
def logistic_regression(Y, X, w, iterations):
    for i in range(iterations):
        w -= np.dot(((1.0 /
              (1.0 + np.exp(-Y * np.dot(X, w)))
              - 1.0) * Y), X)
    return w
Now let's look at the same code, using numba before and after the performance comparison with C. For example, if we want to find out all the prime numbers within 10 million, the algorithm logic of the code is the same: Python code:
import math
import time

def is_prime(num):
    if num == 2:
        return True
    if num <= 1 or not num % 2:
        return False
    for div in range(3, int(math.sqrt(num) + 1), 2):
        if not num % div:
            return False
    return True

def run_program(N):
    total = 0
    for i in range(N):
        if is_prime(i):
            total += 1
    return total


if __name__ == "__main__":
    N = 10000000
    start = time.time()
    total = run_program(N)
    end = time.time()
    print(f"total prime num is {total}")
    print(f"cost {end - start}s")
Time-consuming execution:
total prime num is 664579
cost 47.386465072631836s
The code for C+ is as follows:
#include <iostream>
#include <cmath>
#include <time.h>
using namespace std;


bool isPrime(int num) {

    if (num == 2) return true;
    if (num <= 1 || num % 2 == 0) return false;
    double sqrt_num = sqrt(double(num));
    for (int div = 3; div <= sqrt_num; div +=2){
       if (num % div == 0) return false;
    }
     return true;
}

int run_program(int N){

    int total = 0;
    for (int i; i < N; i++) {
        if(isPrime(i)) total ++;
    }
    return total;
}

int main()
{
    int N = 10000000;
    clock_t start,end;
    start = clock();
    int total = run_program(N);
    end = clock();
    cout << "total prime num is " << total;
    cout << "\ncost " << (end - start) / ((double) CLOCKS_PER_SEC) << "s\n";
    return 0;
}
$ g++ isPrime.cpp -o isPrime
$ ./isPrime
total prime num is 664579
cost 2.36221s
 Python can be faster than C2
It's true that c-C-plus is only 2.3 seconds, but the play is still behind us, and now we're using Numba to speed it up, it's simple, you don't need to change the original code, you don't need to change the original code, you import Numba's njit first, and then you put a decorator @njit above the function, and the rest stays the same, the code is as follows:
import math
import time
from numba import njit

# @njit 相当于 @jit(nopython=True) 
@njit
def is_prime(num):
    if num == 2:
        return True
    if num <= 1 or not num % 2:
        return False
    for div in range(3, int(math.sqrt(num) + 1), 2):
        if not num % div:
            return False
    return True

@njit
def run_program(N):
    total = 0
    for i in range(N):
        if is_prime(i):
            total += 1
    return total


if __name__ == "__main__":
    N = 10000000
    start = time.time()
    total = run_program(N)
    end = time.time()
    print(f"total prime num is {total}")
    print(f"cost {end - start}s")
Running, you can see that the time has been reduced from 47.39 seconds to 3 seconds.
total prime num is 664579
cost 3.0948808193206787s
It's still a little slower than the 2.3 seconds of C++, and you might say Python still can't. Wait, we still have room for optimization, which is Python's for loop, which is a 10 million loop, for which Numba provides the prange parameter to calculate in parallel, thus concurrently processing the loop statement, only need to modify range to prange, decorator pass a parameter: parallel , true, other unchanged, code changes as follows:
import math
import time
from numba import njit, prange

@njit
def is_prime(num):
    if num == 2:
        return True
    if num <= 1 or not num % 2:
        return False
    for div in range(3, int(math.sqrt(num) + 1), 2):
        if not num % div:
            return False
    return True

@njit(parallel = True)
def run_program(N):
    total = 0
    for i in prange(N):
        if is_prime(i):
            total += 1
    return total


if __name__ == "__main__":
    N = 10000000
    start = time.time()
    total = run_program(N)
    end = time.time()
    print(f"total prime num is {total}")
    print(f"cost {end - start}s")
Now run:
python isPrime.py
total prime num is 664579
cost 1.4398791790008545s
It's only 1.43 seconds, faster than C, numba's a real cow! I ran twice more to make sure I wasn't mistaken, averaging 1.4 seconds:  Python can be faster than C3
Python saw it here, and Numba made me passionate about Python again, and I didn't turn to C, Python was enough. H ow does Numba do that? T he official document says this: It reads the Python bytecode of the decorative function, combines it with information about the type of argument input to the function, analyzes and optimizes the code, and finally uses the Compiler Library (LLVM) to generate machine code tailored to your CPU. T his compiled version is used every time a function is called. N umba has more detailed usage, not much to say here, and please move on to the official documentation.

Last words

Python has solutions in almost every area, and the Numba library mentioned in this article is dedicated to addressing Python's underperformance in compute-intensive tasks, which can be very helpful if you're working in areas such as machine learning, data mining, and if this article is useful to you, like it, read it, and focus on support.

Reprinted from: Rookie Python

That's all you've got for you about what Python can do faster than C.