全部產品
Search
文件中心

Elastic Compute Service:C/C++語言遷移

更新時間:Nov 20, 2024

C/C++屬於靜態編譯語言,C/C++編譯是將原始碼經由編譯器、彙編器處理產生機器指令,再通過連結器和庫函數結合產生可執行程式。但x86平台和ARM平台屬於不同的架構,指令集也不同,其開發的程式從x86平台遷移到ARM平台時,必須重新編譯。本文介紹從x86平台遷移到倚天雲端服務器時,如何對C/C++中系統宏或函數進行相應修改。

宏相關

從平台相容性來看,系統中的宏可以分為x86平台宏、ARM平台宏以及x86和ARM都支援的平台宏。不同平台的宏格式如下:

ARM平台宏

x86平台宏

ARM和x86都支援的宏

__arm__

__amd64__

__STDC_HOSTED__

__thumb__

i386

__INT64_TYPE__

__ARM_ARCH_4T__

__k8__

_LP64

__aarch64__

__SSE2__

__WCHAR_MAX__

built-in函數

built-in函數是GCC編譯器中的內建函數,可以實現一些簡單快捷的功能方便程式的編寫。這些函數大多數都是以__builtin_作為首碼使用。x86平台編譯環境下的built-in函數(類似builtin_ia32_xxx)在倚天雲端服務器中直接編譯會出現編譯失敗。

從x86平台遷移built-in函數到倚天雲端服務器時,需要進行相應修改,如x86平台crc相關builtin_ia32_crc32qi(a, b)需要修改成ARM平台的builtin_aarch64_crc32cb(a, b)

intrinsic函數

intrinsic函數是與x86 CPU架構密切相關的函數,是SIMD(Single Instruction Multiple Data,單指令多資料)操作的介面。從x86平台遷移到倚天雲端服務器時,主要工作集中在simd相關intrinsic的遷移。

從x86平台遷移intrinsic函數到倚天雲端服務器時,主要有以下兩個步驟:

  1. 添加標頭檔(arm_neon.h、arm_sve.h)以支援intrinsics函數在ARM系統上使用。

  2. 替換intrinsic,更多資訊,請參見Arm Developer

說明
  • 以上兩部分的處理指示和資料類型都需要修改成ARM平台支援。例如:

    • x86的m128 mm_load_ps需要修改為float32x4 vld1q_f32。

    • 由於x86支援AVX指令,寄存器長度為256 bit,而aarch64隻支援128 bit長度的寄存器,因此,需要進行相同語義的展開。例如:m256d mm_add_ps則需要在aarch64上使用兩條SIMD指令vaddq_f32 + vaddq_f32。

  • 倚天雲端服務器支援SVE指令,但由於其編程模式的特殊性,不推薦轉換成SVE intrinsic。您可以參考業界開源的sse2neon專案來解決此問題。

內聯彙編

x86平台的彙編指令與ARM有所不同,從x86平台遷移彙編指令到倚天雲端服務器時,需要將x86平台的彙編指令修改成相同語義的aarch64指令。例如:asm("bswap %0": "=r"(val): "0"(val)) 可以修改成相同語義的sev指令asm("rev %[dst], %[src]":  [dst]"=r"(val): [src]"r"(val))。更多資訊,請參見How to Use Inline Assembly Language in C Code

樣本說明

從x86平台遷移C/C++代碼到倚天雲端服務器時,具體代碼修改樣本如下所示。

原代碼:

#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
/* GCC-compatible compiler, targeting x86/x86-64 */
#include <x86intrin.h>
#endif
uint32_t crc32_4k(uint32_t acc, char* buf) {
    for (char* end = buf + 4096; buf < end; buf += 4) {
        acc = __builtin_ia32_crc32si(acc, *(uint32_t*)buf);
    }
    return acc;
}

修改後代碼:

#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
     /* GCC-compatible compiler, targeting x86/x86-64 */
     #include <x86intrin.h>
#elif defined(__GNUC__) && defined(__ARM_NEON)
     /* GCC-compatible compiler, targeting ARM with NEON */
     #include <arm_neon.h>
  #if defined(__ARM_FEATURE_SVE)
     #include <arm_sve.h>
  #endif 
#endif

uint32_t crc32_4k(uint32_t acc, char* buf) {
    for (char* end = buf + 4096; buf < end; buf += 4) {
        acc = __builtin_aarch64_crc32cw(acc, *(uint32_t*)buf);
    }
    return acc;
}