Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >一种将Python速度提高1000倍的解决方案

一种将Python速度提高1000倍的解决方案

作者头像
用户7466307
发布于 2021-04-22 03:28:21
发布于 2021-04-22 03:28:21
1.2K00
代码可运行
举报
运行总次数:0
代码可运行

人们说Python很慢,可能会很慢

每当出现编程速度竞赛时,Python通常都会走到最底层。有人说这是因为Python是一种解释语言。所有的解释语言都很慢。但是我们知道Java也是一种语言,它的字节码由JVM解释。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/python3-java.html

如本基准测试所示,Java比Python快得多。

这是一个可以演示Python慢度的示例。使用传统的for循环产生倒数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import numpy as np
np.random.seed(0)
values = np.random.randint(1, 100, size=1000000)
def get_reciprocal(values):
    output = np.empty(len(values))
    for i in range(len(values)):
        output[i] = 1.0/values[i]
%timeit get_reciprocal(values)

结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
每个循环3.37582毫秒(平均±标准偏差,共7次运行,每个循环1次)

神圣的xxx,计算1,000,000个倒数需要3.37s。C语言中的相同逻辑只需要眨一下就可以了:9ms ; C#需要19毫秒; Nodejs花费26ms ; Java需要5毫秒!而Python则采用了自我怀疑的3.37秒。(我在最后附加了所有测试代码)。

缓慢的根本原因

我们通常将Python称为动态类型编程语言。而且Python程序中的所有内容都是object,换句话说,每次Python代码处理数据时,都需要将对象包装拆箱。在for循环内部,每次迭代都需要拆箱对象,检查类型并计算倒数。那3秒钟都在类型检查中浪费了

与C之类的传统语言不同,对数据的访问是直接的,而在Python中,大量的CPU周期用于检查类型。

即使是简单的数字分配也将花费很长时间。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
a = 1
步骤1.设置a->PyObject_HEAD->typecode为整数
步骤2.设置a->val =1
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
那么,有没有一种方法可以解决类型检查,从而提高性能呢?

解决方案:NumPy通用函数

与Python列表不同,NumPy数组是围绕C数组构建的对象。NumPy中的访问项无需任何步骤即可检查类型。这使我们了解了解决方案,它是NumPy通用函数(又称UFunc)

简而言之,UFunc是一种我们可以直接对整个数组进行算术运算的方法。将第一个慢速Python示例转换为UFunc版本,它将像这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import numpy as np
np.random.seed(0)
values = np.random.randint(1, 100, size=1000000)
%timeit result = 1.0/values

此代码不仅可以提高速度,还可以缩短代码长度。猜猜现在需要多少时间?比我上面提到的任何其他语言快2.7ms

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
每个循环2.71 ms±50.8 µs(平均±标准偏差,共运行7次,每个循环100个)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
返回代码,关键是1.0/values。值这里是不是一个数字,它是一个NumPy的阵列。像除法运算符一样,还有很多其他运算符。

检查这里的所有Ufunc运营商。

对于那些使用Python的人,您很有可能使用Python处理数据和数字。这些数据可以存储在NumPy或Pandas DataFrame中,因为DataFrame是基于NumPy实现的。因此,Ufunc也可以。

UFunc使我们能够在Python中以数量级更快的速度执行重复操作。最慢的Python甚至可以比C语言更快。太棒了。

附录— C,C#,Java和NodeJS的测试代码

C语言:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>

