修改ncnn的openmp异步处理方法 附C++样例代码
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++样例代码的更多相关文章
- vc弹出USB的方法. 附试验通过的代码!
vc弹出USB的方法. 附试验通过的代码! http://blog.sina.com.cn/s/blog_4fcd1ea30100qrzn.html (2011-04-15 10:09:48) boo ...
- Java 序列化Serializable具体解释(附具体样例)
Java 序列化Serializable具体解释(附具体样例) 1.什么是序列化和反序列化 Serialization(序列化)是一种将对象以一连串的字节描写叙述的过程:反序列化deserializa ...
- Java向上转型和向下转型(附具体样例)
Java向上转型和向下转型(附具体样例) 熬夜整理的关于Java向上和向下转型的样例,很的通俗易懂哦~~~~ 一 ...
- 10分钟理解Android数据库的创建与使用(附具体解释和演示样例代码)
1.Android数据库简单介绍. Android系统的framework层集成了Sqlite3数据库.我们知道Sqlite3是一种轻量级的高效存储的数据库. Sqlite数据库具有以下长处: (1) ...
- boost写的异步客户端样例代码修改为支持断开重连的代码
考虑到boost的工业级强度,因此就直接用了,代码的官方示例地址:https://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/examples/ ...
- MySQL——修改root密码的4种方法(以windows为例)
方法1: 用SET PASSWORD命令 首先登录MySQL. 格式:mysql> set password for 用户名@localhost = password('新密码'); 例子:my ...
- [MySQL]修改root密码的4种方法(以windows为例)
方法1: 用SET PASSWORD命令 首先登录MySQL. 格式:mysql> set password for 用户名@localhost = password('新密码'); 例子:my ...
- Swift - 继承UIView实现自定义可视化组件(附记分牌样例)
在iOS开发中,如果创建一个自定义的组件通常可以通过继承UIView来实现.下面以一个记分牌组件为例,演示了组件的创建和使用,以及枚举.协议等相关知识的学习. 效果图如下: 组件代码:Score ...
- ListView中pointToPosition()方法使用具体演示样例
MainActivity例如以下: package cc.testpointtoposition; import java.util.ArrayList; import java.util.HashM ...
随机推荐
- python的range()函数
range函数的三种用法:>>> range(1,5) # 代表从1到5(不包含5) [1, 2, 3, 4] >>> range(1,5,2) # 代表从1到5, ...
- js小知识-replace的回调函数
replace() 方法返回一个由替换值替换一些或所有匹配的模式后的新字符串.模式可以是一个字符串或者一个正则表达式, 替换值可以是一个字符串或者一个每次匹配都要调用的函数. 注意:原字符串不会改变. ...
- scala的Option
当一个函数既要返回对象,又要返回null的时候,使用Option[] http://www.runoob.com/scala/scala-options.html Option是scala的选项,用来 ...
- dubbo filter链构建过程
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException { if (Consta ...
- 深入理解cookie和session
cookie和session在java web开发中扮演了十分重要的作用,本篇文章对其中的重要知识点做一些探究和总结. 1.cookie存在于浏览器 随意打开一个网址,用火狐的调试工具,随意选取一个链 ...
- Linux 监测命令
1. ps -ef -e显示所有进程:-f 显示完整格式的输出: 2. ps -l -l 显示一个长列表 3. ps -efH -H 用层级格式显示进程(树状) [ps 命令:显示某个特定 ...
- 【STL深入理解】vector
这篇文章不打算讲述vector的基本用法,而是总结一下近期我大量阅读C++经典书籍时遇到的一些关于vector的容易忽略的知识点,特意将它们记录下来,以便以后查阅. 1.v[0]和v.at(0)的区别 ...
- Nginx常用功能(5)
一.反向代理 1.多域名跳转(location) server www.test.com location / { proxy_pass http://192.168.100.100:8080/web ...
- Vue入门
一.引入vue 方法一:下载vue.js,然后像引用jquery一样,在HTML中使用script标签引入 <script src="https://unpkg.com/vue/dis ...
- [hdu5632][BC#73 1002]Rikka with Array
点开BC发现今晚没比赛..然后似乎上一场有数位DP?...(幸好我没去 一开始被BCDcode那题的思路带歪了..后来发现得把n转成二进制才能搞TAT 题目大概是要求一种类似逆序对的鬼东西: 有一个长 ...