我想静态初始化巨大的(兆字节)uint8_t数组。
一开始我试过这个:
possition: absolute
不幸的是,上面的编译时间非常长(没有优化 - 大约30秒,优化时间 - 小时以上)。
如果我们使用c样式字符串初始化,我发现编译时间可以减少到可以忽略不计(在优化关闭和开启情况下):
constexpr uint8_t arr[HUGE_SIZE] = { 0, 255, ... };
这是C ++中的好方法吗?我应该使用一些字符串文字来使上述赋值的两面类型相等吗?
答案 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
。