本文转载请注明出处 —— polobymulberry-博客园

0x00 - 前言


最近想优化ORB-SLAM2,准备使用并行计算来提高其中ORB特征提取的速度。之前对并行计算方面一窍不通。借此机会,学习一下基本的并行编程。

在选择并行编程的工具时,需要考虑以下问题:即该工具尽量不要使用与平台相关的API,如iOS端的GCD(Grand Central Dispatch),因为希望程序具有很强的移植性。一开始我想到的只有两种选择,一个是以TBB和OpenMP为首的第三方线程库,另一个是原生线程库。其中TBB和OpenMP对于Xcode的支持不是很好,原生线程库又依赖于系统平台,所以尝试后都放弃了。后来想到C++11已经从语言层面支持了多线程开发,也就是提供了thread库,于是抱着试一试学一学的态度就入坑了。

并行计算中一个很经典的案例就是数组求和,网络上有很多介绍C++11的thread使用、源码分析的文章,不过使用C++11进行数组求和并行计算的示例却很少,所以才有了这篇博文。

0x01 - 代码解析


在iOS系统使用C++11进行开发。

//
// ViewController.m
// TestDispatch
//
// Created by poloby on 2017/1/7.
// Copyright © 2017年 polobymulberry. All rights reserved.
// #import "ViewController.h"
#include <iostream>
#include <thread> using namespace std; // 作为求和函数的参数
// 封装了求和函数的输入和输出
typedef struct ThreadArg {
long long base; // 从base~base+length数列求和
long long length;
long long sum; // 将上述数列的和存储在sum中
}ThreadArg; void sum(ThreadArg *arg)
{
long long begin = arg->base;
long long end = arg->base + arg->length;
long long sum = 0;
// 不要直接使用for(long long i = arg->base; i < arg->base + arg->length)
// 也不要使用arg->sum += i;
// 因为指针的读取比普通栈的读取需要多花费一些时间
for (long long i = begin; i < end; ++i) {
sum += i;
}
arg->sum = sum;
} @interface ViewController () @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; // 计算1~count数列之和
const long long count = 1000000000; // 单线程常用方法
NSDate *commonMethodDate = [NSDate date];
long long commonMethodSum = 0;
for (long long i = 0; i < count; ++i) {
commonMethodSum += i;
}
// 计算单线程使用时间
double commonMethodDuration = [[NSDate date] timeIntervalSinceDate:commonMethodDate]; NSLog(@"Common method spend time = %fms, sum = %lld", commonMethodDuration * 1000, commonMethodSum); // 并行计算方法
// 将1~count数列平均分为threadCount组,求解每组数列之和,再将其相加得到总和
NSDate *parallelMethodDate = [NSDate date];
// 设置并行线程数目
const int threadCount = 2;
thread threads[threadCount];
ThreadArg args[threadCount];
// 初始化线程及其参数
for (int i = 0; i < threadCount; ++i) {
long long offset = (count / threadCount) * i;
args[i].base = offset;
args[i].length = MIN(count - offset, count / threadCount);
threads[i] = thread(sum, &args[i]);
} // 启动线程并等待线程退出
for (int i = 0; i < threadCount; ++i) {
threads[i].join();
} long long parallelMethodSum = 0;
// 将每组数列之和相加得到总和
for (int i = 0; i < threadCount; ++i) {
parallelMethodSum += args[i].sum;
} // 计算多线程使用时间
double parallelMethodDuration = [[NSDate date] timeIntervalSinceDate:parallelMethodDate]; NSLog(@"Parallel method spend time = %fms, sum = %lld", parallelMethodDuration * 1000, parallelMethodSum);
} @end

0x02 - 结果分析


Xcode8.2.1+iPhone7模拟器+1~1000000000数列之和:

线程数目 2 4 8
多线程耗时 1921.253026ms 981.853008ms 684.603035ms
单线程耗时 3171.698034ms 3472.517014ms 3447.206974ms

Xcode8.2.1+iPhone7模拟器+1~10000数列之和:

线程数目 2 4 8
多线程耗时 0.279963ms 0.212014ms 0.297010ms
单线程耗时 0.038981ms 0.027955ms 0.032008ms

可见多线程本身也需要消耗一定的资源,所以只有在系统规模较大的情况下才能取得显著的性能提升。

0x03 - 注意事项


1. thread调用类的成员函数:

thread memberFuncThread(&ClassName::MemberFuncName, this, arg1, arg2...);

2. thread传递引用参数:

需要使用std::ref进行包装,详见thread - 传递引用参数

