C++中如何以时钟周期为单位测量指令执行时间及相关验证
关于时钟周期计算函数与指令执行时间测量的问题
核心疑问
- 不确定自己实现的
calcClockCycles函数是否正确 - 不清楚以时钟周期为单位测量指令执行时间的精确公式
- 测试发现
v1 = v2;的测量结果为1时钟单位,但该语句对应2条movaps指令,对结果准确性存疑 - 当前处于Debug无优化编译模式,开发编程语言过程中需要估算表达式的时钟周期,但难以构建合理的估算方式
背景说明
需要测量_multiply等多个函数的执行时间,且要求测量结果固定不变。已将原函数名calcClock修改为calcClockCycles,变量totalPerformedInstructions改为totalPerformedExpressions。使用的CPU为Intel(R) Core(TM) i7-5500U @2.40GHz,代码中GHz参数设为2.4。
代码实现
Chrono结构体代码
#include <chrono> struct Chrono { // Referenced from: // - https://en.cppreference.com/w/cpp/chrono/high_resolution_clock/now // - https://levelup.gitconnected.com/8-ways-to-measure-execution-time-in-c-c-48634458d0f9 private: std::chrono::high_resolution_clock::time_point _start, _end; public: void start() { _start = std::chrono::high_resolution_clock::now(); } void end() { _end = std::chrono::high_resolution_clock::now(); } double elapsed() { std::chrono::duration<double> diff = _end - _start; } double calcClockCycles(int totalPerformedExpressions, float GHz) { // I set GHz to 2.4 with "Intel(R) Core(TM) i7-5500U CPU @ 2.40GHz (4 CPUs), ~2.4GHz". return elapsed() / totalPerformedExpressions * GHz*1000*1000*1000; } };
main.cpp应用示例
Chrono g_ch; int g_iterations = 2*1000*1000; float g_GHz = 2.4f; #define ITERx100_EXPRESSIONS(X) \ for (int i = 0; i < g_iterations; i++) { \ X; X; X; X; X; X; X; X; X; X; \ X; X; X; X; X; X; X; X; X; X; \ X; X; X; X; X; X; X; X; X; X; \ X; X; X; X; X; X; X; X; X; X; \ X; X; X; X; X; X; X; X; X; X; \ X; X; X; X; X; X; X; X; X; X; \ X; X; X; X; X; X; X; X; X; X; \ X; X; X; X; X; X; X; X; X; X; \ X; X; X; X; X; X; X; X; X; X; \ X; X; X; X; X; X; X; X; X; X; \ } inline vec2 _multiply(const vec2 &_v, const mat2x2 &_M) { // |6|T |2 3|T |6*2+4*3| |24| // |4| * |7 5| = |6*7+4*5| = |62| #if defined(__GNUC__) // M = {[0],[1], // [2],[3]} v4sf o; v4sf &v = *(v4sf *)&_v; v4sf &M = *(v4sf *)&_M; #if 0 o[0] = v[0]*M[0] + v[1]*M[1]; o[1] = v[0]*M[2] + v[1]*M[3]; #elif 1 // v4sf a = __builtin_shuffle(v, v4si{0,1,0,1}) * M; // o[0] = a[0] + a[1]; // o[1] = a[2] + a[3]; // // v4sf a = __builtin_shuffle(v, v4si{0,1,0,1}) * M; // o = __builtin_shuffle(a, v4si{0,2}) + __builtin_shuffle(a, v4si{1,3}); v4sf a = __builtin_shuffle(v, v4si{0,0,1,1}) * __builtin_shuffle(M, v4si{0,2,1,3}); o = a + __builtin_shuffle(a, v4si{2,3}); #endif return *(vec2 *)&o; #else return _multiply_slow(_v, _M); #endif } void mat2x2_vxM() { mat2x2 M = v4sf{ 2,3, 7,5, }; vec2 v(6,4); vec2 V; g_ch.start(); ITERx100_EXPRESSIONS(V = _multiply(v, M)); g_ch.end(); printf("%s: %s, %g\n", __func__, to_string(V).c_str(), g_ch.calcClockCycles(100 * g_iterations, g_GHz)); } int main() { mat2x2_vxM(); return 0; }
内容的提问来源于stack exchange,提问作者mandaxyz
相关产品推荐
相关产品推荐

