C/C++知识点之修改ncnn的openmp异步处理方法 附C++样例代码
小标 2019-01-10 来源 : 阅读 2257 评论 0

摘要:本文主要向大家介绍了 C/C++知识点之修改ncnn的openmp异步处理方法 附C++样例代码,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

本文主要向大家介绍了 C/C++知识点之修改ncnn的openmp异步处理方法 附C++样例代码,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

C/C++知识点之修改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 
#include    
#include 

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

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

#include 

#if defined(_OPENMP)
#    include 
#else 
#include 

#include 
#endif

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

static void ParallelFor(int inclusiveFrom, int exclusiveTo, std::function 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;

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

    if (entry_per_thread < 1)
    {
        for (int i = inclusiveFrom; i < exclusiveTo; ++i)
        {
            func(i);
        }
        return;
    }
    std::vector 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] = 4 * b[i];
}

int main()
{
    int N = 10000;
    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);
        }
        return -1;
    }
    for (int i = 0; i < N; i++)
    {
        a1[i] = i;
        a2[i] = i;
        b[i] = i;
    }
    double beforeTime = bench([&] {
        for (int i = 0; i < N; i++)
        {
            test_scale(i, a1, b);
        }
    });

    std::cout << " \nbefore: " << int(beforeTime * 1000) << "ms" << std::endl;
    double afterTime = bench([&] {
        ParallelFor(0, N, [a2, b](size_t i)
        {
            test_scale(i, a2, b);
        });
    });
    std::cout << " \nafter: " << int(afterTime * 1000) << "ms" << std::endl;

    for (int i = 0; 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();
    return 0;
}

要使用OPENMP,加个编译选项/openmp  或者定义一下 _OPENMP 即可。
建议c++11编译。
示例代码比较简单。
ncnn代码修改例子如下:

   #pragma omp parallel for
        for (int q=0; 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(0, channels, [&](int  q) {
                {
                    const Mat m = src.channel(q);
                    Mat borderm = dst.channel(q);

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

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程