Enterprise Just Builder

Solution for Enterprise Software Architecture

python

PyDAAL 简介 (1)数据结构

Intel DAAL 是在针对英特尔架构优化过构建模块上编写的, 为所有数据分析阶段提供了支持。通过 DAAL, 数据驱动决策获得了包括数据获取、预处理、转换、数据挖掘、建模和验证等等基础支撑。Python 用户可以通过称为 PyDAAL 的 Python API 获取这些基础支撑。 利用 Python 进行机器学习时,你可以通过一个简单的脚本 API 来访问 PyDAAL。此外, PyDAAL 提供了独特功能, 可以轻松地将 Python 脚本化的批处理分析扩展到在线 (流) 数据获取和/或分布式数学处理。

在本系列文章中, 我们将从最基础的部分开始,逐一介绍 PyDAAL 的基础知识。第一部分将介绍 Intel DAAL 的自定义数据结构、数值表和数据管理在 PyDAAL 世界里的表示。1

一、PyDAAL 数据管理
Intel DAAL 支持以下几种数据处理方式:

  • 批处理
  • 在线处理
  • 分布式处理
  • 复杂处理(结合在线处理和分布式处理)

本文重点关注批处理方式。在线和分布式处理将在后面的文章中进行讨论。

编程方面的一些思考
强类型:Python 脚本大量使用了动态类型 (鸭子类型) , 借助于 Python 解释器在运行时来进行类型推断。但对于内存占用敏感或进行混合代码部署的情况, 这种做法可能会导致问题。PyDAAL API 调用了用 C++ 和汇编语言编写的库, 这迫使用户使用混合代码环境。因此, PyDAAL 需要一致的类型, 其支持 numpy 类型 “np.float32”, “np.float64”, 和 “np.intc” 。静态/强类型不仅允许显式声明数据类型以实现最佳内存管理, 还可以在编译过程中强制进行类型检查, 大大缩短了运行时间。

>>> 阅读全文

 

, , ,

用 libclang 实现代码生成器

文章评价:
代码生成器对大型 C++ 项目而言是非常有用的工具。由于语言层面上缺乏自省(introspection)机制,要实现反射、脚本绑定(script binding)及序列化都需要编写代码样板(boilerplate) 以保留相关信息,否则在编译时这些数据会全部被丢弃。大部分解决方案要嘛是侵入式的(严重依赖于宏 — Macro,结果难以调试且要求怪异的语法声明)要嘛非常脆弱(fragile)(要根据实际代码不断更新样板,常常没有任何警告就中止运行)。提高鲁棒性的方法之一是自动生成这类样板。要实现这一目标,需要用某种方式解析代码,换句话说,需要了解什么信息该被保留。然而,解析 C++ 本身就是极其复杂的工作,要考虑各种怪异情况,如果真想这样做,消费的时间可能相当漫长。 1

即使只针对 C++ 某个“差堪可用”的子集进行解析,这类尝试要嘛失败了要嘛对编码规则有严格要求。也就是说,要求避免使用解析器无法理解的语法 — 一旦有人不按规矩提交代码解析器就会中止工作。要解决这个问题,我发现 LLVM 项目中有一个很好的工具:libclang2。由于 CLANG C++ 前端 和 libclang 调用的代码是相同的,所以它了解 C++ 的一切。该类库的最新发布可以支持 C++1x(如不出意外将是 C++14)的功能。唯一略有欠缺的是文档方面:其官方文档不过是 Doxygen 生成的参考,虽然有用,但不足以介绍如何使用该类库;加上问题本身的复杂性,学习曲线将十分陡峭。

本文要讲述的是如何用 libclang 及其 Python 绑定来实现一个实用的 C++ 代码生成器。在某种意义上,“实用” 意味着这不是一个通用的解决方案。这里所演示的不是某种具体的实现,而是一种解决问题的思路、一个详细的范例。借助这些想法,你可以自己创建通用的反射方案。本文的另一设计原则是尽力减少代码侵入以便能按自然 C++ 语法编写代码。同时我也鼓励读者自己动手,从头开始尝试实现自己的代码生成器。

