1. 程式人生 > 實用技巧 >luogu-P5367 康託展開【模板】

luogu-P5367 康託展開【模板】

作業要求參見:https://edu.cnblogs.com/campus/nenu/2020Fall/homework/11207

作業0(5分)

修改create.cpp檔案,改成由命令列引數確定生成的資料的資料量。修改readme.md的對應部分。(要求貼出修改之後的程式碼和read.md。)

查詢C++命令列引數相關介紹:引數argc就代表啟動程式時,命令列引數的個數,argv是一個數組,其中的每個元素都是一個char*型別的指標,該指標指向一個字串,這個字串裡就存放著命令列引數。查詢atoi()函式含義:將數字格式的字串轉換為整數型別。

修改後的程式碼:

//create.cpp
#include <iostream>
#include 
<stdlib.h> #include <time.h> using namespace std; int main(int argc, char* argv[]) { int n = atoi(argv[1]); srand((unsigned)time(NULL)); for (int i = 0; i < n; i++) { cout << rand() << "\n"; } cout << endl; return 0; }

修改後的ReadMe.md

作業1(10分)

對上面兩段老楊寫的程式碼任選其一進行profile,觀察現象(要求有截圖記錄)。

選擇對brute.cpp程式進行profile,效能分析圖如下:

分析:發現brute.cpp程式中的輸入、輸出CPU使用佔比較大,尤其是輸出,導致brute.cpp程式執行緩慢。

你是一個好人,為了讓老楊知道為什麼要對程式碼進行profile,於是你在原來的題目的基礎上做出了修改,修改之後的題要求如下:

1)讀入兩個檔案,一個用控制檯,一個用命令列引數指出檔名。

檔案biggerwhitelist,包含1列整數1M個,隨機生成(要求老楊自己想辦法),通過命令列引數指出檔名。

設定命令列引數截圖:

結果截圖:

檔案biggerq,包含1列整數10M個,隨機生成(也要求老楊自己想辦法),通過控制檯讀入。

控制檯讀入截圖:

結果截圖:

2)在檔案biggerq中查詢所有不在biggerwhitelist中的整數,重定向輸出到一個檔案中。

控制檯截圖:

結果截圖:

3)寫一份如何部署執行程式碼的readme。

作業2(10分)

以biggerwhitelist和biggerq作為輸入,對作業1中選擇的程式碼再次進行profile,找到程式碼執行最“慢”的地方,截圖為證並文字說明。

對作業1選擇的檔案brute.cpp程式碼(原基礎上有做修改---is_match函式)再次profile,效能分析圖如下:

執行時間截圖:

分析:從效能分析圖中可以看到is_match函式佔用CPU很大,達到94.52%,從執行時間截圖中可以看出用了17:47min,時間很長。所以is_match函式處是執行最慢的地方。具體到相應程式碼位置,得出結論是:is_match函式中的for迴圈CPU佔比較大,所以下一步應該對is_match函式進行優化。

作業3(10分)

根據作業2找到的最慢的地方,優化作業1中你選擇的程式碼,在保證輸出結果正確的前提下,減少老楊程式執行的時間。(優化後的程式碼需要你提交到git上,作為教師的判斷依據。優化後的程式的名字應該是better.cpp或者better.cs。)

對brute.cpp檔案程式碼的is_match函式部分使用二分法查詢進行優化,可以大大提高查詢的速度。

優化後的重要程式碼:

bool is_match(int t, int w[], int w_length)
{    
    int left = 0, right = w_length - 1, mid;
    while (left < right)
    {
        mid = (left + right) / 2;
        if (t == w[mid])
            return false;
        else if (t < w[mid])
        {
            right = mid - 1;
        }
        else if (t > w[mid])
        {
            left = mid + 1;
        }
    }
    return true;
}

coding.net程式碼地址:https://zhangwenyan1.coding.net/public/writelist/brute/git

作業4(5分)

對作業3優化後的程式碼進行profile,結果與作業2的結果做對比。畫表格並文字說明。

對優化後的程式碼進行profile,效能分析圖如下:

執行時間截圖:

分析:從效能分析圖中可以看出better.cpp程式中的is_match函式執行過程中CPU佔比是1.14%,比較上次profile的結果,明顯優化成功。從執行時間截圖中可以看出用了2:54min,時間相比優化前縮短很多。

優化前後表格對比:

分析:優化前後,is_match函式CPU佔比大大減小,減少了93.38%,且執行時間也明顯縮短,縮短了14:53min。因此我認識到了profile的重要性,以及優化程式碼所起到的作用,可以減小CPU佔比,提高程式執行效率。

做業5(5分)

你覺得老楊的文件(readme),註釋和程式碼風格又哪些問題,該如何改進?

  • 文件(readme)中不夠詳細。

例如這句:執行“create 10>whitelist”生成檔案whitelist;

我認為可以寫成這樣:執行“create10>whitelist”除錯create.cpp檔案成whitelist檔案;可能更易讓讀者清楚其中的過程。

  • 文件(readme)中有錯誤。

例如這句:執行“brute-wq < whitelist > output”

根據功能要求應改為:執行“brute-wwhitelist < q > output”

  • 程式中的註釋不規範,且有多餘,建議規範程式碼,刪除多餘處。

例如這部分程式碼:

// init w
////    for(int i=0;i<w_1m)
////    {
////        w[i]=-1; //填充非法資料
////    }

多行註釋可用:/* 註釋 */ 如下圖所示:

  • 在原brute.cpp檔案中,發現is_match函式程式碼與程式要求不匹配,需要進行修改,修改前後程式碼如下:

修改前is_match函式程式碼:

bool is_match(int t, int w[], int w_length)
{
    for(int i=0;i<w_length;i++)
    {
        if(t!=w[i])
        {
            return true;
        }
    }
    return false;
}

且修改之前的brute.cpp中這段程式碼中!=中的!使用了中文!導致程式錯誤。

修改後is_match函式程式碼:

bool is_match(int t, int w[], int w_length)
{
    for(int i=0;i<w_length;i++)
    {
        if(t==w[i])
        {
            return false;
        }
    }
    return true;
}