如何在ARM平臺(tái)上開發(fā)低功耗的軟件系統(tǒng)
摘要:在強(qiáng)調(diào)便攜式設(shè)備的電池壽命時(shí),看起來比較奇怪是,很少有軟件工程師在其日常項(xiàng)目任務(wù)中真正做到了減少能耗。我猜想對(duì)這個(gè)課題有所想法的那些人可能都是本著榮辱自擔(dān)的想法才關(guān)注此課題的。我們到了要做些改變的時(shí)期。隨著電池壽命和性能要求的矛盾持續(xù),我們作為軟件工程師不得不要用更多時(shí)間來找出如何才能以節(jié)能方式來設(shè)計(jì)和編寫我們的軟件,至少在工具能滿足我們要求之前需要這樣做。
我們這些軟件工程師都熱衷于為我們遇到的問題找出完美的解決方案。但奇怪的是,我們會(huì)發(fā)現(xiàn)在這個(gè)特定的領(lǐng)域,沒有一個(gè)完美的解決方案。聰明的技巧可能會(huì)節(jié)省一些功率,但是這個(gè)領(lǐng)域是由其他更簡(jiǎn)單的因素支配的。就象房間里有幾頭很大的大象,我們必須要先小心翼翼地獵取我們可以看到的大象,然后再花精力去獵捕體型小的動(dòng)物。
在考量某個(gè)系統(tǒng)的功耗時(shí),重要的是要弄清楚我們實(shí)際測(cè)量的對(duì)象是什么。我們說的“節(jié)省功耗”可能意味著幾個(gè)方面。它意味著“功率”還是“能量”。實(shí)際上,我們既需要功率也需要能量。大多數(shù)手持便攜式設(shè)備均具有以下兩個(gè)不同的預(yù)算:功率預(yù)算——它管理著瞬間功耗、避免過熱或產(chǎn)生熱應(yīng)力,而能量預(yù)算則管理著長(zhǎng)期使用的能量總數(shù)。而軟件則需要滿足短期的功率預(yù)算和長(zhǎng)期的能量預(yù)算。
很明顯,我們可以把任何設(shè)備的功耗降低到接近零,只要不讓它做任何操作或任何有意義的操作即可!不得已的是,實(shí)現(xiàn)有用的功能就需要耗費(fèi)能量。因此,我們只能在有意義的操作和節(jié)能二者中不斷采取折衷方案。為了實(shí)現(xiàn)所需的功能,我們必須耗能;但我們必須盡量確保以節(jié)能的方式來實(shí)現(xiàn)這些功能。
功耗時(shí)間積 有關(guān)該主題的學(xué)術(shù)材料中常用的更好度量方式是采用“功耗時(shí)間積”。盡管既沒有標(biāo)準(zhǔn)單位也沒有具體方法,但是這種度量方式將能耗和性能度量結(jié)合到了一起。增加能耗或降低性能會(huì)增加功耗時(shí)間積的值,因此我們的目標(biāo)是找出最低的可接受的功耗時(shí)間積的值,換句話說,最低的能耗要與允許的時(shí)間內(nèi)所需任務(wù)的執(zhí)行保持一致。
能量去哪兒了? 所有計(jì)算器械均會(huì)執(zhí)行兩個(gè)基本功能。這兩個(gè)功能都是必需的,沒有這兩個(gè)功能就不能完成任何有意義的任務(wù)。
我們首先想到的自然是計(jì)算或數(shù)據(jù)處理。通常,計(jì)算是對(duì)機(jī)器寄存器中保存的值實(shí)施的操作。為了盡可能高效地實(shí)施計(jì)算任務(wù),我們需要在最短的時(shí)間內(nèi)執(zhí)行最少的指令。最重要的是,高效計(jì)算允許以下二選一:要么我們可以早點(diǎn)完成計(jì)算去睡覺,要么我們調(diào)慢時(shí)鐘且仍然在規(guī)定時(shí)間內(nèi)完成計(jì)算任務(wù)。
這里經(jīng)常被人忽視的是數(shù)據(jù)通信(數(shù)據(jù)移動(dòng))。在大多數(shù)架構(gòu)中(A R M采用加載/存儲(chǔ)架構(gòu),也不例外),數(shù)據(jù)移動(dòng)是必需的。如果不將信息從一個(gè)位置移動(dòng)到另一個(gè)位置且經(jīng)常返回原來的位置,用戶就無法處理任何信息。例如,內(nèi)存中的值需要移動(dòng)到寄存器中進(jìn)行處理,然后把結(jié)果寫回到內(nèi)存中。
但是哪個(gè)耗用的能量更多呢?最大的償付在哪兒?
圖1顯示了普遍存在的事實(shí),與程序有關(guān)的內(nèi)存存取操作中有大約60%是指令抓取,另外40%才是數(shù)據(jù)存取。
圖1:內(nèi)存存取分布
圖2:內(nèi)存存取能耗
圖2顯示了A R M進(jìn)行的一些研究。如果執(zhí)行一條指令的能耗是1,那么,緊耦合存儲(chǔ)器(TCM)存取的能耗約為1/25,緩存存取的能耗大約為1/6。而外部R A M存取的能耗則是指令執(zhí)行能耗的7倍。
換言之,對(duì)于每次外部R A M存取所用的能耗,我們可以執(zhí)行7條指令,40次緩存存取或大約170次TCM存取。
計(jì)算廉價(jià)但通信昂貴
因此,似乎數(shù)據(jù)移動(dòng)要比數(shù)據(jù)處理更昂貴。因此,第一頭大象就是數(shù)據(jù)效率。
我們可以為內(nèi)存存取的能耗管理提出兩個(gè)規(guī)則。
近距離 - 從能量角度講,內(nèi)存越靠近核心,訪問內(nèi)存的相對(duì)能耗越低。
少存取 - 減少內(nèi)存存取次數(shù)比減少指令數(shù)量更加重要。
充分利用片上存儲(chǔ)器
從我們的能量圖可以清楚地看出,TCM是到目前為止系統(tǒng)具有的最高效存儲(chǔ)器類型。不是所有的系統(tǒng)均具有A R M稱為TCM的存儲(chǔ)器(通過專用和優(yōu)化的接口連接到內(nèi)核),但是大部分系統(tǒng)至少具有某種片上快速存儲(chǔ)器類型。為了便于討論,我們指的是常見的片上存儲(chǔ)器(SPM)。假定S PM單次存取能耗大約是外部R A M存取能耗的1/170,充分利用這種SPM存儲(chǔ)器應(yīng)該是首選。
圖3:SPM的能量?jī)?yōu)勢(shì)
圖3中的圖表顯示了簡(jiǎn)單的“多類”基準(zhǔn),甚至128個(gè)字節(jié)的S PM區(qū)域都可以減少大約一半的功耗。1k字節(jié)的存儲(chǔ)器最大可減少70%的功耗。本次研究(Mar wedel, 2004)中采用的方法是從外部R AM到S PM動(dòng)態(tài)重定位代碼和數(shù)據(jù)片段。甚至在按需移動(dòng)各項(xiàng)開銷方面,不僅降低了能耗,性能也提高了大約60%。
很顯然,我們?cè)谀硞€(gè)點(diǎn)上正在損失回報(bào)。這種情況下,S PM超過1k時(shí),性能提升幅度變緩,系統(tǒng)總能耗也會(huì)稍微升高。在這里,我們實(shí)際上在承擔(dān)這種特定應(yīng)用無法使用的S P M能耗,因?yàn)檫@種應(yīng)用程序本身并不夠大。
您還可以注意到,在結(jié)合了所使用的分配算法時(shí),這種特定的應(yīng)用無法使用小于64字節(jié)的S P M區(qū)域,因?yàn)闆]有足夠小的可用片段與之相配。本次研究中還展示了一個(gè)更加成熟的算法,可以在最佳狀況下節(jié)省能耗可以超過80%。
永遠(yuǎn)做緩存友好的事
分析緩存優(yōu)點(diǎn)有時(shí)可能比分析S PM優(yōu)點(diǎn)更加復(fù)雜。一方面,緩存基本上是自我管理的。另一方面,緩存不是對(duì)單個(gè)存儲(chǔ)位置進(jìn)行操作,而是對(duì)固定大小的“線路”進(jìn)行操作。因此,訪問單個(gè)可緩存的存儲(chǔ)位置可能加載整條線路,從而造成突發(fā)的內(nèi)存存取。如果該附加的數(shù)據(jù)從未被訪問過,則所消耗的能量就浪費(fèi)了。
另一個(gè)不利之處是緩存所需的其他邏輯成本(就硅片面積和功耗而言)。[!--empirenews.page--]
圖4:緩存的能量?jī)?yōu)勢(shì)
圖4摘自普林斯頓(Brooks,2000)一份論文,顯示了針對(duì)某簡(jiǎn)單應(yīng)用基準(zhǔn)的三套數(shù)據(jù)。針對(duì)不同的緩存大小,這些條塊分別代表性能IP C(單位周期指令數(shù))、功耗和功耗時(shí)間積(ED P)??偟膩碚f,性能會(huì)隨著緩存大小的增加而提升。但是,系統(tǒng)的功耗也會(huì)增加,因?yàn)樵龃缶彺鎲卧獣?huì)相應(yīng)增加功耗。功耗時(shí)間積允許我們?cè)谛阅芎途彺娲笮≈g取得平衡。在這個(gè)例子里,存在一個(gè)最佳點(diǎn),即緩存大小為64k時(shí),此時(shí)的功耗時(shí)間積最小。
最大限度減少數(shù)據(jù)內(nèi)存存取
A RM架構(gòu)的一個(gè)特性是其常量是不確定的,特別是,不可能用單條指令把一個(gè)任意32位常量放到一個(gè)寄存器中。實(shí)際上,所有內(nèi)存存取必須按寄存器中的地址操作,這就意味著程序需要把這些地址和其他常量頻繁地放到寄存器中,而這一點(diǎn)很難做到。解決此問題的標(biāo)準(zhǔn)方法是把常量作為文字?jǐn)?shù)據(jù)嵌入到代碼段中,在運(yùn)行時(shí)使用PC相關(guān)的加載進(jìn)行加載。
因此,這種最大限度減少常量影響的方法很實(shí)用。確保在編譯時(shí)這些常量是已知的,如果可能,最好能把這些常量嵌入到單條ARM指令中。為了存取全局變量,盡可能減少加載基址指針的需求。這就需要確保全局變量在運(yùn)行時(shí)都在內(nèi)存中,這樣才能使用單個(gè)指針存取多個(gè)變量。實(shí)現(xiàn)這個(gè)目標(biāo)最簡(jiǎn)單的方式是將全局變量放到一個(gè)結(jié)構(gòu)中。
盡管A R M的堆棧訪問相對(duì)高效(堆棧訪問可較好地加載和存儲(chǔ)多條指令),但是程序員還可以通過很多方式來減少堆棧訪問:減少活動(dòng)變量、避免占用本地變量地址、可能時(shí)充分利用尾部調(diào)用優(yōu)化、將傳遞到函數(shù)的參數(shù)數(shù)量減少到四個(gè)以下、允許編譯器主動(dòng)內(nèi)聯(lián)函數(shù)等。
遞歸情形和避免遞歸情形的做法更加復(fù)雜。通常編譯器可以對(duì)歸函數(shù)很好地進(jìn)行尾部?jī)?yōu)化。實(shí)際上將所有數(shù)據(jù)存儲(chǔ)到堆棧中可以比其他做法獲得更好的局部性?;蛟S建議可能最好表達(dá)為“除非其他做法讓數(shù)據(jù)局部性更糟或您確信編譯器可以對(duì)遞歸調(diào)用進(jìn)行尾部?jī)?yōu)化,否則不要使用遞歸算法”。應(yīng)編寫異常處理程序,增加尾部連鎖的機(jī)會(huì),進(jìn)而避免堆棧環(huán)境內(nèi)不必要的保存和恢復(fù)。
現(xiàn)在我們把注意力轉(zhuǎn)到這個(gè)問題的第二頭大象,即指令執(zhí)行。
最大限度減少指令數(shù)目
事實(shí)上,減少指令執(zhí)行次數(shù)本質(zhì)上與性能優(yōu)化是相同的,執(zhí)行的指令數(shù)越少,能耗就越低。另外,還要增加一些明顯的指針。
首先,正確地配置工具。在編譯器和鏈接器完全了解目標(biāo)平臺(tái),甚至無法實(shí)施一些基本的優(yōu)化。
編寫代碼時(shí)要保持敏銳,才能避免不必要的操作。對(duì)于A R M架構(gòu),32位數(shù)據(jù)類型是高效的:一般8位和16位數(shù)據(jù)類型,盡管占用的存儲(chǔ)空間較少,但是處理效率也較低。在v6和v7架構(gòu)中,打包和接包指令以及S IM D操作一定程序上對(duì)此有些幫助,但是要注意,在主程序中無法從C訪問這些指令。
編寫循環(huán)時(shí)要當(dāng)心
可以按照以下一些簡(jiǎn)單的規(guī)則來編寫循環(huán):使用無符號(hào)的整數(shù)計(jì)數(shù)器,向下倒數(shù),并把是否等于零作為終止條件。這可以讓循環(huán)更短,速度更快,使用的寄存器更少。還要記住,要采用矢量化來編寫循環(huán)。即使在嘗試展開和矢量化最簡(jiǎn)單的循環(huán)時(shí),有關(guān)控制結(jié)構(gòu)和數(shù)據(jù)聲明的一些簡(jiǎn)單規(guī)則都可以讓編譯器的作業(yè)變得更簡(jiǎn)單。
圖5:循環(huán)展開
圖5顯示了與一個(gè)特定循環(huán)優(yōu)化有關(guān)的一些數(shù)據(jù),這個(gè)循環(huán)優(yōu)化就是循環(huán)展開(Brooks,2000)。按照預(yù)期,隨著展開因子的增加,執(zhí)行時(shí)間和指令數(shù)目會(huì)減少。我們看到了減少循環(huán)開銷和減少地址計(jì)算的效果。功率結(jié)果更加有趣,但不太明顯。因?yàn)轭A(yù)測(cè)器可用來訓(xùn)練其行為的分支更少且針對(duì)循環(huán)結(jié)束失敗的最終錯(cuò)誤預(yù)測(cè)比例大增,所以隨著循環(huán)進(jìn)一步展開,分支預(yù)測(cè)器的準(zhǔn)確性出現(xiàn)下降。但是,因?yàn)轫樞蛉≈傅倪B續(xù)數(shù)據(jù)流不經(jīng)常被中斷,所以取指階段的效率可以提升。組合的結(jié)果是減少了每條指令的凈能耗。
因此盡管執(zhí)行時(shí)間基本上低于展開因子4,但是因?yàn)楣某掷m(xù)降低,所以所有重要的功耗時(shí)間積也隨之降低。因此有能耗意識(shí)的編譯器或開發(fā)人員與只考慮執(zhí)行時(shí)間的編譯器或開發(fā)人員相比,會(huì)更傾向于展開循環(huán)。
精度滿足需求即可
還必須考慮輸出要求的精度。即使有浮點(diǎn)硬件可用,定點(diǎn)實(shí)現(xiàn)的計(jì)算通常比浮點(diǎn)實(shí)現(xiàn)的計(jì)算更有效率。如果您正在渲染一個(gè)供屏幕查看的圖像,可能并不需要完全符合標(biāo)準(zhǔn),您只需要渲染出可以接受的圖像。
對(duì)標(biāo)準(zhǔn)M P E G- 4解碼函數(shù)進(jìn)行遞進(jìn)優(yōu)化的一項(xiàng)研究(S h i n,2002)已經(jīng)表明,把軟浮點(diǎn)切換為定點(diǎn)二進(jìn)制可以把能耗降低72%。精度損失意味著該結(jié)果不再符合標(biāo)準(zhǔn),但是在所研究的系統(tǒng)上仍然足以滿足渲染用途。
關(guān)于Thumb
T humb指令集專門設(shè)計(jì)用于改進(jìn)代碼密度,還可以提升窄內(nèi)存系統(tǒng)的性能。但是,在代碼密度確實(shí)改進(jìn)的同時(shí),指令數(shù)也同時(shí)增加了。這是因?yàn)?,與A R M指令相比,減少了個(gè)別Thumb指令的功能。因此Thumb重新編譯會(huì)造成能耗增加,這看起來是合理的,而我們看到的事實(shí)也的確是這樣。
上述研究表明,如果代碼大小減少4%,指令執(zhí)行數(shù)增加38%,而能耗增加28%。為了找到第三頭大象,我們需要走出處理器及其內(nèi)存的領(lǐng)域,著眼于范圍更大的系統(tǒng)。我們這些天使用的系統(tǒng)已經(jīng)被我們的硬件設(shè)計(jì)同事組合到了一起,這個(gè)系統(tǒng)提供了大量節(jié)能選項(xiàng)。
更廣系統(tǒng)中的節(jié)能
顯而易見,沒有使用的組件應(yīng)盡可能置于低功耗狀態(tài)。這也是所有敏銳的設(shè)計(jì)系統(tǒng)不可分割的組成部分,這些組件應(yīng)包括內(nèi)存和緩存系統(tǒng)、甚至是處理器本身。在多核系統(tǒng)中,我們必須考慮在處理要求相對(duì)低時(shí)中止一個(gè)或多個(gè)內(nèi)核運(yùn)行的可能性。
首先,一個(gè)很小但值得考慮的問題是:處理外設(shè)時(shí),要始終嘗試使用中斷機(jī)制,而不是輪詢機(jī)制。輪詢循環(huán)只會(huì)耗用能量而無任何目的。幾乎所有架構(gòu)均包括了某種等待中斷的指令,可以把這種情況下的系統(tǒng)置于待機(jī)狀態(tài)。對(duì)于A R M系統(tǒng),內(nèi)核通常帶有時(shí)鐘門控,只保留靜態(tài)漏電。
通過設(shè)計(jì)中斷架構(gòu)來增加拖尾連鎖,一般可以避免不必要的睡眠喚醒循環(huán)。ARM Cortex-M3架構(gòu)可以自動(dòng)實(shí)現(xiàn)這一點(diǎn)。[!--empirenews.page--]
對(duì)于個(gè)別計(jì)算單元,選擇一種關(guān)機(jī)方案是很容易的。對(duì)于可以預(yù)測(cè)需要與否的單元,在不需要時(shí)通過應(yīng)用程序或操作系統(tǒng)就可以停止運(yùn)行這些單元。對(duì)于不可預(yù)測(cè)需要與否的單元,可以通過按需通電啟動(dòng)系統(tǒng),也可以在空閑超過某段時(shí)間之后再自動(dòng)斷電。子系統(tǒng)斷電的時(shí)標(biāo)可以通過以下兩方面來得出:通電但處于空閑狀態(tài)時(shí)的功耗以及睡眠喚醒循環(huán)的能耗。從根本上講,這取決于應(yīng)用場(chǎng)合。但是,動(dòng)力循環(huán)代碼的簡(jiǎn)單循環(huán)計(jì)數(shù)將是最明顯的起點(diǎn)。
測(cè)量數(shù)據(jù)表明,N e o n引擎相比C o r tex-A9等內(nèi)核的運(yùn)行功率要高大約10%。但是,對(duì)于傳統(tǒng)的信號(hào)處理算法,其性能提升了40% - 150%。在任務(wù)期間啟用NeON而在不需要時(shí)切斷Neon的好處很明顯。很常見的是,不但N e o n引擎可以在任務(wù)完成時(shí)切斷,而且整個(gè)處理器系統(tǒng)可以節(jié)省更多功耗。
通常一個(gè)比較難的選擇是啟用計(jì)算組件提前完成計(jì)算(且因此切斷時(shí)間更長(zhǎng))還是完成計(jì)算時(shí)及時(shí)降低處理器速度以減少功耗。圖6顯示了每次迭代的能耗數(shù)據(jù),這是簡(jiǎn)單的基準(zhǔn)(Domeika, 2009)。采用不同的指令緩存和浮點(diǎn)協(xié)處理器組合,對(duì)于兩個(gè)時(shí)鐘速度,每個(gè)時(shí)鐘速度均要運(yùn)行此基準(zhǔn)四次。有兩個(gè)清晰的重點(diǎn)。首先,盡管指令緩存和浮點(diǎn)單元均減少了能耗,但是浮點(diǎn)單元比指令緩存的表現(xiàn)更優(yōu)異。
圖6:系統(tǒng)組件電源利用
其次,對(duì)于所有配置而言,每次迭代的能耗從本質(zhì)上講是相同的,與時(shí)鐘速度無關(guān)。因此,為了更快地完成任務(wù)而啟用所有功能并全速運(yùn)行要比調(diào)慢時(shí)鐘速度更加高效。
多重處理
眾所周知,與調(diào)高單核的功率相比,采用多核可以獲得更高的性能和更好的能效。使用多核系統(tǒng)時(shí),我們必須考慮在不需要時(shí)選擇中止一個(gè)或多個(gè)內(nèi)核。A R M的研究表明,S M PLinux系統(tǒng)中單核循環(huán)的成本是50000個(gè)周期(大部分周期用于清除一級(jí)緩存),這意味著此操作將在幾百毫秒內(nèi)完成,而不是更短的時(shí)間內(nèi)完成,否則其能耗成本將超過其具有的優(yōu)勢(shì)。
ARM是主動(dòng)研究型架構(gòu),其包含兩個(gè)內(nèi)核,一個(gè)高性能的內(nèi)核用于全功能操作,一個(gè)較小的配套內(nèi)核則以較低的性能完成低功率操作。需要較高的處理功率時(shí),系統(tǒng)運(yùn)行較大的內(nèi)核。任務(wù)完成時(shí),系統(tǒng)可以把所有信息傳遞給小內(nèi)核并關(guān)閉大內(nèi)核。需要逆向信息移動(dòng)時(shí),再切換回大內(nèi)核。如果這兩個(gè)內(nèi)核相連成為相關(guān)系統(tǒng),則切換的能耗成本可降到最低。
關(guān)于操作系統(tǒng)
不巧的是,在操作系統(tǒng)上運(yùn)行時(shí),應(yīng)用程序員無法這樣靈活處理。緩存配置、S PM使用與否、組件的電源周期等很大程度上都是操作系統(tǒng)架構(gòu)和設(shè)備驅(qū)動(dòng)程序來專門決定的。但是,應(yīng)用程序員仍然有很多東西需要考慮。
研究已經(jīng)表明,設(shè)計(jì)不良的進(jìn)程間通信(I P C)會(huì)大大增加系統(tǒng)的能耗。一個(gè)簡(jiǎn)單的技術(shù)稱為“矢量化”進(jìn)程間通信,這種技術(shù)批量處理小的消息并把大量小的消息作為一個(gè)大的消息來發(fā)送,這樣通??梢詼p少上下文的切換開銷。另外,減少進(jìn)程數(shù)量可明顯降低進(jìn)程間通信的需求。需要頻繁通信的進(jìn)程可以合并成一個(gè)進(jìn)程。
在嵌入式Linux中運(yùn)行的最近研究(Tan, 2003)表明,分析和合理設(shè)計(jì)進(jìn)程間通信2 可以潛在改進(jìn)能耗多達(dá)60%。
結(jié)論
盡管我已經(jīng)強(qiáng)調(diào)了許多領(lǐng)域仍然屬于學(xué)術(shù)研究范圍,但我們現(xiàn)在還是可以做許多工作。結(jié)果相對(duì)比較簡(jiǎn)單:減少外部?jī)?nèi)存存取,減少指令執(zhí)行,并在不使用某些單元時(shí)關(guān)掉它們。
在做出這個(gè)結(jié)論的同時(shí),我想起了2 0 0 9年中期在一次培訓(xùn)課上與客戶的一次談話。這些客戶關(guān)心如何在包含了N e o n的C or tex-A8平臺(tái)上實(shí)現(xiàn)信號(hào)處理算法且想要知道個(gè)別指令的確切能耗。我解釋說,實(shí)際上很多這種信息是未知的,而且不管在什么情況下,很難使用當(dāng)前的工具得出這些信息?;仡櫳衔模覀円呀?jīng)認(rèn)識(shí)到在捕獵大象的這個(gè)長(zhǎng)期任務(wù)中,這些信息都是無關(guān)緊要的。實(shí)際上,客戶要捕獵的大象與房間中的其他大象相比,非常的小。不管是經(jīng)過分析還是持續(xù)跟蹤數(shù)據(jù),都可以得出更好的建議,那就是估算每次實(shí)現(xiàn)中涉及的數(shù)據(jù)存取次數(shù)和類型。這樣,再結(jié)合指令計(jì)數(shù),可以做出更加明智的選擇。與內(nèi)存存取布置不良相比,個(gè)別指令的功耗幾乎無關(guān)緊要。
我們這些軟件開發(fā)人員要繼續(xù)對(duì)學(xué)術(shù)和工具供應(yīng)商施加壓力,讓他們?cè)谙乱淮ぞ咧袠?gòu)建出這些功能。這不容易但將會(huì)實(shí)現(xiàn)。
最后,我必須提醒大家所有這些取決于您所用的系統(tǒng)、平臺(tái)、應(yīng)用程序、操作系統(tǒng)、電池和用戶。就像俗話說的“優(yōu)勢(shì)各有不同”。