热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

为什么c比python快_为什么C比python快得多?

我的目标是在Python中为频谱有限元编写一个小型库,为此我尝试使用Boost扩展python和C库,希望它能使我的代码更快.classQuad{public:Quad(i

我的目标是在

Python中为频谱有限元编写一个小型库,为此我尝试使用Boost扩展python和C库,希望它能使我的代码更快.

class Quad {

public:

Quad(int, int);

double integrate(boost::function const&)> const&);

double integrate_wrapper(boost::python::object const&);

std::vector nodes;

std::vector weights;

};

...

namespace std {

typedef std::vector > cube;

typedef std::vector mat;

typedef std::vector vec;

}

...

double Quad::integrate(boost::function const& func) {

double result = 0.;

for (unsigned int i = 0; i

result += func(nodes[i]) * weights[i];

}

return result;

}

// ---- PYTHON WRAPPER ----

double Quad::integrate_wrapper(boost::python::object const& func) {

std::function lambda;

switch (this->nodes[0].size()) {

case 1: lambda = [&func](vec const& v) -> double { return boost::python::extract(func (v[0])); }; break;

case 2: lambda = [&func](vec const& v) -> double { return boost::python::extract(func(v[0], v[1])); }; break;

case 3: lambda = [&func](vec const& v) -> double { return boost::python::extract(func(v[0], v[1], v[2])); }; break;

default: cout <<"Dimension must be 1, 2, or 3" <

}

return integrate(lambda);

}

// ---- EXPOSE TO PYTHON ----

BOOST_PYTHON_MODULE(hermite)

{

using namespace boost::python;

class_("double_vector")

.def(vector_indexing_suite())

;

class_("double_mat")

.def(vector_indexing_suite())

;

class_("Quad", init())

.def("integrate", &Quad::integrate_wrapper)

.def_readonly("nodes", &Quad::nodes)

.def_readonly("weights", &Quad::weights)

;

}

我比较了三种不同方法的性能来计算两个函数的积分.这两个功能是&#xff1a;

>函数f1(x,y,z)&#61; x * x

>一个更难评估的函数&#xff1a;f2(x,y,z)&#61; np.cos(2 * x 2 * y 2 * z)x * y np.exp(-z * z)np.cos(2 * x 2 * y 2 * z)x * y np.exp(-z * z)np.cos(2 * x 2 * y 2 * z)x * y np.exp(-z * z)np.cos (2 * x 2 * y 2 * z)x * y np.exp(-z * z)np.cos(2 * x 2 * y 2 * z)x * y np.exp(-z * z)

使用的方法是&#xff1a;

>从C程序调用库&#xff1a;

double func(vector v) {

return F1_OR_F2;

}

int main() {

hermite::Quad quadrature(100, 3);

double result &#61; quadrature.integrate(func);

cout <<"Result &#61; " <

}

>从Python脚本调用库&#xff1a;

import hermite

def function(x, y, z): return F1_OR_F2

my_quad &#61; hermite.Quad(100, 3)

result &#61; my_quad.integrate(function)

>在Python中使用for循环&#xff1a;

import hermite

def function(x, y, z): return F1_OR_F2

my_quad &#61; hermite.Quad(100, 3)

weights &#61; my_quad.weights

nodes &#61; my_quad.nodes

result &#61; 0.

for i in range(len(weights)):

result &#43;&#61; weights[i] * function(nodes[i][0], nodes[i][1], nodes[i][2])

以下是每种方法的执行时间(使用方法1的time命令测量时间,方法2和3使用python模块时间,使用Cmake和set编译C代码(CMAKE_BUILD_TYPE Release))

>对于f1&#xff1a;

>方法1&#xff1a;0.07s用户0.01s系统99&#xff05;cpu 0.083总计

>方法2&#xff1a;0.19s

>方法3&#xff1a;3.06s

>对于f2&#xff1a;

>方法1&#xff1a;0.28s用户0.01s系统99&#xff05;cpu 0.289总计

>方法2&#xff1a;12.47s

>方法3&#xff1a;16.31s

根据这些结果,我的问题如下&#xff1a;

>为什么第一种方法比第二种方法快得多&#xff1f;

>可以改进python包装器以达到方法1和方法2之间相当的性能吗&#xff1f;

>为什么方法2比方法3更难以集成函数的难度&#xff1f;

编辑&#xff1a;我还尝试定义一个接受字符串作为参数的函数,将其写入文件,然后继续编译文件并动态加载生成的.so文件&#xff1a;

double Quad::integrate_from_string(string const& function_body) {

// Write function to file

ofstream helper_file;

helper_file.open("/tmp/helper_function.cpp");

helper_file <<"#include \n#include \n";

helper_file <<"extern \"C\" double toIntegrate(std::vector v) {\n";

helper_file <<" return " <

helper_file.close();

// Compile file

system("c&#43;&#43; /tmp/helper_function.cpp -o /tmp/helper_function.so -shared -fPIC");

// Load function dynamically

typedef double (*vec_func)(vec);

void *function_so &#61; dlopen("/tmp/helper_function.so", RTLD_NOW);

vec_func func &#61; (vec_func) dlsym(function_so, "toIntegrate");

double result &#61; integrate(func);

dlclose(function_so);

return result;

}

它非常脏,可能不太便携,所以我很乐意找到一个更好的解决方案,但它运行良好,并且与sympy的ccode功能很好地配合.

第二次编辑我用纯粹的Python使用Numpy重写了这个函数.

import numpy as np

import numpy.polynomial.hermite_e as herm

import time

def integrate(function, degrees):

dim &#61; len(degrees)

nodes_multidim &#61; []

weights_multidim &#61; []

for i in range(dim):

nodes_1d, weights_1d &#61; herm.hermegauss(degrees[i])

nodes_multidim.append(nodes_1d)

weights_multidim.append(weights_1d)

grid_nodes &#61; np.meshgrid(*nodes_multidim)

grid_weights &#61; np.meshgrid(*weights_multidim)

nodes_flattened &#61; []

weights_flattened &#61; []

for i in range(dim):

nodes_flattened.append(grid_nodes[i].flatten())

weights_flattened.append(grid_weights[i].flatten())

nodes &#61; np.vstack(nodes_flattened)

weights &#61; np.prod(np.vstack(weights_flattened), axis&#61;0)

return np.dot(function(nodes), weights)

def function(v): return F1_OR_F2

result &#61; integrate(function, [100,100,100])

print("-> Result &#61; " &#43; str(result) &#43; ", Time &#61; " &#43; str(end-start))

有点令人惊讶(至少对我而言),此方法与纯C实现之间的性能没有显着差异.特别是,f1需要0.059s,f2需要0.36s.



推荐阅读
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • 展开全部下面的代码是创建一个立方体Thisexamplescreatesanddisplaysasimplebox.#Thefirstlineloadstheinit_disp ... [详细]
  • switch语句的一些用法及注意事项
    本文介绍了使用switch语句时的一些用法和注意事项,包括如何实现"fall through"、default语句的作用、在case语句中定义变量时可能出现的问题以及解决方法。同时也提到了C#严格控制switch分支不允许贯穿的规定。通过本文的介绍,读者可以更好地理解和使用switch语句。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有