Algorithms, Blockchain and Cloud

How to Async and Await in C++11?


In C#, there is async and await that allows you to write asynchronous code easily e.g. doing some calculations while fetching some data from I/O. Asynchronous code improves the responsiveness and is considered an handy way to write multithreading application.

async_all_the_things-1 How to Async and Await in C++11? c / c++ multithreading

async_all_the_things

In C++ 11, writing the asynchronous code becomes straightforward. See below the example that sums a ‘large’ array by recursively dividing into two halves (two threads).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// parallel_sum.cpp
// https://helloacm.com/how-to-async-and-await-in-c11/
#include <iostream>
#include <vector>
#include <future>
 
// for use of std::accumulate
#if _MSC_VER 
#include <numeric>  // in Visual Studio
#else
#include <algorithm>  // g++ -std=c++14 -pthread parallel_sum.cpp
#endif
 
using namespace std;
 
// generic
template <typename TYPE>
int parallel_sum(TYPE beg, TYPE end) {
    // block size
    auto len = end - beg;
    if (len < 500) {
        // if block is small enough, it is faster to just sum them up.
        return std::accumulate(beg, end, 0);
    }
    // (beg + end) / 2 may overflow
    auto mid = beg + len / 2;
    // sum the left part asynchronously 
    auto handle_left = std::async(launch::async, parallel_sum<TYPE>, beg, mid);
    // sum the right part asynchronously 
    auto handle_right = std::async(launch::async, parallel_sum<TYPE>, mid, end);
    // put them together
    return handle_left.get() + handle_right.get();
}
 
int main() {
    vector<int> v(10000, 1);
    cout << "Sum: " << parallel_sum(v.begin(), v.end()) << endl;
}
// parallel_sum.cpp
// https://helloacm.com/how-to-async-and-await-in-c11/
#include <iostream>
#include <vector>
#include <future>

// for use of std::accumulate
#if _MSC_VER 
#include <numeric>  // in Visual Studio
#else
#include <algorithm>  // g++ -std=c++14 -pthread parallel_sum.cpp
#endif

using namespace std;

// generic
template <typename TYPE>
int parallel_sum(TYPE beg, TYPE end) {
	// block size
	auto len = end - beg;
	if (len < 500) {
		// if block is small enough, it is faster to just sum them up.
		return std::accumulate(beg, end, 0);
	}
	// (beg + end) / 2 may overflow
	auto mid = beg + len / 2;
	// sum the left part asynchronously 
	auto handle_left = std::async(launch::async, parallel_sum<TYPE>, beg, mid);
	// sum the right part asynchronously 
	auto handle_right = std::async(launch::async, parallel_sum<TYPE>, mid, end);
	// put them together
	return handle_left.get() + handle_right.get();
}

int main() {
	vector<int> v(10000, 1);
	cout << "Sum: " << parallel_sum(v.begin(), v.end()) << endl;
}

In order to compile it in Linux using gcc compiler, you need to include the support of pthread and use the syntax of C++11, i.e.

1
g++ -std=c++14 -pthread parallel_sum.cpp
g++ -std=c++14 -pthread parallel_sum.cpp

The .get() method is the ‘await’ operation but you obviously don’t need the ‘async’ keyword. When the partition size is small enough, it is generally considered more efficient to sum the elements locally using a for loop (CPU benefits from the local cache lines e.g. more cache hits) or in this case the std::accumulate.

The keyword launch::async specifies that a new thread must be created to invoke the function. The std::async then takes the function name and its parameters (variable length of parameters).

Multithreading code is a great hint for the OS to utilize all resources e.g. cores.

–EOF (The Ultimate Computing & Technology Blog) —

518 words
Last Post: Multi-Processes Experiments - When Can Windows Utilize All the Cores?
Next Post: How to Make Ping Tests to Global Servers using PHP?

The Permanent URL is: How to Async and Await in C++11? (AMP Version)

Exit mobile version