CまたはC ++ は静的なコンパイル言語です。 CまたはC ++ ソースコードをコンパイルすると、ソースコードはコンパイラとアセンブラによって処理され、機械命令が生成されます。 次に、機械命令は、実行可能なプログラムを生成するために、リンカーおよびライブラリ関数によって組み合わされる。 x86プラットフォームとARMベースのプラットフォームは、異なる命令セットを使用します。 x86プラットフォームからARMベースのプラットフォームにソフトウェアを移行する場合は、ソフトウェアを再コンパイルする必要があります。 このトピックでは、x86プラットフォームからYiTian Elastic Compute Service (ECS) インスタンスにソフトウェアを移行するときに、CまたはC ++ のシステムマクロと関数を変更する方法について説明します。
マクロ
システムマクロは、プラットフォームの互換性に基づいて次のタイプに分類されます。x86プラットフォーム用に定義されたマクロ、ARMベースのプラットフォーム用に定義されたマクロ、x86ベースとARMベースの両方のプラットフォーム用に定義されたマクロです。 次の表に、さまざまなプラットフォームで定義されているマクロを示します。
ARMベースのプラットフォーム用マクロ | x86プラットフォーム用マクロ | x86およびARMベースのプラットフォームのマクロ |
__アーム__ | __amd64__ | __STDC_HOSTED__ |
__thumb__ | i386 | __INT64_TYPE__ |
__ARM_ARCH_4T__ | __k8__ | _LP64 |
__aarch64__ | __SSE2__ | __WCHAR_MAX__ |
組み込み関数
GCCコンパイラの組み込み関数は、プログラムの開発を容易にするためのシンプルで便利な機能を提供します。 ほとんどの関数名には __builtin_
プレフィックスが含まれています。 builtin_ia32_xxxなどのx86プラットフォームで期待どおりに機能する組み込み関数は、YiTianインスタンスでコンパイルできない場合があります。
x86プラットフォームからARMベースのプラットフォームにソフトウェアを移行する場合は、一部の組み込み機能を変更する必要があります。 たとえば、x86プラットフォームのCRC関連のbuiltin_ia32_crc32qi(a, b)
関数をARMベースのプラットフォームのbuiltin_aarch64_crc32cb(a, b)
関数に変更します。
固有関数
固有関数は、x86 CPUアーキテクチャに密接に関連しており、単一命令複数データ (SIMD) 演算を呼び出すためのインターフェースとして使用される。 x86プラットフォームからYiTianインスタンスにソフトウェアを移行する場合、主な焦点はSIMD固有関数を移行することです。
次の手順を実行して、x86プラットフォームからYiTianインスタンスに固有関数を移行します。
arm_neon.hやarm_sve.hなどのヘッダーファイルを追加して、ARMシステムで固有の機能が機能するようにします。
組み込み関数を置き換えます。 詳細については、Arm Developer WebサイトのFind the Best Architecture For youを参照してください。
上記の2つの手順では、ARMベースのプラットフォームに合わせて命令セットとデータ型を変更する必要があります。 例:
x86プラットフォームのm128 mm_load_psをfloat32x4 vld1q_f32に変更します。
x86プラットフォームは、256ビットレジスタを使用するAVX (Advanced Vector Extensions) 命令セットをサポートしています。 AArch64プラットフォームは128ビットレジスタのみをサポートします。 この場合、同じセマンティクスを使用して命令を拡張する必要があります。 たとえば、m256d mm_add_psを、AArch64プラットフォームで使用されるvaddq_f32およびvaddq_f32 SIMD命令に置き換えます。
YiTianインスタンスはSVE命令をサポートしています。 ただし、インスタンスの特殊なプログラミングモードのため、SVE固有関数を使用しないことを推奨します。 コミュニティのオープンソースプロジェクトを参照して、問題を解決できます。 詳細については、「sse2neon」をご参照ください。
インラインアセンブリ
x86プラットフォームは、ARMベースのプラットフォームとは異なるアセンブリ手順を使用します。 アセンブリ命令をx86プラットフォームからYiTianインスタンスに移行する場合、x86プラットフォームで使用されるアセンブリ命令を、AArch64プラットフォームで同じセマンティクスを使用する命令に変更します。 たとえば、asm("bswap % 0": "=r"(val): "0"(val))
をasm("rev %[dst], %[src]": [dst]"=r"(val): [src]"r"(val))
同じセマンティクスを使用するSVE命令に変更します。 詳細については、「Cコードでインラインアセンブリ言語を使用する方法」をご参照ください。
サンプルコード
次のセクションでは、CまたはC ++ コードをx86プラットフォームからYiTianインスタンスに移行するためにコードを変更する方法について説明します。
変更前のコード:
#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;
}