Python可以比C++更快,你不信?

休闲2025-11-05 13:45:352829

 Python 是你不信一个用途非常广泛的编程语言,拥有成千上万的可比快第三方库,在人工智能、你不信机器学习、可比快自动化等方面有着广泛的你不信应用,众所周知,可比快Python 是你不信动态语言,有全局解释器锁,可比快比其他静态语言要慢,你不信也正是可比快这个原因,你也许会转向其他语言如 Java、你不信C++,可比快不过先等等,你不信今天分享一个可以让 Python 比 C++ 还要快的可比快技术,看完再决定要不要转吧。你不信

今天的主角就是 Numba,Numba 是一个开源的即时编译器(JIT compiler),可将 Python 和 NumPy 的代码的转换为快速的机器码,从而提升运行速度。可以达到 C 或 FORTRAN 的b2b供应网速度。

这么牛逼是不是很难用呢?No,No,No,So easy,你不需要替换 Python 解释器,不需要单独编译,甚至不需要安装 C / C ++ 编译器。只需将 Numba 提供的装饰器放在 Python 函数上面就行,剩下的就交给 Numba 完成。举个简单的例子: 

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 是专为科学计算而设计的,在与 NumPy 一起使用时,Numba 会为不同的数组数据类型生成专门的代码,以优化性能: 

@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 

现在我们来看看,同样的代码,使用 Numba 前后与 C++ 的性能对比。比如说我们要找出 1000 万以内所有的素数,代码的算法逻辑是相同的: 

Python 代码:  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") 

执行耗时: 

total prime num is 664579  cost 47.386465072631836s 

C++ 代码如下: 

#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 sqrtsqrt_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) << "sn";      return 0;  }   $ g++ isPrime.cpp -o isPrime  $ ./isPrime  total prime num is 664579  cost 2.36221s 

c++

C++ 确实牛逼,才 2.3 秒,不过好戏还在后头,现在我们使用 Numba 来加速一下,站群服务器操作很简单,不需要改动原有的代码,先导入 Numba 的 njit,再在函数上方放个装饰器 @njit 即可,其他保持不变,代码如下: 

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") 

运行一下,可以看出时间已经从 47.39 秒降低到 3 秒。 

total prime num is 664579  cost 3.0948808193206787s 

相比 C++ 的 2.3 秒还是有一点慢,你可能会说 Python 还是不行啊。等一等,我们还有优化的空间,就是 Python 的 for 循环,那可是 1000 万的循环,对此,Numba 提供了 prange 参数来并行计算,从而并发处理循环语句,只需要将 range 修改为 prange,装饰器传个参数:parallel = True,其他不变,代码改动如下: 

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") 

现在运行一下: 

python isPrime.py  total prime num is 664579  cost 1.4398791790008545s 

才 1.43 秒,比 C++ 还快,Numba 真的牛逼!源码下载我又运行了两次,确认自己没看错,平均就是 1.4 秒:

Python

看到这里,Numba 又让我燃起了对 Python 的激情,我不转 C++ 了,Python 够用了。

Numba 如何做到的呢?官方文档这样介绍:它读取装饰函数的 Python 字节码,并将其与有关函数输入参数类型的信息结合起来,分析和优化代码,最后使用编译器库(LLVM)针对你的 CPU 生成量身定制的机器代码。每次调用函数时,都会使用此编译版本,你说牛逼不?

Numba 还有更多详细的用法,这里不多说,想了解的请移步官方文档[1]。

最后的话

Python 几乎在每一个领域都有对应的解决方案,本文提到的 Numba 库就是专门解决 Python 在计算密集型任务方面性能不足的问题,如果你从事机器学习、数据挖掘等领域,这个会非常有帮助,如果本文对你有用,请点赞、在看、关注支持。 

本文地址:http://www.bzuk.cn/html/142b30199556.html
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

热门文章

全站热门

