优化乘法模数小素数

时间:2012-01-25 19:38:56

标签: python math cryptography

我需要执行以下操作许多次:

  1. 取两个整数a, b
  2. 计算a * b mod p,其中p = 1000000007a, bp的数量级相同
  3. 我的直觉是天真的

    result = a * b
    result %= p
    

    效率低下。我可以优化乘法模p,就像使用p优化取幂模pow(a, b, p)一样吗?

5 个答案:

答案 0 :(得分:11)

您提到a, b与p具有相同的数量级。”通常在加密中,这意味着a,bp附近的大数字,但严格低于p

如果是这种情况,那么您可以使用简单身份

a-p \equiv a \pmod{p}

将您的计算转换为

result = ((a-p)*(b-p))%p

然后你将一个大的乘法转换成两个大的减法和一个小的乘法。你必须分析一下,看哪个更快。

答案 1 :(得分:6)

要在汇编中进行此计算,但是可以从Python调用它,我会 从a尝试inline assembly Python module written in CGCCMSVC summary 编译器具有内联汇编功能,只有不同的语法。

请注意,我们的模数p = 1000000007恰好适合30位。结果 在某些弱点的情况下,可以在Intel 80x86寄存器中计算所需的(a*b)%pa,b的限制不比p大。

a,b

大小的限制

(1)a,b是32位无符号整数

(2)a*b小于p << 32,即p次2 ^ 32

特别是如果a,b每个都小于2*p,则会避免溢出。 给定(1),它们中的任何一个都小于p就足够了。

Intel 80x86指令MUL可以乘以两个32位无符号整数 并将64位结果存储在累加器寄存器对EDX:EAX中。一些 有用的第10.2.1节讨论了MUL的细节和怪癖 {{3}}

指令DIV然后可以将该64位结果除以32位常数 (模数p),将商存储在EAX中,余数存储在EDX中。 见最后一个链接的10.2.2节。我们想要的结果就是余数。

这种划分指令DIV应该存在溢出的风险 分子EDX中的64位乘积:EAX给出的商大于32位 不满足上述(2)。

我正在使用C / inline程序集中的代码片段来进行“概念验证”。 然而,速度的最大好处将取决于批处理数组 数据a,b来处理,分摊函数调用的开销等 Python(如果那是目标平台)。

答案 2 :(得分:2)

这不能直接回答这个问题,但如果您正在寻找性能,我建议不要在纯Python中执行此操作。一些选择:

  • 在C中创建一个用于计算的小型库,并使用Python的ctypes与之交谈。
  • 使用numpy;如果您不想自己处理编译内容,可能是最好的选择。一次执行一个操作并不比Python自己的操作符快,但是如果你可以将多个操作放在一个numpy数组中,那么对它们的计算将比Python中的等价物快得多。
  • 使用cython将变量声明为C整数;再次,和numpy一样,如果你批量生产,你将从中受益最多(因为那时你也可以优化循环)。

答案 3 :(得分:0)

虽然这非常简单,但您可以尝试使用基于mod p构建产品列表,在1000000007步骤上节省一些时间(列表的大小取决于{的大小{1}}和a)。测试每个模数(从最高开始)。当然,这仅在b时有用。

答案 4 :(得分:0)

如果您通过 许多 次澄清了您的意思,可能会有优化的线索,例如,如果您从高频循环中收集结果,循环可以提供优化常规的方法。

说未经优化的循环是:

p = 1000000007
b = 123456789
a = 0
while a < p:
    result = (a * b) % p
    dosomething(a, b, result)
    a += 1

你可以优化高频循环中的*和%:

p = 1000000007
b = 123456789
a = 0
result = (a * b) % p
while a < p:
    dosomething(a, b, result)
    a += 1
    result += b
    if result >= p:
        result -= p