修改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 多进程开发与多线程开发
转自: http://tchuairen.blog.51cto.com/3848118/1720965 博文作者参考的博文: 博文1 博文2 我们先来了解什么是进程? 程序并不能单独运行,只有将程 ...
- 微信小程序开发之详解生命周期方法
生命周期是指一个小程序从创建到销毁的一系列过程 在小程序中 ,通过App()来注册一个小程序 ,通过Page()来注册一个页面 先来看一张小程序项目结构 从上图可以看出,根目录下面有包含了app.js ...
- ASP.NET Core 一步步搭建个人网站(5)_Api模拟和网站分析
前言 经过前面几章,我们的网站已经最基本的功能,接下来就是继续拓展其他的功能,这期一起来实现一个该网站流量分析的工具,统计出这个网站每天用户相关数据,不仅要满足了我们对流量统计数字的基本要求,并且用更 ...
- 我的Python学习笔记(一):==和is
Python中对象包含的三个基本要素:id(身份标识),type(数据类型),value(值) ==是用来比较两个对象的value(值)是否相等, is是用来比较两个对象的id(身份标识)是否相等 = ...
- 用 Identity Server 4 (JWKS 端点和 RS256 算法) 来保护 Python web api
目前正在使用asp.net core 2.0 (主要是web api)做一个项目, 其中一部分功能需要使用js客户端调用python的pandas, 所以需要建立一个python 的 rest api ...
- 编写OC高质量的代码的有效方法
1. 写这个只是为了自己记忆,有相关pdf文件,如需要留下邮箱.. 2. 在类的头文件中尽量少引入其他头文件 除非确有必要,否则不要引入头文件.一般来说,应在某个类的头文件中使用向前声明来提及别的类( ...
- 阿里云服务器Tomcat无法从外部访问
一.环境 阿里云 Ubuntu 12.04.5 LTS tomcat和java都是阿里云默认的7的版本,如下图 二.问题 部署后./startup.sh启动tomcat 之后外部访问http://ip ...
- jetty和tomcat的区别
jetty:是一个开源的servlet容器,基于java的web容器,例如给jsp和servlet提供运行环境,jetty是使用java编写的,他的api是一组以jar包的形式发布,开发人员可以将je ...
- ionic滑动框 ---轮播图(ion-slide-box) 的使用
1. html : <ion-slide-box auto-play="true" slide-interval=3000 show-pager="false&qu ...
- js压缩文件读取处理
1.引入必须依赖库jszip+jsutils=>>>建议使用以下版本,其他版本的jszip会报错 <!--zip文件读取--> <script src=" ...