기존에는 멀티 스레드를 사용하지 않는 작업 시 하이퍼 스레딩이 필요하지 않음. 따라서 남는 레지스터를 활용하자는 생각을 함.
Loop Splitting을 사용하는 프로그램을 만들어, 병렬의 개수를 늘려가며 하이퍼 스레딩 사용 유무에 따라 비교를 해보았다.
#include<stdio.h>
#include<Windows.h>
#include<stdint.h>
/*
vmware의 리눅스에서 하려고 하였다. 하지만 하이퍼 스레딩 유무에 따라 CPU정보 명령어( cat /proc/cpuinfo, grep -c processor /proc/cpuinfo, grep "physical id" /proc/cpuinfo | sort -u | wc -l, grep "cpu cores" /proc/cpuinfo | tail -1)를 사용하여 확인하였지만 차이가 없어 윈도우환경에서 하였다.
*/
//windows에는 gettimeofday함수가 없으므로 인터넷에서 참고하였다.
int gettimeofday(struct timeval* tp, int* tz)
{
LARGE_INTEGER tickNow;
static LARGE_INTEGER tickFrequency;
static BOOL tickFrequencySet = FALSE;
if (tickFrequencySet == FALSE) {
QueryPerformanceFrequency(&tickFrequency);
tickFrequencySet = TRUE;
}
QueryPerformanceCounter(&tickNow);
tp->tv_sec = (long) (tickNow.QuadPart / tickFrequency.QuadPart);
tp->tv_usec = (long) (((tickNow.QuadPart % tickFrequency.QuadPart) * 1000000L) / tickFrequency.QuadPart);
return 0;
}
void main() {
struct timeval startTime, endTime;
double diffTime;
int limit = 100000;
int i;
int loop = 1;
int data[100000];
int a;
for (a = 0; a < limit; a++) {
data[a] = 1;
}
int x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19;
x0 = 1;
x1 = 1;
x2 = 1;
x3 = 1;
x4 = 1;
x5 = 1;
x6 = 1;
x7 = 1;
x8 = 1;
x9 = 1;
x10 = 1;
x11 = 1;
x12 = 1;
x13 = 1;
x14 = 1;
x15 = 1;
x16 = 1;
x17 = 1;
x18 = 1;
x19 = 1;
printf("loop %d, %d loop splitting\n", limit, loop);
gettimeofday(&startTime, NULL);
printf("starttime %d.%d s\n",startTime.tv_sec, startTime.tv_usec);
for (i = 0; i < limit; i += loop) {
x0 = x0 * data[i];
/*x1 = x1 * data[i + 1];
x2 = x2 * data[i + 2];
x3 = x3 * data[i + 3];
x4 = x4 * data[i + 4];
x5 = x5 * data[i + 5];
x6 = x6 * data[i + 6];
x7 = x7 * data[i + 7];
x8 = x8 * data[i + 8];
x9 = x9 * data[i + 9];
x10 = x10 * data[i + 10];
x11 = x11 * data[i + 11];
x12 = x12 * data[i + 12];
x13 = x13 * data[i + 13];
x14 = x14 * data[i + 14];
x15 = x15 * data[i + 15];
x16 = x16 * data[i + 16];
x17 = x17 * data[i + 17];
x18 = x18 * data[i + 18];
x19 = x19 * data[i + 19];*/
}
gettimeofday(&endTime, NULL);
printf("endtime %d.%d s\n",endTime.tv_sec, endTime.tv_usec);
}
테스트를 해보기 전 하이퍼 스레딩 기능을 켰다.
다음은 하이퍼 스레딩이 켜진 상태에서 실행한 결과이다.
<병렬 1개>
<병렬 2개>
<병렬 4개>
<병렬 5개>
<병렬 8개>
<병렬 10 개>
<병렬 20개>
그리고 나서 하이퍼 스레딩을 끄고 테스트를 해보았다.
<병렬 1개>
<병렬 2개>
<병렬 4개>
<병렬 5개>
<병렬 8개>
<병렬 10 개>
<병렬 20개>
각 테스트 결과들을 표로 정리하면 다음과 같다.
startT | endT | 시간(초) | 평균 시간 |
1번 병렬 | |||
158.286745 | 158.286334 | 0.000411 | 0.000529 |
159.294495 | 159.293966 | 0.000529 | |
159.941791 | 159.941145 | 0.000646 | |
2번 병렬 | |||
205.491576 | 205.491193 | 0.000383 | 0.000429 |
206.256555 | 206.256076 | 0.000479 | |
206.781915 | 206.781489 | 0.000426 | |
4번 병렬 | |||
233.779762 | 233.779216 | 0.000546 | 0.000466 |
234.638762 | 234.638302 | 0.00046 | |
235.315725 | 235.315334 | 0.000391 | |
5번 병렬 | |||
276.227503 | 276.227081 | 0.000422 | 0.001615 |
277.362467 | 277.361994 | 0.000473 | |
278.18864 | 278.18469 | 0.00395 | |
8번 병렬 | |||
305.11175 | 305.10701 | 0.00474 | 0.003192 |
306.78751 | 306.78311 | 0.0044 | |
306.816079 | 306.815644 | 0.000435 | |
10번 병렬 | |||
373.782009 | 373.781564 | 0.000445 | 0.000421 |
374.588579 | 374.588149 | 0.00043 | |
375.25087 | 375.250482 | 0.000388 | |
20번 병렬 | |||
411.261493 | 411.261106 | 0.000387 | 0.000412 |
412.976789 | 412.976307 | 0.000482 | |
413.531929 | 413.531562 | 0.000367 | |
HTon |
<하이퍼 스레딩 켰을 때>
startT | endT | 시간(초) | 평균시간 |
1번 병렬 | |||
1193.879285 | 1193.878775 | 0.00051 | 0.001763 |
1195.55735 | 1195.55297 | 0.00438 | |
1195.954497 | 1195.954098 | 0.000399 | |
2번 병렬 | |||
1250.718352 | 1250.718071 | 0.000281 | 0.000349 |
1251.968818 | 1251.968417 | 0.000401 | |
1252.790355 | 1252.789991 | 0.000364 | |
4번 병렬 | |||
1333.682861 | 1333.682653 | 0.000208 | 0.000284 |
1336.171769 | 1336.171549 | 0.00022 | |
1337.950726 | 1337.950303 | 0.000423 | |
5번 병렬 | |||
1449.503198 | 1449.502993 | 0.000205 | 0.000939 |
1452.7616 | 1452.75931 | 0.00229 | |
1452.823454 | 1452.823132 | 0.000322 | |
8번 병렬 | |||
1589.8527 | 1589.852293 | 0.000407 | 0.00044 |
1590.653918 | 1590.653423 | 0.000495 | |
1591.37499 | 1591.374572 | 0.000418 | |
10번 병렬 | |||
1652.622676 | 1652.622495 | 0.000181 | 0.001527 |
1653.424747 | 1653.424336 | 0.000411 | |
1654.68126 | 1654.67727 | 0.00399 | |
20번 병렬 | |||
1875.417252 | 1875.416802 | 0.00045 | 0.001983 |
1876.366084 | 1876.365556 | 0.000528 | |
1877.5143 | 1877.50933 | 0.00497 | |
HToff |
<하이퍼 스레딩을 껐을 때>
하이퍼 스레딩을 켰을 경우와 껐을 경우의 컴퓨터 환경을 최대한 동일하게 하기 위해 네트워크를 차단하고 켜진 프로그램도 최대한 동일하게 유지하였다. (따라서, 각 환경이 동일한 환경이라고 가정하고 차이를 보았다.)
각 병렬개수별 시간을 여러 번 측정하여 그 중 평균치를 사용하였다. 각 병렬개수별 시간 차이는 다음과 같다.
차이를 좀 더 보기 쉽게 시간에 10^5만큼 곱하였다.
병렬 | 차이(HTon - HToff) |
1 | 52.86490367 |
2 | 8.066666663 |
4 | 18.2 |
5 | 67.59999999 |
8 | 275.1666667 |
10 | -110.6333333 |
20 | -157.0666667 |
병렬의 개수를 많이 늘렸을 때 하이퍼 스레딩을 껐을 경우가 더 시간이 오래 걸리는 것으로 보아, 하이퍼 스레딩을 껐을 때, 남은 Architectural state(레지스터)를 활용하지 못하는 것으로 판단하였다.
따라서 이러한 단일 프로세스만 수행해야하는 상황에서 어떻게 하면 효율적으로 수행할 수 있을까 생각해보게 되었고, 결국 레지스터를 어떻게 하면 최대한 많이 넣고 많이 사용할 수 잇을까에 대해 생각해보게 되었다.
문제 인식 후 무어의 법칙을 근거로 다양한 기능 시도
1. 병렬적 작업을 하는 단일 프로세스만 수행할 때, 하이퍼 스레딩기능을 끄고 하이퍼 스레딩을 위한 레지스터를 활용하면 많은 레지스터를 쓸 수 있지 않을까?
PROPOSAL
<기존의 멀티코어 시스템>
예전 Pentium D processor의 듀얼 코어와 달리 캐시와 버스 인터페이스를 cpu간에 공유하기 시작하면서 본격적으로 멀티코어 기술에 대한 관심이 많아졌고, 그 중에 Architectural State부분에서 아래와 같이 cpu내부에 스레드를 여러 개 두어 문맥 교환을 os가 아닌 cpu에서 처리하도록 한 Hyper threading 기술이 있고 더욱 효율적인 Architectural state를 두 가지로 제안을 하게 되었다.
1. 기존의 cpu와 첫 번째 제안
1-1 기존의
cpu와 첫 번째 제안
1- 2 제안
'공부 > 운영체제&시스템프로그래밍' 카테고리의 다른 글
myshell (0) | 2020.07.16 |
---|---|
mycp (0) | 2020.07.16 |
EXT2 file system 실습 (6번 디렉토리안의 82번 파일 찾기) (0) | 2020.07.16 |