【问题标题】:Fast multiplication and subtraction modulo a prime以素数为模的快速乘法和减法
【发布时间】:2011-12-16 09:50:57
【问题描述】:

我需要优化一些代码,将整数向量(32 位)乘以模 p 标量(其中 p 是质数 (2^32)-5),然后从另一个模 p 向量中减去该向量.

代码如下:

public static void multiplyAndSubtract(long fragmentCoefficient, long[] equationToSubtractFrom, long[] equationToSubtract) {
    for (int i = 0; i < equationToSubtractFrom.length; i++) {
        equationToSubtractFrom[i] =  modP(equationToSubtractFrom[i] - multiplyModP(fragmentCoefficient, equationToSubtract[i]));
    }
}

我使用 long 是因为 Java 不支持无符号整数,但两个向量都是 mod p,因此您可以期望每个数字都是 0

有什么想法可以优化这个吗? mod p 操作占用了大部分执行时间,因此优化此操作的一种方法可能是在乘法后不执行 modP,而仅在减法后执行。关于如何做到这一点的任何想法?

【问题讨论】:

    标签: java performance optimization primes modulo


    【解决方案1】:

    使用 2^32 = 5 (mod p) 可以加快计算速度并避免任何除法。

    在乘法和减法之后,将结果分成低 (x%2^32) 和高 (x / 2^32) 部分。然后将高部分乘以 5 并与低部分相加。然后再次重复此过程。如果结果大于 p,则减去 p。对于否定结果,添加 p。

    编辑:由于组合的乘法和减法可能会溢出,所以乘法的结果也应该取模 p。但上述过程只需一步即可:拆分、乘以 5 并相加。

    【讨论】:

      【解决方案2】:

      我知道不使用除法或模数的两种方法:

      方法一:不变乘法。 (see this paper)

      这里的基本思想是预先计算和近似p 的倒数,这允许您只使用几个整数乘法来进行整数除法。然后你可以乘回并获得你的模数。这是更容易实现的方法。

      方法二:(我常用的那个),是用浮点数。将数字转换为浮点数并乘以预先计算的倒数 p。然后四舍五入并转换回整数。这种方法更难正确,但根据我的经验,如果做得好,速度会更快。

      除了预先计算整数或浮点数的倒数之外,这两种方法都不涉及除法。

      这两种方法是否比直接使用% 更快,将取决于您实现它们的能力。所以我不能保证哪一个会更快。

      【讨论】:

        【解决方案3】:
        e - (f * e mod p) mod p = (e-e f) mod p
        

        Wolfram Alpha

        【讨论】:

        • 谢谢。我尝试在乘法后删除 mod p 但现在我的回归测试失败了。我想我得到了某种形式的溢出错误。我会更仔细地研究它。
        猜你喜欢
        • 2021-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-19
        • 1970-01-01
        • 2011-04-10
        • 2017-01-25
        • 1970-01-01
        相关资源
        最近更新 更多