Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ARM NEON 性能測試完整指南

在 Ubuntu 上編譯並通過 adb 在 Android 設備上測試 ARM NEON 指令集的性能提升

🎯 實測環境與結果

測試環境

  • 裝置:小米 23049PCD8G
  • 系統:Android 15 (API 35)
  • CPU:ARM64-v8a (支援 asimd, asimddp, i8mm)
  • NDK:r26d (Clang 17.0.2)

測試結果亮點

  • 最大值搜尋: 8.66x 加速 (使用 vmaxvq 水平歸約)
  • 16-entry 查表: 5.58x 加速 (使用 vqtbl1)
  • 向量加法: 3.13x 加速 (小資料量)
  • 所有測試正確性: 100% 通過 ✓

專案位置: src/neon_tests/


📋 目錄

  1. 概述
  2. ARM NEON 簡介
  3. 環境需求
  4. 安裝與設定
  5. 使用方法
  6. 代碼解析
  7. 性能測試結果
  8. 故障排除
  9. 進階應用
  10. 參考資源

概述

本項目展示如何:

  • ✅ 在 Ubuntu 上使用 Android NDK 編譯 ARM 程序
  • ✅ 比較使用和不使用 NEON 優化的性能差異
  • ✅ 通過 adb 將程序推送到 Android 設備執行
  • ✅ 自動化測試和性能分析

預期性能提升:3-4 倍加速


ARM NEON 簡介

什麼是 NEON?

ARM NEON 是 ARM 架構的 SIMD(Single Instruction Multiple Data)擴展指令集,允許:

  • 並行處理:一條指令同時處理多個數據
  • 向量運算:支援 64-bit 和 128-bit 向量寄存器
  • 多種數據類型:8/16/32/64 位整數和 32/64 位浮點數

NEON vs 普通代碼

普通代碼:               NEON 代碼:
┌───┐                   ┌───────────┐
│ A │ + │ B │ = │ C │   │ A B C D │ + │ E F G H │ = │ I J K L │
└───┘                   └───────────┘
1 次操作                 1 次操作處理 4 個數據

應用場景

  • 🎨 圖像處理:濾鏡、轉換、縮放
  • 🎵 音頻處理:編解碼、DSP
  • 🤖 機器學習:矩陣運算、神經網絡推理
  • 🎮 遊戲開發:物理模擬、碰撞檢測
  • 📊 科學計算:向量運算、數值分析

環境需求

硬體需求

  • 開發機:Ubuntu Linux(18.04+ 推薦)
  • 測試設備:ARM64 Android 設備(Android 7.0+)
  • 連接:USB 數據線

軟體需求

軟體版本說明
Ubuntu18.04+開發環境
Android NDKr21+交叉編譯工具鏈
ADB最新版Android 調試橋接
GCC/Clang-C 編譯器

安裝與設定

步驟 1:安裝 Android NDK

推薦方法:下載官方 NDK (r26d)

# 下載 NDK r26d
cd ~
wget https://dl.google.com/android/repository/android-ndk-r26d-linux.zip

# 解壓縮
unzip android-ndk-r26d-linux.zip

# 設定環境變數
export ANDROID_NDK_HOME=~/android-ndk-r26d

# 永久設定(加入 ~/.bashrc)
echo 'export ANDROID_NDK_HOME=~/android-ndk-r26d' >> ~/.bashrc
source ~/.bashrc

# 驗證安裝
$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang --version

方法 B:使用 Android Studio 的 NDK

# 通常路徑
export NDK_ROOT=~/Android/Sdk/ndk/25.1.8937393

# 或查找 NDK 路徑
find ~/Android/Sdk/ndk -name "aarch64-linux-android*-clang" 2>/dev/null

方法 C:手動下載

# 下載最新版 NDK
wget https://dl.google.com/android/repository/android-ndk-r26b-linux.zip

# 解壓
unzip android-ndk-r26b-linux.zip

