【NCNN】arm架构cpu的硬件加速代码样例

66 篇文章 1 订阅
44 篇文章 4 订阅

NCNN加速框架介绍

NCNN(Nihui’s CNN)是一个轻量级、高性能的深度学习推理框架,由腾讯优图实验室的大神Nihui开发。该框架在移动端应用和嵌入式设备上实现了高效的深度学习模型推理,具有较低的内存占用和高度优化的计算性能。

特点

轻量级:NCNN的核心代码非常精简,没有任何第三方依赖,只有一个头文件和一个源文件,非常适合移植到各种平台上使用。

高性能:NCNN通过优化计算流程,充分发挥硬件平台的计算能力,实现了高效的模型推理。在多核CPU和GPU上都能够获得很好的加速效果。

多平台支持:NCNN支持多种操作系统和硬件平台,包括Android、iOS、Linux等。同时,它还提供了Caffe和Tensorflow的模型转换工具,可以方便地将其他框架的模型转换为NCNN可用的格式。

低内存占用:NCNN在设计上采用了内存共享和复用的策略,有效减小了内存占用。这对于移动设备和嵌入式设备来说非常重要,可以降低能耗和提高系统性能。

易于使用:NCNN提供了简洁的API接口,方便用户进行模型的载入和推理。同时,它还提供了丰富的示例代码和文档,帮助用户快速上手。

NCNN对各种硬件平台的指令集进行了充分的利用,例如SIMD指令集(如ARM的NEON指令集、x86的SSE指令集等)和GPU的并行计算能力。通过使用这些指令集,NCNN能够并行地执行计算任务,提高计算效率。

示例代码

比较文件夹下两两图片的相似度,模型采用arcface。


#ifndef Retinaface_RetinafacePostSelfPlug_H
#define Retinaface_RetinafacePostSelfPlug_H
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <net.h>
#include <mat.h>
#include <opencv2/opencv.hpp>
#include <chrono>
// 计算特征向量的单位向量
std::vector<float> calculateUnitVector(const std::vector<float>& feature)
{
    // for (const auto& element : feature) {
    //     std::cout << element << " ";
    // }

    std::vector<float> unitVector(feature.size());
    float norm = 0.0f;
    for (float value : feature)
    {
        norm += value * value;
    }
    norm = std::sqrt(norm);
    std::transform(feature.begin(), feature.end(), unitVector.begin(), [norm](float value) {
        return value / norm;
    });
    return unitVector;
}
std::vector<float> extractFeatureVector(const std::string& imagePath)
{
    std::string modelPath = "/home/kylin/ncnnbuild2/ncnnwork/model/iresnetface1s.param";
    std::string weightPath = "/home/kylin/ncnnbuild2/ncnnwork/model/iresnetbin1s.bin";
    cv::Mat image = cv::imread(imagePath);
    
    // 加载模型
    ncnn::Net net;
    ncnn::Option opt;
    net.opt.use_fp16_packed = false;
    net.opt.use_fp16_storage = false;
    net.opt.use_fp16_arithmetic = false;
    opt.num_threads = 4; 
    opt.use_vulkan_compute = false; 
    net.opt=opt;
    net.load_param(modelPath.c_str());
    net.load_model(weightPath.c_str());
    
    // 读取图片
    //ncnn::Mat input = ncnn::Mat::from_pixels(image.data, ncnn::Mat::PIXEL_BGR2RGB, image.cols, image.rows);
    ncnn::Mat input = ncnn::Mat::from_pixels(image.data, ncnn::Mat::PIXEL_BGR, image.cols, image.rows);
    // 减均值除标准差
    // const float mean_vals[3] = { 127.5f, 127.5f, 127.5f };
    // const float norm_vals[3] = { 1.0 / 127.5, 1.0 / 127.5, 1.0 / 127.5 };
    // input.substract_mean_normalize(mean_vals, norm_vals);
    //如果模型是keras,输入为NHWC时需要的额外变换:
    // ncnn::Mat oo;
    // ncnn::convert_packing(input,oo,3);
    // 创建推理对象
    ncnn::Extractor ex = net.create_extractor();
    ex.input("data", input);
    
    ncnn::Mat feature;
    ex.extract("fc1", feature);
    
    // 取出特征向量
    std::vector<float> featureVector((float*)(feature.data), (float*)(feature.data) + feature.w);
    
    // 计算特征向量的单位向量C*H*W
    std::vector<float> unitVector = calculateUnitVector(featureVector);
    
    return unitVector;
}
float dotProduct(const std::vector<float>& vec1, const std::vector<float>& vec2)
{
    if(vec1.size() != vec2.size())
    {
        std::cerr << "Vector sizes do not match." << std::endl;
        return 0.0f;
    }
    float result = 0.0f;
    for(size_t i = 0; i < vec1.size(); i++)
    {
        result += vec1[i] * vec2[i];
    }
    return result;
}
void fun(const std::string& path1, const std::string& path2) {

    auto v1=extractFeatureVector(path1);
    auto v2=extractFeatureVector(path2);
    std::cout << "Comparing " << path1 << " and " << path2 <<":"<<dotProduct(v1,v2)<< std::endl;
}
int main() {
    using namespace std;
    string folder = "/home/kylin/ncnnbuild2/ncnnwork/pic";
    vector<string> imagePaths;
    // 遍历文件夹,获取所有图片的路径
    cv::glob(folder, imagePaths);
    // 两两对比图片路径
    for (int i = 0; i < imagePaths.size(); ++i) {
        for (int j = i + 1; j < imagePaths.size(); ++j) {
            fun(imagePaths[i], imagePaths[j]);
        }
    }
    return 0;
}
#endif // Retinaface_RetinafacePostSelfPlug_H