我必须感谢 Eli Bendersky 的有关帖子3,它是我收集的资料中最好的参考之一。

准备工作
要读懂本文,读者可能需要具备以下知识点:

>>> 阅读全文

 

, , , , ,

Python编写的强大的通用解析器

Spark 是一种用 Python 编写的强大的、通用的解析器/编译器框架。在某些方面,Spark 所提供的比 SimpleParse 或其它 Python 解析器要多得多。不过由于它完全是用 Python 编写的,所以速度也会比较慢。

我将在本文中继续介绍一些解析的基本概念,并对 Spark 模块进行了讨论。解析框架是一个内容丰富的主题,它值得多花时间去全面了解;这篇文章为读者和我自己都开了一个好头。

在日常的编程中,我经常需要标识存在于文本文档中的部件和结构,这些文档包括:日志文件、配置文件、定界的数据以及格式更自由的(但还是半结构化的)报表格式。所有这些文档都拥有它们自己的“小语言”,用于规定什么能够出现在文档内。我编写这些非正式解析任务的程序的方法总是有点象大杂烩,其中包括定制状态机、正则表达式以及上下文驱动的字符串测试。这些程序中的模式大概总是这样:“读一些文本,弄清是否可以用它来做些什么,然后可能再多读一些文本,一直尝试下去。”

解析器将文档中部件和结构的描述提炼成简明、清晰和说明性的规则,确定由什么组成文档。大多数正式的解析器都使用扩展巴科斯范式(Extended Backus-Naur Form,EBNF)上的变体来描述它们所描述的语言的“语法”。基本上,EBNF 语法对您可能在文档中找到的部件赋予名称;另外,较大的部件通常由较小的部件组成。小部件在较大的部件中出现的频率和顺序由操作符指定。

举例来说,清单 1 是 EBNF 语法 typographify.def,我们在 SimpleParse 那篇文章中见到过这个语法(其它工具运行的方式稍有不同):
  

>>> 阅读全文

 

, , , , , ,

编译Python源代码 为嵌入Python做准备

在上面几篇文章我们已经详细介绍如何在 C/C++ 程序中嵌入 Python 解释器,或者是利用 C/C++ 来扩展 Python 的功能。如果你从网上下载 Python 的 MSI 安装包中的类库和 Dll 文件来运行例子,很有可能你会遇到 access violation 异常,导致宿主程序崩溃。这是因为宿主程序和 Python 的 Dll 文件依赖于不同的 C 语言运行时。

为了提高应用的稳定性,建议应该采用目标编译器从头编译 Python 源代码。本文将详细介绍如何用 VC++ 8.0 和 VC++ 10.0 从头编译 Python 源代码,这里选用的是最新的 Python 2.7.2 版本。(Python 3.x 版本因为与 Python 2.X 版本语法不兼容,而未曾普遍使用)

Python 的标准库内置了许多功能, 如要完整的编译, 需要下载一些第三方的开源程序:

Python 2.7.2 对各软件的版本在 Python-2.7.2\PC\VS8.0\pyproject.props 中有定义,如果需要不同的版本,只需要修改pypoject.props 里的版本号即可,不过注意,高版本的软件包未必兼容于 Python 2.7.2。

这些源文件下载后需要解压到和 Python 2.7.2 同层的目录, 如下图所示,并需将文件夹的名字改为和图中一致:

>>> 阅读全文

 

,

在多线程C/C++应用中使用嵌入式Python

文章评价:
脚本语言是快速编写富有弹性的代码的重要方法之一,在 Unix 系统自动化管理中已经应用了多种脚本语言。现在,在许多应用开发中,也提供了脚本层,这大大方便用户实现通用任务自动处理或者编写应用扩展,许多成功的应用,诸如 GIMP、Emacs、MS Office、PhotoShop、AutoCAD 等都应用了脚本技术。在某种意义上,一切皆可脚本化。

