簡體   English   中英

“const unordered_map”作為全局變量的編譯速度慢

[英]Slow compilation speed for "const unordered_map" as global variable

我的編譯時間非常慢,可能是由於存在std::unordered_map類型的全局變量。 您可以在下面找到代碼行,它們位於名為correspondance.h的文件中

    using Entry_t = std::tuple<Cfptr_t, short int, short int>;
    ...
    #include "map_content.h"
        inline const std::unordered_map<std::string, Entry_t> squaredampl{MAP_CONTENT};
    #undef MAP_CONTENT

並且,在map_content.h中有 map 的內容:

     #define MAP_CONTENT \
    { {EMPTYCHAR+corr::su_R,ANTICHAR,EMPTYCHAR+corr::sd_L,EMPTYCHAR+corr::A,EMPTYCHAR+corr::W},{    &mssm2to2::sumSqAmpl_su_R_anti_sd_L_to_A_W, 9,2}},\
    { {EMPTYCHAR+corr::su_L,ANTICHAR,EMPTYCHAR+corr::sd_R,EMPTYCHAR+corr::A,EMPTYCHAR+corr::W},{  &mssm2to2::sumSqAmpl_su_L_anti_sd_R_to_A_W, 9,2}},\
    ...

它像這樣持續了大約 3500 行。 注意

  1. Cfptr_t是一個function指針
  2. EMPTYCHARcorr::something類型的所有變量都是整數,所以它們定義了鍵值字符串

我遇到的問題是 makefile 每個包含correspondace.h的文件需要 10 分鍾,因為確實有很多代碼行要處理。

正如您可能已經理解的那樣,需要這個 map 來允許用戶在不知道函數名稱的情況下訪問函數,而只需要一個字符串。 出於這個原因,我目前無法消除此功能,因為它是基本功能。

盡我所能,我嘗試將此文件包含在盡可能少的文件中。 無論如何,將它包含在每個將生成可執行文件的文件中是不可避免的,因此,總的來說,這迫使我每次必須調試某些東西時都要等待很長時間。

如果您對如何加速編譯保持此功能有任何建議,那對我來說真的很有幫助:)

改變

#include "map_content.h"
inline const std::unordered_map<std::string, Entry_t> squaredampl{MAP_CONTENT};
#undef MAP_CONTENT

extern const std::unordered_map<std::string, Entry_t> squaredampl;

在一個新的.cpp文件中:

#include "correspondance.h"
#include "map_content.h"
const std::unordered_map<std::string, Entry_t> squaredampl{MAP_CONTENT};
#undef MAP_CONTENT

這將導致僅發出 map 的一個定義(與內聯相反, inline將在每個翻譯單元 odr-using 中發出它)。

只要 map 在進入main之前的另一個 static 存儲持續時間 object 的構造期間不被使用,它就是安全的。 如果需要,最好使 map 成為 function 中的本地 static 變量,通過引用返回它以供調用者使用。 這將避免“靜態初始化順序慘敗”。


它也可能有助於制作一個 function 來初始化 map 每個條目的insert語句而不是在初始化程序中完成所有操作,即有一個 function initSquaredampl返回一個std::unordered_map<std::string, Entry_t>按值然后:

auto initSquaredampl() {
    std::unordered_map<std::string, Entry_t> squaredampl;
    // Insert items one-by-one
    return squaredampl;
}

const std::unordered_map<std::string, Entry_t> squaredampl = initSquaredampl();

可能會有所幫助,因為編譯器可能不會針對非常長的表達式或初始化程序的編譯進行優化。 然而,他們也可能在處理非常長的函數時遇到麻煩。

我要感謝@Kaldrr 和@user17732522 的精彩見解。 我通過以下方式解決了我的問題。 correspondance.h我只是把:

inline std::unordered_map<std::string, Entry_t> squaredampl;

即空 map 的簡單初始化。然后,我使用以下幾行創建了一個新的 header init_map.h

#include "correspondance.h"

int Initialise();

當然,還有一個相應的initialise_map.cpp文件,其中定義了 function

#include "initialise_map.h"

int Initialise()
{
  if (!corr::squaredampl.empty()) return 0;
  corr::squaredampl.reserve(3500);
  corr::squaredampl = {
#include "map_content_body.h"
  };
  return 0;
}

其中map_content_body.h是map的內容行。這樣:

  1. map 的代碼只在一個文件中
  2. 我避免定義宏並復制它
  3. 一旦我有了 object 文件initialise_map.o ,所有將生成可執行文件的 .cpp 文件將不包含代碼,但 function 將在鏈接階段存在

因此,除非我刪除initialise_map.o或更新initialise_map.cpp ,否則我的代碼會以正常速度編譯,因為它應該是這樣。

當然,我注意在每個 header 文件中使用#pragma once或類似的代碼以避免無用的代碼副本。

也非常感謝@JaMiT 的鼓勵話語:)

編輯:正如我在評論中所建議的那樣,我最終通過@user17732522 實現了解決方案。 這樣我就不必每次都調用 function 來進行初始化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM