【问题标题】:how to create 4096 aligned table[x][4096]如何创建 4096 对齐表[x][4096]
【发布时间】:2012-11-30 07:51:30
【问题描述】:

我想得到一个 [x][4096] 的表(例如 int table[4096][4096]) 但我不知道该怎么做——尤其是以更一般的方式(它是 在许多编译器上还有较旧的编译器(mingw、dmc、lcc、b55)

我想让表格女巫每一行都填充到一个(或多个)系统中 页面(为了提高效率,它会更快吗?据我所知)
所以我想得到一个填充一组系统页面的数组,它 与他们非常一致

(我不希望出现任何错误,页面中没有空格)

1) 我可以通过这种方式获得静态数组吗(在许多编译器中) 2)如何以malloc方式完成? (我依稀记得 malloc 可以在他分配的 ram 之前放置一些元数据,这样会破坏图像, 也许它也没有分配精确的字节数(?)但我不确定 到那个

我可以把这样清晰的分配 - 例如 256 个对齐的 4K 页面作为一个表格吗?

【问题讨论】:

    标签: c++ c winapi optimization memory-alignment


    【解决方案1】:

    Windows 中的页面分配函数是VirtualAlloc。同时传递MEM_COMMIT | MEM_RESERVE 以获得实际分配,而不仅仅是保留。

    【讨论】:

      【解决方案2】:

      由于问题被标记为 winapi,我假设您使用的是 Windows。 在这种情况下,您可能只想使用_aligned_malloc()

      在 Linux/POSIX 系统上,有posix_memalign()

      使用这些 API 之一,您应该分配将对齐到 4KB 的大内存块。然后,您只需使用普通指针访问它。

      【讨论】:

      • 您确定它会给出例如一页,并且不触及其他页面吗?
      • 我不知道微软在这里到底承诺了什么。但是您可以通过检查返回的地址是否可以被 4096 整除来测试它
      • 静态表格怎么样(尤其是二维的 t[100][4096] ?我可以让它完全适合页面吗?)
      【解决方案3】:

      您可以按照您的要求进行对齐,但由于C/C++ 中没有用于对齐定义的标准说明,因此无法移植。

      对于静态数据,它通常是一些#pragma 或编译器内在函数。

      例如,在 VC++ 中有一个 __declspec( align( # ) ) 可用于数据对齐:http://msdn.microsoft.com/en-us/library/83ythb65(v=vs.110).aspx

      对于动态数据,它是相同的非便携式解决方案,有关详细信息,请参阅@mvp 答案。但是,对于动态数据,您可以根据标准 malloc 函数实现自己的对齐数据分配器。由于它基于标准库,您的分配器将是可移植的

      【讨论】:

      • 怎么样?通过分配更多并向上对齐?
      • 是的。这实际上是一个常见的面试问题
      【解决方案4】:

      您可以过度分配和微调指针:

       int *a = malloc(4096*4096*4+4095);
       int *b = (int*) (((int)a)+4095 & (~4095)));
      

      也有可能(但不能保证)分配,例如64 + 64字节,发现地址相隔80字节,然后计算下一个分配单元L的长度,使大单元与给定地址对齐。

      #include <string.h>
      #include <stdio.h>
      int main()
      {
        int *a = malloc(64);
        int *b = malloc(64);
        long long excess = ((long)b - (long)a)-64;
        int *c = malloc(4096 - (((int)(b) & 4095) + excess*2 + 64));
        int *d = malloc(4096*4);
        printf("%x %x %x %x\n",
           (int)a & 0xffffffff,(int)b & 0xffffffff, 
           (int)c & 0xffffffff,(int)d & 0xffffffff);
      }
      

      输出:18e2010 18e2060 18e20b0 18e3000

      但有一个通知:d=malloc(4096*4096) 失败的最后一个 malloc(并产生 0x55505010),因为 glib 实现从不同的池或使用不同的方法(例如系统调用kmalloc)。每次运行的第一个分配地址似乎正好偏移了 10(十六进制)字节,因为这是簿记所需的空间,而且显然系统已经将堆对齐到 4096 字节边界。

      【讨论】:

      • 你写的第一个例子似乎是合理的方式(你确定它会工作吗?)静态表怎么样,你知道静态对齐的方式吗(至少在某些编译器上,如果不是全部??)新标准中有 Alignas_ 运算符或类似的东西,它会起作用吗?
      • 我确信第一个可以将指针对齐到 4096 字节边界。但不能保证它会与某些特殊操作系统(或分段架构 DOS+8086)中的页面边界对齐。
      • 我发现它是一个部分答案(不是关于 ststic 只是动态的)但是你写的例程很好,我会在上面写对齐的 malloc() 所以 tnx :)
      • @AkiSuihkonen 屏蔽低位以获得对齐的地址会起作用,但是一旦你释放a,你就会在这里发生内存泄漏。您需要将原始指针存储在某处并将其传递给free。你的第二个例子我不明白,我试图执行它并没有收到任何对齐的东西:ideone.com/Kv9XSx
      • @AkiSuihkonen 我指的是您的解决方案中的问题,而不是正确的部分。在您的第一个示例中,您破坏了操作系统提供给您的原始指针,并且您无法检索它以进行释放。您的第二个示例根本不起作用。
      猜你喜欢
      • 2016-11-20
      • 2014-09-11
      • 2013-03-06
      • 2016-03-28
      • 1970-01-01
      • 2010-09-16
      • 2014-09-14
      • 2016-02-25
      相关资源
      最近更新 更多