精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

不朽 C++ 為新貴 Python 應用提速 8000 倍!

新聞 前端
在人工智能浪潮之下,全民學習 Python 已成為必然趨勢。Python 作為一門膠水語言,以簡單的語法、良好的交互性、移植性等優勢受到諸多開發者的喜愛,但要和老牌的 C++ 相較而言,誰運行的速度更快一些?

 在人工智能浪潮之下,全民學習 Python 已成為必然趨勢。Python 作為一門膠水語言,以簡單的語法、良好的交互性、移植性等優勢受到諸多開發者的喜愛,但要和老牌的 C++ 相較而言,誰運行的速度更快一些?相信很多開發者會毫無疑問地選擇了 C++,而本文作者也證實了這一點。

不朽 C++ 為新貴 Python 應用提速 8000 倍!

最近我在開發一個名為 Bard(https://github.com/antlarr/bard)的命令行應用,它是個管理本地音樂庫的音樂管理器。Bard 會根據歌曲生成聲音指紋(利用 acoustid:https://acoustid.org/)并將所有歌曲的元數據保存到 sqlite 數據庫中。這樣你就可以很容易地進行查詢,并找到重復的歌曲,即使歌曲的標簽不正確也能找到。本文筆者分享了查找重復歌曲的算法,并使用 Python 和 C++ 對該算法進行兩次優化,探索如何使這個算法比原來快 8000 倍。

1.算法

不朽 C++ 為新貴 Python 應用提速 8000 倍!

要判斷兩首歌曲是否相似,需要比較它們的聲音指紋。聽上去很容易(實際上的確不難),但并不是初看上去那么直接。acoustid 計算出的聲音指紋并不是一個數字,而是一個數字的數組,更準確地說,是一系列字符的數組。因此不能比較數字本身,而要比較數字中的字符。如果所有字符完全一致,則可以認為兩首歌曲是同一個。如果 99% 的字符一致,則可以認為有 99% 的可能性兩者相同,兩者的差異可能是由編碼問題(如一首歌用 192kbits/s 編碼成 mp3,另一首用的是 128kbits/s)等造成的。

但在比較歌曲時還需要考慮更多情況。有時兩首歌開頭的空白時間長短不同,因此指紋的比特不會完美地對齊,直接比較會不匹配,但將其中一個指紋移動一位可能就能匹配。

因此,要比較兩首歌,我們不僅要比較它們的指紋,還要模擬增加或減少開頭空白的長度,看看它們的匹配程度是上升還是下降。目前 Bard 會將數組向一個方向移動 100 位,再向相反方向移動 100 位,也就是說每首歌都要進行 200 次指紋比較。

因此,如果要比較一個曲庫中的所有歌曲以查找重復,我們需要比較 ID1 和 2,然后將 ID 3 與 ID 1 和 ID 2 比較,一般來說每首歌都要與前面的所有歌曲進行比較。這樣,如果曲庫里有 100 首歌曲,那么需要比較 1000 * 1001/ 2 = 500500 首歌曲(也就是說,要比較 100100000 次指紋)。

2.最初的 Python 實現

[[324578]]

Bard 是用 Python 寫的,所以第一版實現采用了 Python 的列表以整數數組的方式保存指紋。每次迭代過程中需要移位時,我會在其中一個指紋數組前面加個 0,然后迭代整個數組,依次比較每個元素。比較的方法是對兩個元素執行異或操作,然后用一個算法來數出整數中的比特個數:

def count_bits_set(i):

i = i – ((i >> 1) & 0x55555555)

i = (i & 0x33333333) + ((i >> 2) & 0x33333333)

return (((i + (i >> 4) & 0xF0F0F0F) * 0x1010101) & 0xffffffff) >> 24

我們把這個實現的速度作為參考值,稱之為一倍速。

3.第一個改進

不朽 C++ 為新貴 Python 應用提速 8000 倍!

第一個改進,我嘗試將比特計數算法改成較快的gmpy.popcount(http://gmpy2.readthedocs.io/en/latest/mpz.html#mpz-functions),還加入了終止閾值來改進算法。這個新的算法會在超過終止閾值時判斷為不可能匹配,從而停止比較。例如,如果在計算的過程中發現,即使剩余的比特全部匹配,兩首歌的匹配程度也不可能超過 55%,那就直接返回“不同歌曲”(但還是要與其他歌曲比較,以防萬一)。

這個改進使得比較速度幾乎提高到了兩倍速。

4.使用 C++

[[324579]]

此時,我認為這段代碼沒辦法很容易擴展到更大的曲庫上,因此我認為 Bard 需要更好的實現。修改內存很慢,而 C/C++ 可以實現更細粒度的底層優化,但我并不想用 C++ 重寫整個應用,因此我采用了Boost.Python(https://www.boost.org/doc/libs/1_65_0/libs/python/doc/html/index.html),僅把這個算法用 C++ 實現了,并從 Python 應用中調用這個算法。不得不說,我發現在 Python 中集成 C++ 方法非常容易,因此我非常推薦使用 Boost.Python。

在新的 C++ 實現中,我使用了 STL 的 vector 來保存指紋,并且事先加入了最大的偏移量,這樣在算法中就無需修改向量中的元素,只需模擬位移即可。我還使用 STL 的 map,以歌曲的 ID 為索引來保存所有指紋。最后,我還添加了一個重要的優化措施,通過 gcc 的__builtin_popcount(https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005fpopcount),利用 CPU 指令來計算字符。

這個算法最大的好處就是比較過程不會修改或復制任何指紋,這使得速度增加了 126.47 倍。此時我開始計算另一個度量:每秒鐘比較的歌曲數(別忘了每比較一對歌曲就要做 200 次指紋比較)。這個算法的平均速度是 580 首/秒。或者換句話說,要想比較 1000 首歌,需要花費大約 14 分 22 秒(注意原來的 Python 實現大約需要一天 6 小時 16 分 57 秒)。

5.首次并行算法嘗試

[[324580]]

我運行 Brad 的是一顆 i7 CPU,我總為我的程序只用了一個 CPU 感到遺憾。由于比較兩個歌曲的算法并不會改變任何數據,我覺得可以嘗試使用并行算法,使它能在所有 8 個核心中一起運行,并在每次迭代結束時合并結果。因此我開始研究怎樣實現,我發現每首歌與前面的所有歌進行的比較是通過對包含所有已處理過的歌曲的 std::map 進行循環實現的。那么,如果有個 for-each 循環能在不同的線程上運行每次迭代就好了。結果還真有!C++17 中的std::for_each(https://en.cppreference.com/w/cpp/algorithm/for_each)可以指定 ExecutionPolicy,通過它可以讓循環在不同的線程上執行。然后是壞消息:這個標準還沒有被 gcc 完全支持。

所以我搜索了一些 for_each 的實現,最后在一個 stackoverflow 的問題下(https://stackoverflow.com/questions/40805197/parallel-for-each-more-than-two-times-slower-than-stdfor-each)找到了一個。這個問題提到了一個從《C++Concurrency in Action》一書中的實現方案,我不確定這段代碼的版權如何,所以不能直接復制到 Brad 中,但我可以用它做一些測試以便進行測量。

這個方法能把速度提高到 1897 倍,或者說大約 8700 首歌曲/秒(1000 首歌曲需要處理大約57秒。很不錯,是吧!)

6.第二次并行嘗試

不朽 C++ 為新貴 Python 應用提速 8000 倍!

我需要找個我能用的并行版本的 for_each。幸運的是,最終我發現 gcc 包含了 C++ 標準庫中部分算法的實驗性并行實現,其中包含了__gnu_parallel::for_each(https://gcc.gnu.org/onlinedocs/libstdc++/manual/parallel_mode_using.html,文檔頁面上還有更多的并行算法)。只需要鏈接 openmp 庫就可以了。

所以我修改了代碼,結果遇到一個問題:雖然我調用了 __gnu_parallel::for_each 但每次測試時發現它只會串行執行!花了點功夫才找出原因,但閱讀 gcc 關于 __gnu_parallel::for_each 的實現后,我注意到它需要一個隨機訪問迭代器(http://www.cplusplus.com/reference/iterator/RandomAccessIterator/),但我讓它在 std::map 上迭代,而 map 結構是雙向迭代器,不是隨機迭代器。

于是我修改了代碼,將指紋從 std::map<int,std::vector> 復制到 std:;vector<std::pair<int,std:vector>>,這樣 __gnu_parallel::for_each 就能用 8 個線程的線程池運行了。

gcc 實現比 stackoverflow 上的實現更快,速度是 2442 倍,約 11200 首歌曲/秒,1000 首歌曲只需 44 秒。

7.很顯然我卻忘記了的重要改進

在檢查 Bard 的編譯器時,我發現我沒有使用優化速度的編譯器開關!于是我給編譯器加上了 -Ofast-march=native -mtune=native -funroll-loops,就這么簡單。猜猜發生了什么……

速度提高到了 6552 倍,約 30050 首歌曲/秒,1000 首歌曲只需 16 秒。

8.免費得到的 Tumbleweed 的改進

[[324581]]

我開發所用的系統里運行了 openSUSETumbleweed,你們估計知道,它是個非常好用的滾動發布的 Linux 發行版。有一天我在做測試時,Tumbleweed 把編譯器從 gcc 7.3 更新到了 gcc8.1。所以我覺得我應該再測試一下。

僅僅是把編譯器升級到最新版,速度就提高到了 7714 倍,35380 首歌曲/秒,1000 首歌曲只需 14 秒。

9.最終的優化

不朽 C++ 為新貴 Python 應用提速 8000 倍!

我還沒做的一個非常明顯的優化就是把 map 換成 vector,這樣就無需每次調用 for_each 之前進行轉換了。而且,vector 能提前分配空間,由于我知道在整個算法結束時 vector 的最終大小,因此我修改了代碼,以便事先分配空間。

這個修改給了我最后一次提速,速度提高到 7998 倍,36680 首歌曲/秒,完全處理 1000 首歌曲的曲庫僅需 13 秒。

結論

從這次經歷中得到的一些值得記錄的經驗:

  • 花點時間優化代碼,會物有所值。
  • 讓編譯器為你做一些工作。你不需要花任何時間,它就能優化代碼。
  • 盡可能少地復制或移動數據。這樣會降低速度,而且多數情況下只需在開發開始之前仔細考慮下數據結構就能避免。
  • 可能時使用線程。
  • 可能是最重要的一條經驗:測量一切。沒有測量就沒辦法提高。(也許可以,但你得不到準確的結論。)

 

責任編輯:張燕妮 來源: 今日頭條
相關推薦

2017-11-28 15:18:13

機器人JavaPython

2022-08-09 09:10:31

TaichiPython

2025-08-22 14:48:27

2023-04-03 14:25:01

Python編譯

2021-05-17 09:57:42

Python 開發編程語言

2021-02-17 13:20:51

forpandas語言

2016-10-08 16:02:37

WIFIMegaMIMO系統

2018-03-28 14:10:10

GoPython代碼

2024-10-16 09:34:50

2013-02-28 10:35:59

hadoop大數據Hortonworks

2016-03-21 10:16:06

RedisSpark大數據處理

2013-04-02 15:32:28

2010-12-01 14:36:16

趨勢科技Web信譽查詢

2013-09-24 09:40:41

Java圖形加速

2009-10-22 09:17:16

C++ CLR

2010-03-26 16:17:24

Python嵌入

2023-01-02 18:15:42

PythonC++模塊

2016-02-18 09:36:52

光纖wifi

2009-12-16 11:43:28

卡巴斯基NVIDIA Tesl

2010-01-14 11:14:47

C++應用程序
點贊
收藏

51CTO技術棧公眾號

亚洲 欧美 成人| 男人的天堂影院| 欧美日韩视频在线播放| 国产在线视频精品一区| 欧美另类老女人| 中文字幕一区二区人妻电影丶| 中文在线免费视频| 国产精品不卡视频| 国产91aaa| www.com亚洲| 香蕉久久网站| 日韩av在线免费播放| 丁香婷婷激情网| 色噜噜狠狠狠综合欧洲色8| 久久先锋资源网| 亚洲va码欧洲m码| 亚洲精品中文字幕乱码三区91| 日韩在线视屏| 国产视频久久久| 欧美一级大片免费看| 无人区在线高清完整免费版 一区二| 综合色天天鬼久久鬼色| 欧美一区二区在线视频观看| 国产高清视频免费观看| 日韩av不卡在线观看| 欧美激情亚洲另类| 97在线观看视频免费| 亚洲宅男一区| 亚洲第一精品夜夜躁人人躁| а 天堂 在线| 国产一区二区三区影视| 香蕉av福利精品导航| 久久免费看毛片| 国产在线日本| 久久一夜天堂av一区二区三区| 97人人模人人爽视频一区二区| 久久国产香蕉视频| 香蕉国产精品偷在线观看不卡| 欧美人成在线视频| 黄色录像二级片| 久久国产影院| 中文字幕av一区二区三区谷原希美| www.日本高清| 精品五月天堂| 亚洲成人在线视频播放| 久久久无码人妻精品无码| 亚洲网站三级| 欧美精品少妇一区二区三区| 不卡av免费在线| 另类专区亚洲| 日本电影亚洲天堂一区| 少妇高清精品毛片在线视频| 亚洲插插视频| 午夜欧美一区二区三区在线播放| 欧美极品少妇无套实战| 伊人手机在线| 一区二区三区在线观看欧美| 99精品一区二区三区的区别| 国产精品一区二区三区视频网站| 中文字幕高清不卡| 一本久道久久综合| 欧美jizzhd欧美| 亚洲天堂福利av| 国产精品波多野结衣| 黄色在线免费网站| 亚洲综合无码一区二区| 中文精品无码中文字幕无码专区| 亚洲区欧洲区| 亚洲成人一区二区| 黄在线观看网站| 亚洲电影有码| 欧美精品久久久久久久多人混战 | 国产美女高潮久久白浆| 正在播放亚洲精品| 国产一区二区久久| av一区和二区| 四虎在线视频| 日本一区二区视频在线| 自拍另类欧美| 超碰在线99| 欧美在线观看禁18| 日本黄色一级网站| 精品国产导航| 日韩欧美激情在线| 国产肉体xxxx裸体784大胆| 妖精视频一区二区三区免费观看| 这里只有精品丝袜| 国产va在线播放| 亚洲欧美日本国产专区一区| 国产精品久久久久久久av电影 | 亚洲国产精品久| 国产欧美91| 国产精品一区二区三区毛片淫片| 精品免费久久久| 久久综合色综合88| 国产精品99久久久久久大便| 国产在线88av| 欧美精品色综合| 亚洲精品成人无码熟妇在线| 91综合久久| 欧美一级黑人aaaaaaa做受| 一二三区中文字幕| aaa国产一区| 中文字幕久久综合| 自拍视频在线看| 欧美一区二区久久| 日本欧美一区二区三区不卡视频| 欧美在线精品一区| 国产精品成人播放| 丁香六月色婷婷| 国产精品久久夜| 欧美精品99久久| 亚洲成人黄色| 自拍偷拍免费精品| 视频一区二区三区四区五区| 国产美女在线精品| 日本精品一区二区三区高清 久久| 18在线观看的| 欧美老肥妇做.爰bbww| 永久免费看片在线观看| 成人区精品一区二区婷婷| 性欧美视频videos6一9| 国产熟女一区二区三区五月婷| 久久女同互慰一区二区三区| 99久久免费观看| 日韩一区二区三区四区五区| 亚洲欧美国产精品专区久久| 国产一级二级三级| 国产一区二区在线视频| 色一情一乱一伦一区二区三区| 高清毛片在线观看| 精品国产自在久精品国产| 永久免费看mv网站入口| 免费看欧美美女黄的网站| 欧美精品中文字幕一区二区| 99久久精品免费看国产小宝寻花 | 无人码人妻一区二区三区免费| 国产成人久久| 日本精品久久久久影院| 亚欧洲精品视频| 午夜欧美视频在线观看| av在线播放网址| 伊人精品视频| 国产精品免费看一区二区三区| 18videosex性欧美麻豆| 日韩一区二区视频在线观看| 免费成年人视频在线观看| 久久精品国产网站| 亚洲精品国产一区| 四虎国产精品成人免费影视| 中文字幕亚洲欧美日韩在线不卡| 亚洲大尺度在线观看| 国产亚洲综合av| 三年中国国语在线播放免费| 欧美午夜精彩| 国产男女猛烈无遮挡91| 午夜国产福利在线| 欧美一区二区在线播放| 加勒比婷婷色综合久久| 国产成人亚洲综合a∨婷婷图片 | 国产精品日本| 欧美日韩成人一区二区三区 | av中文字幕在线| 欧美色综合天天久久综合精品| 亚洲色图日韩精品| 精品亚洲成a人| 国产乱子伦精品视频| 成人激情自拍| 欧美一级黑人aaaaaaa做受| 国产高清在线| 欧美精品日日鲁夜夜添| av资源吧首页| 久久尤物电影视频在线观看| 中文字幕亚洲欧洲| 亚洲欧美综合国产精品一区| 国产精品伊人日日| 人人视频精品| 久久精品91久久香蕉加勒比| 国产福利小视频| 欧美性猛交xxxxx免费看| 丰满的亚洲女人毛茸茸| 国产在线不卡一区| 免费观看美女裸体网站| 国产精品一区高清| 91pron在线| 26uuu亚洲电影| 久久伊人精品天天| 亚欧洲精品视频| 538在线一区二区精品国产| 久久精品美女视频| 国产精品午夜电影| 亚洲色图欧美日韩| 免费在线观看日韩欧美| 欧美中日韩在线| 精品国产成人| 国产精品区一区| 99久久久国产精品免费调教网站 | 久久精品女人毛片国产| 国产亚洲欧美色| 在线中文字日产幕| 日本中文在线一区| 国产无限制自拍| 97精品在线| 蜜桃传媒视频麻豆一区| 日韩不卡在线视频| 国产精品亚洲网站| 91在线超碰| 久久国产精彩视频| 国家队第一季免费高清在线观看| 日韩亚洲欧美成人一区| 懂色av蜜臀av粉嫩av喷吹| 午夜精品久久久久久久久久久 | 亚洲破处大片| 日本午夜精品一区二区三区| 在线精品国产亚洲| 国产日韩中文在线| 免费观看成人性生生活片 | www.日韩av.com| 美国成人毛片| 亚洲精品国产欧美| 蜜臀av中文字幕| 日韩一级大片在线| 一区二区不卡视频在线观看| 日韩欧美国产一区二区| 日本少妇xxxx动漫| 伊人色综合久久天天| 久久av红桃一区二区禁漫| 久久精品一区二区三区av| zjzjzjzjzj亚洲女人| 国产一区二区毛片| 色呦色呦色精品| 蜜桃精品在线观看| 天天影视综合色| 日韩精品五月天| 天天摸天天碰天天添| 国产一区二区你懂的| 久无码久无码av无码| 欧美一区高清| 成人午夜免费剧场| 欧美成人一品| 男同互操gay射视频在线看| 久久久久免费av| 欧美日韩一级在线| 欧美伊人影院| 777久久精品一区二区三区无码 | 粉嫩av一区二区夜夜嗨| 日韩精品一区二区三区中文精品| 国产情侣激情自拍| 91精品国产高清一区二区三区蜜臀| 中文字幕+乱码+中文乱码www| 日韩欧美999| av片免费观看| 欧美亚洲日本国产| 亚洲天堂999| 欧美精品在线观看一区二区| 一区二区精品视频在线观看| 欧美日韩电影一区| 国产三级精品在线观看| 欧美成人官网二区| 男人天堂综合网| 亚洲精品日韩欧美| 成年网站在线| 久久久国产视频91| 日韩成人伦理| 热re91久久精品国99热蜜臀| 日韩福利一区| 国产日韩欧美夫妻视频在线观看 | 快播亚洲色图| 国内成人精品| 亚洲国产精品日韩| 欧美精品日韩| 国产免费黄视频| 日本不卡高清视频| 精产国品一区二区三区| 91丨porny丨首页| 美国黄色特级片| 一区二区三区在线免费视频| 欧美日韩一二三四区| 欧美日韩亚洲综合| 成人av一区二区三区在线观看| 亚洲国产成人91精品| 国产精品久久久久一区二区国产| 久久精品99久久久香蕉| 超碰在线资源| 国产成人aa精品一区在线播放| 四虎影视国产精品| 国产在线一区二区三区播放| 成人激情视频| 国产黄色片免费在线观看| 老司机午夜免费精品视频| 波多野结衣免费观看| 2014亚洲片线观看视频免费| www欧美com| 色综合久久久久久久久久久| 亚洲在线免费观看视频| 亚洲精品99999| 欧美激情黑人| 日本精品久久久| 中文字幕视频精品一区二区三区| 日本一区二区三区在线视频 | 欧美激情亚洲精品| 成人久久网站| 精品免费国产| 亚洲一区色图| 五月天婷婷激情视频| 成人午夜电影久久影院| 亚洲色图 激情小说| 亚洲成av人综合在线观看| 在线不卡免费视频| 亚洲精品在线视频| 国产一线二线在线观看| 国产精品自产拍在线观看中文| 欧美精品中文| 黄色成人在线免费观看| 久久99久久99| 亚洲AV无码成人精品区明星换面| 亚洲大片精品永久免费| 国产女人爽到高潮a毛片| 国产一区二区日韩精品欧美精品| 黄页网站在线观看免费| 91精品视频免费| 日韩大片在线| 别急慢慢来1978如如2| 暴力调教一区二区三区| 九九热只有精品| 91麻豆精品国产| 欧美日韩在线资源| 国产免费一区二区三区在线观看| 国产videos久久| 欧美日韩在线视频一区二区三区| 成人国产精品视频| 九九热精彩视频| 欧美va日韩va| 日韩123区| 91大片在线观看| 亚洲视频电影在线| 污污网站在线观看视频| 中文字幕不卡三区| 中文字幕资源网| 日韩中文字幕不卡视频| 成人国产精品| 亚洲午夜精品久久久久久浪潮| 日韩高清在线一区| 亚洲欧美va天堂人熟伦| 在线观看免费一区| shkd中文字幕久久在线观看| 国产精品视频色| 日韩精品久久| 中文字幕精品一区二区三区在线| 国产精品久久三| 国产男女裸体做爰爽爽| 欧美精品在线免费| 亚洲日本va中文字幕| 精品视频在线观看一区二区| 成人三级在线视频| 日韩在线视频免费播放| 亚洲欧美日韩成人| а√天堂资源国产精品| 制服国产精品| 国产成人精品午夜视频免费| 国产成年人免费视频| 亚洲精品久久久久久久久久久久| 少妇淫片在线影院| 日本一区二区三区视频在线播放 | 成人综合国产精品| 欧美三级黄美女| 亚洲一区二区乱码| 欧洲亚洲精品在线| www.久久久久.com| 国产免费高清一区| 久久xxxx精品视频| 萌白酱视频在线| 亚洲成人网在线| 成人日韩精品| 波多野结衣 作品| 成人动漫视频在线| 无码人妻精品一区二区| 久久精品亚洲94久久精品| 红杏aⅴ成人免费视频| www.亚洲天堂网| 综合中文字幕亚洲| 人人妻人人玩人人澡人人爽| 日本久久久a级免费| 91精品亚洲| 香蕉视频黄色在线观看| 欧美精品三级日韩久久| 久久青草伊人| 亚洲无玛一区| 99久久伊人精品| 亚洲香蕉在线视频| 97免费视频在线播放| 三级电影一区| 中文在线观看免费视频| 欧美日韩在线电影| 99re6在线精品视频免费播放| 三区精品视频观看| av高清不卡在线| 一级久久久久久久| 国产999在线观看| 韩日视频一区|