2013-03-08 35 views
1

我正在實施一些深度學習神經網絡和Matlab現有的代碼正常打印出來的控制檯,這樣的用戶有一個進步的想法。我應該如何創建進度報告在計算需求的算法在c + +

當我在爲C++做設計時,已經將算法的核心部分分爲不同的功能,我不想將東西打印出來給控制檯,有沒有方法或設計原則,使用算法得到某種進度指示?

我們可以讓一個可選參數成爲人們可以掛鉤的函數指針,或者我會怎麼做?

void my_heavy_algorithm(int * data, int n,...); 

回答

2

如果你暴露你的算法函數的集合,然後要走的路將有一個參數是一個函數指針像這樣的簽名:

void (*reportProgress)(void*, int) 

但是,如果你正在設計你的算法在C++中應該可以利用封裝併爲你的算法創建一個類(或一組類)。在這種情況下,您不希望將函數指針作爲參數添加到各個函數中。

相反,您可能會使函數指針成爲類的成員。並有訪問器方法來獲取/設置它。或者更好的是,爲報告進度提供一個抽象類。

class ProgressReporter 
{ 
    public: 
    virtual ~ProgressReporter() = 0; 
    virtual void notifyProgressChanged(void* source, int progressValue) = 0; 
} 

class Algo 
{ 
    private: 
    ProgressReporter* _userProvidedReporter = NULL; 

    public: 
    void set_ProgressReporter(ProgressReporter*); // set accessor 
    ProgressReporter* get_ProgressReporter();  // get accessor 
    void my_heavy_algorithm(int*, int, ...);  // your algo. implementation fn. 
} 

void Algo::set_ProgressReporter(ProgressReporter* reporter){ 
    _userProvidedReporter = reporter; 
} 

ProgressReporter* Algo::get_ProgressReporter(){ 
    return _userProvidedReporter; 
} 

void Algo::my_heavy_algorithm(int * data, int n,...){ 

    // do stuff 

    if(_userProvidedReporter != NULL) 
     _userProvidedReporter->notifyProgressChanged((void*)this, currentProgress); 

    // do more stuff 

    if(_userProvidedReporter != NULL) 
     _userProvidedReporter->notifyProgressChanged((void*)this, currentProgress); 

    // so on and so forth.. 
} 

當然,以上是一個非常簡單的例子。如果你期望你的算法支持併發性,你應該同步訪問內部用戶記者,你可以考慮爲你的算法創建一個基類,並提供具體派生實現。

+0

我可以封裝我的算法中的一類。你的ProgressReporter例子是封裝類還是我應該把它包含在我的課上? – 2013-03-08 18:12:36

+0

舉一個例子來說明你在最後一種情況下的含義是否會很好。 – 2013-03-08 18:23:21

+0

ProgressReporter是一個抽象的基類(相當於一個接口),您可以在算法中使用它。類(ES)。你的算法的用戶。類將被要求提供他們自己實現的一個來自ProgressReporter的類,然後你可以使用算法。類報告進度.. – 2013-03-08 18:27:30

0

看看Dependancy Injection。

您可以傳遞實現IProgress接口的對象。 NullProgress對象可能只有存根,但對於您不感興趣監視的對象沒有真正的工作。

通常的方法是在單獨的線程中運行繁重的計算工作,並使用它通過鎖來更新一部分內存。然後UI線程定期從該內存位置讀取並相應地更新屏幕。

0

要報告正確的進度,你需要三件事:

  1. 估計要完成的總工作量。
  2. 估計到目前爲止已完成了多少工作。
  3. 時間的來源。

您還需要某種方式讓您的「沉重的數學」功能「報告」。一種方法是在「開始功能」,「迄今進展」和「功能結束」中調用某種功能。函數的開始還設置了「要完成的工作總量」。迄今的進展報告「現在做多少」,和「功能的結束」說「我完成了」。

在C++類的環境中,可以這樣做如:

class Progress 
{ 
    Progress() { }; 
    virtual void Start(int todo) = 0; 
    virtual void Done(int doneSoFar) = 0; 
    virtual void Finish(); 
}; 

這提供了其它類可以衍生自的接口。

當然,你仍然需要找到一個有用的步驟來放置你的「完成()」 - 如果你把它放在一個很緊的循環裏面,它會影響性能,但是你需要經常做到這一點,也顯示了一些有用的進展。

1

STL風格函子可以幫助你。這也可以使yor算法可以用於任何進度指示器。

例如,假設您想提供百分比進度指標。

// disclaimer - I didn't compile this code 
class NoProgressFeedback; // see below 
void my_heavy_algorithm(int * data, int n, ProgressFeedback giveFeedback = NoProgressFeedback() { 
    int percentProgress = 0; 
    giveFeedback(percentProgress); 
    /* start calculations, do stuff */ 
    percentProgress++; 
    giveFeedback(percentProgress); 
    /* continue over and repeat percentProgress updates and giveFeedback calls */ 
} 

/* NoProgressFeedback will do no progress feedback */ 
class NoProgressFeedback { 
public: 
    operator()(int percent) {} 
} 

如果用戶代碼想要的反饋,那麼就應該通過你的my_heavy_algorithm功能不同的進度指示器,即前人的精力是這樣的:

class GetProgressFeedback { 
public: 
    void operator()(int percent) { std::cout << "percent advance: " << percent; } 
} 
+0

編譯器是否會優化空函數調用?或者它是否有意義取而代之,如果(giveFeedback!= 0)giveFeedback-> operator(); ? – 2013-03-08 18:22:08

+0

如果您保留NoProgressFeedback類,如圖所示,operator()將被內聯,並且它將被優化爲AFAIK,因爲它是NOOP。 – valir 2013-03-10 10:56:53