【发布时间】:2017-01-05 19:35:37
【问题描述】:
我试图将一些使用 C 样式整数向量的代码重构为 QVector(因为其余代码使用 Qt)。
在我这样做之前,我进行了性能测试以检查这种变化会有多糟糕。
我使用以下代码:
#include <QVector>
#include <vector>
#include <cstdio>
#include <ctime>
void test1(int MAX_ELEMENTS, int TIMES) {
int vec[MAX_ELEMENTS];
int nelems = 0;
for (int j=0; j<TIMES; j++) {
nelems = MAX_ELEMENTS;
for (int i=0; i<MAX_ELEMENTS; i++)
vec[i] = 2;
}
printf("Vec[0] = %d\n", vec[0]);
}
void test2(int MAX_ELEMENTS, int TIMES) {
std::vector<int> vec;
vec.reserve(MAX_ELEMENTS);
for (int j=0; j<TIMES; j++) {
vec.clear();
for (int i=0; i<MAX_ELEMENTS; i++)
vec.push_back(2);
}
printf("Vec[0] = %d\n", vec[0]);
}
void test3(int MAX_ELEMENTS, int TIMES) {
QVector<int> vec;
vec.reserve(MAX_ELEMENTS);
for (int j=0; j<TIMES; j++) {
vec.clear();
for (int i=0; i<MAX_ELEMENTS; i++)
vec.push_back(2);
}
printf("Vec[0] = %d\n", vec[0]);
}
void test4(int MAX_ELEMENTS, int TIMES) {
QVector<int> vec;
vec.reserve(MAX_ELEMENTS);
for (int j=0; j<TIMES; j++) {
vec.resize(MAX_ELEMENTS);
for (int i=0; i<MAX_ELEMENTS; i++)
vec[i] = 2;
}
printf("Vec[0] = %d\n", vec[0]);
}
double measureExecutionTime(void (*func)(int, int)) {
const int MAX_ELEMENTS=30000;
const int TIMES=2000000;
clock_t begin, end;
begin = clock();
(*func)(MAX_ELEMENTS, TIMES);
end = clock();
return (double)(end - begin) / CLOCKS_PER_SEC;
}
int main() {
double time_spent;
time_spent = measureExecutionTime(test1);
printf("Test 1 (plain c): %lf\n", time_spent);
time_spent = measureExecutionTime(test2);
printf("Test 2 (std::vector): %lf\n", time_spent);
time_spent = measureExecutionTime(test3);
printf("Test 3 (QVector clear): %lf\n", time_spent);
time_spent = measureExecutionTime(test4);
printf("Test 4 (QVector resize): %lf\n", time_spent);
return 0;
}
结果是:
Vec[0] = 2
Test 1 (plain c): 16.130129
Vec[0] = 2
Test 2 (std::vector): 92.719583
Vec[0] = 2
Test 3 (QVector clear): 109.882463
Vec[0] = 2
Test 4 (QVector resize): 46.261172
对于提高 QVector 性能的不同方式有什么想法吗? 这个向量每秒从 0 填充到它的新大小几次(用于时间表调度软件)。
Qt 版本:5.7.1(+dsfg1,来自 Debian 测试)。
我用来从 Linux shell 编译的命令行:
g++ -c -m64 -pipe -O2 -Wall -W -D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I. -I. -isystem /usr/include/x86_64-linux-gnu/qt5 -isystem /usr/include/x86_64-linux-gnu/qt5/QtGui -isystem /usr/include/x86_64-linux-gnu/qt5/QtCore -I. -I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++-64 -o teste.o teste.cpp
并且要明确:向量元素不相等,我只是将它们等于 2。向量中的有效元素数量随着时间表的活动数量成功安排而不断变化 - 当给定活动无法放入时剩下的插槽,算法开始回滚,删除一些最后放置的活动,以便开始另一次调度尝试。
【问题讨论】:
-
结果是: -- 用于构建测试的编译器选项是......?换句话说,如果您正在为未优化的构建计时,那么您的发现毫无价值。
-
如果性能对时间至关重要,则不应在代码的时间敏感部分分配然后清除 QVector(或任何容器,实际上)。
-
如果你想创建一个全是2的向量,最快的方法大概是
std::vector<int> vec(MAX_ELEMENTS, 2);。现在您将苹果与橙子进行比较。 -
如果您碰巧在使用 Visual Studio 并运行“调试”构建,那么所有这些都是有争议的。原因是
vector由于调试版本中的迭代器检查而出名地慢。这就是为什么在询问性能时说明使用了哪些优化非常重要的原因。 -
@PaulMcKenzie,好的,对不起,我忘了这些信息很重要。帖子已编辑。