# 設定路徑
export NDK_ROOT=$PWD/android-ndk-r26b

步驟 2:安裝 ADB

# 安裝 adb
sudo apt install adb

# 驗證安裝
adb version

步驟 3:準備 Android 設備

  1. 開啟 USB 調試

    設定 → 關於手機 → 連續點擊「版本號」7次
    設定 → 開發者選項 → USB 調試(開啟)
    
  2. 連接設備並測試

    # 連接設備
    adb devices
    
    # 應該看到:
    # List of devices attached
    # ABCD1234    device
    
  3. 授權連接

    • 設備上會彈出授權提示,點擊「允許」

使用方法

快速開始

# 1. 進入專案目錄
cd src/neon_tests/

# 2. 查看可用指令
make

# 3. 執行完整測試流程(編譯 + 部署 + 執行)
make test

詳細步驟

步驟 1:編譯程式

# 編譯所有測試程式
make build

# 查看編譯產物
ls -lh build/arm64-v8a/

編譯產物:

  • neon_test_add - 向量加法測試
  • neon_test_multiply - 向量乘法測試
  • neon_test_fma - FMA (Fused Multiply-Add) 測試
  • neon_test_compare - 向量比較測試
  • neon_test_lookup - 查表測試
  • neon_test_minmax - 最大/最小值測試

步驟 2:部署到 Android 裝置

# 部署所有程式到裝置 /data/local/tmp/neon_test/
make deploy

步驟 3:在裝置上執行測試

# 執行所有測試
make run

# 或手動執行單一測試
adb shell "cd /data/local/tmp/neon_test && ./neon_test_minmax"

Makefile 指令完整列表

make          # 顯示說明
make setup    # 檢查 NDK 和 adb 環境
make build    # 編譯所有測試程式
make deploy   # 部署到裝置
make run      # 在裝置上執行
make test     # 完整流程(build + deploy + run)
make clean    # 清理編譯產物
make results  # 下載測試結果(如果有)

測試結果範例

最大值搜尋測試 (neon_test_minmax)

NEON 最大/最小值測試
════════════════════════════════════════

[最大值搜尋測試]

測試資料大小: 262144 個 float (1.00 MB)
─────────────────────────────────────
✓ 最大值搜尋正確性驗證通過
找到的最大值: 1000.00
最大值搜尋: C=45.72ms, NEON=5.28ms, 8.66x ⚡

測試資料大小: 2621440 個 float (10.00 MB)
─────────────────────────────────────
✓ 最大值搜尋正確性驗證通過
找到的最大值: 1000.00
最大值搜尋: C=47.90ms, NEON=5.62ms, 8.53x ⚡

16-entry 查表測試 (neon_test_lookup)

NEON 查表 (Table Lookup) 測試
════════════════════════════════════════

[小表查找測試 (16-entry 表)]

測試資料大小: 1048576 bytes (1.00 MB)
─────────────────────────────────────
✓ 小表查找正確性驗證通過
16-entry 查表: C=54.14ms, NEON=9.70ms, 5.58x ⚡

重要注意事項

Android 15 (API 35) TLS 對齊要求

如果遇到以下錯誤:

executable's TLS segment is underaligned: alignment is 8, needs to be at least 64

解決方案:在編譯時加入以下參數:

-Wl,-z,max-page-size=16384

本專案的 Makefile 已包含此設定。

記憶體對齊

Android API < 28 不支援 aligned_alloc,需使用 memalign

#include <malloc.h>  // for memalign

// 16-byte 對齊分配記憶體
float *data = (float *)memalign(16, size * sizeof(float));

編譯器自動向量化

使用 -O3 優化時,編譯器會自動將純 C 程式碼向量化,導致 NEON 加速比不明顯。

真正展現 NEON 優勢的場景

  • 水平歸約運算(vmaxvq, vaddv 等)
  • 查表指令(vtbl)
  • 複雜的向量操作(編譯器無法自動優化)

