没有合适的资源?快使用搜索试试~ 我知道了~
Why Python is Slow: Looking Under the Hood
需积分: 9 3 下载量 131 浏览量
2018-01-25
18:40:02
上传
评论
收藏 517KB PDF 举报
温馨提示
Why Python is Slow: Looking Under the Hood # Why Python is Slow Python is slower than Fortran and C for a variety of reasons # Python meta-hacking: Don't take my word for it # Just for fun: a few "never use these" hacks
资源推荐
资源详情
资源评论
Fri 09 May 2014
Why Python is Slow: Looking Under the
Hood
We've all heard it before: Python is slow.
When I teach courses on Python for scientific computing, I make this point very early
(http://nbviewer.ipython.org/github/jakevdp/2013_fall_ASTR599/blob/master/notebooks/11_EicientNumpy.ipynb)
in the course, and tell the students why: it boils down to Python being a dynamically typed,
interpreted language, where values are stored not in dense buers but in scattered objects. And then
I talk about how to get around this by using NumPy, SciPy, and related tools for vectorization of
operations and calling into compiled code, and go on from there.
But I realized something recently: despite the relative accuracy of the above statements, the words
"dynamically-typed-interpreted-buers-vectorization-compiled" probably mean very little to
somebody attending an intro programming seminar. The jargon does little to enlighten people
about what's actually going on "under the hood", so to speak.
So I decided I would write this post, and dive into the details that I usually gloss over. Along the way,
we'll take a look at using Python's standard library to introspect the goings-on of CPython itself. So
whether you're a novice or experienced programmer, I hope you'll learn something from the
following exploration.
# Why Python is Slow
Python is slower than Fortran and C for a variety of reasons:
## 1. Python is Dynamically Typed rather than Statically
Typed.
What this means is that at the time the program executes, the interpreter doesn't know the type of
the variables that are defined. The dierence between a C variable (I'm using C as a stand-in for
compiled languages) and a Python variable is summarized by this diagram:
For a variable in C, the compiler knows the type by its very definition. For a variable in Python, all
you know at the time the program executes is that it's some sort of Python object.
So if you write the following in C:
/*Ccode*/
inta=1;
intb=2;
intc=a+b;
the C compiler knows from the start that a and b are integers: they simply can't be anything else!
With this knowledge, it can call the routine which adds two integers, returning another integer which
is just a simple value in memory. As a rough schematic, the sequence of events looks like this:
### C Addition
1. Assign <int>1 to a
2. Assign <int>2 to b
3. call binary_add<int,int>(a,b)
4. Assign the result to c
The equivalent code in Python looks like this:
#pythoncode
a=1
b=2
c=a+b
here the interpreter knows only that 1 and 2 are objects, but not what type of object they are. So
the The interpreter must inspect PyObject_HEAD for each variable to find the type information, and
then call the appropriate summation routine for the two types. Finally it must create and initialize a
new Python object to hold the return value. The sequence of events looks roughly like this:
### Python Addition
1. Assign 1 to a
1a. Set a‐>PyObject_HEAD‐>typecode to integer
1b. Set a‐>val=1
2. Assign 2 to b
2a. Set b‐>PyObject_HEAD‐>typecode to integer
2b. Set b‐>val=2
3. call binary_add(a,b)
3a. find typecode in a‐>PyObject_HEAD
3b. a is an integer; value is a‐>val
3c. find typecode in b‐>PyObject_HEAD
3d. b is an integer; value is b‐>val
3e. call binary_add<int,int>(a‐>val,b‐>val)
3f. result of this is result , and is an integer.
4. Create a Python object c
4a. set c‐>PyObject_HEAD‐>typecode to integer
4b. set c‐>val to result
The dynamic typing means that there are a lot more steps involved with any operation. This is a
primary reason that Python is slow compared to C for operations on numerical data.
## 2. Python is interpreted rather than compiled.
We saw above one dierence between interpreted and compiled code. A smart compiler can look
ahead and optimize for repeated or unneeded operations, which can result in speed-ups. Compiler
optimization is its own beast, and I'm personally not qualified to say much about it, so I'll stop there.
For some examples of this in action, you can take a look at my previous post
(http://jakevdp.github.io/blog/2013/06/15/numba-vs-cython-take-2/) on Numba and Cython.
## 3. Python's object model can lead to ineicient memory
access
We saw above the extra type info layer when moving from a C integer to a Python integer. Now
imagine you have many such integers and want to do some sort of batch operation on them. In
Python you might use the standard List object, while in C you would likely use some sort of buer-
based array.
A NumPy array in its simplest form is a Python object build around a C array. That is, it has a pointer
to a
contiguous
data buer of values. A Python list, on the other hand, has a pointer to a contiguous
buer of pointers, each of which points to a Python object which in turn has references to its data (in
this case, integers). This is a schematic of what the two might look like:
It's easy to see that if you're doing some operation which steps through data in sequence, the numpy
layout will be much more eicient than the Python layout, both in the cost of storage and the cost of
access.
## So Why Use Python?
Given this inherent ineiciency, why would we even think about using Python? Well, it comes down
to this: Dynamic typing makes Python easier to use than C. It's extremely flexible and forgiving,
this flexibility leads to eicient use of development time, and on those occasions that you really
need the optimization of C or Fortran, Python oers easy hooks into compiled libraries. It's why
Python use within many scientific communities has been continually growing. With all that put
together, Python ends up being an extremely eicient language for the overall task of doing science
with code.
# Python meta-hacking: Don't take my word for
it
Above I've talked about some of the internal structures that make Python tick, but I don't want to
stop there. As I was putting together the above summary, I started hacking around on the internals
of the Python language, and found that the process itself is pretty enlightening.
In the following sections, I'm going to
prove
to you that the above information is correct, by doing
some hacking to expose Python objects using Python itself. Please note that everything below is
written using Python 3.4. Earlier versions of Python have a slightly dierent internal object
structure, and later versions may tweak this further. Please make sure to use the correct version!
Also, most of the code below assumes a 64-bit CPU. If you're on a 32-bit platform, some of the C
types below will have to be adjusted to account for this dierence.
In[1]:
importsys
print("Pythonversion=",sys.version[:5])
## Digging into Python Integers
Integers in Python are easy to create and use:
In[2]:
x=42
print(x)
But the simplicity of this interface belies the complexity of what is happening under the hood. We
briefly discussed the memory layout of Python integers above. Here we'll use Python's built-in
ctypes module to introspect Python's integer type from the Python interpreter itself. But first we
Pythonversion=3.4.0
42
剩余23页未读,继续阅读
资源评论
about_itt
- 粉丝: 0
- 资源: 4
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- (源码)基于Java的医药管理系统.zip
- (源码)基于Java和MySQL的学生信息管理系统.zip
- (源码)基于ASP.NET Core的零售供应链管理系统.zip
- (源码)基于PythonSpleeter的戏曲音频处理系统.zip
- (源码)基于Spring Boot的监控与日志管理系统.zip
- (源码)基于C++的Unix V6++二级文件系统.zip
- (源码)基于Spring Boot和JPA的皮皮虾图片收集系统.zip
- (源码)基于Arduino和Python的实时歌曲信息液晶显示屏展示系统.zip
- (源码)基于C++和C混合模式的操作系统开发项目.zip
- (源码)基于Arduino的全球天气监控系统.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功