[NCNN学习笔记]-4

1、前言

继续学习NCNN。本次学习binaryop和eltwise。

2、学习内容
2.1、binaryop

binaryop是用来二元计算的op,先来看binaryop.h的中关于二元计算的定义,其中二元计算定义了如下操作。

enum OperationType
{
    Operation_ADD = 0,
    Operation_SUB = 1,
    Operation_MUL = 2,
    Operation_DIV = 3,
    Operation_MAX = 4,
    Operation_MIN = 5,
    Operation_POW = 6,
    Operation_RSUB = 7,
    Operation_RDIV = 8,
    Operation_RPOW = 9,
    Operation_ATAN2 = 10,
    Operation_RATAN2 = 11
};

在binaryop.cpp中,实际调用了二元计算函数。

template<typename Op>
static void binary_op_broadcast(const Mat& a, const Mat& b, Mat& c, const Option& opt){
    ...
}

static void binary_op_broadcast(const Mat& a, const Mat& b, Mat& c, int op_type, const Option& opt)
{
    if (op_type == BinaryOp::Operation_ADD) return binary_op_broadcast<binary_op_add>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_SUB) return binary_op_broadcast<binary_op_sub>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_MUL) return binary_op_broadcast<binary_op_mul>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_DIV) return binary_op_broadcast<binary_op_div>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_MAX) return binary_op_broadcast<binary_op_max>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_MIN) return binary_op_broadcast<binary_op_min>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_POW) return binary_op_broadcast<binary_op_pow>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_RSUB) return binary_op_broadcast<binary_op_sub>(b, a, c, opt);
    if (op_type == BinaryOp::Operation_RDIV) return binary_op_broadcast<binary_op_div>(b, a, c, opt);
    if (op_type == BinaryOp::Operation_RPOW) return binary_op_broadcast<binary_op_pow>(b, a, c, opt);
    if (op_type == BinaryOp::Operation_ATAN2) return binary_op_broadcast<binary_op_atan2>(a, b, c, opt);
    if (op_type == BinaryOp::Operation_RATAN2) return binary_op_broadcast<binary_op_atan2>(b, a, c, opt);
}

可以看出,二元操作是通过函数模板实现的。在binaryop_arm.cpp中实现了具体的二元操作的例子。

template<typename Op>
static void binary_op_vector_no_broadcast(const float* ptr, const float* ptr1, float* outptr, int size)
{
    const Op op;

    int i = 0;
#if __ARM_NEON
    for (; i + 3 < size; i += 4)
    {
        float32x4_t _p = vld1q_f32(ptr);
        float32x4_t _b = vld1q_f32(ptr1);
        float32x4_t _outp = op(_p, _b);    // 通过op来确定最终的操作
        vst1q_f32(outptr, _outp);
        ptr += 4;
        ptr1 += 4;
        outptr += 4;
    }
#endif // __ARM_NEON
    for (; i < size; i++)
    {
        *outptr = op(*ptr, *ptr1);
        ptr += 1;
        ptr1 += 1;
        outptr += 1;
    }
}
2.2、eltwise

elwise 主要用于两个Mat类型的数据逐元素之间的操作。在eltwise.h 中定义了三种三种计算方式

enum OperationType
{
    Operation_PROD = 0,
    Operation_SUM = 1,
    Operation_MAX = 2
};

eltwise_arm.h 继承于 eltwise.h,在eltwise_arm.cpp中实现了三种操作在arm上的实现方式。

int Eltwise_arm::forward(const std::vector<Mat>& bottom_blobs, std::vector<Mat>& top_blobs, const Option& opt) const
{
    // first blob
    const Mat& bottom_blob = bottom_blobs[0];  
    int w = bottom_blob.w;
    int h = bottom_blob.h;
    int d = bottom_blob.d;
    int channels = bottom_blob.c;
    int elempack = bottom_blob.elempack;
    int size = w * h * d * elempack;
    // 逐元素相乘
    if (op_type == Operation_PROD)
    { 
		// second blob
        const Mat& bottom_blob1 = bottom_blobs[1];    // out = bottom_blobs[0] .* bottom_blobs[1];
        for (int q = 0; q < channels; q++){  // 每个channel计算
            const float* ptr = bottom_blob.channel(q); // 0
            const float* ptr1 = bottom_blob1.channel(q); // 1
            float* outptr = top_blob.channel(q);   // 0
            // 计算8的整数倍的数据
            for (; i + 7 < size; i += 8){}
            // 计算4的整数倍的数据
            for (; i + 3 < size; i += 4){}
        }   
        
        // out  = out .* bottom_blobs[i]
        for (size_t b = 2; b < bottom_blobs.size(); b++){
            
        }

    }
    
    // 逐元素相加
    if (op_type == Operation_SUM)
    {
        
    }
    
    // 逐元素计算最大值
    if (op_type == Operation_SUM)
    {
        
    }

}
3、总结

本次学习了NCNN中的binaryop、eltwise操作,学会了两个向量之间的操作还能用模板实现,省去了不少的代码量。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
realesrgan-ncnn-vulkan-20211212-windows是一个基于ncnn框架和Vulkan图形API开发的图像超分辨率增强模型。它是由GitHub用户realsrgan开发的最新版本,最新发布日期为2021年12月12日,专为Windows操作系统而设计。 该模型的主要应用是图像超分辨率增强,通过提高图像的分辨率和细节,使图像看起来更加清晰和真实。它采用深度学习和卷积神经网络等先进的技术,能够将低分辨率的图像转换成高分辨率的图像,从而提升图像的质量和视觉效果。 realesrgan-ncnn-vulkan-20211212-windows的开发使用了ncnn框架和Vulkan图形API,这使得它能够在Windows系统上实现快速且高效的图像处理。ncnn是一个轻量级的深度学习框架,专注于在移动平台和嵌入式设备上实现高性能和低延迟的推理。而Vulkan图形API是一种跨平台的图形渲染和计算API,可以充分利用计算设备的性能,提供高效的图像处理和渲染能力。 realesrgan-ncnn-vulkan-20211212-windows的使用可以通过命令行或者图形界面进行,用户可以根据自己的需求和偏好选择适合的方式。该模型提供了训练好的权重参数,用户可以直接加载这些参数并进行图像超分辨率增强。此外,该模型还支持批量处理和视频处理,方便用户对多个图像进行处理。 总之,realesrgan-ncnn-vulkan-20211212-windows是一个高效、快速且易于使用的图像超分辨率增强模型,适用于Windows系统,并利用了ncnn框架和Vulkan图形API的优势,为用户提供了出色的图像处理效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Rex久居

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

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

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

打赏作者

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

抵扣说明:

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

余额充值