반응형
728x170
우리가 스레드를 만드는 이유는..
효율적으로 사용하기 위해서다.
1부터 10000까지 더하는 작업은 얼마나 걸릴까???
물론 우리는 n(n+1)/2라는 것을 알고 있지만
컴퓨터는 한 번 경험을 통해서 알게 해주고 싶다.
해보자
우선 스레드 하나로 돌려보자
#include <iostream>
#include <thread>
#include<chrono>
using namespace std;
using namespace chrono;
void func1(int *result) {
for (int i = 1; i <= 10000; i++) {
*result += i;
}
}
int main() {
int sum = 0;
steady_clock::time_point start = steady_clock::now();
thread t1(func1, &sum); //스레드 객체 t1을 생성 후 해당 스레드로 func1 실행
t1.join();
steady_clock::time_point end = steady_clock::now();
cout << sum << '\n';
duration<double> sec = end - start;
cout << "elapsed time " << sec.count();
}
결과는?
대략 0.03초 정도 걸렸다.
그럼 화끈하게 10개 이용해볼까??
근데 스레드에게 인자를 전달해줘서 갱신되게 해보자.
thread를 생성할 때 같이 전달해준다.
#include <iostream>
#include <thread>
#include <chrono>
#include <vector>
using namespace std;
using namespace chrono;
void func(int start, int end, int *result) {
int s = 0;
for (int i = start; i <= end; i++) {
s += i;
}
*result += s;
}
int main() {
int sum = 0;
vector<thread> threads;
steady_clock::time_point start = steady_clock::now();
for (int i = 0; i < 10; i++) {
threads.push_back(thread(func, i * 1000 + 1, i * 1000 + 1000, &sum)); // 스레드 10개를, 범위를 나누어주어서 실행
}
for (int i = 0; i < 10; i++) {
threads[i].join(); //스레드 10개 반환 기다림
}
steady_clock::time_point end = steady_clock::now();
cout << sum << '\n';
duration<double> sec = end - start;
cout << "elapsed time " << sec.count();
}
결과는???
???????
뭐야 더 걸려..?
3가지 경우가 있겠다.
1. 내 잘못
2. 스레드 생성자체가 오버헤드가 더 심함 -> 일 것 같다. 1부터 1만하는 것은 너무 작은 연산이잖아..
3. OS 스케줄러 탓
???
다른 분의 도움을 받아
다르게 작성해보았다.
#include <iostream>
#include <thread>
#include <chrono>
#include <vector>
using namespace std;
using namespace chrono;
void worker(vector<int>::iterator start, vector<int>::iterator end,int* result) {
int sum = 0;
for (auto itr = start; itr < end; ++itr) {
sum += *itr;
}
*result = sum;
}
int main() {
//10000짜리 컨테이너에 순서대로 값 초기화
vector<int> data(10000);
for (int i = 0; i < 10000; i++) {
data[i] = i+1;
}
// 각 쓰레드에서 계산된 부분 합들을 저장하는 벡터
vector<int> partial_sums(10);
//thread 넣을 벡터
vector<thread> workers;
steady_clock::time_point start = steady_clock::now();
for (int i = 0; i < 10; i++) {
workers.push_back(thread(worker,
data.begin() + i * 1000,
data.begin() + (i + 1) * 1000,
&partial_sums[i]));
}
for (int i = 0; i < 10; i++) {
workers[i].join();
}
int total = 0;
for (int i = 0; i < 10; i++) {
total += partial_sums[i];
}
steady_clock::time_point end = steady_clock::now();
cout << total << '\n';
duration<double> sec = end - start;
cout << "elapsed time " << sec.count();
}
결과는???
???
내가 잘못한 것이 아니구나..ㅎ
사실 이 글을 읽는 사람을 깨우쳐주려고 했다.
어떠한 작업이냐에 따라 멀티스레딩이 유용할 수도 있고
그렇지 않을수도 있다.
싱글코어면 context switching 오버헤드가 더 크기 때문에 더 오래 걸릴 것이고
thread 생성하는 것도 오버헤드가 커서 적당히 나누는 것이 필요하고
간단한 작업은 그냥하는 것이 필요하다.
아무튼 멀티 스레딩을 이용해서 연산을 해보았다.
728x90
반응형
그리드형
'프로그래밍 지식 > C++' 카테고리의 다른 글
C++문법 / Race condition, 경쟁상태 해결 - 뮤텍스, Mutex (0) | 2021.12.03 |
---|---|
C++ 문법 / typedef, using, auto, decltype, constexpr, (0) | 2021.12.03 |
C++문법 / Thread, 스레드 - 생성, join, detach (4) | 2021.12.02 |
C++ 문법 / 기본 수학 연산 함수 (0) | 2021.12.02 |
C++문법/ 타입캐스팅, 캐스트 연산자 (0) | 2021.12.02 |