精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

編譯器的優(yōu)化選項

科技綠洲 ? 來源:Qt教程 ? 作者:Qt教程 ? 2023-11-24 15:37 ? 次閱讀

一個程序首先要保證正確性,在保證正確性的基礎上,性能也是一個重要的考量。要編寫高性能的程序,第一,必須選擇合適的算法和數(shù)據(jù)結(jié)構(gòu);第二,應該編寫編譯器能夠有效優(yōu)化以轉(zhuǎn)換成高效可執(zhí)行代碼的源代碼,要做到這一點,需要了解編譯器的能力和限制;第三,要了解硬件的運行方式,針對硬件特性進行優(yōu)化。本文著重展開第二點和第三點。

簡單認識編譯器

要寫出高性能的代碼,首先需要對編譯器有基礎的了解,原因在于現(xiàn)代編譯器有很強的優(yōu)化能力,但有些代碼編譯器不能進行優(yōu)化。對編譯器有了基礎的了解,才能寫出編譯器友好型高性能代碼。

編譯器的優(yōu)化選項

GCC 為例,GCC 支持以下優(yōu)化級別:

  • -O,其中 number 為 0/1/2/3,數(shù)字越大,優(yōu)化級別越高。默認為 -O0。
  • -Ofast,除了開啟 -O3 的所有優(yōu)化選項外,會額外打開 -ffast-math 和 -fallow-store-data-races。注意這兩個選項可能會引起程序運行錯誤。

-ffast-math: Sets the options -fno-math-errno, -funsafe-math-optimizations, -ffinite-math-only, -fno-rounding-math, -fno-signaling-nans, -fcx-limited-range and -fexcess-precision=fast. It can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that do not require the guarantees of these specifications.

-fallow-store-data-races: Allow the compiler to perform optimizations that may introduce new data races on stores, without proving that the variable cannot be concurrently accessed by other threads. Does not affect optimization of local data. It is safe to use this option if it is known that global data will not be accessed by multiple threads.

  • -Og,調(diào)試代碼時推薦使用的優(yōu)化級別。

gcc -Q --help=optimizer -Ox 可查看各優(yōu)化級別開啟的優(yōu)化選項。

參考鏈接:https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

編譯器的限制

為了保證程序運行的正確性,編譯器不會對代碼的使用場景做任何假設,所以有些代碼編譯器不會進行優(yōu)化。下面舉兩個比較隱晦的例子。

1、memory aliasing

void twiddle1(long *xp, long *yp) {
    *xp += *yp;
    *xp += *yp;
}
void twiddle2(long *xp, long *yp) {
    *xp += 2 * *yp;
}

xpyp 指向同樣的內(nèi)存(memory aliasing)時,twiddle1twiddle2 是兩個完全不同的函數(shù),所以編譯器不會嘗試將 twiddle1 優(yōu)化為 twiddle2。如果本意是希望實現(xiàn) twiddle2 的功能,應該寫成 twiddle2 而非 twwidle1 的形式,twiddle2 只需要 2 次讀 1 次寫,而 twiddle1 需要 4 次讀 2 次寫。

可以顯式使用 __restrict 修飾指針,表明不存在和被修飾的指針指向同一塊內(nèi)存的指針,此時編譯器會將 twiddle3 優(yōu)化為和 twiddle2 等效。可自行通過反匯編的方式觀察匯編碼進一步理解。

void twiddle3(long *__restrict xp, long *__restrict yp) {
    *xp += *yp;
    *xp += *yp;
}

2、side effect

long f();
long func1() {
    return f() + f() + f() + f();
}
long func2() {
    return 4 * f();
}

由于函數(shù) f 的實現(xiàn)可能如下,存在 side effect,所以編譯器不會將 func1 優(yōu)化為 func2。如果本意希望實現(xiàn) func2 版本,則應該直接寫成 func2 的形式,可減少 3 次函數(shù)調(diào)用。

long counter = 0;
long f() {
    return counter++;
}

程序性能優(yōu)化

在介紹之前,我們先引入一個程序性能度量標準每元素的周期數(shù)(Cycles Per Element, CPE),即每處理一個元素需要花費的周期數(shù),可以表示程序性能并指導性能優(yōu)化。

下面通過一個例子介紹幾個優(yōu)化程序性能的手段。首先定義一個數(shù)據(jù)結(jié)構(gòu) vector 以及一些輔助函數(shù),vector 使用一個連續(xù)存儲的數(shù)組實現(xiàn),可通過 typedef 來指定元素的數(shù)據(jù)類型 data_t

