对齐大小的阵列和非对齐大小的阵列上的速度不同

时间:2011-12-20 03:13:42

标签: c++ arrays memory-alignment

我尝试对齐大小的数组和非对齐大小的数组进行操作,但结果是一个难题,非对齐大小的数组比对齐大小的数组快,这是我的代码:

TimeMeter timeMeter;

const int N = 100000;

_Tp A[64];
_Tp B[65];

int szA = sizeof(A);
int szB = sizeof(B);

//  Method 1
timeMeter.start();
for ( int n = 0; n < N; n++ )
{
    memset(A, 0, szA);
}
timeMeter.stop();
printf("Method 1 Time usage = %f ms\n", timeMeter.span());

//  Method 2
timeMeter.start();
for ( int n = 0; n < N; n++ )
{
    memset(B, 0, szB);
}
timeMeter.stop();
printf("Method 2 Time usage = %f ms\n", timeMeter.span());
  • _Tpchar时(8):方法1费用为2.195毫秒,方法2费用为2.175毫秒
  • _Tpint时(32):方法1费用为13.313毫秒,方法2费用为5.987毫秒
  • _Tpdouble时(64):方法1费用为14.266毫秒,方法2费用为11.304毫秒

2 个答案:

答案 0 :(得分:2)

您的基准测试无效,原因如下:

  1. 这里似乎没有任何东西可以检查对齐方式。您只需要两种不同大小的数组。另外,memset也不会太在意对齐,因为它在字节级工作。
  2. 正如ildjarn指出的那样,memset上这么少的内存并不是很好。它太快了,但这本身并不是一个大问题......
  3. ...您没有使用您正在设置的任何内存。优化器可以有效地消除除memset之外的所有调用。
  4. 由于您不使用任何内存,因此CPU实际上可能会进行大量重新排序/缓存,特别是在循环之间。
  5. 你的基准测试在许多操作系统上都有接近时间片大小的运行时间(你不会说哪一个,所以我猜测很多Linux上的1分钟时间)。这意味着操作系统切换开销可能会大大改变您的测试结果。
  6. 您的阵列是一个接一个地分配的。 CPU倾向于预测排序,因此这实际上可能会影响结果。尝试切换循环的顺序,看看它是否有所作为。
  7. 您没有说明您正在使用的时间。许多计时器根本没有ms精度测试所需的分辨率,所以你可能会对结果产生偏差。

答案 1 :(得分:0)

类型只需要在它们自身内对齐,即char必须在1字节边界上对齐,int必须在4字节边界上对齐,double必须在8字节边界上对齐。

要真正测试未对齐的访问,请尝试执行

_Tp* A = (_Tp*)((char*)(new char[num * sizeof(_Tp)]) + 1);

...

delete[] (_Tp*)((char*)A - 1);

此外,memset将所有内容视为指向一系列char s的指针,这些指针永远不会对齐,因此无论您使用数组做什么,都无法获得memset做一个未对齐的写作。