int main(){
    struct timeval stop, start;
    gettimeofday(&start, NULL);
    int length = 1000000;
    int rand_array[length];
    float output_array[length];
    for(int i = 0; i<length; i++){
        rand_array[i] = rand();
    }
    for(int i = 0; i<length; i++){
        output_array[i] = 1.0/(rand_array[i]*1.0);
    }
    gettimeofday(&stop, NULL);
    printf("took %lu us\n", (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec); 
    printf("done\n");
    return 0;
}

C#(dotnet 5.0):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System;
namespace speed_test{
    class Program{
        static void Main(string[] args){
            int length = 1000000;
            double[] rand_array =new double[length];
            double[] output = new double[length];
            var rand = new Random();
            for(int i =0; i<length;i++){
                rand_array[i] = rand.Next();
                //Console.WriteLine(rand_array[i]);
            }
            long start = DateTimeOffset.Now.ToUnixTimeMilliseconds();
            for(int i =0;i<length;i++){
                output[i] = 1.0/rand_array[i];
            }
            long end = DateTimeOffset.Now.ToUnixTimeMilliseconds();
            Console.WriteLine(end - start);
        }
    }
}

Java:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.Random;

public class speed_test {
    public static void main(String[] args){
        int length = 1000000;
        long[] rand_array = new long[length];
        double[] output = new double[length];
        Random rand = new Random ();
        for(int i =0; i<length; i++){
            rand_array[i] = rand.nextLong();
        }
        long start = System.currentTimeMillis();
        for(int i = 0;i<length; i++){
            output[i] = 1.0/rand_array[i];
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
}

NodeJS:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let length = 1000000;
let rand_array = [];
let output = [];
for(var i=0;i<length;i++){
    rand_array[i] = Math.floor(Math.random()*10000000);
}
let start = (new Date()).getMilliseconds();
for(var i=0;i<length;i++){
    output[i] = 1.0/rand_array[i];
}
let end = (new Date()).getMilliseconds();
console.log(end - start);
代码语言:javascript
代码运行次数:0
运行
复制
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-04-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 软件测试test 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
4-Numpy通用函数
计算这百万个操作并存储结果需要几秒钟!甚至现在的手机的处理速度都以Giga-FLOPS衡量时(即每秒数十亿次数字运算)。 不过事实证明,这里的瓶颈不是操操作系统作本身,而是CPython在循环的每个循环中必须执行的类型检查和函数分派。 每次计算倒数时,Python都会首先检查对象的类型,并动态查找要用于该类型的正确函数。如果我们使用的是已编译的代码(静态语言的优势),则在代码执行之前便会知道此类型规范,并且可以更有效地计算结果。
用户1418372
2020/03/20
8660
数据科学 IPython 笔记本 9.5 NumPy 数组上的计算:通用函数
到目前为止,我们一直在讨论 NumPy 的一些基本要点;在接下来的几节中,我们将深入探讨 NumPy 在 Python 数据科学领域如此重要的原因。也就是说,它为数据数组的最优计算,提供了一个简单而灵活的接口。
ApacheCN_飞龙
2022/12/02
9450
NumPy学习笔记—(1/3)
想要有效的掌握数据驱动科学和计算需要理解数据是如何存储和处理的。本节将描述和对比数组在 Python 语言中和在 NumPy 中是怎么处理的,NumPy 是如何优化了这部分的内容。
可以叫我才哥
2021/08/05
1.5K0
Python代码转换成C++
Python和C++在代码结构上存在一些差异。Python是一种解释型语言,可以直接执行,而C++是一种编译型语言,需要先编译后执行。因此,在将Python代码转换为C++代码时,我们需要注意这些差异。
很酷的站长
2023/09/07
6470
Python必备基础:这些NumPy的神操作你都掌握了吗?
本文简单介绍NumPy模块的两个基本对象ndarray、ufunc,介绍ndarray对象的几种生成方法及如何存取其元素、如何操作矩阵或多维数组、如何进行数据合并与展平等。最后说明通用函数及广播机制。
IT阅读排行榜
2019/04/25
4.8K0
Python必备基础:这些NumPy的神操作你都掌握了吗?
一行代码让你的python运行速度提高100倍
python一直被病垢运行速度太慢,但是实际上python的执行效率并不慢,慢的是python用的解释器Cpython运行效率太差。
小小詹同学
2019/11/12
9150
这一行代码,能让你的 Python 运行速度提高 100 倍!
python一直被病垢运行速度太慢,但是实际上python的执行效率并不慢,慢的是python用的解释器Cpython运行效率太差。
杰哥的IT之旅
2020/09/30
6510
如何将数据处理速度提升1000+倍
利用Python进行数据处理时经常使用的是pandas和numpy,这两个工具的功能都很强大,尤其是pandas,更是Python中数据处理方面最强大的工具之一。
气象学家
2020/02/17
3.1K0
如何将数据处理速度提升1000+倍
python random randint_Python random.randint方法代码示例[通俗易懂]
本文整理汇总了Python中numpy.random.randint方法的典型用法代码示例。如果您正苦于以下问题:Python random.randint方法的具体用法?Python random.randint怎么用?Python random.randint使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在模块numpy.random的用法示例。
全栈程序员站长
2022/07/25
4510
Numpy 之ufunc运算
ufunc是universal function的缩写,它是一种能对数组的每个元素进行操作的函数。NumPy内置的许多ufunc函数都是在C语言级别实现的,因此它们的计算速度非常快。让我们来看一个例子:
用户6021899
2019/08/14
1.4K0
Numpy中的通用函数
NumPy数组的计算:通用函数缓慢的循环通用函数介绍探索Numpy的通用函数高级通用函数的特性聚合:最小值、 最大值和其他值数组值求和最大值和最小值其他聚合函数
用户3577892
2020/06/12
1.9K0
用 Taichi 加速 Python:提速 100+ 倍!
Python 已经成为世界上最流行的编程语言,尤其在深度学习、数据科学等领域占据主导地位。但是由于其解释执行的属性,Python 较低的性能很影响它在计算密集(比如多重 for 循环)的场景下发挥作用,实在让人又爱又恨。如果你是一名经常需要使用 Python 进行密集计算的开发者,我相信你肯定会有下面的类似经历:
自学气象人
2022/11/02
1.9K0
用 Taichi 加速 Python:提速 100+ 倍!
python之numpy
list1=[[“张三”,180,23], [“李四”,190,21]] list1=[[“张三”,180,23], [“李四”,190,21]] In [2]:
用户7886150
2021/01/03
4390
快速排序的4种优化[通俗易懂]
快排算法是基于分治策略的排序算法,其基本思想是,对于输入的数组 a[low, high],按以下三个步骤进行排序。
全栈程序员站长
2022/07/30
2K0
快速排序的4种优化[通俗易懂]
Python3快速入门(十二)——Num
NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,同时对数组运算提供了大量的数学函数库。 Numpy 是一个运行速度非常快的数学库,内部解除了CPython的GIL,运行效率极好,主要用于数组计算,是大量机器学习框架的基础库,NumPy主要包括如下: (1)强大的N维数组对象 ndarray (2)广播功能函数 (3)整合 C/C++/Fortran 代码的工具 (4)线性代数、傅里叶变换、随机数生成等功能。 NumPy 通常与 SciPy(Scientific Python)和 Matplotlib(绘图库)组合使用,用于替代 MatLab。
py3study
2020/01/06
4.7K0
Python NumPy缓存优化与性能提升
NumPy 是 Python 中进行科学计算和数据处理的核心库,其强大的多维数组操作功能让其在计算密集型任务中表现优异。然而,当处理大规模数据时,性能问题可能成为瓶颈。合理地利用 NumPy 的缓存机制和优化策略,可以显著提升计算效率。
sergiojune
2024/12/23
1420
Python NumPy缓存优化与性能提升
tensorflow为什么要用placeholder()
Tensorflow的设计理念称之为计算流图,在编写程序时,首先构筑整个系统的graph,代码并不会直接生效,这一点和python的其他数值计算库(如Numpy等)不同,graph为静态的,类似于docker中的镜像。然后,在实际的运行时,启动一个session,程序才会真正的运行。这样做的好处就是:避免反复地切换底层程序实际运行的上下文,tensorflow帮你优化整个系统的代码。我们知道,很多python程序的底层为C语言或者其他语言,执行一行脚本,就要切换一次,是有成本的,tensorflow通过计算流图的方式,帮你优化整个session需要执行的代码,还是很有优势的。
狼啸风云
2022/10/05
7060
Python可以比C++更快,你不信?
Python 是一个用途非常广泛的编程语言,拥有成千上万的第三方库,在人工智能、机器学习、自动化等方面有着广泛的应用,众所周知,Python 是动态语言,有全局解释器锁,比其他静态语言要慢,也正是这个原因,你也许会转向其他语言如 Java、C++,不过先等等,今天分享一个可以让 Python 比 C++ 还要快的技术,看完再决定要不要转吧。
somenzz
2021/04/16
9600
基于Python装饰器的向量化计算速度对比
timer是一个装饰器,功能是给被装饰的函数计时。如果要进一步了解装饰器的使用,点击此链接Python闭包函数和装饰器 sumOfLoop函数是常规的使用for进行循环遍历求和的方法; sumOfComprehension函数使用推导式得出新的列表,然后用内置sum函数求出列表的和; sumOfVectorization函数使用np.dot方法求出两个数据类型的为numpy.ndarray的对象的点积,两个向量a = [a1, a2,…, an]和b = [b1, b2,…, bn]的点积定义为:a·b=a1b1+a2b2+……+anbn。 np.random.rand()方法需要传入一个参数,例如传入参数为5,则返回一个数据类型为numpy.ndarray、长度为5、其中元素的值范围为0-1的对象,如下图所示:
潇洒坤
2018/09/10
4780
基于Python装饰器的向量化计算速度对比
《利用Python进行数据分析·第2版》第4章 NumPy基础:数组和矢量计算4.1 NumPy的ndarray:一种多维数组对象4.2 通用函数:快速的元素级数组函数4.3 利用数组进行数据处理4.
NumPy(Numerical Python的简称)是Python数值计算最重要的基础包。大多数提供科学计算的包都是用NumPy的数组作为构建基础。 NumPy的部分功能如下: ndarray,一个具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组。 用于对整组数据进行快速运算的标准数学函数(无需编写循环)。 用于读写磁盘数据的工具以及用于操作内存映射文件的工具。 线性代数、随机数生成以及傅里叶变换功能。 用于集成由C、C++、Fortran等语言编写的代码的A C API。 由于NumPy提供了一个
SeanCheney
2018/04/24
4.9K0
《利用Python进行数据分析·第2版》第4章 NumPy基础:数组和矢量计算4.1 NumPy的ndarray:一种多维数组对象4.2 通用函数:快速的元素级数组函数4.3 利用数组进行数据处理4.
推荐阅读
相关推荐
4-Numpy通用函数
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验