typedef struct {
    long len;
    data_t *data;
} vec_rec, *vec_ptr;

/* 創(chuàng)建vector */
vec_ptr new_vec(long len) {
    vec_ptr result = (vec_ptr)malloc(sizeof(vec_rec));
    if (!result)
        return NULL;
    data_t *data = NULL;
    result- >len = len;
    if (len > 0) {
        data = (data_t*)calloc(len, sizeof(data_t));
        if (!data) {
            free(result);
            return NULL;
        }
    }
    result- >data = data;
    return result;
}

/* 根據(jù)index獲取vector元素 */
int get_vec_element(vec_ptr v, long index, data_t *dest) {
    if (index < 0 || index >= v- >len)
        return 0;
    *dest = v- >data[index];
    return 1;
}

/* 獲取vector元素個數(shù) */
long vec_length(vec_ptr v) {
    return v- >len;
}

下面的函數(shù)的功能是使用某種運算,將一個向量中所有的元素合并為一個元素。下面的 IDENTOP 是宏定義,#define IDENT 0#define OP + 進行累加運算,#define IDENT 1#define OP * 則進行累乘運算。

void combine1(vec_ptr v, data_t *dest) {
    long i;

    *dest = IDENT;
    for (i = 0; i < vec_length(v); i++) {
        data_t val;
        get_vec_element(v, i, &val);
        *dest = *dest OP val;
    }
}

對于上面的 combine1,可以進行下面三個基礎的優(yōu)化。

1、對于多次執(zhí)行返回同樣結(jié)果的函數(shù),使用臨時變量保存

combine1 的實現(xiàn)在循環(huán)測試條件中反復調(diào)用了函數(shù) vec_length,在此場景下,多次調(diào)用 vec_length 會返回同樣的結(jié)果,所以可以改寫為 combine2 的實現(xiàn)進行優(yōu)化。在極端情況下,注意避免反復調(diào)用返回同樣結(jié)果的函數(shù)是更有效的。例如,若在循環(huán)結(jié)束條件中調(diào)用測試一個字符串長度的函數(shù),該函數(shù)時間復雜度通常是 O(n),若明確字符串長度不會變化,反復調(diào)用會有很大的額外開銷。

void combine2(vec_ptr v, data_t *dest) {
    long i;
    long length = vec_length(v);

    *dest = IDENT;
    for (i = 0; i < length; i++) {
        data_t val;
        get_vec_element(v, i, &val);
        *dest = *dest OP val;
    }
}

2、減少過程調(diào)用

過程(函數(shù))調(diào)用會產(chǎn)生一定的開銷,例如參數(shù)傳遞、clobber 寄存器保存恢復和轉(zhuǎn)移控制等。所以可以新增一個函數(shù) get_vec_start 返回指向數(shù)組的開頭的指針,在循環(huán)中避免調(diào)用函數(shù) get_vec_element。這個優(yōu)化存在一個 trade off,一方面可以一定程序提升程序性能,另一方面這個優(yōu)化需要知道 vector 數(shù)據(jù)結(jié)構(gòu)的實現(xiàn)細節(jié),會破壞程序的抽象,一旦 vector 修改為不使用數(shù)組的方式存儲數(shù)據(jù),則同時需要修改 combine3 的實現(xiàn)。

data_t *get_vec_start(vec_ptr v) {
    return v- >data;
}
void combine3(vec_ptr v, data_t *dest) {
    long i;
    long length = vec_length(v);
    data_t *data = get_vec_start(v);

    *dest = IDENT;
    for (i = 0; i < length; i++) {
        *dest = *dest OP data[i];
    }
}

3、消除不必要的內(nèi)存引用

在上面的實現(xiàn)中,循環(huán)中每次都會去讀一次寫一次 dest,由于可能存在 memory aliasing,編譯器會謹慎地進行優(yōu)化。下面分別是 -O1-O2 優(yōu)化級別時,combine3for 循環(huán)部分的匯編代碼。可以看到,開啟 -O2 優(yōu)化時,編譯器幫我們把中間結(jié)果存到了臨時變量中(寄存器 % xmm0),而不是像 -O1 優(yōu)化時每次從內(nèi)存中讀取;但是考慮到 memory aliasing 的情況,即使 -O2 優(yōu)化,依然需要每次循環(huán)將中間結(jié)果保存到內(nèi)存。

