基元类型比C++中的用户类型慢
Primitive types slower than user types in C++?
我很好奇,做了一些基准测试来确定int
或float
等基元类型与用户类型之间的性能增量。
我创建了一个模板类Var
,创建了一些内联算术运算符。测试包括为基元和Var
向量循环此循环:
for (unsigned i = 0; i < 1000; ++i) {
in1[i] = i;
in2[i] = -i;
out[i] = (i % 2) ? in1[i] + in2[i] : in2[i] - in1[i];
}
我对结果感到非常惊讶,事实证明我的Var
课大部分时间都更快,int 平均而言,该循环在该课程中花费了大约 5700 纳秒。 在 3000 次运行中,int 比 11 倍快。 Var
快了2989倍。与float
的结果类似,其中Var
比浮点数2991的15100 nsec快15100 nsec。
基元类型不应该更快吗?
编辑:编译器是一个相当古老的 mingw 4.4.0,构建选项是 QtCreator 的默认值,没有优化:
qmake call: qmake.exe C:...untitled15.pro -r -spec win32-g++ "CONFIG+=release"
好的,发布完整源代码,平台是 64 位 Win7,4 GB DDR2-800,Core2Duo@3Ghz
#include <QTextStream>
#include <QVector>
#include <QElapsedTimer>
template<typename T>
class Var{
public:
Var() {}
Var(T val) : var(val) {}
inline T operator+(Var& other)
{
return var + other.value();
}
inline T operator-(Var& other)
{
return var - other.value();
}
inline T operator+(T& other)
{
return var + other;
}
inline T operator-(T& other)
{
return var - other;
}
inline void operator=(T& other)
{
var = other;
}
inline T& value()
{
return var;
}
private:
T var;
};
int main()
{
QTextStream cout(stdout);
QElapsedTimer timer;
unsigned count = 1000000;
QVector<double> pin1(count), pin2(count), pout(count);
QVector<Var<double> > vin1(count), vin2(count), vout(count);
unsigned t1, t2, pAcc = 0, vAcc = 0, repeat = 10, pcount = 0, vcount = 0, ecount = 0;
for (int cc = 0; cc < 5; ++cc)
{
for (unsigned c = 0; c < repeat; ++c)
{
timer.restart();
for (unsigned i = 0; i < count; ++i)
{
pin1[i] = i;
pin2[i] = -i;
pout[i] = (i % 2) ? pin1[i] + pin2[i] : pin2[i] - pin1[i];
}
t1 = timer.nsecsElapsed();
cout << t1 << endl;
timer.restart();
for (unsigned i = 0; i < count; ++i)
{
vin1[i] = i;
vin2[i] = -i;
vout[i] = (i % 2) ? vin1[i] + vin2[i] : vin2[i] - vin1[i];
}
t2 = timer.nsecsElapsed();
cout << t2 << endl;;
pAcc += t1;
vAcc += t2;
}
pAcc /= repeat;
vAcc /= repeat;
if (pAcc < vAcc) {
cout << "primitive was faster" << endl;
pcount++;
}
else if (pAcc > vAcc) {
cout << "var was faster" << endl;
vcount++;
}
else {
cout << "amazingly, both are equally fast" << endl;
ecount++;
}
cout << "Average for primitive type is " << pAcc << ", average for Var is " << vAcc << endl;
}
cout << "int was faster " << pcount << " times, var was faster " << vcount << " times, equal " << ecount << " times, " << pcount + vcount + ecount << " times ran total" << endl;
}
相对而言,对于浮点数,Var 类比浮点数快 6-7%,整数约为 3%。
我还以 10 000 000 而不是原来的 1000 的向量长度运行了测试,结果仍然一致并且有利于该类。
QVector
替换为std::vector
,在优化级别-O2
,GCC 为两种类型生成的代码完全相同,指令对指令。
如果没有替换,生成的代码会有所不同,但这并不奇怪,因为QtVector
对于基元和非基元类型以不同的方式实现(在qvector.h
中查找QTypeInfo<T>::isComplex
)。
更新 看起来isComplex
不会影响linner oop,即测量的部分。这两种类型的循环代码仍然不同,尽管非常轻微。看起来差异是由于海湾合作委员会造成的。
我对 QVector 和 float* 的运行时间和内存分配进行了基准测试,两者之间的差异很小
- 有没有办法提示用户使用哪种数据类型作为模板 c++
- 修改"std::set"中用户定义类型的值
- C++:用户定义的显式类型转换函数错误
- 将用户定义的类型与 std::vector 和 std::sort 一起使用
- 如果用户不小心给出了不正确的数据类型,cin 如何工作?
- C++ - 将结构类型的数组传递给用户定义的函数
- 使用用户定义的类型 UDT 实例化 std::atomic<>。如果 UDT 具有虚函数,则 l 墨水将失败。为什么?
- 用户定义的转换无法指定返回类型
- 是否可以创建一个用户定义的文本,将字符串文本转换为 own 类型的数组?
- 运算符重载以显示用户定义的数据类型
- 如何将用户定义的文字放在C++相同类型的 constexpr 类中?
- 内置类型与用户定义的类型 C++
- 使用用户定义的操作隐式转换为类型
- std::begin-类型特征中未考虑用户定义的重载
- 表达式模板玩具示例:用户定义的强制转换不适用于复杂类型
- 是否可以用类似C/C++(或任何语言)的语言,从作为用户输入的字符串或文件中创建用户定义的数据类型
- 在 C++ 中编写一个程序,要求用户输入 C++ 中所有基元类型的值
- cin 对象如何根据用户需要将字符转换为不同类型的字符?
- 在 C++ 中设置的用户定义数据类型
- 当模板返回类型阻止其实例化时,如何向用户提供漂亮的static_assert消息?