我正在實施一些深度學習神經網絡和Matlab現有的代碼正常打印出來的控制檯,這樣的用戶有一個進步的想法。我應該如何創建進度報告在計算需求的算法在c + +
當我在爲C++做設計時,已經將算法的核心部分分爲不同的功能,我不想將東西打印出來給控制檯,有沒有方法或設計原則,使用算法得到某種進度指示?
我們可以讓一個可選參數成爲人們可以掛鉤的函數指針,或者我會怎麼做?
void my_heavy_algorithm(int * data, int n,...);
我正在實施一些深度學習神經網絡和Matlab現有的代碼正常打印出來的控制檯,這樣的用戶有一個進步的想法。我應該如何創建進度報告在計算需求的算法在c + +
當我在爲C++做設計時,已經將算法的核心部分分爲不同的功能,我不想將東西打印出來給控制檯,有沒有方法或設計原則,使用算法得到某種進度指示?
我們可以讓一個可選參數成爲人們可以掛鉤的函數指針,或者我會怎麼做?
void my_heavy_algorithm(int * data, int n,...);
如果你暴露你的算法函數的集合,然後要走的路將有一個參數是一個函數指針像這樣的簽名:
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..
}
當然,以上是一個非常簡單的例子。如果你期望你的算法支持併發性,你應該同步訪問內部用戶記者,你可以考慮爲你的算法創建一個基類,並提供具體派生實現。
看看Dependancy Injection。
您可以傳遞實現IProgress接口的對象。 NullProgress對象可能只有存根,但對於您不感興趣監視的對象沒有真正的工作。
通常的方法是在單獨的線程中運行繁重的計算工作,並使用它通過鎖來更新一部分內存。然後UI線程定期從該內存位置讀取並相應地更新屏幕。
要報告正確的進度,你需要三件事:
您還需要某種方式讓您的「沉重的數學」功能「報告」。一種方法是在「開始功能」,「迄今進展」和「功能結束」中調用某種功能。函數的開始還設置了「要完成的工作總量」。迄今的進展報告「現在做多少」,和「功能的結束」說「我完成了」。
在C++類的環境中,可以這樣做如:
class Progress
{
Progress() { };
virtual void Start(int todo) = 0;
virtual void Done(int doneSoFar) = 0;
virtual void Finish();
};
這提供了其它類可以衍生自的接口。
當然,你仍然需要找到一個有用的步驟來放置你的「完成()」 - 如果你把它放在一個很緊的循環裏面,它會影響性能,但是你需要經常做到這一點,也顯示了一些有用的進展。
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; }
}
編譯器是否會優化空函數調用?或者它是否有意義取而代之,如果(giveFeedback!= 0)giveFeedback-> operator(); ? – 2013-03-08 18:22:08
如果您保留NoProgressFeedback類,如圖所示,operator()將被內聯,並且它將被優化爲AFAIK,因爲它是NOOP。 – valir 2013-03-10 10:56:53
我可以封裝我的算法中的一類。你的ProgressReporter例子是封裝類還是我應該把它包含在我的課上? – 2013-03-08 18:12:36
舉一個例子來說明你在最後一種情況下的含義是否會很好。 – 2013-03-08 18:23:21
ProgressReporter是一個抽象的基類(相當於一個接口),您可以在算法中使用它。類(ES)。你的算法的用戶。類將被要求提供他們自己實現的一個來自ProgressReporter的類,然後你可以使用算法。類報告進度.. – 2013-03-08 18:27:30