嵌入C语言程序-weave

Python作为动态语言其功能虽然强大,但是在数值计算方面有一个最大的缺点:速度不够快。在Python级别的循环和计算的速度只有C语言程序的百分之一。因此才有了NumPy、SciPy这样的扩展库,将高度优化的C、Fortran的函数库进行包装,以供Python程序调用。如果这些高度优化的函数库无法实现我们的算法,必须从头开始写循环、进行数值运算,那么用Python来做显然是不合适的。因此SciPy提供了快速调用C++语言程序的方法:weave模块。下面的程序用weave模块调用C语言对NumPy的数组进行求和运算。

03-scipy/scipy_weave_sum_bentchmark.py

用weave模块调用C语言程序加快运行速度

import scipy.weave as weave
import numpy as np
import time

def my_sum(a):
    n=int(len(a))
    code="""
    int i;

    double counter;
    counter =0;
    for(i=0;i<n;i++){
        counter=counter+a(i);
    }
    return_val=counter;
    """

    err=weave.inline(
        code,   #
        ['a','n'],   #
        type_converters=weave.converters.blitz, #
        compiler="gcc"  #
    )
    return err

a = np.arange(0, 10000000, 1.0)
# 先调用一次my_sum,weave会自动对C语言进行编译,此后直接运行编译之后的代码
my_sum(a)

start = time.clock()
for i in xrange(100):
    my_sum(a)  # 直接运行编译之后的代码
print "my_sum:", (time.clock() - start) / 100.0

start = time.clock()
for i in xrange(100):
    np.sum( a ) # numpy中的sum,其实现也是C语言级别
print "np.sum:", (time.clock() - start) / 100.0

start = time.clock()
sum(a) # Python内部函数sum通过数组a的迭代接口访问其每个元素,因此速度很慢
print "sum:", time.clock() - start

此程序在笔者的电脑上的运行结果为:

my_sum: 0.0311053282622
np.sum: 0.0312218492456
sum: 12.1358849726

可以看到用weave模块编译的C语言程序和NumPy的sum()几乎一样快,而Python的内部函数sum()使用数组的迭代器接口进行运算,因此速度是Python语言级别的,只有weave版本的几百分之一。

❶weave.inline()的第一个参数是一个字符串,其内容为需要执行的C++语言代码。❷第二个参数是一个列表,它告诉inline()把Python中的变量a和n传递给C++程序,注意我们用字符串表示变量名。❸converters.blitz()是一个类型转换器,将NumPy的数组类型转换为C++的blitz类。C++程序中的变量a不是一个数组,而是blitz对象,因此它使用a(i)获得其各个元素的值,而不是用a[i]。❹最后我们通过compiler参数指定采用gcc作为C++编译器。

如果在编译时出现错误信息,请在命令行中输入’where gcc’查看MinGW编译器的安装路径。如果路径中存在空格或中文,请重新安装MinGW编译器到全英文的无空格路径之下。路径中的空格或中文可能会使Python无法正确调用它进行编译。

在本书的实战篇还会对weave模块进行详细介绍。这段程序让我们先吃了一颗定心丸:尽管使用Python解决你手头上的计算问题,不必在乎计算速度不够快,因为我们很容易将需要大量计算的部分使用C语言进行改写。

上一个主题

统计-stats

下一个主题

SymPy-符号运算好帮手

本页

loading...