假如你在Debian或Ubuntu系统上经常感觉到apt-get 或 aptitude包安装速度过慢,那么这里就有几种改善这一情况的方法。你有没有考虑过改变正被使用的默认镜像站点?你有没有排除因特网连接的上游带宽成为瓶颈的可能?假如不是这些原因,你可以尝试第三个选择:使用apt-fast工具。apt-fast实际上是一个围绕apt-get和aptitude所写的shell脚本容器,它能加速包的下载速度。apt-fast本质上采用aria2下载工具,这款工具能够以“块”的方式从多个镜像并行下载一个文件(就像BitTorrent下载)。在Debian或Ubuntu上安装apt-fast下面是在基于Debian的Linux上安装apt-fast的步骤Debian复制代码代码如下: $ sudo apt-get install aria2 $ wget https://github.com/ilikenwf/apt-fast/archive/master.zip $ unzip master.zip $ cd apt-fast-master $ sudo cp apt-fast /usr/bin $ sudo cp apt-fast.conf /etc $ sudo cp ./man/apt-fast.8 /usr/share/man/man8 $ sudo gzip /usr/share/man/man8/apt-fast.8 $ sudo cp ./man/apt-fast.conf.5 /usr/share/man/man5 $ sudo gzip /usr/share/man/man5/apt-fast.conf.5Ubuntu 14.04 以及更高版本复制代码代码如下:$ sudo add-apt-repository ppa:saiarcot895/myppa $ sudo apt-get update $ sudo apt-get install apt-fastUbuntu 11.04 到 Ubuntu 13.10复制代码代码如下:$ sudo add-apt-repository ppa:apt-fast/stable $ sudo apt-get update $ sudo apt-get install apt-fast在安装期间,你需要选择一个默认的软件包管理器 (e.g., apt-get. aptitude ),还需要设置其余选项。但是你可以随时通过编辑配置文件 /etc/apt-fast/conf 来更改设置。配置 apt-get安装完成后,你需要在/etc/apt-fast.conf里配置apt-fast使用的一系列镜像。你可以在下面的URL中找到一系列Debian/Ubuntu镜像。 Debian: http://www.debian.org/mirror/list Ubuntu: https://launchpad.net/ubuntu/+archivemirrors选择完那些地理上靠近你的镜像后,你需按照下面的格式将选择的镜像加入到/etc/apt-fast.conf。复制代码代码如下: $ sudo vi /etc/apt-fast.confDebian:复制代码代码如下:MIRRORS=(http://ftp.us.debian.org/debian/,http://carroll.aset.psu.edu/pub/linux/distributions/debian/,http://debian.gtisc.gatech.edu/debian/,http://debian.lcs.mit.edu/debian/,http://mirror.cc.columbia.edu/debian/)Ubuntu/Mint:复制代码代码如下:MIRRORS=(http://us.archive.ubuntu.com/ubuntu,http://mirror.cc.columbia.edu/pub/linux/ubuntu/archive/,http://mirror.cc.vt.edu/pub2/ubuntu/,http://mirror.umd.edu/ubuntu/,http://mirrors.mit.edu/ubuntu/)如上面所示,对于一个特定档案的个别镜像,需要用逗号分割开来。你需要在/etc/apt/sources.list的MIRRORS字符串中包含默认的镜像指定站点。使用apt-fast安装一个包现在你就可以测试apt-fast的强大了。下面是使用apt-fast的示例:复制代码代码如下:apt-fast [apt-get options and arguments] apt-fast [aptitude options and arguments] apt-fast { { install | upgrade | dist-upgrade | build-dep | download | source } [ -y | --yes | --assume-yes | --assume-no ] ... | clean }使用apt-fast安装包:复制代码代码如下:$ sudo apt-fast install texlive-full在当前目录下载软件包,但不安装:复制代码代码如下:$ sudo apt-fast download texlive-full 如前面所示,apt-fast的并行下载是通过aria2完成的。你可以看到如下图般从多个镜像并行下载。复制代码代码如下:$ sudo netstat -nap | grep aria2c 请注意,apt-fast并没有加速apt-get update。并行下载只在install, upgrade, dist-upgrage和build-dep操作中触发。其余的操作,apt-fast就会简单地回到默认的包管理器apt-get或aptitude。apt-fast有多快?为了比较apt-fast和apt-get,我尝试在两个相同的Ubuntu实例上使用两种方法安装几个软件包。下面的图表展示了所有软件包安装的时间(单位为秒)。正如你所见到的,apt-fast确实比apt-get快(e.g. 快3--4秒),特别是安装庞大软件包的时候。当然,安装性能的提高程度还依赖你上游因特网连通性。以我为例,我有富足的带宽来支持我的上游连接。这也是为什么我看到并行下载带来了成功的提高。

Spring Boot打包不同环境配置与Shell脚本部署

2020年想成为前端开发工程师,这个学习路线收藏起来

在Scrapy中如何利用CSS选择器从网页中采集目标数据——详细教程(上篇)

电脑程序explorer错误及解决方法(如何应对电脑程序explorer错误以确保正常运行)

东汉末年,他们把「服务雪崩」玩到了极致

GitHub十大Python项目推荐,Star最高26.4k

编程不用程序员!低代码是炒作还是趋势?

友情链接

滇ICP备2023006006号-33