Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference in C++11 async behaviour on Mac and Linux

Consider the following C+11 code:

#include <chrono>
#include <future>
#include <iostream>
#include <thread>

using namespace std;

int main() {
    auto start = chrono::steady_clock::now();
    auto elapsed = [start](string s) {
        cout << s << (chrono::steady_clock::now() - start).count() << endl;
    };

    elapsed("A ");
    auto fut (async([]() { this_thread::sleep_for(chrono::seconds(2)); }));
    elapsed("B ");
    this_thread::sleep_for(chrono::seconds(1));
    elapsed("C ");
    fut.wait();
    elapsed("D ");
    return 0;
}

Mac Results

Compiling said code on macOS Sierra with the command c++ -std=c++11 -stdlib=libc++ -Wall question.cc -o question and running, I get the output:

A 27186
B 86970
C 1001961755
D 2001585903

which is expected. It took minimal time to get to A and B, waited 1 second and then got to C, and waiting the remaining of the 2 seconds (1 already elapsed) to get to D.

The Mac compiler is:

$ c++ --version
Apple LLVM version 8.0.0 (clang-800.0.38)
Target: x86_64-apple-darwin16.0.0
Thread model: posix

Linux Results

On Linux, I compiled the same code with c++ -std=c++11 -pthread question.cc -o question and ran, and got the result:

A 32423
B 444340
C 1003635793
D 3006121895

The Linux compiler is:

$ c++ --version
c++ (Debian 4.9.2-10) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.

I also tried clang++ on Linux, the LLVM C++ compiler. Same result.

Q

Why is there the fully 2 second lag between C and D on Linux? Wasn't the async task supposed to run in the background? Am I using the wrong compile options?

like image 290
rityzmon Avatar asked Oct 21 '16 14:10

rityzmon


Video Answer


1 Answers

async takes as an optional parameter if you want to start it in a different thread, or just wait until the .wait is called to run the code.

You chose "I do not care" by omitting it.

If you care, state you want it in a different thread. If not, you should not be surprised if they waited until you .waited to run it, or alternatively started a new thread and ran it there. In your case, one compiler made it lazy, the other put it in its own thread. Both are permitted by the standard.

To get the behavior you expect, pass std::launch::async as the first argument to std::async.


Now, in theory async without being told how to run it is supposed to do something smart. But some compilers punted and said "always doing it lazy is less work for us" (or always async), so did always-lazy whenever you let it.

This is a quality of implementation issue. At this point, you cannot trust async to be smart on all C++11 compilers you are working with. Come back in a decade.

like image 112
Yakk - Adam Nevraumont Avatar answered Oct 12 '22 23:10

Yakk - Adam Nevraumont