在另一篇文章中,我们已经介绍了如何在 C 应用中嵌入 Python 语言,通过这项技术,可以让应用的高级用户来修改或定制化他们的程序,你可以充分利用 Python 的语言能力而不用自己去实现嵌入语言。Python 是一个不错的的选择,因为它提供了干净直观的 C 语言 API。关于如何在 C 应用中嵌入 Python 解释器,你可以参考:让 Python 成为嵌入式语言一文。

现在我们来更深入地探讨一些问题。 鉴于许多复杂的应用都会利用多线程技术,本文将着重介绍如何创建线程安全的界面来调用 Python 解释器。

这里的所有例子都是用 Python 2.7.2,所有的 Python 函数都以 extern “C” 定义,因此对于 C 和 C++,其使用是别无二致的。

Python C 和线程
在C程序中创建执行线程是很简单的。在 Linux 中,通常的做法是使用 POSIX 线程(pthread) API 并调用 pthread_create 函数。关于如何使用 pthreads,你可以参考 Felix Garcia 和Javier Fernandez 著的 “POSIX Thread Libraries”一文。为了支持多线程, Python 使用了互斥使访问内部数据结构串行化。这种互斥即 “全局解释器锁 – global interpreter lock”,当某个线程想使用 Python 的 C API 的时候,它必须获得全局解释器锁,这避免了会导致解析器状态崩溃的竞争条件(race condition)。

>>> 阅读全文

 

, ,

利用C语言扩展Python模块

文章评价:
Pyton 和 C 分别有着各自的优缺点,用 Python 开发程序速度快,可靠性高,并且有许多现成模块可供使用,但执行速度相对较 慢;C 语言则正好相反,其执行速度快,但开发效率低。为了充分利用两种语言各自的优点,比较好的做法是用 Python 开发整个软件框架,而用 C 语言实现其关键模块。本文介绍如何利用 C 语言来扩展 Python 的功能,并辅以具体的实例讲述如何编写Python的扩展模块。

与其它普通脚本语言有所不同,程序员可以借助 Python 语言提供的 API,使用 C 或者 C++ 来对 Python 进行功能性扩展,从而即可以利用 Python 方便灵活的语法和功能,又可以获得与 C 或者 C++ 几乎相同的执行性能。执行速度慢是几乎所有脚本语言都具有的共性,也是倍受人们指责的一个重要因素,Python 则通过与 C 语言的有机结合巧妙地解决了这一问题,从而使脚本语言的应用范围得到了很大扩展。

在用 Python 开发实际软件系统时,很多时候都需要使用 C/C++ 来对 Python 进行扩展。最常见的情况是目前已经存在一个用 C 编写的库,需要在 Python 语言中使用该库的某些功能,此时就可以借助 Python 提供的扩展功能来实现。此外,由于 Python 从本质上讲还是一种脚本语言,某些功能用 Python 实现可能很难满足实际软件系统对执行效率的要求,此时也可以借助 Python 提供的扩展功能,将这些关键代码段用 C 或者 C++ 实现,从而提 供程序的执行性能。

本文主要介绍 Python 提供的 C 语言扩展接口,以及如何使用这些接口和 C/C++ 语言来对 Python 进行功能性扩展,并辅以具体的实例讲述如何实现 Python 的功能扩展。

Python 的 C 语言接口

>>> 阅读全文

 

,

让Python成为嵌入式语言

文章评价:
C 和 C++ 这两种强大的语言可以创建高性能本地编译代码,其缺点也比较明显,即运行时的灵活性差。一旦 C/C++ 应用编译完成,代码基本是静态的,有时这会成为大问题。例如,如果想要通过创建插件来扩展应用的功能,就不得不处理复杂的动态链接问题,这一个大麻烦。而且还要求用户必须对 C/C++ 有所了解,这大大限制了编写应用扩展的人群。

