GPU使用指南

Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.


GPU(图形处理器) 是设备里的一块专用芯片,专门负责"画图"和"计算图像"。如果把手机比作一台电脑:

CPU 负责"思考"——处理逻辑、运行程序,GPU 负责"画画"——把所有内容渲染成屏幕上显示的图像

没有 GPU,设备的屏幕就无法显示界面,游戏、视频、动画都无法运行。GPU 的性能直接影响设备的流畅度和功耗。

用途

说明

系统界面

开机动画、桌面、应用切换、下拉菜单等所有界面渲染

游戏娱乐

3D 游戏、动画效果、AR 应用等图形渲染

视频播放

视频色彩处理、画面增强、HDR 效果

相机拍照

取景画面、滤镜效果、图像美化

通用计算

协助 CPU 做并行计算,如人脸识别、AI 应用加速

GPU配置


类别

M1说 明

L1说明
应用处理器 八核64位ARM Kryo™ 260处理器:
4 × A73 @ 2.0 GHz, 1 MB二级缓存
4 × A53 @ 1.8 GHz,512 KB二级缓存
ARM 四核 64 位处理器:
4 x A53 @ 2.0 GHz,512 KB 二级缓存
GPU 64位Adreno™ 610 @ 1050 MHZ 64 位 Adreno™ 702 @ 845 MHz
显示接口 1 × Micro HDMI接口,HDMI 1.4 (帧率\),编码:1080P(H.264/H.265)@ 60 fps\),解码:1080P (H.264/H.265/VP9) @ 60 fps\*) 1 × Micro HDMI接口,HDMI 1.4 (帧率\),编码:1080P(H.264/H.265)@ 60 fps\),解码:1080P (H.264/H.265/VP9) @ 60 fps\*)
1 × FPC座,基于MIPI标准的FHD+(1080 × 2520)@ 60 fps\* 1 × FPC座,基于MIPI标准的 HD+(1680 × 720)@ 60 fps\*

GPU使用

Android 播放4K高清视频

../../_images/image_PdV8bsFMwopQdNxOf6ic4cUXnEh.webp

Debian OpenCV GPU 加速开发与验证

准备工作

开发环境

  • PC:Windows

  • 开发板:Quectel Pi M1

  • 系统:Debian GNU/Linux 13

开发工具

  • VS Code:用于编写和修改 Benchmark 源码。

  • ADB(Android Debug Bridge):用于连接开发板、执行 Linux 命令、编译及运行程序。

注:除源码编写外,本文涉及的所有 Linux 命令(软件安装、环境验证、程序编译、程序运行等)均在 ADB Shell 中执行。

连接开发板

在PC端ADB文件夹下的地址输入栏输入CMD打开命令行,执行:

adb devices

确认开发板已连接,例如:

List of devices attached
xxxxxxxx    device

进入开发板:

adb shell

测试目的

安装 Debian 官方 OpenCV 4.10.0,验证 Debian是否能够通过镜像自带的Qualcomm OpenCL Runtime调用 Adreno GPU,实现OpenCL GPU加速。

测试环境


项目


内容

开发板

Quectel Pi M1(QSM200U)

系统

Debian GNU/Linux 13

Debian OpenCV

4.10.0

GPU

Qualcomm Adreno 610

OpenCL Runtime

Qualcomm OpenCL Runtime

安装Debian官方软件源OpenCV

apt update
apt install g++ pkg-config libopencv-dev python3-opencv

安装完成后验证:

opencv_version
pkg-config --modversion opencv4
dpkg -l | grep opencv

验证结果:

  • opencv_version:4.10.0

  • pkg-config:4.10.0

  • dpkg:Debian OpenCV 4.10.0

验证 OpenCL Runtime

确认系统 OpenCL 库:

find /usr/lib -name "libOpenCL*"

确认存在:

libOpenCL.so
libOpenCL.so.1
libOpenCL.so.1.2
libOpenCL_adreno.so

编写 Benchmark 程序

在 VS Code 中创建opencv_gpu_benchmark.cpp文件

#include <opencv2/core.hpp>
#include <opencv2/core/ocl.hpp>
#include <iostream>
#include <string>

static double run_cpu(const cv::Mat &src, int loops, cv::Mat &result)
{
    cv::ocl::setUseOpenCL(false);

    cv::Mat current = src.clone();
    cv::Mat next;

    for (int i = 0; i < 5; ++i) {
        cv::multiply(current, 1.000001, next);
        current = next;
    }

    current = src.clone();

    const int64 start = cv::getTickCount();

    for (int i = 0; i < loops; ++i) {
        cv::multiply(current, 1.000001, next);
        current = next;
    }

    const int64 end = cv::getTickCount();

    result = current.clone();

    return (end - start) * 1000.0 / cv::getTickFrequency();
}

static double run_gpu(const cv::Mat &src, int loops, cv::Mat &result)
{
    cv::ocl::setUseOpenCL(true);

    if (!cv::ocl::useOpenCL()) {
        std::cerr << "OpenCL could not be enabled." << std::endl;
        return -1.0;
    }

    cv::UMat current;
    cv::UMat next;

    src.copyTo(current);

    for (int i = 0; i < 5; ++i) {
        cv::multiply(current, 1.000001, next);
        current = next;
    }

    src.copyTo(current);
    cv::ocl::finish();

    const int64 start = cv::getTickCount();

    for (int i = 0; i < loops; ++i) {
        cv::multiply(current, 1.000001, next);
        current = next;
    }

    cv::ocl::finish();

    const int64 end = cv::getTickCount();

    current.copyTo(result);

    return (end - start) * 1000.0 / cv::getTickFrequency();
}