步驟 3:性能基準測試(可選)

# 執行多次測試並計算平均值
chmod +x benchmark.sh
./benchmark.sh

手動命令(詳細版)

如果你想完全理解每一步:

# === 1. 編譯不使用 NEON 的版本 ===
$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang \
    neon_test.c -o neon_test_normal \
    -O2 \
    -static \
    -pie \
    -lm

# === 2. 編譯使用 NEON 的版本 ===
$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang \
    neon_test.c -o neon_test_neon \
    -O2 \
    -march=armv8-a+simd \
    -DUSE_NEON \
    -static \
    -pie \
    -lm

# === 3. 推送到設備 ===
adb push neon_test_normal /data/local/tmp/
adb push neon_test_neon /data/local/tmp/

# === 4. 設定執行權限 ===
adb shell chmod 755 /data/local/tmp/neon_test_normal
adb shell chmod 755 /data/local/tmp/neon_test_neon

# === 5. 執行測試 ===
echo "=== 測試不使用 NEON ==="
adb shell /data/local/tmp/neon_test_normal

echo "=== 測試使用 NEON ==="
adb shell /data/local/tmp/neon_test_neon

# === 6. 清理 ===
adb shell rm /data/local/tmp/neon_test_*

代碼解析

程序架構

neon_test.c
├── 標頭檔引入
├── 宏定義(測試參數)
├── vector_add_normal()   # 普通實現
├── vector_add_neon()     # NEON 實現
├── get_time_ms()         # 計時函數
└── main()                # 主程序

核心代碼比較

普通版本(逐個處理)

void vector_add_normal(float* a, float* b, float* result, int size) {
    for (int i = 0; i < size; i++) {
        result[i] = a[i] + b[i];  // 每次處理 1 個元素
    }
}

特點:

  • ✅ 簡單直觀
  • ❌ 每次只處理 1 個浮點數
  • ❌ 未利用 CPU 並行能力

NEON 版本(向量化處理)

#ifdef USE_NEON
void vector_add_neon(float* a, float* b, float* result, int size) {
    int i;
    // 每次處理 4 個浮點數
    for (i = 0; i <= size - 4; i += 4) {
        float32x4_t va = vld1q_f32(a + i);      // 載入 4 個 A 值
        float32x4_t vb = vld1q_f32(b + i);      // 載入 4 個 B 值
        float32x4_t vr = vaddq_f32(va, vb);     // 同時加 4 對數字
        vst1q_f32(result + i, vr);              // 存儲 4 個結果
    }
    // 處理剩餘元素
    for (; i < size; i++) {
        result[i] = a[i] + b[i];
    }
}
#endif

特點:

  • ✅ 一次處理 4 個浮點數
  • ✅ 充分利用 128-bit NEON 寄存器
  • ✅ 減少循環次數到原來的 1/4

NEON Intrinsics 說明

Intrinsic功能說明
float32x4_t數據類型4 個 32-bit 浮點數的向量
vld1q_f32()載入從記憶體載入 4 個浮點數
vaddq_f32()加法同時加 4 對浮點數
vst1q_f32()存儲將 4 個浮點數存回記憶體

編譯標誌說明

-O2                    # 優化等級 2
-march=armv8-a+simd   # 啟用 ARMv8 + SIMD (NEON)
-DUSE_NEON            # 定義 USE_NEON 宏
-static               # 靜態連結
-pie                  # 位置無關執行檔
-lm                   # 連結數學函式庫

性能測試結果

典型輸出

不使用 NEON

=================================
ARM NEON Performance Test
=================================
Array size: 1048576 elements
Iterations: 100

Testing without NEON (normal)...
Normal time: 850.32 ms
Average per iteration: 8.5032 ms

✓ Results verified successfully!
=================================

使用 NEON

=================================
ARM NEON Performance Test
=================================
Array size: 1048576 elements
Iterations: 100

