1.前言
调用函数的开销大致可分两个部分:传递参数的开销和保存当前程序上下文信息所花费的开销。对于传递参数的开销而言,传递的参数越多开销就越大;对于保存当前程序上下文所花费的开销而言,函数越复杂需要花费的开销就越大。
2.函数调用约定
函数调用约定,是指当一个函数被调用时,函数的参数会被传递给被调用的函数和返回值会被 返回给调用函数。函数的调用约定就是描述参数是怎么传递和由谁平衡堆栈的,当然还有返回值。
-
__stdcall
(1)堆栈平衡是由调用函数来执行 -
__cdecl
(1)堆栈平衡操作是由被调用函数执行的 -
__fastcall
(1)参数应该放在寄存器中,而不是在栈中,最左边的两个不大于4个字节(DWORD)的参数分别放在ecx和edx寄存器。当寄存器用完的时候,其余参数仍然从右到左的顺序压入堆栈。像浮点值、远指针和__int64类型总是通过堆栈来传递的。 -
__thiscall
(1)会使用一个寄存器或在函数中添加一个不可见的参数来传递类指针 -
__pascal
(1)参数从左到右依次入栈 -
__nakedcall
(1)编译器不会生成 prolog 和 epilog 代码 -
__vectorcall
(1)使用的参数寄存器多于__fastcall或默认的x64调用约定,可传递三种参数:整数类型值,矢量类型值和同构向量聚合(HVA)值。
// HVA类型是最多四个具有相同矢量类型的数据成员的复合类型。
// HVA类型与其成员的向量类型具有相同的对齐要求。
// 这是一个包含三个相同矢量类型并具有32字节对齐的HVA 结构定义的示例:
typedef struct {
__m256 x;
__m256 y;
__m256 z;
} hva3;
3.函数类型
3.1.普通函数
形如:
auto [__stdcall,__cdecl] add(int par1,int par2){
return par1+par2;
}
当然,C++ 默认调用方式为__cdecl 即便你什么都不写,其中__cdecl 可以有可变参数 例如 : int add(int a, …);
3.2.模板函数
形如:
template<class _Ty>
auto add(_Ty par1,_Ty par2){
return par1+par2;
}
模板函数在实例化之后效率是和普通函数一样的,如:
auto v = add(1,2);
对应的实例化版本:
template<int>
auto add(int par1,int par2){
return par1+par2;
}
与3.1的add函数一致
3.3 内联函数
内联扩展是一种特别的用于消除调用函数时所造成的固有的时间消耗方法。一般用于能够快速执行的函数,因为在这种情况下函数调用的时间消耗显得更为突出。这种方法对于很小的函数也有空间上的益处,并且它也使得一些其他的优化成为可能。
形如:
inline auto add(int par1,int par2){
return par1+par2;
}
会直接在调用方展开(如果编译器也认为展开更合适)
// 此时如下调用
auto v = add(1,2);
// 生成的汇编会类似
auto v = 1 + 2;
3.4 宏函数
形如:
#define _ADD(a,b) ((a)+(b))
auto v = _ADD(1,2);
// 实际宏展开后
auto v = ((1)+(2));
// 去除多余括号
auto v = 1 + 2;
3.4 虚函数
在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数,用法格式为:virtual 函数返回类型 函数名(参数表) {函数体};实现多态性,通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数。
形如:
class A {
public:
virtual auto virtual_func(void) { return 0.0; }
float mem = 0.0;
};
class B :public A {
public:
virtual auto virtual_func(void){return 1.0;}
};
// 作如下调用
A* obj = new B;
auto v = obj->virtual_func();
// v 为 1.0
虚函数因为调用机制(进行查表寻址),一般是不会被编译器优化为内联函数(如果确实可以确定被调用的函数,如 B b; b.virtual_func(); 如果函数适合内联则内联,那么就会经行内联)
4.函数调用开销测试
因为宏函数的特殊性,不做测试,将其结果视为等同确定内联展开的内联函数开销。
本次测试函数基准,进行大量迭代,其中value 初始值为0.0:
// 调用基准
value += normal_func(0.3, 0.2, 0.7, value);
// 基准函数
double normal_func(float x, float y, float z, float w) {
auto ret = -x * w - y * z - x * z;
ret *= x;
ret -= y * z;
ret = -ret;
ret /= y * w - x * y + z * w;
return ret / 100.0;
}
// 针对虚函数__thiscall 做出了一些平衡
class A {
public:
virtual double virtual_func(double x, double y, double z) { return 0.0; }
double mem = 0.0;
};
class B :public A {
public:
virtual double virtual_func(double x, double y, double z);
};
// 调用方式 value += obj->virtual_func(0.3, 0.2, 0.7);
// 但在最后 value = obj->mem;
double B::virtual_func(double x, double y, double z) {
double ret = -x * mem - y * z - x * z;
ret *= x;
ret -= y * z;
ret = -ret;
ret /= y * mem - x * y + z * mem;
ret ;
return mem += (ret/ 100.0);
}
总的代码清单请见附页
为了确认调用方式,下面是Release64模式下汇编代码
// 普通函数调用
for (int i = 0, i_end = call_count; i < i_end; ++i) {
value += normal_func(0.3, 0.2, 0.7, value);
00007FF714EA11F0 movaps xmm3,xmm6 // 这里被优化为寄存器传递
00007FF714EA11F3 movaps xmm2,xmm7
00007FF714EA11F6 movaps xmm1,xmm8
00007FF714EA11FA movaps xmm0,xmm9
00007FF714EA11FE call normal_func (07FF714EA1030h)
00007FF714EA1203 addsd xmm6,xmm0
00007FF714EA1207 sub rax,1
00007FF714EA120B jne main+130h (07FF714EA11F0h)
}
// 内联函数调用
for (int i = 0, i_end = call_count; i < i_end; ++i) {
value += inline_func(0.3, 0.2, 0.7, value);
00007FF714EA1262 movaps xmm2,xmm6
00007FF714EA1265 movaps xmm1,xmm6
00007FF714EA1268 mulsd xmm2,xmm14
00007FF714EA126D movaps xmm0,xmm6
00007FF714EA1270 mulsd xmm1,xmm8
00007FF714EA1275 mulsd xmm0,xmm7
00007FF714EA1279 subsd xmm2,xmm12
00007FF714EA127E subsd xmm1,xmm4
00007FF714EA1282 subsd xmm2,xmm15
00007FF714EA1287 addsd xmm1,xmm0
00007FF714EA128B mulsd xmm2,xmm9
00007FF714EA1290 subsd xmm2,xmm12
00007FF714EA1295 xorps xmm2,xmm13
00007FF714EA1299 divsd xmm2,xmm1
00007FF714EA129D divsd xmm2,xmm5
00007FF714EA12A1 addsd xmm6,xmm2
00007FF714EA12A5 movaps xmm3,xmm6
00007FF714EA12A8 movaps xmm1,xmm6
00007FF714EA12AB mulsd xmm3,xmm14
00007FF714EA12B0 movaps xmm0,xmm6
00007FF714EA12B3 mulsd xmm1,xmm8
00007FF714EA12B8 mulsd xmm0,xmm7
00007FF714EA12BC subsd xmm3,xmm12
00007FF714EA12C1 subsd xmm1,xmm4
00007FF714EA12C5 subsd xmm3,xmm15
00007FF714EA12CA addsd xmm1,xmm0
00007FF714EA12CE mulsd xmm3,xmm9
00007FF714EA12D3 subsd xmm3,xmm12
00007FF714EA12D8 xorps xmm3,xmm13
00007FF714EA12DC divsd xmm3,xmm1
00007FF714EA12E0 divsd xmm3,xmm5
00007FF714EA12E4 addsd xmm6,xmm3
00007FF714EA12E8 movaps xmm2,xmm6
00007FF714EA12EB movaps xmm1,xmm6
00007FF714EA12EE mulsd xmm2,xmm14
00007FF714EA12F3 movaps xmm0,xmm6
00007FF714EA12F6 mulsd xmm1,xmm8
00007FF714EA12FB mulsd xmm0,xmm7
00007FF714EA12FF subsd xmm2,xmm12
00007FF714EA1304 subsd xmm1,xmm4
00007FF714EA1308 subsd xmm2,xmm15
00007FF714EA130D addsd xmm1,xmm0
00007FF714EA1311 mulsd xmm2,xmm9
00007FF714EA1316 subsd xmm2,xmm12
00007FF714EA131B xorps xmm2,xmm13
00007FF714EA131F divsd xmm2,xmm1
00007FF714EA1323 divsd xmm2,xmm5
00007FF714EA1327 addsd xmm6,xmm2
00007FF714EA132B movaps xmm3,xmm6
00007FF714EA132E movaps xmm1,xmm6
00007FF714EA1331 mulsd xmm3,xmm14
00007FF714EA1336 movaps xmm0,xmm6
00007FF714EA1339 mulsd xmm1,xmm8
00007FF714EA133E mulsd xmm0,xmm7
00007FF714EA1342 subsd xmm3,xmm12
00007FF714EA1347 subsd xmm1,xmm4
00007FF714EA134B subsd xmm3,xmm15
00007FF714EA1350 addsd xmm1,xmm0
00007FF714EA1354 mulsd xmm3,xmm9
00007FF714EA1359 subsd xmm3,xmm12
00007FF714EA135E xorps xmm3,xmm13
00007FF714EA1362 divsd xmm3,xmm1
00007FF714EA1366 divsd xmm3,xmm5
00007FF714EA136A addsd xmm6,xmm3
00007FF714EA136E movaps xmm2,xmm6
00007FF714EA1371 movaps xmm1,xmm6
00007FF714EA1374 mulsd xmm2,xmm14
00007FF714EA1379 movaps xmm0,xmm6
00007FF714EA137C mulsd xmm1,xmm8
00007FF714EA1381 mulsd xmm0,xmm7
00007FF714EA1385 subsd xmm2,xmm12
00007FF714EA138A subsd xmm1,xmm4
00007FF714EA138E subsd xmm2,xmm15
00007FF714EA1393 addsd xmm1,xmm0
00007FF714EA1397 mulsd xmm2,xmm9
00007FF714EA139C subsd xmm2,xmm12
00007FF714EA13A1 xorps xmm2,xmm13
00007FF714EA13A5 divsd xmm2,xmm1
00007FF714EA13A9 divsd xmm2,xmm5
00007FF714EA13AD addsd xmm6,xmm2
00007FF714EA13B1 movaps xmm3,xmm6
00007FF714EA13B4 mulsd xmm3,xmm14
00007FF714EA13B9 movaps xmm1,xmm6
00007FF714EA13BC mulsd xmm1,xmm8
00007FF714EA13C1 movaps xmm0,xmm6
00007FF714EA13C4 mulsd xmm0,xmm7
00007FF714EA13C8 subsd xmm3,xmm12
00007FF714EA13CD subsd xmm1,xmm4
00007FF714EA13D1 subsd xmm3,xmm15
00007FF714EA13D6 addsd xmm1,xmm0
00007FF714EA13DA mulsd xmm3,xmm9
00007FF714EA13DF subsd xmm3,xmm12
00007FF714EA13E4 xorps xmm3,xmm13
00007FF714EA13E8 divsd xmm3,xmm1
00007FF714EA13EC divsd xmm3,xmm5
00007FF714EA13F0 addsd xmm6,xmm3
00007FF714EA13F4 movaps xmm2,xmm6
00007FF714EA13F7 movaps xmm1,xmm6
00007FF714EA13FA mulsd xmm2,xmm14
00007FF714EA13FF movaps xmm0,xmm6
00007FF714EA1402 mulsd xmm1,xmm8
00007FF714EA1407 mulsd xmm0,xmm7
00007FF714EA140B subsd xmm2,xmm12
00007FF714EA1410 subsd xmm1,xmm4
00007FF714EA1414 subsd xmm2,xmm15
00007FF714EA1419 addsd xmm1,xmm0
00007FF714EA141D mulsd xmm2,xmm9
00007FF714EA1422 subsd xmm2,xmm12
00007FF714EA1427 xorps xmm2,xmm13
00007FF714EA142B divsd xmm2,xmm1
00007FF714EA142F divsd xmm2,xmm5
00007FF714EA1433 addsd xmm6,xmm2
00007FF714EA1437 movaps xmm3,xmm6
00007FF714EA143A movaps xmm1,xmm6
00007FF714EA143D mulsd xmm3,xmm14
00007FF714EA1442 movaps xmm0,xmm6
00007FF714EA1445 mulsd xmm1,xmm8
00007FF714EA144A mulsd xmm0,xmm7
00007FF714EA144E subsd xmm3,xmm12
00007FF714EA1453 subsd xmm1,xmm4
00007FF714EA1457 subsd xmm3,xmm15
00007FF714EA145C addsd xmm1,xmm0
00007FF714EA1460 mulsd xmm3,xmm9
00007FF714EA1465 subsd xmm3,xmm12
for (int i = 0, i_end = call_count; i < i_end; ++i) {
value += inline_func(0.3, 0.2, 0.7, value);
00007FF714EA146A xorps xmm3,xmm13
00007FF714EA146E divsd xmm3,xmm1
00007FF714EA1472 divsd xmm3,xmm5
00007FF714EA1476 addsd xmm6,xmm3
00007FF714EA147A movaps xmm1,xmm6
00007FF714EA147D movaps xmm0,xmm6
00007FF714EA1480 mulsd xmm1,xmm8
00007FF714EA1485 movaps xmm2,xmm6
00007FF714EA1488 mulsd xmm2,xmm14
00007FF714EA148D mulsd xmm0,xmm7
00007FF714EA1491 subsd xmm1,xmm4
00007FF714EA1495 subsd xmm2,xmm12
00007FF714EA149A addsd xmm1,xmm0
00007FF714EA149E subsd xmm2,xmm15
00007FF714EA14A3 mulsd xmm2,xmm9
00007FF714EA14A8 subsd xmm2,xmm12
00007FF714EA14AD xorps xmm2,xmm13
00007FF714EA14B1 divsd xmm2,xmm1
00007FF714EA14B5 divsd xmm2,xmm5
00007FF714EA14B9 addsd xmm6,xmm2
00007FF714EA14BD movaps xmm3,xmm6
00007FF714EA14C0 movaps xmm1,xmm6
00007FF714EA14C3 mulsd xmm3,xmm14
00007FF714EA14C8 movaps xmm0,xmm6
00007FF714EA14CB mulsd xmm1,xmm8
00007FF714EA14D0 mulsd xmm0,xmm7
00007FF714EA14D4 subsd xmm3,xmm12
00007FF714EA14D9 subsd xmm1,xmm4
00007FF714EA14DD subsd xmm3,xmm15
00007FF714EA14E2 addsd xmm1,xmm0
00007FF714EA14E6 mulsd xmm3,xmm9
00007FF714EA14EB subsd xmm3,xmm12
00007FF714EA14F0 xorps xmm3,xmm13
00007FF714EA14F4 divsd xmm3,xmm1
00007FF714EA14F8 divsd xmm3,xmm5
00007FF714EA14FC addsd xmm6,xmm3
00007FF714EA1500 sub rax,1
00007FF714EA1504 jne main+1A2h (07FF714EA1262h)
}
// __fastcall调用
for (int i = 0, i_end = call_count; i < i_end; ++i) {
value += fast_func(0.3, 0.2, 0.7, value);
00007FF714EA1550 movaps xmm3,xmm6
00007FF714EA1553 movaps xmm2,xmm7
00007FF714EA1556 movaps xmm1,xmm8
00007FF714EA155A movaps xmm0,xmm9
00007FF714EA155E call normal_func (07FF714EA1030h) // 这里被优化为normal_func
00007FF714EA1563 addsd xmm6,xmm0
00007FF714EA1567 sub rax,1
00007FF714EA156B jne main+490h (07FF714EA1550h)
}
// 虚函数调用
for (int i = 0, i_end = call_count; i < i_end; ++i) {
value += obj->virtual_func(0.3, 0.2, 0.7);
00007FF714EA15C0 mov rcx,qword ptr [obj (07FF714EA5700h)]
for (int i = 0, i_end = call_count; i < i_end; ++i) {
value += obj->virtual_func(0.3, 0.2, 0.7);
00007FF714EA15C7 movaps xmm3,xmm7
00007FF714EA15CA movaps xmm2,xmm8
00007FF714EA15CE movaps xmm1,xmm9
00007FF714EA15D2 mov rax,qword ptr [rcx]
00007FF714EA15D5 call qword ptr [rax]
00007FF714EA15D7 sub rdi,1
00007FF714EA15DB jne main+500h (07FF714EA15C0h)
}
// __vectorcall
for (int i = 0, i_end = call_count; i < i_end; ++i) {
value += vector_func(0.3, 0.2, 0.7, value);
00007FF714EA1630 movaps xmm3,xmm6
00007FF714EA1633 movaps xmm2,xmm7
00007FF714EA1636 movaps xmm1,xmm8
00007FF714EA163A movaps xmm0,xmm9
00007FF714EA163E call normal_func (07FF714EA1030h) // 这里被优化为normal_func
00007FF714EA1643 addsd xmm6,xmm0
00007FF714EA1647 sub rax,1
00007FF714EA164B jne main+570h (07FF714EA1630h)
}
第一次测试结果:
组名 | 测试组1 | 测试组2 | 测试组 3 | 测试组 4 | 测试组 5 | 测试组 6 | 测试组 7 | 测试组 8 | 测试组 9 | 测试组 10 |
---|---|---|---|---|---|---|---|---|---|---|
普通函数计算结果 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 |
内联函数计算结果 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 |
__fastcall函数计算结果 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 |
虚函数函数计算结果 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 |
__vectorcall函数计算结果 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 | -2.72222 |
普通函数所用时间 | 254098 | 198315 | 295810 | 196010 | 231354 | 227261 | 234529 | 193469 | 208299 | 194281 |
内联函数所用时间 | 204532 | 207672 | 220823 | 193657 | 251189 | 214864 | 235892 | 189333 | 197464 | 191431 |
__fastcall函数所用时间 | 219724 | 202143 | 196455 | 193939 | 206037 | 191861 | 234598 | 227355 | 208511 | 222972 |
虚函数函数所用时间 | 249393 | 226958 | 214917 | 215913 | 216678 | 215154 | 275628 | 223812 | 217290 | 214860 |
__vectorcall函数所用时间 | 240161 | 201210 | 192023 | 277484 | 223628 | 195951 | 200724 | 195849 | 194678 | 195168 |
普通函数所用时间最大/小值 | 最大值295810 | 最小值193469 | ||||||||
内联函数所用时间最大/小值 | 最大值251189 | 最小值189333 | ||||||||
__fastcall函数所用时间最大/小值 | 最大值234598 | 最小值191861 | ||||||||
虚函数函数所用时间最大/小值 | 最大值275628 | 最小值214860 | ||||||||
__vectorcall函数所用时间最大/小值 | 最大值277484 | 最小值192023 | ||||||||
普通函数所用时间平均值 | 218018 | |||||||||
内联函数所用时间平均值 | 208292 | |||||||||
__fastcall函数所用时间平均值 | 209642 | |||||||||
虚函数函数所用时间平均值 | 222514 | |||||||||
__vectorcall函数所用时间平均值 | 205921 |
第二次测试结果:
++ 普通函数调用调用平均时间:202104
++ 内联函数调用调用平均时间:199590
++ __fastcall函数调用调用平均时间:200249
++ 虚函数调用调用平均时间:218817
++ __vectorcall函数调用调用平均时间:204897
第三次测试结果
++ 普通函数调用调用平均时间:191915
++ 内联函数调用调用平均时间:190074
++ __fastcall函数调用调用平均时间:194492
++ 虚函数调用调用平均时间:222944
++ __vectorcall函数调用调用平均时间:196064
因为优化关系,大致时间消耗 :
内联 < 普通函数(寄存器优化)、__fastcall 、__vectorcall < 虚函数
因为虚函数涉及堆变量存取以及每次调用的查表操作,时间要慢一些,在本例函数调用测试中,成本在原函数 1.1 ± 0.05左右
附页
代码清单:
class A {
public:
virtual double virtual_func(double x, double y, double z) { return 0.0; }
double mem = 0.0;
};
class B :public A {
public:
virtual double virtual_func(double x, double y, double z);
};
double B::virtual_func(double x, double y, double z) {
double ret = -x * mem - y * z - x * z;
ret *= x;
ret -= y * z;
ret = -ret;
ret /= y * mem - x * y + z * mem;
ret ;
return mem += (ret/ 100.0);
}
#include "pch.h"
#include <iostream>
#include <vector>
#include <Windows.h>
using namespace std;
__forceinline double inline_func(double x, double y, double z, double w) {
double ret = -x * w - y * z - x * z;
ret *= x;
ret -= y * z;
ret = -ret;
ret /= y * w - x * y + z * w;
return ret / 100.0;
}
double normal_func(double x, double y, double z, double w) {
double ret = -x * w - y * z - x * z;
ret *= x;
ret -= y * z;
ret = -ret;
ret /= y * w - x * y + z * w;
return ret / 99.0;
}
double __fastcall fast_func(double x, double y, double z, double w) {
double ret = -x * w - y * z - x * z;
ret *= x;
ret -= y * z;
ret = -ret;
ret /= y * w - x * y + z * w;
return ret / 100.0;
}
double __vectorcall vector_func(double x, double y, double z, double w) {
double ret = -x * w - y * z - x * z;
ret *= x;
ret -= y * z;
ret = -ret;
ret /= y * w - x * y + z * w;
return ret / 100.0;
}
A *obj = new B;
int main(){
// 初始化区域
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq); // 获取计时器精度
const double a = 1000000.0 / freq.QuadPart; // 计时精度纳秒
LARGE_INTEGER begin_time;
LARGE_INTEGER end_time;
double value = 0.0; // 迭代值
double ns_time = 0.0; // 所用时间
constexpr int data_count = 5; // 测试函数种类数量
constexpr int group_count = 10; // 测试次数
constexpr int call_count = 10000000; // 调用次数
double time_arr[data_count][group_count] = { 0.0 }; // 记录函数每次测试调用时间
double result_arr[data_count][group_count] = { 0.0 }; // 统计迭代计算结果
for (int j = 0, j_end = group_count; j < j_end; ++j) {
// ********************************************************
// ********************************************************
// 普通函数调用
QueryPerformanceCounter(&begin_time);
for (int i = 0, i_end = call_count; i < i_end; ++i) {
value += normal_func(0.3, 0.2, 0.7, value);
}
QueryPerformanceCounter(&end_time);
ns_time = (end_time.QuadPart - begin_time.QuadPart) * a;
time_arr[0][j] = ns_time;
result_arr[0][j] = value;
// ********************************************************
// ********************************************************
// 内联函数调用
value = 0.0;
ns_time = 0.0;
QueryPerformanceCounter(&begin_time);
for (int i = 0, i_end = call_count; i < i_end; ++i) {
value += inline_func(0.3, 0.2, 0.7, value);
}
QueryPerformanceCounter(&end_time);
ns_time = (end_time.QuadPart - begin_time.QuadPart) * a;
time_arr[1][j] = ns_time;
result_arr[1][j] = value;
// ********************************************************
// ********************************************************
// __fastcall
value = 0.0;
ns_time = 0.0;
QueryPerformanceCounter(&begin_time);
for (int i = 0, i_end = call_count; i < i_end; ++i) {
value += fast_func(0.3, 0.2, 0.7, value);
}
QueryPerformanceCounter(&end_time);
ns_time = (end_time.QuadPart - begin_time.QuadPart) * a;
time_arr[2][j] = ns_time;
result_arr[2][j] = value;
// ********************************************************
// ********************************************************
// 虚函数
value = 0.0;
ns_time = 0.0;
obj->mem = 0.0;
QueryPerformanceCounter(&begin_time);
for (int i = 0, i_end = call_count; i < i_end; ++i) {
value += obj->virtual_func(0.3, 0.2, 0.7);
// 虽然这里虚函数内部计算了,但还是写出来
}
QueryPerformanceCounter(&end_time);
ns_time = (end_time.QuadPart - begin_time.QuadPart) * a;
time_arr[3][j] = ns_time;
result_arr[3][j] = obj->mem;
// ********************************************************
// ********************************************************
// __vectorcall
value = 0.0;
ns_time = 0.0;
QueryPerformanceCounter(&begin_time);
for (int i = 0, i_end = call_count; i < i_end; ++i) {
value += vector_func(0.3, 0.2, 0.7, value);
}
QueryPerformanceCounter(&end_time);
ns_time = (end_time.QuadPart - begin_time.QuadPart) * a;
time_arr[4][j] = ns_time;
result_arr[4][j] = value;
}
// 函数种类标识
const char* name_arr[data_count] = {
"普通函数调用",
"内联函数调用",
"__fastcall函数调用",
"虚函数调用",
"__vectorcall函数调用",};
// 打印迭代结算结果
std::cout << "计算完毕,打印结果:" << endl;
for (int j = 0, j_end = data_count; j < j_end; ++j) {
std::cout << name_arr[j] << "计算结果:" << endl;
for (int i = 0, i_end = group_count; i < i_end; ++i) {
std::cout << result_arr[j][i] << ",";
}
std::cout << std::endl;
}
// 打印每组测试所用时间,并统计最大最小值下标
std::cout << endl << endl;
int max_index[data_count] = { 0 };
int min_index[data_count] = { 0 };
double sum[data_count] = { 0.0 };
for (int j = 0, j_end = data_count; j < j_end; ++j) {
std::cout << name_arr[j] << "所用时间:" << endl;
for (int i = 0, i_end = group_count; i < i_end; ++i) {
std::cout << time_arr[j][i] << ",";
if (time_arr[j][i] > time_arr[j][max_index[j]]) { max_index[j] = i; }
if (time_arr[j][i] < time_arr[j][min_index[j]]) { min_index[j] = i; }
sum[j] += time_arr[j][i];
}
std::cout << endl;
}
std::cout << endl << endl;
for (int j = 0, j_end = data_count; j < j_end; ++j) {
std::cout << name_arr[j] << "时间最大值:" ;
std::cout << time_arr[j][max_index[j]] << endl;
std::cout << name_arr[j] << "时间最小值:";
std::cout << time_arr[j][min_index[j]] << endl;
sum[j] -= time_arr[j][max_index[j]];
sum[j] -= time_arr[j][min_index[j]];
}
std::cout << endl << endl;
// 打印统计结果
std::cout << "统计完毕,除去一个最大值一个最小值,打印结果:" << endl;
for (int j = 0, j_end = data_count; j < j_end; ++j) {
std::cout << " ++ " << name_arr[j] << "调用平均时间:" << sum[j] / 8.0 << endl;
}
system("pause");
return 0;
}