C dan C++ adalah bahasa pemrograman dengan kompilasi statis. Saat mengompilasi kode sumber C atau C++, kompiler dan assembler memprosesnya untuk menghasilkan instruksi mesin. Kemudian, linker menggabungkan instruksi mesin dengan fungsi pustaka untuk menghasilkan program yang dapat dieksekusi. Platform x86 dan platform berbasis ARM menggunakan set instruksi yang berbeda. Untuk memigrasikan perangkat lunak dari platform x86 ke platform berbasis ARM, Anda harus mengompilasi ulang perangkat lunak tersebut. Topik ini menjelaskan cara memodifikasi makro sistem dan fungsi dalam C atau C++ saat memigrasikan perangkat lunak dari platform x86 ke instans Elastic Compute Service (ECS) YiTian.
Makro
Makro sistem diklasifikasikan berdasarkan kompatibilitas platform: makro yang didefinisikan untuk platform x86, makro yang didefinisikan untuk platform berbasis ARM, dan makro yang didefinisikan untuk kedua platform. Tabel berikut menjelaskan makro yang didefinisikan untuk platform yang berbeda.
Makro untuk platform berbasis ARM | Makro untuk platform x86 | Makro untuk platform x86 dan berbasis ARM |
__arm__ | __amd64__ | __STDC_HOSTED__ |
__thumb__ | i386 | __INT64_TYPE__ |
__ARM_ARCH_4T__ | __k8__ | _LP64 |
__aarch64__ | __SSE2__ | __WCHAR_MAX__ |
Fungsi bawaan
Fungsi bawaan dalam kompiler GCC menyediakan fitur yang sederhana dan nyaman untuk pengembangan program. Sebagian besar nama fungsi memiliki awalan __builtin_. Fungsi bawaan seperti builtin_ia32_xxx yang bekerja di platform x86 mungkin gagal dikompilasi di instans YiTian.
Beberapa fungsi bawaan perlu dimodifikasi saat memigrasikan perangkat lunak dari platform x86 ke platform berbasis ARM. Contohnya, ubah fungsi terkait CRC builtin_ia32_crc32qi(a, b) di platform x86 menjadi fungsi builtin_aarch64_crc32cb(a, b) di platform berbasis ARM.
Fungsi intrinsik
Fungsi intrinsik erat kaitannya dengan arsitektur CPU x86 dan digunakan sebagai antarmuka untuk memanggil operasi Single Instruction Multiple Data (SIMD). Saat memigrasikan perangkat lunak dari platform x86 ke instans YiTian, fokus utamanya adalah memigrasikan fungsi intrinsik SIMD.
Ikuti langkah-langkah berikut untuk memigrasikan fungsi intrinsik dari platform x86 ke instans YiTian:
Tambahkan file header seperti arm_neon.h dan arm_sve.h untuk memastikan bahwa fungsi intrinsik dapat bekerja di sistem ARM.
Ganti fungsi intrinsik. Untuk informasi lebih lanjut, lihat Temukan Arsitektur Terbaik untuk Anda di situs web Arm Developer.
Pada dua langkah sebelumnya, Anda harus memodifikasi set instruksi dan tipe data agar sesuai dengan platform berbasis ARM. Contoh:
Ubah m128 mm_load_ps di platform x86 menjadi float32x4 vld1q_f32.
Platform x86 mendukung set instruksi Advanced Vector Extensions (AVX) yang menggunakan register 256-bit. Platform AArch64 hanya mendukung register 128-bit. Dalam hal ini, Anda perlu memperluas instruksi dengan semantik yang sama. Contohnya, ganti m256d mm_add_ps dengan instruksi SIMD vaddq_f32 yang digunakan di platform AArch64.
Instans YiTian mendukung instruksi SVE. Namun, kami menyarankan agar Anda tidak menggunakan fungsi intrinsik SVE karena mode pemrograman khusus dari instans tersebut. Anda dapat merujuk pada proyek sumber terbuka di komunitas untuk menyelesaikan masalah ini. Untuk informasi lebih lanjut, lihat sse2neon.
Inline assembly
Platform x86 menggunakan instruksi assembly yang berbeda dari platform berbasis ARM. Saat memigrasikan instruksi assembly dari platform x86 ke instans YiTian, ubah instruksi assembly yang digunakan untuk platform x86 menjadi instruksi dengan semantik yang sama untuk platform AArch64. Contohnya, ubah asm("bswap %0": "=r"(val): "0"(val)) menjadi instruksi SVE asm("rev %[dst], %[src]": [dst]"=r"(val): [src]"r"(val)). Untuk informasi lebih lanjut, lihat Cara Menggunakan Bahasa Assembly Inline dalam Kode C.
Kode contoh
Berikut ini menjelaskan cara memodifikasi kode untuk memigrasikan kode C atau C++ dari platform x86 ke instans YiTian:
Kode sebelum modifikasi:
#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
/* Compiler kompatibel GCC, menargetkan 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;
}Kode setelah modifikasi:
#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
/* Compiler kompatibel GCC, menargetkan x86/x86-64 */
#include <x86intrin.h>
#elif defined(__GNUC__) && defined(__ARM_NEON)
/* Compiler kompatibel GCC, menargetkan ARM dengan 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;
}