我正在尋找一種通用的方法來測量像Here這樣的函式計時,但是對于 c 。
我的主要目標是不要到處都有像這樣混亂的代碼:
auto t1 = std::chrono::high_resolution_clock::now();
function(arg1, arg2);
auto t2 = std::chrono::high_resolution_clock::now();
auto tDur = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1);
而是在函式周圍有一個很好的包裝器。到目前為止我得到的是:
計時.hpp:
#pragma once
#include <chrono>
#include <functional>
template <typename Tret, typename Tin1, typename Tin2> unsigned int getDuration(std::function<Tret(Tin1, Tin2)> function, Tin1 arg1, Tin2 arg2, Tret& retValue)
{
auto t1 = std::chrono::high_resolution_clock::now();
retValue = function(arg1, arg2);
auto t2 = std::chrono::high_resolution_clock::now();
auto tDur = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1);
return tDur.count();
}
主.cpp:
#include "timing.hpp"
#include "matrix.hpp"
constexpr int G_MATRIXSIZE = 2000;
int main(int argc, char** argv)
{
CMatrix<double> myMatrix(G_MATRIXSIZE);
bool ret;
// this call is quite ugly
std::function<bool(int, std::vector<double>)> fillRow = std::bind(&CMatrix<double>::fillRow, &myMatrix, 0, fillVec);
auto duration = getDuration(fillRow, 5, fillVec, ret );
std::cout << "duration(ms): " << duration << std::endl;
}
如果某人想測驗代碼,matrix.hpp:
#pragma once
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
template<typename T> class CMatrix {
public:
// ctor
CMatrix(int size) :
m_size(size)
{
m_matrixData = new std::vector<std::vector<T>>;
createUnityMatrix();
}
// dtor
~CMatrix()
{
std::cout << "Destructor of CMatrix called" << std::endl;
delete m_matrixData;
}
// print to std::out
void printMatrix()
{
std::ostringstream oss;
for (int i = 0; i < m_size; i )
{
for (int j = 0; j < m_size; j )
{
oss << m_matrixData->at(i).at(j) << ";";
}
oss << "\n";
}
std::cout << oss.str() << std::endl;
}
bool fillRow(int index, std::vector<T> row)
{
// checks
if (!indexValid(index))
{
return false;
}
if (row.size() != m_size)
{
return false;
}
// data replacement
for (int j = 0; j < m_size; j )
{
m_matrixData->at(index).at(j) = row.at(j);
}
return true;
}
bool fillColumn(int index, std::vector<T> column)
{
// checks
if (!indexValid(index))
{
return false;
}
if (column.size() != m_size)
{
return false;
}
// data replacement
for (int j = 0; j < m_size; j )
{
m_matrixData->at(index).at(j) = column.at(j);
}
return true;
}
private:
// variables
std::vector<std::vector<T>>* m_matrixData;
int m_size;
bool indexValid(int index)
{
if (index 1 > m_size)
{
return false;
}
return true;
}
// functions
void createUnityMatrix()
{
for (int i = 0; i < m_size; i )
{
std::vector<T> _vector;
for (int j = 0; j < m_size; j )
{
if (i == j)
{
_vector.push_back(1);
}
else
{
_vector.push_back(0);
}
}
m_matrixData->push_back(_vector);
}
}
};
問題是,由于 std::function 的使用,這段代碼仍然很丑陋。有更好和/或更簡單的選擇嗎?( 我也確定我把 std::bind 搞砸了,我想我需要使用 std::placeholders,因為我想稍后設定引數。)
// 編輯,在 main 中正確使用占位符:
std::function<bool(int, std::vector<double>)> fillRow = std::bind(&CMatrix<double>::fillRow, &myMatrix, std::placeholders::_1, std::placeholders::_2);
auto duration = getDuration(fillRow, 18, fillVec, ret );
uj5u.com熱心網友回復:
您可以利用 RAII 實作一個記錄代碼塊執行時間的計時器和一個模板函式,該模板函式包裝您希望使用計時器執行的函式。
#include<string>
#include<chrono>
#include <unistd.h>
struct Timer
{
std::string fn, title;
std::chrono::time_point<std::chrono::steady_clock> start;
Timer(std::string fn, std::string title)
: fn(std::move(fn)), title(std::move(title)), start(std::chrono::steady_clock::now())
{
}
~Timer()
{
const auto elapsed =
std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start).count();
printf("%s: function=%s; elasepd=%f ms\n", title.c_str(), fn.c_str(), elapsed / 1000.0);
}
};
#ifndef ENABLE_BENCHMARK
static constexpr inline void dummy_fn() { }
#define START_BENCHMARK_TIMER(...) dummy_fn()
#else
#define START_BENCHMARK_TIMER(title) bench::Timer timer(__FUNCTION__, title)
#endif
template<typename F, typename ...Args>
auto time_fn(F&& fn, Args&&... args) {
START_BENCHMARK_TIMER("wrapped fn");
return fn(std::forward<Args>(args)...);
}
int foo(int i) {
usleep(70000);
return i;
}
int main()
{
printf("%d\n", time_fn(foo, 3));
}
標準輸出:
wrapped fn: function=time_fn; elasepd=71.785000 ms
3
大概的概念:
time_fn是一個簡單的模板函式,它使用提供的引數呼叫START_BENCHMARK_TIMER和呼叫fnSTART_BENCHMARK_TIMER然后創建一個Timer物件。它將記錄當前時間start。請注意,__FUNCTION__它將替換為被呼叫的函式。- 當提供的
fn回傳或拋出例外時,Timer(1)中的物件將被銷毀并呼叫解構式。然后解構式將計算當前時間和記錄start時間之間的時間差并將其列印到標準輸出
筆記:
- 即使宣告
startandendintime_fn而不是 RAII 計時器將起作用,但擁有 RAII 計時器將允許您在fn引發例外時干凈地處理這種情況 - 如果您使用的是 c 11,則需要將
time_fn宣告更改為typename std::result_of<F &&(Args &&...)>::type time_fn(F&& fn, Args&&... args).
編輯:更新了回應以包含包裝函式方法。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/428011.html