// combine3 -O1
.L1:
    vmovsd (%rbx), %xmm0
    vmulsd (%rdx), %xmm0, %xmm0
    vmovsd %xmm0, (%rbx)
    addq $8, %rdx
    cmpq %rax, %rdx
    jne .L1

// combine3 -O2
.L1
    vmulsd (%rdx), %xmm0, %xmm0
    addq $8, %rdx
    cmpq %rax, %rdx
    vmovsd %xmm0, (%rbx)
    jne .L1

為了避免頻繁進行內(nèi)存讀寫,可以人為地使用一個臨時變量保存中間結(jié)果,如 combine4 所示。

void combine4(vec_ptr v, data_t *dest) {
    long i;
    long length = vec_length(v);
    data_t *data = get_vec_start(v);
    data_t acc = IDENT;
    for (i = 0; i < length; i++) {
        acc = acc OP data[i];
    }
    *dest = acc;
}
// combine4 -O1
.L1
    vmulsd (%rdx), %xmm0, %xmm0
    addq $8, %rdx
    cmpq %rax, %rdx
    jne .L1

以上優(yōu)化方法的效果可以通過 CPE 來度量,在 Intel Core i7 Haswell 的測試結(jié)果如下。從測試結(jié)果來看:

  • combine1 版本不同編譯優(yōu)化級別,-O1 的性能是 -O0 的兩倍,表明開啟適當?shù)鼐幾g優(yōu)化級別是很有必要的。
  • combine2 將 vec_length 移出循環(huán)后,在同樣的優(yōu)化級別編譯,相較 combine1 的性能有微小的提升。
  • 但是 combine3 相比 combine2 并沒有性能提升,原因是由于循環(huán)中的其它操作的耗時可以掩蓋調(diào)用 get_vec_element 的耗時,之所以可以掩蓋,得益于 CPU 支持分支預測亂序執(zhí)行,本文的后面會簡單介紹這兩個概念。
  • 同樣地,combine3 的 -O2 版本比 -O1 版本性能好很多,從匯編碼可以看到,-O2 時比 -O1 每次循環(huán)減少了一次對 (% rbx) 的讀,更重要的是消除了對 (% rbx) 寫后讀的訪存依賴。
  • 經(jīng)過 combine4 將中間結(jié)果暫存到臨時變量的優(yōu)化,可以看到即使使用 -O1 的編譯優(yōu)化,也比 combine3 -O2 的編譯優(yōu)化性能更好,表明即使編譯器有強大的優(yōu)化能力,但是注意細節(jié)來編寫高性能代碼也是非常有必要的。

以下測試數(shù)據(jù)引用自《深入理解計算機系統(tǒng)》第五章。

函數(shù)優(yōu)化方法int +int *float +float *
combine1-O022.6820.0219.9820.18
combine1-O110.1210.1210.1711.14
combine2移動 vec_length -O17.029.039.0211.03
combine3減少過程調(diào)用 -O17.179.029.0211.03
combine3減少過程調(diào)用 -O21.603.013.015.01
combine4累積到臨時變量 -O11.273.013.015.01

指令級并行

以上優(yōu)化不依賴于目標機器的任何特性,只是簡單地降低了過程調(diào)用的開銷,以及消除一些 “妨礙優(yōu)化的因素”,這些因素會給編譯器優(yōu)化帶來困難。要進行進一步優(yōu)化,需要了解一些硬件特性。下圖是 Intel Core i7 Haswell 的硬件結(jié)構(gòu)的后端部分:

圖片

完整的 Intel Core i7 Haswell 的硬件結(jié)構(gòu)見:https://en.wikichip.org/w/images/c/c7/haswell_block_diagram.svg

硬件性能

該 CPU 支持以下特性:

  • 指令級并行:即通過指令流水線技術,支持同時對多條指令求值。
  • 亂序執(zhí)行:指令的執(zhí)行順序未必和其書寫的順序一致,可以使硬件達到更好的指令級并行度。主要是通過亂序執(zhí)行、順序提交的機制,使得能夠獲得和順序執(zhí)行一致的結(jié)果。
  • 分支預測:當遇到分支時,硬件會預測分支的走向,如果預測成功則能夠加快程序的運行,但是預測失敗的話則需要把提前執(zhí)行的結(jié)果丟棄,重新 load 正確指令執(zhí)行,會帶來比較大的預測錯誤懲罰。

