Python 什么';在Cython中处理分数的最好方法是什么?

Python 什么';在Cython中处理分数的最好方法是什么?,python,numpy,cython,Python,Numpy,Cython,我有一个np数组,其中的元素是分数形式的,用于机器精度。我想应用线性代数程序,比如高斯消去法。这是我到目前为止的Cython代码(注意,它只显示了获取上三角形式的步骤,但实际上并没有重新定义它) 以Python生成的数据: size = 5 foo = np.array([[Fc(v).limit_denominator(100) for v in r] for r in np.random.randn(size, size)]) identity = np.ar

我有一个np数组,其中的元素是分数形式的,用于机器精度。我想应用线性代数程序,比如高斯消去法。这是我到目前为止的Cython代码(注意,它只显示了获取上三角形式的步骤,但实际上并没有重新定义它)

以Python生成的数据:

size = 5
foo = np.array([[Fc(v).limit_denominator(100) for v in r]
                for r in np.random.randn(size, size)])
identity = np.array([[Fc(v) for v in r] for r in np.identity(len(foo))])
m_id = np.concatenate([foo, identity], axis=1)
赛顿:

%%cython
import numpy as np
cimport numpy as np
from quicktions import Fraction as Fc
cimport cython

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
def invert_gaussian4(np.ndarray matrix):

    cdef int matrix_size = matrix.shape[1] // 2
    cdef int c_i
    cdef int r_i
    cdef int swap

    for c_i in range(matrix_size - 1):
        swap = np.argmax(np.abs(matrix[c_i:, c_i])) + c_i
        matrix[[swap, c_i]] = matrix[[c_i, swap]]
        row = matrix[c_i, :] / matrix[c_i, c_i]
        for r_i in range(c_i+1, matrix_size):
            del_row = row * matrix[r_i, c_i]
            matrix[r_i, :] = matrix[r_i, :] - del_row

与Python相比,Cython函数的性能并没有多大提高。我已经认识到,循环和分数元素中的np函数调用是减慢代码速度的原因。关于如何更好地优化此代码,您有什么建议吗?

您可以提高速度,也可以保持极高的精度。你需要做出决定。

您在评论中说,这些数据用于“研究”,但没有指定领域。在相当多的研究领域中,产生的数据并不准确。相反,它们是通过测量真实世界的现象得到的近似值。我们说每个值都有许多有效数字。这些重要的数字将通过计算传播,最后,您需要舍入任何不重要的数字

虽然浮点数学确实涉及中间舍入,但这种舍入通常会保留足够多的有效数字,从而不会影响最终结果。例如,使用64位双精度IEEE 754浮点值(Python默认情况下会这样做),有效位在基数2中有53个有效数字,这相当于基数10中的有效数字。如果您的实际数据只有,比如说,五个有效数字,那么对于最合理的操作,您不应该关心中间舍入

如果这一段描述了您正在做的事情,那么您应该用标准浮点数替换分数对象。仅此一项就将大大加快您的计算速度

如果这不能准确地描述你在做什么(例如,因为你的领域是纯数学或其他理论学科的变体),那么你可能别无选择,只能忍受缓慢。你可能会看到,它被设计用来做这些领域倾向于关注的那种符号操作

如果您使用的是真实世界的数据,但它的有效位数超过15位,那么您应该知道64位整数的最高值只有~10^18。这意味着您的分数对象很可能是使用任意精度的整数实现的,这确实非常慢。在本例中,您希望使用支持128位整数和/或浮点的(超级计算)平台,并且可能不希望使用Python进行编码(阅读:对于这样一个平台,预编译的Python二进制文件可能存在,也可能不存在,并且取决于它的标准一致性,它们可能也可能不可能自己编译;不管性能如何,充其量也会有问题)


最后,您不应该编写自己的高斯消去例程。相反,使用。这可能会更快更精确。

您可以有速度,也可以保持极高的精度。您需要做出决定。

您在评论中说过,这些数据用于“研究”但是没有指定领域。在相当多的研究领域中,产生的数据并不精确。相反,它们是通过测量真实世界现象得到的近似值。我们说每个值都有许多有效数字。这些有效数字通过计算传播,最后,你可以我们希望把任何无关紧要的数字取整

虽然浮点数学确实涉及中间舍入,但这种舍入通常会保留足够多的有效数字,从而不会影响最终结果。例如,使用64位双精度IEEE 754浮点值(Python默认情况下会这样做),您的有效位在基数2中有53个有效数字,这相当于基数10中的有效数字。如果您的实际数据只有,比如说,五个有效数字,那么您不应该为最合理的操作考虑中间舍入

如果这一段描述了你正在做的事情,那么你应该用标准的浮点数替换分数对象。这将大大加快你的计算速度

如果这不能准确地描述你正在做什么(例如,因为你的领域是纯数学或其他理论学科的一个变种),那么你可能别无选择,只能忍受这种缓慢。你可以看看,这是设计用来做这些领域倾向于关注的那种符号操作的

如果您使用的是真实世界的数据,但它的有效位数超过15位,那么您应该知道64位整数的最高值只有~10^18。这意味着您的分数对象很可能是使用任意精度的整数实现的,这确实非常慢。在这种情况下,您希望使用(超级计算)平台,支持128位整数和/或浮点,您可能不想使用Python进行编码(阅读:对于这样一个平台,预编译的Python二进制文件可能存在,也可能不存在,并且取决于它的标准一致性,它们可能也可能不可能自己编译;不管性能如何,充其量也会有问题)


最后,您不应该编写自己的高斯消去例程。相反,使用。这可能会更快、更精确。

这个答案不会解决问题,但会解释您遇到问题的原因,并可能为您提供一些需要妥协的线索。基本上,您有两个问题:

1.您正在使用Python对象的numpy数组 如果numpy数组是由单个整数或fl组成的数组,那么Cython最适用于numpy数组