Suppose the following code:
#include <thread>
#include <iostream>
#include <vector>
#include <future>
#include <chrono>
#include <cmath>
long long int partialSum(const std::vector<int>& v, int begin, int end) {
long long int sum = 0;
for (int i = begin; i < end; i++) {
sum += (v[i]);
}
return sum;
}
int main() {
std::vector<int> v(10000000, 1);
//2 threads
auto start = std::chrono::high_resolution_clock::now();
std::future<long long int> f1 = std::async(std::launch::async, partialSum, v, 0, 10000000 /2);
std::future<long long int> f2 = std::async(std::launch::async, partialSum, v, 10000000 / 2, 10000000);
volatile long long int a = f1.get() + f2.get();
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono:: duration_cast<std::chrono::microseconds>(end - start);
std::cout << "With 2 threads-> " << duration.count() << std::endl;
//1 thread
start = std::chrono::high_resolution_clock::now();
volatile long long int b = partialSum(v, 0, 10000000);
end = std::chrono::high_resolution_clock::now();
duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << "With 1 thread-> " << duration.count() << std::endl;
}
And the output for my machine (VS2019):
With 2 threads-> 35477
With 1 thread-> 7000
Note that I had to add volatile to avoid more optimization being performed by the compiler.
Also note that I know that there is an accumulate in the std, but I'm currently learning about multithreading and this was a POC.
Basically, I want to know which kind of optimization the compiler is doing here, because it's optimizing it really well compared to the threaded version.
When I change partialSum and replace the operation (maybe log10), then the threaded version is twice as better as the regular one.
Edit: After some suggestions, I changed the code to the following one:
#include <thread>
#include <iostream>
#include <vector>
#include <future>
#include <chrono>
#include <cmath>
long long int partialSum(const std::vector<int>& v, int begin, int end) {
long long int sum = 0;
for (int i = begin; i < end; i++) {
sum += (v[i]);
}
return sum;
}
int main() {
std::vector<int> v(10000000, 1);
//2 threads
auto start = std::chrono::high_resolution_clock::now();
std::future<long long int> f1 = std::async(std::launch::async, partialSum, std::cref(v), 0, 10000000 /2);
std::future<long long int> f2 = std::async(std::launch::async, partialSum, std::cref(v), 10000000 / 2, 10000000);
volatile long long int a = f1.get() + f2.get();
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono:: duration_cast<std::chrono::microseconds>(end - start);
std::cout << "With 2 threads-> " << duration.count() << std::endl;
//1 thread
start = std::chrono::high_resolution_clock::now();
f1 = std::async(std::launch::async, partialSum, std::cref(v), 0, 10000000);
end = std::chrono::high_resolution_clock::now();
duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
std::cout << "With 1 thread-> " << duration.count() << std::endl;
}
And output:
With 2 threads-> 11835
With 1 thread-> 0