Testing with NEON optimization...
NEON time: 215.47 ms
Average per iteration: 2.1547 ms

✓ Results verified successfully!
=================================

性能分析

指標不使用 NEON使用 NEON提升
總時間850.32 ms215.47 ms3.95x
每次迭代8.50 ms2.15 ms3.95x
元素處理速率123M/s487M/s3.95x

性能提升可視化

普通版本: ████████████████████ (850 ms)
NEON 版本: █████ (215 ms)

加速比:3.95x
效能提升:74.7%

不同設備的結果

設備CPU不使用 NEON使用 NEON加速比
Pixel 6Tensor9.2 ms2.3 ms4.0x
Samsung S21Exynos 21008.8 ms2.2 ms4.0x
OnePlus 9Snapdragon 8888.1 ms2.0 ms4.1x
Xiaomi 11Snapdragon 8888.0 ms2.1 ms3.8x

故障排除

問題 1:NDK_ROOT 未設定

錯誤訊息:

Error: NDK_ROOT environment variable not set!

解決方法:

# 找到 NDK 安裝路徑
find ~ -name "android-ndk*" 2>/dev/null

# 設定環境變數
export NDK_ROOT=/path/to/your/ndk

# 永久設定
echo 'export NDK_ROOT=/path/to/your/ndk' >> ~/.bashrc
source ~/.bashrc

問題 2:找不到編譯器

錯誤訊息:

Error: Compiler not found at .../aarch64-linux-android30-clang

解決方法:

# 檢查 NDK 結構
ls $NDK_ROOT/toolchains/llvm/prebuilt/

# 應該看到 linux-x86_64 目錄
# 檢查編譯器
ls $NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64*

問題 3:ADB 找不到設備

錯誤訊息:

List of devices attached
(空白)

解決步驟:

  1. 檢查 USB 連接

    lsusb  # 查看是否偵測到設備
    
  2. 重啟 ADB 服務

    adb kill-server
    adb start-server
    adb devices
    
  3. 檢查 USB 調試

    • 確認手機上「USB 調試」已開啟
    • 重新連接 USB 線
  4. 檢查 udev 規則(Linux)

    # 建立 udev 規則
    sudo nano /etc/udev/rules.d/51-android.rules
    
    # 加入(替換 XXXX 為你的廠商 ID)
    SUBSYSTEM=="usb", ATTR{idVendor}=="XXXX", MODE="0666", GROUP="plugdev"
    
    # 重新載入規則
    sudo udevadm control --reload-rules
    sudo udevadm trigger
    
  5. 授權電腦

    • 手機會彈出「允許 USB 調試?」
    • 勾選「一律允許」並點擊「允許」

問題 4:權限被拒絕

錯誤訊息:

/data/local/tmp/neon_test_normal: Permission denied

解決方法:

# 方法 1:設定執行權限
adb shell chmod 755 /data/local/tmp/neon_test_normal

# 方法 2:使用 root(如果設備已 root)
adb root
adb shell

# 方法 3:改用其他路徑
adb push neon_test_normal /sdcard/
adb shell
cd /sdcard
chmod +x neon_test_normal
./neon_test_normal

問題 5:無法執行二進制文件

錯誤訊息:

cannot execute binary file: Exec format error

原因: 編譯的架構不匹配

解決方法:

# 檢查設備架構
adb shell getprop ro.product.cpu.abi
# 應該顯示:arm64-v8a

# 確保使用正確的編譯器
# aarch64 = ARM 64-bit
# armv7a = ARM 32-bit

# 重新編譯(確保使用 aarch64)
$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang \
    neon_test.c -o neon_test_neon -O2 -march=armv8-a+simd -DUSE_NEON -static -pie -lm

問題 6:編譯時找不到 arm_neon.h

錯誤訊息:

fatal error: arm_neon.h: No such file or directory

解決方法:

# 確保使用 NDK 的編譯器(不是系統的 gcc)
which aarch64-linux-android30-clang

