ncnn刚发布不久,博主在ios下尝试编译。

遇上了openmp的编译问题。

寻找各种解决方案无果,亲自操刀。

采用std::thread 替换 openmp。

ncnn项目地址:

https://github.com/Tencent/ncnn

后来询问ncnn的作者才知道在ios下的编译方法。

至此,当时的临时方案 采用std::thread 替换 openmp。

想想也许在一些特定情况下还是比较适用的,当前方便两者之间进行切换验证。

抽空写了一个示例项目。

项目地址:

https://github.com/cpuimage/ParallelFor

贴上完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#if defined(_OPENMP)
// compile with: /openmp
#include <omp.h>
auto const epoch = omp_get_wtime();
double now() {
    return omp_get_wtime() - epoch;
};
#else
#include <chrono>
auto const epoch = std::chrono::steady_clock::now();
double now() {
    return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - epoch).count() / 1000.0;
};
#endif

template<typename FN>
double bench(const FN &fn) {
    auto took = -now();
    return (fn(), took + now());
}

#include <functional>

#if defined(_OPENMP)
#    include <omp.h>
#else
#include <thread>

#include <vector>
#endif

#ifdef _OPENMP
static int processorCount = static_cast<int>(omp_get_num_procs());
#else
static int processorCount = static_cast<int>(std::thread::hardware_concurrency());
#endif

static void ParallelFor(int inclusiveFrom, int exclusiveTo, std::function<void(size_t)> func)
{
#if defined(_OPENMP)
#pragma omp parallel for num_threads(processorCount)
    for (int i = inclusiveFrom; i < exclusiveTo; ++i)
    {
        func(i);
    }
    return;
#else
    if (inclusiveFrom >= exclusiveTo)
        return;

    ;
    )
    {
        thread_cnt = std::thread::hardware_concurrency();
    }
    size_t entry_per_thread = (exclusiveTo - inclusiveFrom) / thread_cnt;

    )
    {
        for (int i = inclusiveFrom; i < exclusiveTo; ++i)
        {
            func(i);
        }
        return;
    }
    std::vector<std::thread> threads;
    int start_idx, end_idx;

    for (start_idx = inclusiveFrom; start_idx < exclusiveTo; start_idx += entry_per_thread)
    {
        end_idx = start_idx + entry_per_thread;
        if (end_idx > exclusiveTo)
            end_idx = exclusiveTo;

        threads.emplace_back([&](size_t from, size_t to)
        {
            for (size_t entry_idx = from; entry_idx < to; ++entry_idx)
                func(entry_idx);
        }, start_idx, end_idx);
    }

    for (auto& t : threads)
    {
        t.join();
    }
#endif
}

void test_scale(int i, double* a, double* b) {
    a[i] =  * b[i];
}

int main()
{
    ;
    double* a2 = (double*)calloc(N, sizeof(double));
    double* a1 = (double*)calloc(N, sizeof(double));
    double* b = (double*)calloc(N, sizeof(double));
    if (a1 == NULL || a2 == NULL || b == NULL)
    {
        if (a1)
        {
            free(a1);
        }if (a2)
        {
            free(a2);
        }if (b)
        {
            free(b);
        }
        ;
    }
    ; i < N; i++)
    {
        a1[i] = i;
        a2[i] = i;
        b[i] = i;
    }
    double beforeTime = bench([&] {
        ; i < N; i++)
        {
            test_scale(i, a1, b);
        }
    });

    std::cout << ) << "ms" << std::endl;
    double afterTime = bench([&] {
        ParallelFor(, N, [a2, b](size_t i)
        {
            test_scale(i, a2, b);
        });
    });
    std::cout << ) << "ms" << std::endl;

    ; i < N; i++)
    {
        if (a1[i] != a2[i]) {
            printf("error %f : %f \t", a1[i], a2[i]);
            getchar();
        }
    }
    free(a1);
    free(a2);
    free(b);
    getchar();
    ;
}

要使用OPENMP,加个编译选项/openmp  或者定义一下 _OPENMP 即可。

建议c++11编译。

示例代码比较简单。

ncnn代码修改例子如下:

   #pragma omp parallel for
        ; q<channels; q++)
        {
            const Mat m = src.channel(q);
            Mat borderm = dst.channel(q);

            copy_make_border_image(m, borderm, top, left, type, v);
        }

 改为

    ParallelFor(, channels, [&](int  q) {
                {
                    const Mat m = src.channel(q);
                    Mat borderm = dst.channel(q);

                    copy_make_border_image(m, borderm, top, left, type, v);
                }});

本来计划抽点时间把ncnn整体都改一下,发个修改版本出来。

想想还是把做法贴出来,给有需求的人吧。

自己动手丰衣足食。

若有其他相关问题或者需求也可以邮件联系俺探讨。

邮箱地址是: 
gaozhihan@vip.qq.com