int main(int argc, char **argv)
{
    if (argc != 2) {
        std::cout << "Usage: " << argv[0] << " cpu|gpu|both" << std::endl;
        return 1;
    }

    const std::string mode = argv[1];
    const int loops = 500;

    cv::Mat src(2160, 3840, CV_32FC1);
    cv::randu(src, 0.0f, 1.0f);

    std::cout << "OpenCV version: " << CV_VERSION << std::endl;
    std::cout << "haveOpenCL: " << cv::ocl::haveOpenCL() << std::endl;
    std::cout << "Image size: 3840x2160, CV_32FC1" << std::endl;
    std::cout << "Loops: " << loops << std::endl;

    if (mode == "cpu") {
        cv::Mat cpu_result;
        const double cpu_ms = run_cpu(src, loops, cpu_result);

        std::cout << "Mode: CPU" << std::endl;
        std::cout << "CPU total time: " << cpu_ms << " ms" << std::endl;
        std::cout << "CPU average time: "
                  << cpu_ms / loops << " ms" << std::endl;
    }
    else if (mode == "gpu") {
        cv::ocl::Context context;

        if (!context.create(cv::ocl::Device::TYPE_GPU)) {
            std::cerr << "Failed to create GPU context." << std::endl;
            return 1;
        }

        cv::ocl::Device device = context.device(0);

        std::cout << "Mode: GPU" << std::endl;
        std::cout << "Device name: " << device.name() << std::endl;
        std::cout << "Vendor: " << device.vendorName() << std::endl;
        std::cout << "OpenCL version: " << device.version() << std::endl;

        cv::Mat gpu_result;
        const double gpu_ms = run_gpu(src, loops, gpu_result);

        if (gpu_ms < 0.0) {
            return 1;
        }

        std::cout << "GPU total time: " << gpu_ms << " ms" << std::endl;
        std::cout << "GPU average time: "
                  << gpu_ms / loops << " ms" << std::endl;
    }
    else if (mode == "both") {
        cv::Mat cpu_result;
        cv::Mat gpu_result;

        const double cpu_ms = run_cpu(src, loops, cpu_result);
        const double gpu_ms = run_gpu(src, loops, gpu_result);

        if (gpu_ms < 0.0) {
            return 1;
        }

        const double max_difference =
            cv::norm(cpu_result, gpu_result, cv::NORM_INF);

        std::cout << "Mode: BOTH" << std::endl;
        std::cout << "CPU average time: "
                  << cpu_ms / loops << " ms" << std::endl;
        std::cout << "GPU average time: "
                  << gpu_ms / loops << " ms" << std::endl;
        std::cout << "Speedup: "
                  << cpu_ms / gpu_ms << "x" << std::endl;
        std::cout << "Maximum result difference: "
                  << max_difference << std::endl;

        if (max_difference < 0.01) {
            std::cout << "Result check: PASS" << std::endl;
        } else {
            std::cout << "Result check: FAIL" << std::endl;
            return 1;
        }
    }
    else {
        std::cerr << "Invalid mode. Use cpu, gpu or both." << std::endl;
        return 1;
    }

    return 0;
}

程序主要完成以下功能:

  • 创建测试图像

  • CPU 执行 cv::multiply()

  • GPU(UMat)执行 cv::multiply()

  • 分别统计 CPU、GPU 平均耗时

  • 校验 CPU 与 GPU 运算结果

  • 输出 GPU 加速比(Speedup)

编译 Benchmark

把vscode中的opencv_gpu_benchmark.cpp文件保存到adb文件夹下然后推送到板子:

adb push opencv_gpu_benchmark.cpp /data/local/tmp/

进入源码目录:

cd /data/local/tmp

编译:

g++ -O2 opencv_gpu_benchmark.cpp -o opencv_gpu_benchmark $(pkg-config --cflags --libs opencv4)

生成可执行文件:

opencv_gpu_benchmark

运行 Benchmark

export LD_LIBRARY_PATH=/opt/qcom/lib:$LD_LIBRARY_PATH 
./opencv_gpu_benchmark both

运行结果:

OpenCV version: 4.10.0
haveOpenCL: 1
CPU average time: 28.9083 ms
GPU average time: 0.0474746 ms
Speedup: 608.92x
Maximum result difference: 0.000506639
Result check: PASS

OpenCV Benchmark 能够正常调用 GPU,测试结果 PASS

测试说明

本次测试中,Debian官方OpenCV GPU Benchmark测得GPU加速比约 608.92×, 需要说明的是,该测试程序仅使用OpenCV的 cv::multiply() 单一算子进行性能验证,属于OpenCL基础功能验证,其计算量较小,GPU计算耗时接近测试计时精度,因此得到的加速比明显偏高。 因此,本次Benchmark结果主要用于验证OpenCV能够成功调用GPU完成OpenCL计算,不建议将 608.92× 作为GPU综合性能指标。

常见问题

设备界面卡顿、掉帧?

  • 先确认是否后台运行了过多应用,关闭不用的程序

  • 若设备发热严重,等待降温后频率会自动恢复

屏幕花屏、显示异常?

  • 检查 HDMI 线/屏幕连接是否牢固

  • 确认屏幕或显示器的分辨率、刷新率设置是否正确

  • 更换线材或显示器测试,排除硬件问题

  • 若为新接入的 LCD 屏,需确认屏幕规格与设备支持的分辨率匹配

运行大型游戏或 3D 应用崩溃?

  • 该设备 GPU 为入门级,超高负载应用可能出现性能不足

  • 尝试降低游戏画质/分辨率设置

  • 保持设备散热良好(避免覆盖、遮挡)

GPU 发热、耗电快?

  • 高负载运行时发热属正常现象,系统会自动降频保护

  • 检查是否有应用持续占用 GPU(如后台视频、动画)