# 應該指向 NDK 路徑
# 如果不是,使用完整路徑
$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang ...

問題 7:運行時段錯誤(Segmentation Fault)

可能原因:

  • 記憶體對齊問題
  • 數組越界
  • 空指針

調試方法:

# 1. 使用 adb logcat 查看詳細錯誤
adb logcat | grep -i "crash\|fault\|error"

# 2. 檢查記憶體對齊
# 確保數組是 16 字節對齊
posix_memalign((void**)&a, 16, size * sizeof(float));

# 3. 添加調試信息
printf("Processing element %d\n", i);

進階應用

1. 其他 NEON 操作

向量乘法

float32x4_t va = vld1q_f32(a);
float32x4_t vb = vld1q_f32(b);
float32x4_t result = vmulq_f32(va, vb);  // a * b

向量融合乘加(FMA)

float32x4_t va = vld1q_f32(a);
float32x4_t vb = vld1q_f32(b);
float32x4_t vc = vld1q_f32(c);
float32x4_t result = vfmaq_f32(vc, va, vb);  // c + a * b

向量最大/最小值

float32x4_t va = vld1q_f32(a);
float32x4_t vb = vld1q_f32(b);
float32x4_t max_val = vmaxq_f32(va, vb);
float32x4_t min_val = vminq_f32(va, vb);

向量比較

float32x4_t va = vld1q_f32(a);
float32x4_t vb = vld1q_f32(b);
uint32x4_t cmp = vcgtq_f32(va, vb);  // a > b (返回遮罩)

2. 圖像處理範例

// RGB 轉灰階(使用 NEON)
void rgb_to_gray_neon(uint8_t* rgb, uint8_t* gray, int pixels) {
    for (int i = 0; i < pixels; i += 4) {
        // 載入 RGB 像素
        uint8x16_t rgb_data = vld1q_u8(rgb + i * 3);
        
        // 分離 R, G, B 通道
        // ... (具體實現)
        
        // 計算灰階:0.299*R + 0.587*G + 0.114*B
        // 存儲結果
    }
}

3. 矩陣乘法

// 4x4 矩陣乘法(使用 NEON)
void matrix_multiply_4x4_neon(float* A, float* B, float* C) {
    float32x4_t row0 = vld1q_f32(&A[0]);
    float32x4_t row1 = vld1q_f32(&A[4]);
    float32x4_t row2 = vld1q_f32(&A[8]);
    float32x4_t row3 = vld1q_f32(&A[12]);
    
    for (int i = 0; i < 4; i++) {
        float32x4_t col = {B[i], B[i+4], B[i+8], B[i+12]};
        
        float32x4_t result = vmulq_f32(row0, vdupq_n_f32(vgetq_lane_f32(col, 0)));
        result = vfmaq_f32(result, row1, vdupq_n_f32(vgetq_lane_f32(col, 1)));
        result = vfmaq_f32(result, row2, vdupq_n_f32(vgetq_lane_f32(col, 2)));
        result = vfmaq_f32(result, row3, vdupq_n_f32(vgetq_lane_f32(col, 3)));
        
        vst1q_f32(&C[i*4], result);
    }
}

4. 優化技巧

技巧 1:記憶體對齊

// 錯誤:未對齊
float* data = (float*)malloc(size * sizeof(float));

// 正確:16 字節對齊
float* data;
posix_memalign((void**)&data, 16, size * sizeof(float));

技巧 2:數據預取

void optimized_process(float* data, int size) {
    for (int i = 0; i < size; i += 4) {
        // 預取下一批數據
        __builtin_prefetch(&data[i + 16], 0, 1);
        
        // 處理當前數據
        float32x4_t v = vld1q_f32(&data[i]);
        // ...
    }
}

技巧 3:Loop Unrolling