上圖中,主要關注執(zhí)行單元 (EUs),執(zhí)行單元由多個功能單元組成。功能單元的性能可以由延遲發(fā)射時間容量來度量。

  • 延遲:執(zhí)行完一條指令需要的時鐘周期數(shù)。
  • 發(fā)射時間:兩個連續(xù)的同類型的運算之間需要的最小時鐘周期數(shù)。
  • 容量:某種執(zhí)行單元的數(shù)量。從上圖可以看出,在 EUs 中,有 4 個整數(shù)加法單元 (INT ALU)、1 個整數(shù)乘法單元 (INT MUL)、1 個浮點數(shù)加法單元 (FP ADD) 和 2 個浮點數(shù)乘法單元 (FP MUL)。

Intel Core i7 Haswell 的功能單元性能數(shù)據(jù)(單位為周期數(shù))如下,引自《深入理解計算機系統(tǒng)》第五章:

運算延遲 (int)發(fā)射時間 (int)容量 (int)延遲 (float)發(fā)射時間 (float)容量 (float)
加法114311
乘法311512

這些算術運算的延遲、發(fā)射時間和容量會影響上述 combine 函數(shù)的性能,我們用 CPE 的兩個界限來描述這種影響。吞吐界限是理論上的最優(yōu)性能。

  • 延遲界限:任何必須按照嚴格順序完成 combine 運算的函數(shù)所需要的最小 CPE,等于功能單元的延遲。
  • 吞吐界限:功能單元產(chǎn)生結(jié)果的最大速率,由容量/發(fā)射時間決定。若使用 CPE 度量,則等于容量/發(fā)射時間的倒數(shù)。

由于 combine 函數(shù)需要 load 數(shù)據(jù),故要同時受到加載單元的限制。由于只有兩個加載單元且其發(fā)射時間為 1 個周期,所以整數(shù)加法的吞吐界限在本例中只有 0.5 而非 0.25。

界限int +int *float +float *
延遲1.03.03.05.0
吞吐0.51.01.00.5

處理器操作的抽象模型

為了分析在現(xiàn)代處理器上執(zhí)行的機器級程序的性能,我們引入數(shù)據(jù)流圖,這是一種圖形化表示方法,展現(xiàn)了不同操作之間的數(shù)據(jù)相關是如何限制它們的執(zhí)行順序的。這些限制形成了圖中的關鍵路徑,這是執(zhí)行一組機器指令所需時鐘周期的一個下界。

通常 for 循環(huán)會占據(jù)程序執(zhí)行的大部分時間,下圖是 combine4 的 for 循環(huán)對應的數(shù)據(jù)流圖。其中箭頭指示了數(shù)據(jù)的流向。可以將寄存器分為四類:

  1. 只讀:這些寄存器只用作源值,在循環(huán)中不被修改,本例中的 %rax
  2. 只寫:作為數(shù)據(jù)傳送的目的。本例沒有這樣的寄存器。
  3. 局部:在循環(huán)內(nèi)部被修改和使用,迭代與迭代之間不相關,比例中的條件碼寄存器。
  4. 循環(huán):這些寄存器既作為源值,又作為目的,一次迭代中產(chǎn)生的值會被下一次迭代用到,本例中的 %rdx%xmm0。由于兩次迭代之間有數(shù)據(jù)依賴,所以對此類寄存器的操作通常是程序性能的限制因素。 圖片

將上圖重排,并只留下循環(huán)寄存器相關的路徑,可得到簡化的數(shù)據(jù)流圖。 圖片

將簡化完的數(shù)據(jù)流圖進行簡單地重復,可以得到關鍵路徑,如下圖。如果 combine4 中計算的是浮點數(shù)乘法,由于支持指令級并行,浮點數(shù)乘法的的延遲能夠掩蓋整數(shù)加法 (指針移動,圖中右半邊的路徑) 的延遲,所以 combine4CPE 的理論下界就是浮點乘法的延遲 5.0,與上面給出的測試數(shù)據(jù) 5.01 基本一致。 圖片

循環(huán)展開

目前為止,我們程序的性能只達到了延遲界限,這是因為下一次浮點乘法必須等上一次乘法結(jié)束后才開始,不能充分利用硬件的指令級并行。使用循環(huán)展開的技術,可以提高關鍵路徑的指令并行度。

