作為(現已完成)挑戰的一部分,我最終創建了一個要使用的分數類。在分析完我的整體代碼后,我將不到一半的時間花在__init__了該課程上,而不是做一些有用的事情。
這是__init__:
class fraction(Number):
__slots__ = ("n", "d")
def __init__(self, n, d, returnint = False) -> None:
if type(n) == int and type(d) == int:
pass
elif type(n) not in (fraction, int) or type(d) not in (fraction, int):
raise TypeError("Can't create fraction ({a}, {b}) numerator and denominator must be int or fraction.".format(a = n, b = d))
else:
if type(n) == fraction:
d = d * n.d
n = n.n
if type(d) == fraction:
n = n * d.d
d = d.n
if d == 0:
raise ValueError("Denominator cannot be zero")
a = n
b = d
while not b == 0:
r = a%b
a = b
b = r
gcd = int(a)
self.n = int(n/gcd)
self.d = int(d/gcd)
這是 cprofile 關于整個代碼的示例輸出:
1971273 function calls (1935347 primitive calls) in 3.232 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
...
272503/250039 1.516 0.000 1.541 0.000 doomsday.py:46(__init__)
...
是的,我正在創建很多它們,對于我的解決方案的某些變體,我可能會調整演算法以避免分數,但是......它真的很瑣碎,在其他情況下,如果沒有很多分數,我就無法逃脫。
我還嘗試拆分簡化步驟(從a=n到gcd = int(a))并重新分析 - 這向我表明 50-60% 的時間都在進行此操作(但為額外的函式呼叫增加了 10% 的開銷)。我仍然有不到 25% 的運行時間用于簡單地啟動物件而不進行實際計算。
我怎樣才能加快速度?
uj5u.com熱心網友回復:
感謝評論者的指點。
tldr; 使用類會產生開銷。重構主代碼以使用整數數學更快。
使用物件/類有明顯的開銷。我通過兩種方式改進了原始代碼的性能:
- 使用
isinstance()代替type() == int()洗掉簡化代碼中的呼叫
在這些更改之后,大約一半的時間花費在__init__開銷上(包括 if 陳述句)。另一半正在運行簡化。
基于此,我還通過實作 Bareiss 演算法重構了我的主要代碼以使用整數數學(在此處查看此(我的)答案:https ://scicomp.stackexchange.com/questions/34512/bareiss-algorithm-vs-lu-分解/41262#41262 ) 用于矩陣行列式,并盡可能避免使用分數。
最終代碼如下所示:
class fraction(Number):
__slots__ = ("n", "d")
def __init__(self, n, d, returnint = False) -> None:
if isinstance(n, int) and isinstance(d, int):
pass
elif not isinstance(n, (fraction, int)) or not isinstance (d, (fraction, int)):
raise TypeError("Can't create fraction ({a}, {b}) numerator and denominator must be int or fraction.".format(a = n, b = d))
else:
if isinstance(n, fraction):
d = d * n.d
n = n.n
if isinstance(d, fraction):
n = n * d.d
d = d.n
if d == 0:
raise ValueError("Denominator cannot be zero")
a = n
b = d
while not b == 0:
r = a%b
a = b
b = r
gcd = a
self.n = n//gcd
self.d = d//gcd
為了完整起見,這里是關于設定物件開銷的視圖:
from timeit import timeit
class dummy(object):
__slots__ = "i"
def __init__(self, i = 0):
self.i = i
def do_int(x):
a = x
def do_dummy(x):
a = dummy(x)
print("Int")
print(timeit(lambda: do_int(6)))
print("Class")
print(timeit(lambda: do_dummy(6)))
給出:
Int
0.261943900026381
Class
0.7345267999917269
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/459263.html
上一篇:遍歷二進制數的真位(快速)
下一篇:合并來自不同陣列的物件