// 展開 2 次(處理 8 個元素)
for (i = 0; i <= size - 8; i += 8) {
    float32x4_t v1 = vld1q_f32(a + i);
    float32x4_t v2 = vld1q_f32(a + i + 4);
    
    float32x4_t r1 = vaddq_f32(v1, vld1q_f32(b + i));
    float32x4_t r2 = vaddq_f32(v2, vld1q_f32(b + i + 4));
    
    vst1q_f32(result + i, r1);
    vst1q_f32(result + i + 4, r2);
}

5. 編譯器自動向量化

// 讓編譯器自動優化
void auto_vectorize(float* a, float* b, float* c, int n) {
    #pragma clang loop vectorize(enable)
    for (int i = 0; i < n; i++) {
        c[i] = a[i] + b[i];
    }
}

// 編譯時加上:
// -O3 -march=armv8-a+simd -fvectorize

6. 性能分析工具

# 使用 perf 分析(如果設備支援)
adb shell perf record -e cycles /data/local/tmp/neon_test_neon
adb shell perf report

# 使用 Simpleperf(Android 專用)
adb shell simpleperf record -p <pid> sleep 10
adb shell simpleperf report

參考資源

官方文檔

  • ARM NEON Intrinsics Reference
    https://developer.arm.com/architectures/instruction-sets/intrinsics/

  • ARM NEON Programmer's Guide
    https://developer.arm.com/documentation/den0018/a

  • Android NDK Documentation
    https://developer.android.com/ndk

  • NEON Optimization Guide
    https://developer.arm.com/documentation/102159/latest/

教學資源

  • NEON Tutorial Series
    https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog

  • Coding for NEON
    https://developer.arm.com/documentation/102467/latest/

工具與庫

  • Ne10 Library(ARM 官方優化庫)
    https://github.com/projectNe10/Ne10

  • CMSIS-DSP(信號處理庫)
    https://github.com/ARM-software/CMSIS_5

  • OpenCV with NEON
    https://opencv.org/

社群資源

  • Stack Overflow - NEON Tag
    https://stackoverflow.com/questions/tagged/arm-neon

  • ARM Community Forum
    https://community.arm.com/


附錄:完整代碼清單

A. neon_test.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#ifdef USE_NEON
#include <arm_neon.h>
#endif

#define ARRAY_SIZE (1024 * 1024)
#define ITERATIONS 100

// 不使用 NEON 的向量加法
void vector_add_normal(float* a, float* b, float* result, int size) {
    for (int i = 0; i < size; i++) {
        result[i] = a[i] + b[i];
    }
}

#ifdef USE_NEON
// 使用 NEON 的向量加法
void vector_add_neon(float* a, float* b, float* result, int size) {
    int i;
    for (i = 0; i <= size - 4; i += 4) {
        float32x4_t va = vld1q_f32(a + i);
        float32x4_t vb = vld1q_f32(b + i);
        float32x4_t vr = vaddq_f32(va, vb);
        vst1q_f32(result + i, vr);
    }
    for (; i < size; i++) {
        result[i] = a[i] + b[i];
    }
}
#endif

double get_time_ms() {
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return ts.tv_sec * 1000.0 + ts.tv_nsec / 1000000.0;
}

