6

巨大な (メガバイト) uint8_t 配列を静的に初期化したいと思います。

最初に私はこれを試しました:

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

残念ながら、上記のコンパイル時間は非常に長くなります (最適化なし - 約 30 秒、最適化あり - 1 時間以上)。

C スタイルの文字列初期化を使用すると、(最適化がオフの場合とオンの場合の両方で) コンパイル時間がごくわずかに短縮されることがわかりました。

constexpr uint8_t arr[HUGE_SIZE + 1] = "\x00\xFF\x...";

これは C++ での適切なアプローチですか? 上記の割り当ての両側の型を等しくするには、文字列リテラルを使用する必要がありますか?

4

4 に答える 4

4

配列が非常に大きい場合は、ユーティリティを使用して配列からオブジェクト ファイルを直接生成することを検討してください。たとえば、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[];
于 2015-12-28T11:44:28.860 に答える
1

配列を小さなチャンクに分割すると、大きな配列のコンパイル時間が少し改善されることがわかりました。それでも、文字列アプローチは依然として大幅に高速です。このようなスキームでは、真の配列はunionこの配列の配列である可能性があります。

百万バイトのソース ファイルを明示的にコーディングせずに OP の問題をテストする方法の例として、以下を投稿します。これは多くの回答ではなく、調査のためのリソースであるため、このコミュニティ wiki をマークします。

#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;
}
于 2015-12-28T18:28:04.277 に答える