当前位置: 首页 > 网络应用技术

如何更快地生成随机整数?python python中randint功能的效率缺陷

时间:2023-03-05 17:25:50 网络应用技术

  几天前,当我编写了一个与差异隐私有关的简单程序时,我发现了一些奇怪的事情:与其他随机数生成功能相比,Python的功能感觉非常慢。因为它是Python中最常用的API,我决定去深入研究其实施机制加深以了解其运营效率低的原因。

  本文讨论了随机模块的实现,并讨论了一些更快的替代方法来生成伪随机整数。

  首先,我们可以观察到运营效率:

  显然,在[0,128]中生成随机整数的成本约为[0,1)之间随机浮点数的20倍。

  接下来,我们将分析Python的源代码的实现机制。

  让我们从Random()开始。此函数在lib/andural.py文件中定义。该函数是随机类的随机方法的别名,随机方法直接从_random继承。如果您继续向下跟踪,您会发现该随机方法的真实定义是在模块/_randomboly.c中实现的。。实际上,当前代码如下:

  该函数是由C语言实现的泥工旋转算法,可以快速生成伪随机数。

  总而言之,当我们在Python中调用时,该函数直接调用C函数,而C函数的唯一函数是生成随机数并将结果转换为float -point号码。此外,没有额外的额外。

  现在让我们查看实现代码:

  该函数调用该函数,因此我们再次观察到的源代码。

  在调用函数的下一层之前,需要对功能参数进行大量检查。但是,如果我们不使用停止参数,则检查速度将更快。经过一堆检查后,我们可以调用该方法。

  默认情况下,它映射到:

  从该函数的源代码中,可以发现该功能的逻辑是计算n位数字的数量,然后根据位数量生成一个随机位。因此,当尺寸n不是2时,该函数可能需要多个调用。它是由C语言定义的函数,最终将调用此函数,但是由于该功能需要与Random()函数相比,它需要更多的处理过程跑步速度是两倍。

  总而言之,C可以通过Python代码或C代码来调用C的函数。由于Python由字节代码解释,在调用C函数之前,由Python语言定义的任何处理过程都会导致函数运行很多比直接调用C函数慢。

  以下是一些实验,可以帮助我们测试这个假设。首先,让我们尝试通过无参数在中间拨打参数并提高程序执行速度来减少中间参数检查过程:

  正如预期的那样,由于中间操作过程的减少,操作时间比原始时间更好。

  正如预期的那样,这些pypy中这些调用之间的差异很小。

  因此,randint()结果非常慢。需要生成少数随机数时,可以忽略该功能的性能损失。当需要生成大量随机数时,您需要找到一种高效率方法。

  一种技术是使用替换,乘以我们的整数限制来获得整数。由于Random()可以生成均匀的[0,1)分布,因此它在扩展后也可以在整数上获得均匀分布:

  这为我们提供了[0,128)范围内的伪随机整数,这要更快。应该指出的是:Python以双重精度代表其浮点,准确性为53位。53位,我们使用此方法获得的数字不是完全随机的,并且会丢失多个位。如果您不需要这么大的整数,则可以忽略此问题。

  生成伪随机整数的另一种快速方法是直接使用getrandbits():

  该方法很快,但是数据范围是有限的:它支持的范围为[0,2^n]。如果我们要限制范围,则不能限制成型方法 - 这会扭曲分布;因此,我们必须使用与上面示例类似的循环。但是它将放慢速度。

  最后,我们可以完全放弃随机模块并使用numpy:

  生成单个数据的速度非常慢。这是因为Numpy不适合单个数据:Numpy可以在C语言中创建或操作的大数组或操作上摊销成本。要证明这一点,这是100个随机的时间整数生成100个随机整数:

  比生成一个!每个整数0.019微秒慢60%,这是目前最快的方法 - 比调用快三次。此方法的原因太快了,numpy将呼叫的呼叫开销分布到所有生成的整数,并且运行有效的效率c循环在numpy中生成它们以生成它们。

  简而言之,如果要生成大量随机整数,建议使用numpy;如果它只是一代人之一,那么它可能不是特别有效。

  原始:https://juejin.cn/post/7097242084079304717