【原】C++11并行计算 — 数组求和的更多相关文章

  1. Java并发和多线程2:3种方式实现数组求和

    本篇演示3个数组求和的例子. 例子1:单线程例子2:多线程,同步求和(如果没有计算完成,会阻塞)例子3:多线程,异步求和(先累加已经完成的计算结果) 例子1-代码 package cn.fansuni ...

  2. JavaScript 系列--JavaScript一些奇淫技巧的实现方法(三)数字取整,数组求和

    一.前言 简短的sleep函数,获取时间戳:https://www.mwcxs.top/page/746.html 数字格式化 1234567890 --> 1,234,567,890:argr ...

  3. js数组去重 数组拼接 替换数组中的指定值 递归数组 判断数组中是否存在指定值 数组求和 根据条件判数组值

    这是学习过程中记录的一些关于数组操作的常用属性或方法,记录一下方便以后使用. // 数组去重 var arr1 = [1,1,2,3,4,5,6,3,2,4,5,'a','b','c','a',6,7 ...

  4. C# 使用SIMD向量类型加速浮点数组求和运算(1):使用Vector4、Vector<T>

    作者: 目录 一.缘由 二.使用向量类型 2.1 基本算法 2.2 使用大小固定的向量(如 Vector4) 2.2.1 介绍 2.2.2 用Vector4编写浮点数组求和函数 2.3 使用大小与硬件 ...

  5. js数组求和

    array1.reduce(callbackfn[, initialValue]) callback : 函数执行在数组中每个值 initialValue : 对象作为第一个参数回调的第一次调用使用 ...

  6. 《Intel汇编第5版》 数组求和

    一.LOOP指令 二.间接寻址 三.汇编数组求和 INCLUDE Irvine32.inc includelib Irvine32.lib includelib kernel32.lib includ ...

  7. Javascript数组求和的方法总结 以及由斐波那契数列得到的启发

    一次面试中,面试官要求用三种不同的Javascript方法进行一个数字数组的求和,当时思来想去只想到了使用循环这一种笨方法,因此面试比较失败,在这里总结了六种Javascript进行数组求和的方法,以 ...

  8. [java大数据面试] 2018年4月百度面试经过+三面算法题:给定一个数组,求和为定值的所有组合.

    给定一个数组,求和为定值的所有组合, 这道算法题在leetcode应该算是中等偏下难度, 对三到五年工作经验主要做业务开发的同学来说, 一般较难的也就是这种程度了. 简述经过: 不算hr面,总计四面, ...

  9. 个人项目-数组求和(语言:C++)

    prog1详细要求: [第一版本程序Prog1要求:] + 给定一个数组,实现数组元素求和:,具体要求:实现对一维数组(a[100])的所有元素相加运算. + 数据准备:a)数组长度:100:b)数组 ...

随机推荐

  1. hdu 6058 Kanade's sum(模拟链表)

    Kanade's sum Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  2. springboot jpa 批量保存数据--EntityManager和 JpaRepository

    1: 项目里面使用springboo-boot-start-data-jpa操作数据库,通过源码,在repository上继承JpaRepository 可以实现保存操作,其中源码接口为: <S ...

  3. qml 知识积累

    本文仅仅只是记录,怕日后遗忘. ListView相关应用 https://www.cnblogs.com/SaveDictator/p/8192391.html ListView 清空操作 https ...

  4. UITextField 限制用户输入小数点后位数的方法

    UITextField 限制用户输入小数点后位数的方法 位数限制: limited 在UITextField的代理方法中添加类似如下代码 - (BOOL)textField:(UITextField ...

  5. LeetCode之Regular Expression Matching

    [题目描述] Implement regular expression matching with support for '.' and '*'. '.' Matches any single ch ...

  6. New Concept English there (1)Typing speed exercise

    Today,I start learn new concept english there,Mainly for listening practice and typing speed exercis ...

  7. Shell 命令行统计 apache 网站日志访问IP以及IP归属地

    Shell 命令行统计 apache 网站日志访问IP以及IP归属地 我的一个站点用 apache 服务跑着,积攒了很多的日志.我想用 shell 看看有哪些人访问过我的站点,并且他来自哪里. 因为日 ...

  8. Android gradle 安装成功,但是报虚拟机过大的错误处理方法

    一.这个是项目中遇到的问题,记下来,以后再出现方便查看. 1.首先看图吧. 虚拟机内容过大 解决办法: 在.gradle目录下更改配置文件gradle.properjties 里面的 将标记的改成51 ...

  9. 在ROS Kinetic和Gazebo 8中使用智能汽车仿真演示

    在ROS Kinetic和Gazebo 8中使用智能汽车仿真演示 智能车无人驾驶技术是目前人工智能和机器人技术的研究热点,有许多开源平台可以使我们零基础零成本入门无人驾驶技术.本文分享一下目前ROS官 ...

  10. Leetcode 814. Binary Tree Pruning

    dfs 要点是这一句: return node.val==1 or node.left or node.right 完整代码: # Definition for a binary tree node. ...