해결된 질문
작성
·
254
1
오타가 없는 것 같은데 무슨 이유로 다른 값이 나오는지 알수가 없네요. 도움부탁드립니다.
아래는 코드 전문입니다.
#include <iostream>
#include <thread>
#include <mutex>
#include <utility>
#include <future>
#include <vector>
#include <atomic>
#include <chrono>
#include <numeric>
#include <random>
#include <execution>
using namespace std;
auto dotProductFuture(const vector<int>& v0, const vector<int>& v1,
const unsigned i_start, const unsigned i_end)
{
int sum = 0;
for(unsigned i = i_start; i < i_end; ++i)
{
sum += v0[i] * v1[i];
}
return sum;
}
auto dotProductNaive(const vector<int>& v0, const vector<int>& v1,
const unsigned i_start, const unsigned i_end, unsigned long long & sum)
{
for(unsigned i = i_start; i < i_end; ++i)
sum += v0[i] * v1[i];
return sum;
}
mutex mtx;
auto dotProductLock(const vector<int>& v0, const vector<int>& v1,
const unsigned i_start, const unsigned i_end, unsigned long long & sum)
{
for(unsigned i = i_start; i < i_end;++i)
{
std::scoped_lock lock(mtx); //c++17
sum += v0[i] * v1[i];
}
}
int main()
{
const long long n_data = 100'000'000;
const unsigned n_threads = 4;
//init vectors
std::vector<int> v0, v1;
v0.reserve(n_data);
v1.reserve(n_data);
random_device seed;
mt19937 engine(seed());
uniform_int_distribution<> uniformDist(1, 10);
for(long long i = 0; i < n_data; ++i)
{
v0.push_back(uniformDist(engine));
v1.push_back(uniformDist(engine));
}
cout << "std::inner_product" << endl;
{
const auto sta = chrono::steady_clock::now();
const auto sum = std::inner_product(v0.begin(), v0.end(), v1.begin(), 0ull);//unsigned long long
const chrono::duration<double> dur = chrono::steady_clock::now() - sta;
cout << dur.count() << endl;
cout << sum << endl;
cout << endl;
}
cout << "Naive" << endl;
{
const auto sta = std::chrono::steady_clock::now();
std::vector<thread> threads;
threads.resize(n_threads);
const unsigned n_per_thread = n_data / n_threads;
unsigned long long sum = 0;
for(unsigned t = 0; t < n_threads; ++t)
{
threads[t] = std::thread(dotProductNaive, std::ref(v0),
std::ref(v1), t*n_per_thread, (t+1)*n_per_thread, std::ref(sum));
}
for(unsigned t = 0; t < n_threads; ++t)
threads[t].join();
const auto dur = std::chrono::steady_clock::now() - sta;
cout << dur.count() << endl;
cout << sum << endl;
cout << endl;
}
cout << "Lock Guard" << endl;
{
const auto sta = std::chrono::steady_clock::now();
unsigned long long sum = 0;
std::vector<thread> threads;
threads.resize(n_threads);
const unsigned n_per_thread = n_data / n_threads;
for(unsigned t = 0; t < n_threads; ++t)
{
threads[t] = std::thread(dotProductLock, std::ref(v0),
std::ref(v1), t*n_per_thread, (t+1)*n_per_thread, std::ref(sum));
}
// for(unsigned t = 0; t < n_threads; ++t)
// threads[t].join();
const chrono::duration<double> dur = std::chrono::steady_clock::now() - sta;
cout << dur.count() << endl;
cout << sum << endl;
cout << endl;
}
return 0;
}
답변 2
2
안녕하세요, 답변 도우미 Soobak 입니다.
주석으로 처리하신 threads[t].join()
코드라인 부분 때문입니다.
Lock Guard
방식으로 각 연산마다 락을 사용하였기에, 스레드들은 순차적으로 sum
의 값을 갱신하게 됩니다.
그러나, 이 때 주석처리된 thread[t].join()
을 사용하지 않으면, 메인 스레드에서 결과를 출력하기 전에 모든 스레드가 종료되지 않을 수 있습니다.
이로 인해서 일부 스레드의 계산 결과가 최종 결과에 포함되지 않을 수 있게 되어버리는 것입니다.
첨부해주신 코드의 thread[t].join()
부분의 주석을 해제하신 후 확인해보세요.
정상적으로 작동하는 빌드 후 출력 결과 사진을 첨부드립니다.
1