為期兩周的個人專案就這樣過去了。雖然說還有很多不足的地方,但自己還是比較滿意吧,畢竟是認真做了的。
專案挺簡單的,就是做乙個詞頻統計程式,用來統計文章裡各個單詞出現的次數。可以說,這已經簡單到不能稱為「專案」了。不過,寫這個程式前前後後還是遇到挺多問題——畢竟,要將效率優化到極致實在是很麻煩的事情。
一開始秋豐老師給出超級指標——要讓程式能處理10g資料。當時一看到這個指標我就各種囧,因為萬一10g資料裡所有單詞都不同(即每個單詞的詞頻都為1),這堆單詞連直接存放在記憶體中都做不到。為了解決這個問題,程式就不得不在處理了部分資料後就將該部分的詞頻統計結果儲存到檔案上,最後再將這些檔案合併輸出結果。將資料分開來處理倒還不是很困難,真正難的部分在於合併。所謂的合併指的是,比如a檔案裡記錄單詞hello出現了1次,b檔案裡記錄單詞hello出現了2次,那我們要將結果合併為hello出現了3次。為了在較低的複雜度下完成合併,程式就需要先將各個檔案整理為有序,最後再採用多路合併將這些檔案綜合在一起得到結果——這本質上就是外部排序。眾所周知,外部排序的效率與磁碟塊大小、磁碟快取大小、檔案系統快取大小等息息相關,為了達到最高效率,**必須呼叫win 32 api來完成有關的檢測。
於是,在秋豐老師超級指標的壓迫下,乙份極其複雜的外部排序**誕生了。然而,在做測試時我就發現,雖然程式對付大資料確實非常高效,但對付小資料實在力不從心——對於乙份只有幾m的檔案,採用簡單的雜湊或紅黑樹,在記憶體中完成對所有單詞的統計顯然會比優化到極致的外部排序還要快得多。一想到要針對不同大小的檔案寫不同演算法,還要通過大量測試來選定乙個最佳的閾值(超過閾值就切換演算法),我的心頓時就發毛了……於是,果斷聯絡了秋豐老師。在打擾了秋豐老師n次之後,終於得到乙個肯定的答覆——測試資料中不同單詞數不會超過100萬個。這總算讓我舒了一口氣,終於不用去尋找最優閾值了;但這也同時宣告那堆外部排序的**可以進垃圾桶了……
就這樣,重建乙個工程,開始用雜湊表來解決詞頻統計的問題。既然提到雜湊表,那首先就要選定乙個優秀的雜湊函式。字串雜湊印象中效果比較好的有elf hash、bkdf hash這幾個。我生成了些資料,測試一下各個雜湊函式的碰撞率,同時記錄下各個雜湊函式進行雜湊運算的時間開銷,最後發現bkdf hash無論是碰撞率還是雜湊開銷都遠遠優於其他函式,於是bkdf hash就成必然選擇了。
之後要將雜湊函式運用到容器上。c++0x下的stl多了個unorder_map,是乙個基於雜湊的無序容器,理論上能提供 比紅黑樹的map更優的查詢與插入效能。不過,根據我以前寫**的經歷,stl的各種容器向來都是低效的代表,這個unorder_map估計也是如此。經過測試,果然很坑爹慢……算了,反正自己寫個雜湊表也不麻煩,於是就動手寫了。為了容易解決衝突,用了開放式鍊錶法;為了減少new操作的開銷,又將開放式鍊錶法裡的鍊錶換成陣列鍊錶。
除此以外,為了減少那緩慢的string所帶來的開銷,還重寫了string類……
除了還有一些微不足道的最小堆優化等等,程式基本上也沒什麼好說的了。事實上,一開始在採用雜湊表之前,我也考慮過用字典樹來解決。但後來一想,字典樹是o(length)插入,雜湊表也是o(length)插入,而且字典樹的插入常數與基於bkdf hash的雜湊表基本一樣(對於每個字元,字典樹是一次判斷一次賦值外加一次new,bkdf是一次乘法一次加法外加一次賦值;字典樹的new操作不一定發生,但一旦發生開銷極大——雖然我也試過用記憶體池或者預先分配來改進之,但效果不明顯,有時反而更慢),再加上字典樹有爆記憶體的風險,因此最後並沒有採用(**留著,但沒有呼叫)。
最後經過秋豐老師的測試,在普通機械硬碟上,340m的資料大概4s多就跑完,平均1s能處理80m資料,可以說瓶頸已經不在程式而是在硬碟上了。這還是讓我較為滿意的。
ps 1.
按秋豐老師要求,我在完成這個個人專案時也統計了下**行數和開發時間。如今對比一下完成專案前的時間預估,發現結果很搞笑。一開始我預計大概要寫1500行**,總的開發時間則預估為50小時;但最後總共才寫了627行**,總的開發時間卻花了29小時。雖然真實的開發時間比預計的要少,但從單位時間所編寫的**量來看,原有預計還是過高估計了產出效率了……不過,能提前完成任務也是件不錯的事情。
ps 2.
有人問我為什麼沒有用c#。確實啊,我是個重度c#控,為何在上文一直沒提到c#呢?呃,其實原因是——我在做個人專案前公升級了.net framework,結果不小心給安裝失敗了,不但新裝的.net framework 4.5用不了,連以前的.net framework 2.0/3.5/4.0一律都用不了。而我當時又忙著看**,所以沒有時間去檢查安裝失敗的原因,於是只能蛋疼地用c++了……
專案個人總結
於我,算是過了把pm的癮,用軟體工程的方法親身實踐專案管理 雖然與真實的於我,算是過了把pm的癮,用軟體工程的方法親身實踐專案管理 雖然與真實的產品生產過程和環境還有一定差距。我覺得自己做的好的地方大概保證了專案進度不掉線吧 事實上還挺快 不會說期末了開始爆肝拼命趕,而是每次團隊作業保質保量去完成,...
專案個人總結
進銷存專案個人總結 怡佳樂超市管理系統 開發環境 win10 tomcat idea jdk1.8 mysql 專案簡介 用途 為了讓商品的管理變得更加便捷和清晰,進 售 存資訊更加直觀.對員工 以及員工對商品的各項操作變得更加簡單。架構 ssh easyui shiro quartz 模組 系統模...
個人專案總結
此次個人專案我最後在實現了基本要求的基礎上,還做了算式的自動生成,還有mfc的圖形介面程式。圖形介面的設計圖如上所示。使用者能夠選擇生成題目的數量,使用者輸入相應數量後,需點選開始測試。之後題目會一道一道的顯示。程式可以自動判斷答案的正誤並統計正確題數,錯誤題數已經正確率。圖形化的程式只是將之前做好...