当前位置:   article > 正文

【NCNN】arm架构cpu的硬件加速代码样例_ncnn哪里用到了arm指令集优化

ncnn哪里用到了arm指令集优化

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109

对应的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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/297990
推荐阅读
相关标签
  

闽ICP备14008679号