问题描述
我正在使用Daniel Lemire建议的随机数生成器。使用gcc -O3
进行编译时,它在C中非常有效。只需 3.9秒即可生成 10 ^ 9 个随机数。但是,当我在Python中调用C函数时,它慢了大约 100倍。
这是C代码:
#include <stdint.h>
static __uint128_t g_lehmer64_state = (__uint128_t)513543212345676543;
uint64_t lehmer64() {
g_lehmer64_state *= 0xda942042e4dd58b5ull;
return g_lehmer64_state >> 64;
}
但是,我想在Python中使用此C函数。因此,我使用GCC创建了一个库:
gcc -o liblehmer64.so -shared -fPIC -O3 rand_test.c
from ctypes import c_uint64,CDLL
lib = CDLL('liblehmer64.so')
lehmer64 = lib.lehmer64
lehmer64.restype = c_uint64
for i in range (1000000000):
rnd = lehmer64()
问题
解决方法
为什么Python代码比C代码慢100倍?
因为调用该函数有很多事情要做。函数调用本身很昂贵。
如何提高Python代码的性能?
如果您想要庞大的随机数列表,则可以编写一个C函数来返回庞大的列表,从而最大程度地减少调用次数。
例如,您可以在python中实现一个存储10000个随机数的队列。您可以使用上述C函数对其进行初始化。然后,每次您从队列中弹出最后一个数字时,队列都会自动调用该函数。如果那也太慢,那么也许您也应该使用C中的随机数来编写函数。在Python中创建庞大的列表非常昂贵。
一个通过编写C函数而受益匪浅的例子是is_prime(x)
函数,也就是说,如果x
是质数,则返回true,否则返回false。特别是如果我们谈论的是非常大的数字。这种情况具有以下两个关键属性:
- 与
is_prime(x)
函数之间来回的数据很少。您将其发送给一个简单的整数并返回一个布尔值。 - 对于大型
x
,这是非常繁重的操作
我创建队列的示例在第一点失败。在C和Python之间会发送大量数据。
您的功能在第二点失败。与函数调用开销相比,该计算非常轻巧。