2013-03-16 24 views
2

防止空語句優化考慮下面的代碼:LWS爲基準

#include <iostream> 
#include <chrono> 
#include <cmath> 
#include <ctime> 
#include <cstdlib> 

template <class Counter, class Function, class... Args> 
inline double benchmark(const Counter& counter, Function&& f, Args&&... args) 
{ 
    const std::chrono::high_resolution_clock::time_point marker 
    = std::chrono::high_resolution_clock::now(); 

    for (Counter i = Counter(); i < counter; ++i) { 
     f(args...); 
    } 

    return std::chrono::duration_cast<std::chrono::duration<double> > 
    (std::chrono::high_resolution_clock::now()-marker).count(); 
} 

int main(int argc, char* argv[]) 
{ 
    srand(time(nullptr)); 
    double y = rand()%10+1; 
    std::cout<<benchmark(1000000, [](double x){return std::sin(x);}, y)<<"\n"; 
    return 0; 
} 

功能benchmark測量功能的執行時間。問題是函數在優化過程中被作爲空語句擦除。有沒有辦法強制該功能真正執行?

編輯: 1)我尋找在一個標準的C的溶液++(無特定編譯器指令) 2)這將是更好的,如果f能(保持儘可能通用例如void返回類型)

+0

LWS代碼未發佈 – 2013-03-16 03:15:53

+0

謝謝,現在發佈 – Vincent 2013-03-16 03:17:13

+0

標準中有很多verbage說C++編譯器可以自由刪除副作用的免費代碼......但是,許多編譯器不好看到副作用編譯單元之間的自由度(即鏈接時間優化)。這可能是一種解決問題的方法。 – Yakk 2013-03-16 03:48:17

回答

3

我發現使用揮發性臨時此解決方案:

#include <iostream> 
#include <chrono> 
#include <cmath> 

template <class Clock = std::chrono::high_resolution_clock, class Counter, class Function, class... Args> 
inline double benchmark(const Counter& counter, Function&& f, Args&&... args) 
{ 
    volatile decltype(f(args...)) temporary = decltype(f(args...))(); 
    const typename Clock::time_point marker = Clock::now(); 
    for (Counter i = Counter(); i < counter; ++i) { 
     temporary = f(args...); 
    } 
    return std::chrono::duration<double>(Clock::now()-marker).count(); 
} 

int main(int argc, char* argv[]) 
{ 
    std::cout<<benchmark(1000000000, [](double x){return std::sin(x);}, 3.)<<"\n"; 
    return 0; 
} 

,如果你知道如何改進這個代碼,請發表評論。

+2

你可能會仔細檢查你是不是隻測量1e9商店到'臨時'。我懷疑'sin'有'attribute(pure)'或'attribute(const)',並且你的常量參數(即使是在循環外部選擇的一個隨機參數)可能會導致sin(x)被從循環中提出。 – 2013-03-16 06:09:24

+0

@BenJackson你是對的。對於一個像常量的正弦那樣簡單的函數來說,這個調用是最優化的,而且我基本上測量了複製的時間。但對於函數更復雜,如std :: lgamma(),它似乎工作得很好(但當然我測量std :: lgamma()+複製返回值所需的時間)的計算時間。 – Vincent 2013-03-16 07:15:20

0

由於(匿名)函數返回一個值,爲什麼不在benchmark中捕獲該值並對它做一些微不足道的操作,如將其添加到通過引用傳入的值中?像這樣:

template <class Counter, class Function, class... Args> 
inline double benchmark(double& sum, const Counter& counter, Function&& f, Args&&... args) 
{ 
    const std::chrono::high_resolution_clock::time_point marker 
    = std::chrono::high_resolution_clock::now(); 

    for (Counter i = Counter(); i < counter; ++i) { 
     sum += f(args...); 
    } 

    return std::chrono::duration_cast<std::chrono::duration<double> > 
    (std::chrono::high_resolution_clock::now()-marker).count(); 
} 

我覺得編譯器現在將有一個很難優化函數調用遠(假定您打印或以某種方式在main()使用的總和)。