【问题标题】:Value Initialization vs Calloc vs Manual Initialization Speed值初始化 vs Calloc vs 手动初始化速度
【发布时间】:2014-07-24 14:15:45
【问题描述】:

哪个最快?

我尝试用这个基本能力测试这三种方法的速度:

#include "stdafx.h"
#include "stdlib.h"
#include "stdio.h"
#include "time.h"

int _tmain(int argc, _TCHAR* argv[])
{
  const unsigned long long ARR_SIZ = 0x4fffffff;
  clock_t val_init_dur, calloc_dur, manual_dur;
  clock_t cur = clock();
  char* val_init = new char[ARR_SIZ]();
  clock_t after = clock();
  val_init_dur = after-cur;
  delete[] val_init;

  cur = clock();
  void* calloc_init = calloc(ARR_SIZ, sizeof(char));
  after = clock();
  calloc_dur = after-cur;
  free(calloc_init);

  cur = clock();
  char* manual_init = new char[ARR_SIZ];
  for (unsigned long i=0; i < ARR_SIZ; i++)
    manual_init[i] = 0;
  after = clock();
  manual_dur = after-cur;
  delete[] manual_init;

  printf("Value Initialization Duration: %d\n", val_init_dur);
  printf("Calloc Initialization Duration: %d\n", calloc_dur);
  printf("Manual Initialization Duration: %d\n", manual_dur);
  fgetc(stdin);
  return 0;
}

我的结果是:

值初始化持续时间:541

Calloc 初始化持续时间:493

手动初始化持续时间:3424

但我目前的测试有几个问题:

  • 不知道是否正确隔离了三种不同的初始化方法
  • 我没有测试初始化​​零数组的所有方法(memset 和 malloc,我怀疑它们的工作方式类似于 calloc)
  • 结果以秒为单位(ew!),这是可怕的量化。 (没有毫秒时间?)
  • ARR_SIZ 的值不是 VS '12 (0x7FFFFFFF) 允许的最大大小。尽管代码正在编译,但我无法将值设置为高于上面代码中的值,因为我从第一个新调用中收到了bad_alloc 异常。
  • 我怀疑有比我做的更快的方法来通过迭代手动初始化数组

我将上面的一个要点用斜体表示,因为我很好奇为什么会这样。

有没有人建议如何改进我的测试代码?或者更好的是,对于最初的问题,哪一个最快有一个直接的答案吗?

另外:我已关闭编译器优化

编辑:我更新了我的代码以使用时钟()。结果也更新了。

【问题讨论】:

  • 测试是不等价的,因为使用 calloc 和可能的值初始化,实际上并没有将内存归零,直到它被触摸。而您将 malloc 的内存手动设置为 0 会导致它被触摸并因此被分配。尝试读取 value 和 calloc'd 内存的每个元素,并且(假设优化器不会因为 value 未使用而消除读取)你应该得到相同的结果。
  • 请勿使用time() 进行此类测量。使用clock() 甚至更好的&lt;chrono&gt; 设施。
  • 这对元素有效吗?就像如果我访问单个数组元素只是那个单个元素初始化为 0?还是当访问一个元素时整个数组都被初始化了?
  • 这取决于操作系统。通常内存被分成页面。通常,在程序触及页面之前,操作系统不会实际分配页面。它只是“保留”的。这是为了加速那些最终不会使用它们分配的所有内存的程序。如果你删除修改 malloc 内存的代码,也许它会加速。
  • 如果你有优化,它们应该是等价的。具有完全优化的 GCC 会针对 value-init 情况和手动初始化情况发出 memset 调用。 (它还完全优化了 calloc 调用,除非您在使用其结果的 free 之外添加其他内容。)

标签: c++ c performance


【解决方案1】:

测试是不等价的,因为使用 calloc 和可能的值初始化,实际上在内存被触摸之前不会为 0。而您将 malloc 的内存手动设置为 0 会导致它被触摸并因此被分配。尝试读取 value 和 calloc'd 内存的每个元素,并且(假设优化器不会因为 value 未使用而消除读取)你应该得到相同的结果。

它确实取决于操作系统。一个更简单的操作系统可能不会这样做。通常内存被分成页面。通常,在程序触及页面之前,操作系统不会实际分配页面。它只是“保留”的。这是为了加速那些最终不会使用它们分配的所有内存的程序。如果你删除修改malloc内存的代码,也许它会加速。

澄清一下 - 所有这一切都发生在操作系统的幕后。从值初始化和 calloc 开始,您的程序完全可以假设值在 0 随时准备就绪。

除非特殊情况,否则我个人会对所有动态数组使用向量。默认情况下,它将值设置为 0。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多