- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我将一些使用 NumPy 的代码移植到 Cython 中以获得一些性能提升。我取得了相当大的进步,但我遇到了一个问题。
Cython 得到的结果与Python 得到的结果不同。我不知道为什么会这样,所以我决定查看将什么推送到 Cython 模块。
在到达 Cython 之前,数据如下所示:
azimuth = 0.000349065850399
rawDistance = [ 2.682 7.234 2.8 7.2 2.912 7.19 3.048 7.174 3.182 7.162
3.33 7.164 3.506 7.158 3.706 7.154 3.942 7.158 4.192 7.158
4.476 7.186 4.826 7.19 5.218 7.204 5.704 7.224 6.256 7.248
6.97 7.284]
intensity = [19 34 25 28 26 48 21 56 21 60 31 49 24 37 26 37 34 37 23 84 15 59 23 45
18 47 20 55 18 36 15 39]
一旦它进入 Cython,同样的数据看起来像:
azimuth = 0.000349065850399
rawDistance = [2.686, 7.23, 2.7960000000000003, 7.204, 2.91, 7.188, 3.044, 7.174, 3.19,
7.16, 3.3280000000000003, 7.16, 3.5, 7.154, 3.704, 7.144, 3.936, 7.158,
4.196, 7.156000000000001, 4.478, 7.19, 4.8260000000000005, 7.192, 5.22,
7.204, 5.708, 7.22, 6.256, 7.252, 6.97, 7.282]
intensity = [19, 34, 27, 28, 26, 48, 22, 52, 21, 60, 31, 49, 24, 37, 28, 34, 32, 37,
23, 84, 15, 59, 23, 45, 18, 47, 20, 58, 18, 36, 15, 36]
这就解释了为什么结果与纯Python方法计算的结果不完全一样。
这是信息被传输到的 Cython 模块:
from libc.math cimport sin, cos
import numpy as np
cimport numpy as np
cimport cython
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
def calculateXYZ(list frames, double[:] cosVertCorrection, double[:] sinVertCorrection):
cdef long numberFrames = len(frames)
cdef long i, j, k, numberBlocks
cdef list finalResults = []
cdef list intensities = []
cdef list frameXYZ = []
cdef double azimuth, xy, x, y, z, sinRotational, cosRotational
cdef double[32] rawDistance
cdef int[32] intensity
cdef double[:] tempX
cdef double[:] tempY
cdef double[:] tempZ
cdef int positionsFilled = 0
for i in xrange(numberFrames):
numberBlocks = len(frames[i])
tempX = np.zeros(numberBlocks * 32, dtype=np.double)
tempY = np.zeros(numberBlocks * 32, dtype=np.double)
tempZ = np.zeros(numberBlocks * 32, dtype=np.double)
frameXYZ = [[] for i in range(3)]
positionsFilled = 0
for j in xrange(numberBlocks):
# This is where I tested for the data in Cython
# This is the information that is different.
# It is reading from what was passed to it from python.
azimuth = frames[i][j][0]
rawDistance = frames[i][j][1]
intensity = frames[i][j][2]
sinRotational, cosRotational = sin(azimuth), cos(azimuth)
for k in xrange(32):
xy = rawDistance[k] * cosVertCorrection[k]
x, y = xy * sinRotational, xy * cosRotational
z = rawDistance[k] * sinVertCorrection[k]
if x != 0 or y != 0 or z != 0:
tempX[positionsFilled] = x
tempY[positionsFilled] = y
tempZ[positionsFilled] = z
intensities.append(intensity[k])
positionsFilled = positionsFilled + 1
frameXYZ[0].append(np.asarray(tempX[0:positionsFilled].copy()).tolist())
frameXYZ[1].append(np.asarray(tempY[0:positionsFilled].copy()).tolist())
frameXYZ[2].append(np.asarray(tempZ[0:positionsFilled].copy()).tolist())
finalResults.append(frameXYZ)
return finalResults, intensities
这是它的纯 Python 版本:
documentXYZ = []
intensities = []
# I tested to see what the original data was in here adding prints
for frame in frames:
frameXYZ = [[] for i in range(3)]
frameX, frameY, frameZ = [], [], []
for block in frame:
sinRotational, cosRotational = np.math.sin(block[0]), np.math.cos(block[0])
rawDistance, intensity = np.array(block[1]), np.array(block[2])
xy = np.multiply(rawDistance, cosVertCorrection)
x, y, z = np.multiply(xy, sinRotational), np.multiply(xy, cosRotational), np.multiply(rawDistance, sinVertCorrection)
maskXYZ = np.logical_and(np.logical_and(x, x != 0), np.logical_and(y, y != 0), np.logical_and(z, z != 0))
frameX += x[maskXYZ].tolist()
frameY += y[maskXYZ].tolist()
frameZ += z[maskXYZ].tolist()
intensities += intensity[maskXYZ].tolist()
frameXYZ[0].append(frameX), frameXYZ[1].append(frameY), frameXYZ[2].append(frameZ)
documentXYZ.append(frameXYZ)
我知道浮点值的精度可能存在差异(尽管我认为不应该存在,因为我在所有结构中都使用了 doubles
),但我不明白为什么作为整数的 intensity
值也被更改。我希望精度与 Python 中的精度相同。
关于如何改进这个的任何想法?
谢谢。
最佳答案
解决问题的前两个步骤是:
确定 NumPy 在您的平台上使用的特定整数类型(例如 int32
、int64
...),例如检查 dtype
整数数组的属性或其值之一。
确定int
的位宽在您的平台上使用您选择的 C 实现。通常它是 32 位,但并非总是如此(例如使用 sizeof
检查)。
一旦了解了这两个细节,您就可以确定以何种方式进行普通 (C) int
无法匹配 NumPy 一直使用的整数精度。一个常见的猜测是 NumPy 使用的是 int64
但在 C 中你使用的是 int
这可能是 int32
为您的平台/实现。另一个常见的情况是 NumPy 使用无符号整数,而在 C 中 int
将被签名,即使具有相同的位数也会导致不同的表示。
在Cython中可以很方便的引用定宽整数,至少有以下三种方式:
自从您使用了cimport numpy as np
可以引用NumPy的定宽整数类型,比如np.int64_t
或 np.uint8_t
. “_t”类型定义在 NumPy 的 Cython 支持中可用。
您可以尝试从您的 C 实现和平台中找出标准类型名称,例如 cython.longlong
对于 64 位整数或 cython.uchar
对于一个无符号的 8 位整数,它恰好对应于整数的正确位数和正确的符号性,以匹配 NumPy 使用的任何类型的精度和符号性。
也可以从C标准库导入,比如from libc.stdint import int64_t, uint8_t
如果您更喜欢将 C 的标准头文件用于指定大小的固定宽度整数。
假设您选择了合适的整数类型,然后您可以声明您的 intensity
具有正确类型的数组,例如以下任何一种,具体取决于您选择用于表达正确整数类型的方法:
cdef np.uint8_t[32] intensity # If using NumPy integer types
cdef uint8_t[32] intensity # If importing from libc.stdint
cdef cython.uchar[32] intensity # If using Cython integer types
最后一点,最好记住常规 Python 整数是无限精度的,所以如果您设法获得 int
的 NumPy 数组类型(不是 C int
,而是 Python int
),在 Cython 中工作时,您必须决定不同的固定精度表示,或者使用包含 Python int
的数组或类型化内存 View 。类型(这通常违背了首先使用 Cython 的目的)。
关于python - 一旦数据进入 Cython 模块,精度就会丢失/更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37625628/
我最近在我的机器上安装了 cx_Oracle 模块,以便连接到远程 Oracle 数据库服务器。 (我身边没有 Oracle 客户端)。 Python:版本 2.7 x86 Oracle:版本 11.
我想从 python timeit 模块检查打印以下内容需要多少时间,如何打印, import timeit x = [x for x in range(10000)] timeit.timeit("
我盯着 vs 代码编辑器上的 java 脚本编码,当我尝试将外部模块包含到我的项目中时,代码编辑器提出了这样的建议 -->(文件是 CommonJS 模块;它可能会转换为 ES6 模块。 )..有什么
我有一个 Node 应用程序,我想在标准 ES6 模块格式中使用(即 "type": "module" in the package.json ,并始终使用 import 和 export)而不转译为
我正在学习将 BlueprintJS 合并到我的 React 网络应用程序中,并且在加载某些 CSS 模块时遇到了很多麻烦。 我已经安装了 npm install @blueprintjs/core和
我需要重构一堆具有这样的调用的文件 define(['module1','module2','module3' etc...], function(a, b, c etc...) { //bun
我是 Angular 的新手,正在学习各种教程(Codecademy、thinkster.io 等),并且已经看到了声明应用程序容器的两种方法。首先: var app = angular.module
我正在尝试将 OUnit 与 OCaml 一起使用。 单元代码源码(unit.ml)如下: open OUnit let empty_list = [] let list_a = [1;2;3] le
我在 Angular 1.x 应用程序中使用 webpack 和 ES6 模块。在我设置的 webpack.config 中: resolve: { alias: { 'angular':
internal/modules/cjs/loader.js:750 return process.dlopen(module, path.toNamespacedPath(filename));
在本教程中,您将借助示例了解 JavaScript 中的模块。 随着我们的程序变得越来越大,它可能包含许多行代码。您可以使用模块根据功能将代码分隔在单独的文件中,而不是将所有内容都放在一个文件
我想知道是否可以将此代码更改为仅调用 MyModule.RED 而不是 MyModule.COLORS.RED。我尝试将 mod 设置为变量来存储颜色,但似乎不起作用。难道是我方法不对? (funct
我有以下代码。它是一个 JavaScript 模块。 (function() { // Object var Cahootsy; Cahootsy = { hello:
关闭。这个问题是 opinion-based 。它目前不接受答案。 想要改进这个问题?更新问题,以便 editing this post 可以用事实和引文来回答它。 关闭 2 年前。 Improve
从用户的角度来看,一个模块能够通过 require 加载并返回一个 table,模块导出的接口都被定义在此 table 中(此 table 被作为一个 namespace)。所有的标准库都是模块。标
Ruby的模块非常类似类,除了: 模块不可以有实体 模块不可以有子类 模块由module...end定义. 实际上...模块的'模块类'是'类的类'这个类的父类.搞懂了吗?不懂?让我们继续看
我有一个脚本,它从 CLI 获取 3 个输入变量并将其分别插入到 3 个变量: GetOptions("old_path=s" => \$old_path, "var=s" =
我有一个简单的 python 包,其目录结构如下: wibble | |-----foo | |----ping.py | |-----bar | |----pong.py 简单的
这种语法会非常有用——这不起作用有什么原因吗?谢谢! module Foo = { let bar: string = "bar" }; let bar = Foo.bar; /* works *
我想运行一个命令: - name: install pip shell: "python {"changed": true, "cmd": "python <(curl https://boot
我是一名优秀的程序员,十分优秀!