使用合理的编译时间静态初始化巨大的uint8_t数组

时间:2015-12-28 11:25:05

标签: c++ arrays uint8t

我想静态初始化巨大的(兆字节)uint8_t数组。

一开始我试过这个:

possition: absolute

不幸的是,上面的编译时间非常长(没有优化 - 大约30秒,优化时间 - 小时以上)。

如果我们使用c样式字符串初始化,我发现编译时间可以减少到可以忽略不计(在优化关闭和开启情况下):

constexpr uint8_t arr[HUGE_SIZE] = { 0, 255, ... };

这是C ++中的好方法吗?我应该使用一些字符串文字来使上述赋值的两面类型相等吗?

4 个答案:

答案 0 :(得分:5)

如果数组非常大,请考虑使用实用程序直接从数组生成目标文件。例如,使用GNU汇编程序,您可以执行以下操作:

    .section .rodata # or .data, as needed
    .globl arr
arr:
    .incbin "arr.bin" # assuming arr.bin is a file that contains the data
    .size arr,.-arr

然后使用GNU汇编程序汇编此文件并将其链接到您的程序。要在程序的其他位置使用此数据,只需将其声明为extern "C"

extern "C" const uint8_t arr[];

答案 1 :(得分:1)

发现如果将数组分解为更小的块,大型数组的编译时间确实会有所改善。然而,字符串方法仍然明显更快。使用这样的方案,真正的数组可以union这个数组数组。

发布以下内容作为如何在不明确编码百万字节源文件的情况下测试OP问题的示例。因为这不是一个答案,而是一个调查资源,标记这个社区维基。

#include <iostream>
using namespace std;

#include <cstdint>

#define METHOD 5

#if METHOD == 1
// 1 byte blocks 28 secs
#define ZZ16 65, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
#define ZZ256 ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16
#define ZZ4K  ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256
#define ARR constexpr uint8_t arr[]
#define COUT cout << arr << endl

#elif METHOD == 2
// 16 byte blocks 16 secs
#define ZZ16 {66, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255},
#define ZZ256 ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16
#define ZZ4K  ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256
#define ARR constexpr uint8_t arr[][16]
#define COUT cout << arr[0] << endl

#elif METHOD == 3
// 256 byte blocks 16 secs
#define ZZ16 67, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
#define ZZ256 {ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16},
#define ZZ4K  ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256
#define ARR constexpr uint8_t arr[][256]
#define COUT cout << arr[0] << endl

#elif METHOD == 4
// 4K byte blocks 13 secs
#define ZZ16 68, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
#define ZZ256 ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16
#define ZZ4K  {ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256},
#define ARR constexpr uint8_t arr[][4096]
#define COUT cout << arr[0] << endl

#elif METHOD == 5
// String 4 sec
#define ZZ16 "\x45\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF"
#define ZZ256 ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16  ZZ16
#define ZZ4K  ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256 ZZ256
#define ARR constexpr uint8_t arr[]
#define COUT cout << arr << endl
#endif

#define ZZ64K ZZ4K  ZZ4K  ZZ4K  ZZ4K  ZZ4K  ZZ4K  ZZ4K  ZZ4K  ZZ4K  ZZ4K  ZZ4K  ZZ4K  ZZ4K  ZZ4K  ZZ4K  ZZ4K
#define ZZ1M  ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K ZZ64K
#define ZZ16M ZZ1M  ZZ1M  ZZ1M  ZZ1M  ZZ1M  ZZ1M  ZZ1M  ZZ1M  ZZ1M  ZZ1M  ZZ1M  ZZ1M  ZZ1M  ZZ1M  ZZ1M  ZZ1M

// 3 million bytes
ARR = {
    ZZ1M ZZ1M ZZ1M
};

int main() {
  cout << "!!!Hello World!!!" << endl;
  COUT;
  cout << sizeof(arr) << endl;
  return 0;
}

答案 2 :(得分:0)

您是否打算重新编译经常定义数组的文件?如果没有,您可以将数组的定义放入单独的.cpp文件中,并在.h文件中使用前向声明。因此,只有在数组发生变化时才会面临编译开销。

答案 3 :(得分:0)

将数组定义移动到单独的C文件中并按原样编译。 C ++可以引用来自C对象模块的外部全局数据。

如果gcc编译时间过长,请使用tcc