void combine5(vec_ptr v, data_t *dest) {
    long i;
    long length = vec_length(v);
    long limit = length - 1;
    data_t *data = get_vec_start(v);
    data_t acc0 = IDENT;
    data_t acc1 = IDENT;

    for (i = 0; i < limit; i += 2) {
        acc0 = acc0 OP data[i];
        acc1 = acc1 OP data[i + 1];
    }

    for (; i < length; ++i) {
        acc0 = acc0 OP data[i];
    }

    *dest = acc0 OP acc1;
}

combine5 的關鍵路徑的數(shù)據(jù)流圖如下,圖中有兩條關鍵路徑,但兩條關鍵路徑是可以指令級并行的,每條關鍵路徑只包含 n/2 個操作,因此性能可以突破延遲界限,理論上浮點乘法的 CPE 約為 5.0/2=2.5圖片

假如增加臨時變量的個數(shù)進一步增加循環(huán)展開次數(shù),理論上可以提高指令并行度,最終達到吞吐界限。但是不能無限制地增加循環(huán)展開次數(shù),一是由于硬件的功能單元有限,CPE 的下界由吞吐界限限制,達到一定程度后繼續(xù)增加也不能提高指令并行度;二是由于寄存器資源有限,增加循環(huán)展開次數(shù)會增加寄存器的使用,使用的寄存器個數(shù)超過硬件提供的寄存器資源之后,則會發(fā)生寄存器溢出,可能會需要將寄存器的內(nèi)存臨時保存到內(nèi)存,使用時再從內(nèi)存恢復到寄存器,反而導致性能的下降,如下表中循環(huán)展開 20 次相較展開 10 次性能反而略有下降。幸運的是,大多數(shù)硬件在寄存器溢出之前已經(jīng)達到了吞吐界限。

函數(shù)展開次數(shù)int +int *float +float *
combine520.811.511.512.51
combine5100.551.001.010.52
combine5200.831.031.020.68
延遲界限/1.003.003.005.00
吞吐界限/0.501.001.000.50

SIMD(single instruction multi data)

SIMD 是另外一種行之有效的性能優(yōu)化手段,不同于指令級并行,其采用數(shù)據(jù)級并行。SIMD 即單指令多數(shù)據(jù),一條指令操作一批向量數(shù)據(jù),需要硬件提供支持。X86 架構(gòu)的 CPU 支持 AVX 指令集,ARM CPU 支持 NEON 指令集。在我們開發(fā)的一款深度學習編譯器 MegCC 中,就廣泛使用了 SIMD 技術。MegCC 是曠視天元團隊開發(fā)的深度學習編譯器,其接受 MegEngine 格式的模型為輸入,輸出運行該模型所需的所有 kernel,方便模型部署,具有高性能和輕量化的特點。為了方便用戶將其它格式的模型轉(zhuǎn)換為 MegEngine 格式模型,曠視天元團隊同時提供了模型轉(zhuǎn)換工具 MgeConvert,您可以將模型轉(zhuǎn)換為 onnx,然后使用 MgeConvert 轉(zhuǎn)換為 MegEngine 格式模型。同時如果您想測試您設備上某條指令的吞吐和延遲,以指導您的優(yōu)化,可以使用 MegPeak。

MegCC 中實現(xiàn)了許多高性能的深度學習算子,卷積和矩陣乘法是典型的計算密集型的算子,同時卷積也可以借助矩陣乘法來實現(xiàn) (im2col/winograd 算法等)。

MegCC 在 ARM 平臺支持了 NEON DOT 和 I8MM 指令實現(xiàn)的矩陣乘和卷積。一條 DOT 指令可完成 32 次乘加運算 (16 次乘法和 16 次加法運算);一條 I8MM 指令可完成 64 次乘加運算 (32 次乘法和 32 次加法運算)。這就是 SIMD 技術能夠加速計算的原理。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 硬件
    +關注

    關注

    11

    文章

    3252

    瀏覽量

    66111
  • 程序
    +關注

    關注

    116

    文章

    3775

    瀏覽量

    80844
  • 源代碼
    +關注

    關注

    96

    文章

    2944

    瀏覽量

    66668
  • 編譯器
    +關注

    關注

    1

    文章

    1618

    瀏覽量

    49048