对应的cmakelist:


# #设置CMAKE最`在这里插入代码片`低版本
# CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3)
# MESSAGE(STATUS "start!")
# #设置项目名称
# SET(PROJECT_NAME ncnnwork)
# set(NCNN_INCLUDE_DIRS /home/kylin/ncnnbuild2/ncnn/build/install/include/ncnn/)
# #这里添加刚刚安装的opencv的目录,需要包含OpenCVConfig.cmake
# SET(OpenCV_DIR /usr/local/lib/cmake/opencv4)
# #建立项目
# PROJECT(${PROJECT_NAME})
# #寻找OpenCV库
# FIND_PACKAGE(OpenCV REQUIRED)
# INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
# INCLUDE_DIRECTORIES(${NCNN_INCLUDE_DIRS})
# INCLUDE_DIRECTORIES(/home/kylin/ncnnbuild2/ncnn/build/install/include/)
# #获取代码,在项目中,将所有代码都放在src文件夹中
# file(GLOB_RECURSE cpp_srcs ${PROJECT_SOURCE_DIR}/src/*.cpp)
# link_directories(/home/kylin/ncnnbuild2/ncnn/build/install/lib/)
# #编译可执行程序
# ADD_EXECUTABLE(${PROJECT_NAME} ${cpp_srcs})

# #添加链接库
# TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${OpenCV_LIBS})
# TARGET_LINK_LIBRARIES(${PROJECT_NAME}  libncnn.a )


# 将生成的库文件放到安装目录:make install
# install(TARGETS ${TARGET_LIBRARY}
#         LIBRARY DESTINATION ${INSTALL_DIR})
# install(CODE "execute_process(COMMAND sh /home/HwHiAiUser/selfwork/retinafaceplug/models/soworkvscode-file://vscode-app/e:/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html.sh)")
# 最低cmake版本
cmake_minimum_required(VERSION 3.2)
# 工程名
project(ncnnTest)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# --- ncnn
# set函数里的路径是指包含ncnnConfig.cmake的目录
set(ncnn_DIR /home/kylin/ncnnbuild2/ncnn/build/install/lib/cmake/ncnn)
find_package(ncnn REQUIRED)

# --- opencv
SET(OpenCV_DIR /usr/local/lib/cmake/opencv4)
find_package(OpenCV REQUIRED)
file(GLOB_RECURSE cpp_srcs ${PROJECT_SOURCE_DIR}/src/*.cpp)
ADD_EXECUTABLE(${PROJECT_NAME} ${cpp_srcs})
target_link_libraries(ncnnTest ncnn ${OpenCV_LIBS})

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颢师傅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值