更好的方法是用某种脚本语言来扩展应用。使用脚本语言,你可以获得更多运行时的灵活性,同时缩短开发时间,降低开发扩展的学习曲线。不幸的是,创建一种脚本语言是个艰巨的任何甚至本身就可能成为一个大问题。不过,我们可以利用现成的脚本语言。比如 Python,你可以将解释器直接嵌入在应用中,无需在应用中添加太多代码就能获得 Python 的强大功能和灵活性。

在应用中使用Python
在程序包含 Python 解释器是相当简单的。Ptyhon 提供了单一的头文件Python.h,包括了在应用中嵌入解释器的所有定义。其中包含很多内容,包括一些标准头文件。为了高效地编译,如果仅包括你用到的那部分接口固然不错,不过 Python 并未提供这个选项。如果你看过Python.h,你可以看到它定义了多个重要的宏,包括相当数量的公用头文件,这些都是文件后续的独立组件所需要的。

要将应用和 Python 解释器链接在一起,你需要运行python-config程序来获得链接选项,并将之传递给编译器。在我的系统上,参数是

-lpython27 -lm -L/usr/local/python27/libs

一个非常简单的嵌入应用

>>> 阅读全文

 

,

Ironruby与CLR语言的互操作 (一)

ironruby 是 .Net 平台下的一个 ruby 实现,众所周知,ruby 吸取了 Perl,python 等脚本语言的灵活性,带有实体对象模型,是一门动态/解释语言。从进入 ironruby 0.9.1 之后,ironruby 日趋稳定,之后发布的 Ironruby 1.0,兼容于 ruby 1.8.6,1.1 版本则增加了了对 .NET 扩展方法的支持,可以完美的运行 LINQ,目前开发中的 Ironruby 1.1.1 则是第一个兼容 ruby 1.9.2 的版本。

由于 IronRuby 是基于 .NET DLR,因此你可以在 IronRuby 中调用任何已有的 .NET 代码。这意味着可以在 IrongRuby 中使用任何框架,比如 Windows Forms、WPF 或者 GTK(#),因为.NET 和 Mono(分)拥有对这些框架的 CLI 绑定。Mono 甚至有一个使用GTK 实现的 Windows Forms,这样应用程序无须修改就可以运行在两个实现上。

Ironruby与CLR语言的互操作
IronRuby 带来的改变:
1. 与静态语言的互操作:IronRuby 与 .NET 框架集成的非常紧密,在 IronRuby 中调用 C#/VB 代码不会感觉是在使用“互操作”。C# 也可以通过 DLR Hosting API 调用 IronRuby 代码。而在 .NET 4.0 中,动态方法分配已经成为了 C# 的一部分,因此在 C# 中调用 IronRuby 代码和调用 C# 方法差不多。由于 IronRuby 基于 DLR,因此也可以方便的与其它 DLR 语言进行交互,如今 Python 和 Ruby 可以很好的合作,未来的 DLR 语言也一样可以。

2. 更稳定且丰富的支持,你可以抛弃 rubyforge 上许多质量不高的无人维护的 gems,改用 .Net 自身丰富的资源,你可以放弃ruby 中频繁变更的 win32api,而使用 .net 的 p/invoke,你可以放弃无人维护的 fireruby,而简单用 .net firebird provider 为自己添加 firebird 的 activerecord 支持而不用再担心找不到数据库的 activerecord 支持。

3. 为 .Net 带来 Rails,基于 Ironruby 0.9.2 你只需要对 rails 2.3.4 做一些小小的修改,就可以在 CLR/DLR 上运行最新的Rails,同时使用 Ironruby 也可以为.Net 的 MVC 框架带了许多新的变化,这些在后面会详述。

>>> 阅读全文

 

, , , , , , ,