收藏 人收藏

    評論

    相關推薦

    專業(yè)模式無法正常工作

    我一直在自由模式下工作。購買專業(yè)許可證。用BAT文件安裝。將編譯器優(yōu)化選項更改為“PRO”,但它仍然以空閑模式編譯。 以上來自于百度翻譯 以下為原文 I have been wor
    發(fā)表于 10-08 09:53

    STM32 FreeRTOS RAM 使用情況及優(yōu)化方法實用資料分享~

    及軟件定時,當然每一個任務還需要一定的堆棧空間。在具體的應用中,使用的任務數(shù)量可能不同,每個任務的堆棧空間也可能不一樣,任務間通訊的方式也可能不同,當然我們還要考慮到 MCU 得內(nèi)核和編譯器優(yōu)化
    發(fā)表于 01-26 14:10

    EFR32上實現(xiàn)精確的軟件延時相關資料推薦

    編譯器優(yōu)化選項設置為“-O0”,即不優(yōu)化時:void DelayMs(int n){ int i, loops = SystemSYSCLKGet() / 12000; for(
    發(fā)表于 12-07 11:53

    SIMD計算機的優(yōu)化編譯器設計

    利用處理的相關資源,提高編譯器優(yōu)化性能和增強代碼可適應性是SIMD處理優(yōu)化編譯的關鍵。該文基
    發(fā)表于 04-03 08:47 ?30次下載

    編譯器_keil的優(yōu)化選項問題

    keil編譯器優(yōu)化選項針對ARM,對STM32編譯的一些優(yōu)化的問題
    發(fā)表于 02-25 14:18 ?3次下載

    C編譯器及其優(yōu)化

    本章將幫助讀者在ARM處理上編寫高效的C代碼。本章涉及的一些技術不僅適用于ARM處理,也適用于其他RISC處理。本章首先從ARM編譯器及其優(yōu)化
    發(fā)表于 10-17 17:22 ?2次下載

    IAR編譯器優(yōu)化對程序的影響

    IAR編譯優(yōu)化選項
    的頭像 發(fā)表于 07-05 00:25 ?4731次閱讀

    如何使用編譯器進行定位優(yōu)化信息

    在本次網(wǎng)絡研討會中,我們將向您展示如何使用編譯器選項來定位您正在尋找的確切優(yōu)化信息以及如何使用此信息來加速你的申請。
    的頭像 發(fā)表于 11-01 06:50 ?2594次閱讀

    關于volatile關鍵字對編譯器優(yōu)化的影響

    volatile關鍵字對編譯器優(yōu)化的影響
    的頭像 發(fā)表于 02-28 17:15 ?2909次閱讀

    編譯器優(yōu)化對函數(shù)的影響

    編譯器如gcc,可以指定不同的優(yōu)化參數(shù),在某些條件下,有些函數(shù)可能會被優(yōu)化掉。
    的頭像 發(fā)表于 06-22 14:58 ?2803次閱讀
    <b class='flag-5'>編譯器</b><b class='flag-5'>優(yōu)化</b>對函數(shù)的影響

    EFR32上實現(xiàn)精確的軟件延時

    編譯器優(yōu)化選項設置為“-O0”,即不優(yōu)化時:void DelayMs(int n){ int i, loops = SystemSYSCLKGet() / 12000; for(
    發(fā)表于 11-24 19:06 ?3次下載
    EFR32上實現(xiàn)精確的軟件延時

    IAR Systems全面支持芯海科技32位MCU芯片

    IAREmbedded Workbench for Arm 擁有高度靈活的編譯器優(yōu)化選項和強大的優(yōu)化性能,助力生成體積小、速度快的代碼,實現(xiàn)MCU更高效能、更低能耗,同時滿足不同的用戶
    的頭像 發(fā)表于 12-16 11:48 ?989次閱讀

    深入淺出編譯優(yōu)化選項(下)

    在《深入淺出編譯優(yōu)化選項(上)》中,我們介紹了如何在IAR Embedded Workbench編譯器中進行編譯
    的頭像 發(fā)表于 04-21 10:19 ?1221次閱讀

    IAR Systems全面支持芯海科技32位MCU芯片

    ,其IARSystems為芯海科技CS32系列MCU提供完整的工具鏈。IAREmbeddedWorkbenchforArm擁有高度靈活的編譯器優(yōu)化選項和強大的優(yōu)化
    的頭像 發(fā)表于 12-19 11:48 ?980次閱讀
    IAR Systems全面支持芯海科技32位MCU芯片

    Keil編譯器優(yōu)化方法

    我們都知道,代碼是可以通過編譯器優(yōu)化的,有的時候,為了提高運行速度或者減少代碼尺寸,會開啟優(yōu)化選項
    的頭像 發(fā)表于 10-23 16:35 ?322次閱讀
    Keil<b class='flag-5'>編譯器</b><b class='flag-5'>優(yōu)化</b>方法