Python 在嵌入式應(yīng)用程序開(kāi)發(fā)中變得越來(lái)越普遍,特別是對(duì)于在網(wǎng)絡(luò)邊緣運(yùn)行的機(jī)器學(xué)習(xí)框架。但是,這種高級(jí)通用編程語(yǔ)言抽象出代碼中的許多細(xì)節(jié),這些細(xì)節(jié)可能會(huì)以開(kāi)發(fā)人員可能不知道的方式影響實(shí)現(xiàn)的性能。
讓我們舉一個(gè)明顯的例子:計(jì)算 斐波那契數(shù)列。至少有兩種不同的方法可以執(zhí)行此操作,遞歸算法和標(biāo)準(zhǔn)迭代算法,性能水平差異很大。
可以使用稱(chēng)為 Tracealyzer 的工具評(píng)估不同實(shí)現(xiàn)或算法的性能。這是來(lái)自 Percepio 的可視化跟蹤診斷工具,可讓嵌入式軟件開(kāi)發(fā)人員在運(yùn)行時(shí)深入了解代碼,以便更輕松地調(diào)試系統(tǒng)級(jí)問(wèn)題,并幫助他們改進(jìn)軟件的設(shè)計(jì)和性能。
Tracealyzer 可以與傳統(tǒng)調(diào)試器(如開(kāi)源 Eclipse 工具)并排使用,并通過(guò)系統(tǒng)級(jí)別的幾個(gè)附加視圖補(bǔ)充詳細(xì)的調(diào)試器視圖。這有助于理解經(jīng)典調(diào)試器不足以解決的實(shí)時(shí)問(wèn)題。
結(jié)合Linux 操作系統(tǒng)發(fā)行版中的LTTng開(kāi)源跟蹤包,Tracealyzer 可以展示不同級(jí)別的性能。這與處理器無(wú)關(guān),并且是所選算法的結(jié)果。
對(duì)于評(píng)估,斐波那契數(shù)列的每個(gè)實(shí)現(xiàn)都在一個(gè)模塊中執(zhí)行:
def recur_fibo(n):
if n 《=1 n:
return n
else:
return(recur_fibo(n-1) + recur_fibo(n-2))
def non_recur_fibo(n):
result = []
a,b = 0,1
while a 《 n:
result.append(a)
a,b = b, a+b
return result
有單獨(dú)的 Python 源文件調(diào)用上面的兩個(gè)函數(shù):
import lttngust
import logging
import fib
def example():
logging.basicConfig()
logger = logging.getLogger(‘my-logger’)
logger.info(‘Start’)
fib.recur_fibo(10)
logger.info(‘Stop’)
logger.info(‘Start’)
fib.non_recur_fibo(10)
logger.info(‘Stop’)
if __name__ == ‘__main__’:
example()
以下命令捕獲 LTTng 中的跟蹤,然后可以在 Tracealyzer 中檢查:
$》 lttng 創(chuàng)建
$》 lttng 啟用事件--kernel sched_switch
$》 lttng 啟用事件--python my-logger
$》 lttng 開(kāi)始
$》 蟒蛇3.py
$》 lttng 停止
$》 lttng 銷(xiāo)毀
將標(biāo)準(zhǔn) Python 記錄器替換為名為“my-logger”的記錄器允許 Tracealyzer 在工具的跟蹤視圖中顯示事件。由于 Tracealyzer 在此特定示例中未捕獲任何應(yīng)用程序數(shù)據(jù),因此無(wú)需將軟件配置為讀取數(shù)據(jù)值。相反,只需要一個(gè)自定義間隔來(lái)標(biāo)記兩個(gè)函數(shù)的進(jìn)入和退出。
雖然在上面的跟蹤視圖中可以看到顯著的性能差異,但 Tracealyzer 還可以提供更具體的性能指標(biāo)。這可以通過(guò)轉(zhuǎn)到視圖并單擊間隔和狀態(tài)機(jī)來(lái)完成,并使用代碼中的 logger.info() 調(diào)用插入的“開(kāi)始”和“停止”字符串創(chuàng)建自定義間隔,并標(biāo)記條目和候選函數(shù)的退出。
區(qū)間圖顯示遞歸算法(首先執(zhí)行)和迭代算法(其次執(zhí)行)之間存在 20 倍的差異。
在此示例中,我們僅使用每種算法計(jì)算 10 個(gè)斐波那契數(shù)。如果沒(méi)有 Tracealyzer,可能需要更多的迭代才能獲得一些有意義的見(jiàn)解,但這有兩個(gè)問(wèn)題。首先,當(dāng)遞歸 Fibonacci 算法運(yùn)行到 1000(甚至 100)時(shí),Python 會(huì)簡(jiǎn)單地坐在那里。這將是令人擔(dān)憂的,因?yàn)椴磺宄@種不響應(yīng)是由于實(shí)現(xiàn)中的錯(cuò)誤還是其他原因。在這種情況下,我們可能會(huì)猜到為什么會(huì)發(fā)生這種情況,但是對(duì)于更復(fù)雜的問(wèn)題,需要大量的日志記錄來(lái)了解瓶頸在哪里。
其次,如果在嵌入式系統(tǒng)上運(yùn)行多個(gè)應(yīng)用程序,這些其他應(yīng)用程序可能會(huì)破壞目標(biāo)應(yīng)用程序,這也會(huì)增加算法或函數(shù)完成執(zhí)行的時(shí)間。沒(méi)有蹤跡,就沒(méi)有簡(jiǎn)單的方法來(lái)確定是否是這種情況。
相反,Python 中的 LTTng 和 Tracealyzer 的結(jié)合突出表明,問(wèn)題在于所選算法的基本特征。這在開(kāi)發(fā)更復(fù)雜的算法時(shí)非常寶貴。此示例實(shí)現(xiàn)可作為如何評(píng)估未來(lái)算法實(shí)現(xiàn)的性能的參考。在單獨(dú)的 Python 模塊中實(shí)現(xiàn)核心功能通常是一種很好的編程習(xí)慣,這也簡(jiǎn)化了對(duì)特定功能的跟蹤。
由于跟蹤開(kāi)銷(xiāo)幾乎可以忽略不計(jì),跟蹤點(diǎn)可以保留在應(yīng)用程序中,因?yàn)樗谀繕?biāo)嵌入式系統(tǒng)甚至生產(chǎn)中進(jìn)行測(cè)試,從而允許 Tracealyzer 工具在生產(chǎn)代碼庫(kù)中生成性能指標(biāo)。這對(duì)于常規(guī)系統(tǒng)測(cè)試非常有用,并且允許使用相同的代碼庫(kù)來(lái)確保應(yīng)用程序在功能上正確且高性能,而只需進(jìn)行最少的更改。
結(jié)論
使用 Tracealyzer 和 LTTng 捕獲 Python 應(yīng)用程序中的性能指標(biāo)提供了對(duì)算法實(shí)現(xiàn)的寶貴分析。
這種方法的最小開(kāi)銷(xiāo)意味著可以保留代碼的檢測(cè)以在目標(biāo)嵌入式系統(tǒng)上使用。這可以對(duì)目標(biāo)應(yīng)用程序進(jìn)行更多監(jiān)控,并促進(jìn)對(duì)與其他應(yīng)用程序和操作系統(tǒng)交互的分析。例如,可能有另一個(gè)進(jìn)程或線程搶占目標(biāo)應(yīng)用程序并影響性能。Tracealyzer 和 LTTng 的組合可以識(shí)別此類(lèi)異常的原因,這允許開(kāi)發(fā)人員改進(jìn)實(shí)現(xiàn)以防止進(jìn)一步的問(wèn)題。
雖然斐波那契數(shù)列的示例實(shí)現(xiàn)相對(duì)無(wú)害,但它突出了 Python 語(yǔ)言的一個(gè)關(guān)鍵特征,可以為更復(fù)雜實(shí)現(xiàn)的開(kāi)發(fā)提供信息。
此示例還顯示了在設(shè)計(jì)中使用單獨(dú)模塊的價(jià)值。使用跟蹤,開(kāi)發(fā)人員可以在擴(kuò)展到完整的系統(tǒng)實(shí)現(xiàn)之前測(cè)量和驗(yàn)證這些模塊中關(guān)鍵核心功能的性能,而無(wú)需大量開(kāi)銷(xiāo)。這有助于證明應(yīng)用程序在功能上正確且性能良好,且目標(biāo)環(huán)境中的更改最少。
審核編輯:郭婷
-
嵌入式
+關(guān)注
關(guān)注
5088文章
19160瀏覽量
306549 -
python
+關(guān)注
關(guān)注
56文章
4802瀏覽量
84890
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論