Python 用于打印进度的有效可分性检查

Python 用于打印进度的有效可分性检查,python,modulo,Python,Modulo,在我的程序中,当我觉得需要很长时间时,我会执行一个进度检查:我使用0的模(如果I%n==0…)打印迭代器的当前值和每n次迭代的时间差 Python解释器(或任何其他编程语言编译器)是否有效地检查2的幂的可除性?就像取最后一个(幂)位并检查所有值是否都等于0一样?Python中任何整数运算的效率充其量都是值得怀疑的。除了解释器开销外,您还需要处理整数是可变精度的事实,这需要对每个操作进行更多处理 也就是说,您可以使用位旋转来检查2次方的可整除性。对于给定的n,您可以 p = (1 <<

在我的程序中,当我觉得需要很长时间时,我会执行一个进度检查:我使用0的模(
如果I%n==0…
)打印迭代器的当前值和每n次迭代的时间差


Python解释器(或任何其他编程语言编译器)是否有效地检查2的幂的可除性?就像取最后一个(幂)位并检查所有值是否都等于0一样?

Python中任何整数运算的效率充其量都是值得怀疑的。除了解释器开销外,您还需要处理整数是可变精度的事实,这需要对每个操作进行更多处理

也就是说,您可以使用位旋转来检查2次方的可整除性。对于给定的
n
,您可以

p = (1 <<  n) - 1 # n of your choice
...
if not i & p:
    ...

p=(1查看以下lambda的格式化字节码,CPython中的字节码级别似乎没有任何差异:

In [1]: import dis

In [2]: dis.dis(lambda x: x % 3 == 0)
  1           0 LOAD_FAST                0 (x)
              2 LOAD_CONST               1 (3)
              4 BINARY_MODULO
              6 LOAD_CONST               2 (0)
              8 COMPARE_OP               2 (==)
             10 RETURN_VALUE

In [3]: dis.dis(lambda x: x % 2 == 0)
  1           0 LOAD_FAST                0 (x)
              2 LOAD_CONST               1 (2)
              4 BINARY_MODULO
              6 LOAD_CONST               2 (0)
              8 COMPARE_OP               2 (==)
             10 RETURN_VALUE

In [4]:
二进制_模(取2个参数的模运算,因此为“二进制”)最终由
Objects/longobject.c
中的
long_mod
函数在CPython中处理(对于2个整数,也称为“longs”)

通过浏览代码,对于操作数只有一个位数的情况,似乎有一些初始优化

如果没有,则最终会调用包含以下注释的
x_divrem

/* We follow Knuth [The Art of Computer Programming, Vol. 2 (3rd
       edn.), section 4.3.1, Algorithm D], except that we don't explicitly
       handle the special case when the initial estimate q for a quotient
       digit is >= PyLong_BASE: the max value for q is PyLong_BASE+1, and
       that won't overflow a digit. */
我真的不想花时间去理解代码中的算法(我没有提到这本书),但通过略读,它看起来像是在执行一些巧妙的位移位操作。我打赌,在除数是2的幂的情况下,这个算法会运行得更快。不过,还不能完全确定

您可以在这里查看:

我可以向您保证,单模运算并不是程序中的瓶颈。在出现问题时,请尽量只考虑性能。此外,在PythonKeep中,检查模运算的速度非常快。在Python中,打印通常非常慢,尤其是“我觉得”不是找到性能不佳原因的良好基础。您是否尝试过使用探查器?我认为OP只是想要一些进度指示,而不是试图找到加速循环的方法。这似乎比较慢。我做了一次timeit,大约用了73纳秒,而
not I%m
大约用了55纳秒。@HeapOverflow。我一点也不奇怪。整数运算的瓶颈是循环,它跨越了无限精度的整数数据,而不是运算本身。您是否将时间以ns为算术平均值?以ns为单位进行测量似乎更像是一个测量错误。@Ferazhu我没有做任何不寻常的事情。例如,我运行了
python-m timeit-s“i=1000;p=4095”“不是i&p”
,它报告了
5000000个循环,每个循环的最佳值为5:71.4nsec
@madpysicator不确定你的意思,但是
python-m timeit“对于范围内的i(10**6):pass”
表示31毫秒,而
python-m timeit-s“p=4095”表示范围内的i(10**6):不是i&p“
表示92毫秒。因此,在这种情况下,循环/步进似乎不是瓶颈。