修改ncnn的openmp异步处理方法 附C++样例代码的更多相关文章

  1. vc弹出USB的方法. 附试验通过的代码!

    vc弹出USB的方法. 附试验通过的代码! http://blog.sina.com.cn/s/blog_4fcd1ea30100qrzn.html (2011-04-15 10:09:48) boo ...

  2. Java 序列化Serializable具体解释(附具体样例)

    Java 序列化Serializable具体解释(附具体样例) 1.什么是序列化和反序列化 Serialization(序列化)是一种将对象以一连串的字节描写叙述的过程:反序列化deserializa ...

  3. Java向上转型和向下转型(附具体样例)

                                                Java向上转型和向下转型(附具体样例) 熬夜整理的关于Java向上和向下转型的样例,很的通俗易懂哦~~~~ 一 ...

  4. 10分钟理解Android数据库的创建与使用(附具体解释和演示样例代码)

    1.Android数据库简单介绍. Android系统的framework层集成了Sqlite3数据库.我们知道Sqlite3是一种轻量级的高效存储的数据库. Sqlite数据库具有以下长处: (1) ...

  5. boost写的异步客户端样例代码修改为支持断开重连的代码

    考虑到boost的工业级强度,因此就直接用了,代码的官方示例地址:https://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/examples/ ...

  6. MySQL——修改root密码的4种方法(以windows为例)

    方法1: 用SET PASSWORD命令 首先登录MySQL. 格式:mysql> set password for 用户名@localhost = password('新密码'); 例子:my ...

  7. [MySQL]修改root密码的4种方法(以windows为例)

    方法1: 用SET PASSWORD命令 首先登录MySQL. 格式:mysql> set password for 用户名@localhost = password('新密码'); 例子:my ...

  8. Swift - 继承UIView实现自定义可视化组件(附记分牌样例)

    在iOS开发中,如果创建一个自定义的组件通常可以通过继承UIView来实现.下面以一个记分牌组件为例,演示了组件的创建和使用,以及枚举.协议等相关知识的学习. 效果图如下:    组件代码:Score ...

  9. ListView中pointToPosition()方法使用具体演示样例

    MainActivity例如以下: package cc.testpointtoposition; import java.util.ArrayList; import java.util.HashM ...

随机推荐

  1. Head First设计模式之目录

    只有沉淀.积累,才能远航:沉沉浮浮,脚踏实地. 这本书已经闲置了好久,心血来潮,决定写个目录,让自己坚持看完这本书 创建型模式 抽象工厂模式(Abstract factory pattern): 提供 ...

  2. 谨慎修改Python的类属性

    Python的类和类实例都是可变对象,可以随时给属性赋值,并且在原处修改. 在对类属性进行修改时需要特别小心,因为所有的类实例都继承共享类属性,除非实例本身存在和类属性同名的属性.对类属性进行修改,会 ...

  3. [js高手之路]html5 canvas动画教程 - 跟着鼠标移动消失的一堆炫彩小球

    综合利用前面所学,实现一个绚丽的小球动画,这个实例用到的知识点,在我的博客全部都有,可以去这里查看所有的canvas教程 <head> <meta charset='utf-8' / ...

  4. BASIC-2 01字串

      基础练习 01字串   时间限制:1.0s   内存限制:256.0MB        问题描述 对于长度为5位的一个01串,每一位都可能是0或1,一共有32种可能.它们的前几个是: 00000 ...

  5. 从0到1搭建spark集群---企业集群搭建

    今天分享一篇从0到1搭建Spark集群的步骤,企业中大家亦可以参照次集群搭建自己的Spark集群. 一.下载Spark安装包 可以从官网下载,本集群选择的版本是spark-1.6.0-bin-hado ...

  6. Sequelize 基本操作

    Sequelize 是 Node 的一个 ORM(Object-Relational Mapping) 框架,用来方便数据库操作. 配置 sequelize 以 mysql 为例 首先我们要引入npm ...

  7. 第四章:Python基础の快速认识內置函数和操作实战

    本課主題 內置函数介紹和操作实战 装饰器介紹和操作实战 本周作业 內置函数介紹和操作实战 返回Boolean值的內置函数 all( ): 接受一個可以被迭代的對象,如果函数裡所有為真,才會真:有一個是 ...

  8. 前端学习:html基础学习一

    1.HTML的语法(主要内容HTML语法格式.文档注释.代码格式) HTML的特点 1.可以设置文本的格式,比如标题.字号.文本颜色.段落等等 2.可以创建列表(例如打开百度,我们可以看到这样的列表) ...

  9. Python 集合 深浅copy

    一,集合. 集合是无序的,不重复的数据集合,它里面的元素是可哈希的(不可变类型),但是集合本身是不可哈希(所以集合做不了字典的键)的.以下是集合最重要的两点: 去重,把一个列表变成集合,就自动去重了. ...

  10. 10、ABPZero系列教程之拼多多卖家工具 拼团提醒逻辑功能实现

    上篇文章已经封装好了类库,现在继续实现功能,在ABPZero框架的基础上来实现一个完整的功能. Redis缓存 编写功能前先在本机安装好Redis,需要用到Redis做缓存,以下分享2个Windows ...