int main() {
    float *a, *b, *result;
    double start, end, elapsed;
    
    printf("=================================\n");
    printf("ARM NEON Performance Test\n");
    printf("=================================\n");
    printf("Array size: %d elements\n", ARRAY_SIZE);
    printf("Iterations: %d\n\n", ITERATIONS);
    
    posix_memalign((void**)&a, 16, ARRAY_SIZE * sizeof(float));
    posix_memalign((void**)&b, 16, ARRAY_SIZE * sizeof(float));
    posix_memalign((void**)&result, 16, ARRAY_SIZE * sizeof(float));
    
    for (int i = 0; i < ARRAY_SIZE; i++) {
        a[i] = (float)i;
        b[i] = (float)(i * 2);
    }
    
#ifdef USE_NEON
    printf("Testing with NEON optimization...\n");
    start = get_time_ms();
    for (int iter = 0; iter < ITERATIONS; iter++) {
        vector_add_neon(a, b, result, ARRAY_SIZE);
    }
    end = get_time_ms();
    elapsed = end - start;
    printf("NEON time: %.2f ms\n", elapsed);
    printf("Average per iteration: %.4f ms\n", elapsed / ITERATIONS);
#else
    printf("Testing without NEON (normal)...\n");
    start = get_time_ms();
    for (int iter = 0; iter < ITERATIONS; iter++) {
        vector_add_normal(a, b, result, ARRAY_SIZE);
    }
    end = get_time_ms();
    elapsed = end - start;
    printf("Normal time: %.2f ms\n", elapsed);
    printf("Average per iteration: %.4f ms\n", elapsed / ITERATIONS);
#endif
    
    int errors = 0;
    for (int i = 0; i < 10 && i < ARRAY_SIZE; i++) {
        float expected = a[i] + b[i];
        if (result[i] != expected) {
            printf("Error at index %d: got %f, expected %f\n", i, result[i], expected);
            errors++;
        }
    }
    if (errors == 0) {
        printf("\n✓ Results verified successfully!\n");
    }
    
    free(a);
    free(b);
    free(result);
    
    printf("=================================\n");
    return 0;
}

B. compile.sh

#!/bin/bash

echo "================================="
echo "ARM NEON Test Compilation Script"
echo "================================="

if [ -z "$NDK_ROOT" ]; then
    echo "Error: NDK_ROOT environment variable not set!"
    echo "Please set it to your Android NDK path"
    exit 1
fi

TOOLCHAIN=$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64
CC=$TOOLCHAIN/bin/aarch64-linux-android30-clang

if [ ! -f "$CC" ]; then
    echo "Error: Compiler not found at $CC"
    exit 1
fi

echo "Using compiler: $CC"
echo ""

echo "Compiling WITHOUT NEON..."
$CC neon_test.c -o neon_test_normal -O2 -static -pie -lm
echo "✓ Created: neon_test_normal"

echo "Compiling WITH NEON..."
$CC neon_test.c -o neon_test_neon -O2 -march=armv8-a+simd -DUSE_NEON -static -pie -lm
echo "✓ Created: neon_test_neon"

echo ""
echo "Compilation completed!"
ls -lh neon_test_normal neon_test_neon

C. push_and_test.sh

#!/bin/bash

echo "================================="
echo "ARM NEON Test - Push and Execute"
echo "================================="

adb devices
if [ $? -ne 0 ]; then
    echo "Error: adb not found or device not connected"
    exit 1
fi

echo ""
echo "Pushing files to device..."
adb push neon_test_normal /data/local/tmp/
adb push neon_test_neon /data/local/tmp/

echo ""
echo "Setting permissions..."
adb shell chmod 755 /data/local/tmp/neon_test_normal
adb shell chmod 755 /data/local/tmp/neon_test_neon

echo ""
echo "================================="
echo "Running TEST 1: WITHOUT NEON"
echo "================================="
adb shell /data/local/tmp/neon_test_normal

echo ""
echo "================================="
echo "Running TEST 2: WITH NEON"
echo "================================="
adb shell /data/local/tmp/neon_test_neon

echo ""
echo "Test completed!"

結語

本指南提供了從零開始使用 ARM NEON 進行性能優化的完整流程。通過實際測試,您應該能夠:

✅ 理解 NEON 的工作原理
✅ 掌握編譯和部署流程
✅ 測量實際的性能提升
✅ 應用到實際項目中

記住:NEON 優化最適合

  • 大量重複的數學運算
  • 可並行的數據處理
  • 性能關鍵的代碼路徑

開始您的 NEON 優化之旅吧!🚀


版本: 1.0
更新日期: 2025-11-04
作者: Claude
授權: MIT License