【发布时间】:2018-08-25 20:37:21
【问题描述】:
我正在使用下面的简单交换排序算法在 Windows 的 Visual Studio 项目中试验不同的整数类型。处理器是英特尔。代码在版本 x64 中编译。优化设置为“最大化速度 (/O2)”。编译设置对应的命令行是
/permissive- /GS /GL /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Fd"x64\Release\vc141.pdb" /Zc:inline /fp:precise /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oi /MD /Fa"x64\Release\" /EHsc /nologo /Fo"x64\Release\" /Fp"x64\Release\SpeedTestForIntegerTypes.pch" /diagnostics:classic
代码本身:
#include <ctime>
#include <vector>
#include <iostream>
void sort(int N, int A[], int WorkArray[]) // exchange sort
{
int i, j, index, val_min;
for (j = 0; j < N; j++)
{
val_min = 500000;
for (i = j; i < N; i++)
{
if (A[i] < val_min)
{
val_min = A[i];
index = i;
}
}
WorkArray[j] = A[j];
A[j] = val_min;
A[index] = WorkArray[j];
}
}
int main()
{
std::vector<int> A(400000), WorkArray(400000);
for(size_t k = 0; k < 400000; k++)
A[k] = 400000 - (k+1);
clock_t begin = clock();
sort(400000, &A[0], &WorkArray[0]);
clock_t end = clock();
double sortTime = double(end - begin) / CLOCKS_PER_SEC;
std::cout << "Sort time: " << sortTime << std::endl;
return 0;
}
WorkArray 只需要在排序前保存向量。
关键是,这个排序花了我 22.3 秒来完成。有趣的部分是,如果我将数组A、WorkArray 的类型int 更改为size_t(在std::vector 和函数sort 的参数列表中)以及val_min ,时间增加到67.4!这是 三倍 慢!新代码如下:
#include <ctime>
#include <vector>
#include <iostream>
void sort(int N, size_t A[], size_t WorkArray[]) // exchange sort
{
int i, j, index;
size_t val_min;
for (j = 0; j < N; j++)
{
val_min = 500000U;
for (i = j; i < N; i++)
{
if (A[i] < val_min)
{
val_min = A[i];
index = i;
}
}
WorkArray[j] = A[j];
A[j] = val_min;
A[index] = WorkArray[j];
}
}
int main()
{
std::vector<size_t> A(400000), WorkArray(400000);
for(size_t k = 0; k < 400000; k++)
A[k] = 400000 - (k+1);
clock_t begin = clock();
sort(400000, &A[0], &WorkArray[0]);
clock_t end = clock();
double sortTime = double(end - begin) / CLOCKS_PER_SEC;
std::cout << "Sort time: " << sortTime << std::endl;
return 0;
}
请注意,对于函数局部变量 i、j、index、N,我仍然保留类型 int,因此只有 i++ 和 j++ 这两个算术运算应该采用在这两种情况下执行相同的时间。因此,这种放缓与其他原因有关。它与内存对齐问题或寄存器大小或其他有关吗?
但最离谱的部分是当我将int 更改为unsigned int 时。 unsigned int 和 int 都占用相同的字节数,即 4(sizeof 表明了这一点)。但是unsigned int 的运行时间是 65.8 秒!虽然第一个结果可以接受,但第二个结果完全让我感到困惑!为什么运行这样一个甚至不涉及符号检查的简单算法所需的时间会有如此显着的差异?
感谢所有解决这两个问题的人。我可以从哪里开始阅读有关这些硬件级优化特性的更多信息?我不关心排序算法本身,这里只是为了说明问题。
更新:我再次强调 在所有三种情况下我都使用整数作为数组索引。
【问题讨论】:
-
当你改变类型时,你是在所有地方都改变还是只在 main 改变?您能否发布 2 个行为不同的代码版本来回答我的问题?
-
您的优化设置是什么?一般来说,基准测试应该只应用于已发布的、非调试的构建。
-
没有通过 Coliru 对 GCC 进行复制。另外,还有一个警告:
main.cpp:23:16: warning: 'index' may be used uninitialized in this function [-Wmaybe-uninitialized] A[index] = WorkArray[j];不幸的是,我面前没有 MSVC 来测试这个 atm。 -
在我的机器上测试了代码。 int 为 42s,无符号 int 为 41s。当您测试这两种情况时,您的机器是否处于闲置状态? (我对 size_t 不感兴趣,因为这对我来说有点像“呃,它的数据量是两倍”。)
-
@StephenNewell 这很能说明问题。 MSVC 使用
size_t进行矢量化,但不是int。但是int与unsigned几乎相同。
标签: c++ performance int size-t