SyntaxHighlighter.all();

[설명]

clflush는 x86 instruction set reference중 하나로 intel c/c++ 컴파일러의 내장 함수로서 사용할 수 있습니다.

 

clflush는 프로세서의 모든 레벨의 캐시에서 피연산자로 지정된 주소를 포함하는 캐시라인을 제거합니다.

* 전부 삭제하는 것이 아니라 파라미터로 넘겨진 주소만 해당된다.

 

clflush 명령어는 모든 권한수준에서 사용할 수 있는 명령어입니다.

 

[동작]

프로세서가 clflush 명령어를 통해 받아온 메모리 주소를 수신한다. 이후 해당 주소가 캐시에 존재하는지 식별합니다.

만약 메모리 주소가 식별되면, 해당 주소는 캐시에서 제거(flush)합니다.

 

[참고]

- cache coherency (캐시 일관성)

 

각 프로세서별로 별도의 캐시 메모리를 가지고 있는 공유 메모리 멀티프로세서에서, 한 명령어 피연산자의 복제본이 주기억장치에 하나, 그리고 각 코어의 캐시 메모리에 하나씩, 여러 개 존재할 수 있습니다.  이러한 상황에서 피연산자가 변경되면, 나머지 복제본 역시 반드시 변경되어야만 합니다.

  즉, 캐시 일관성은 공유된 피연산자의 값이 변경되면, 그 사실이 전체 캐시에 즉시 전파되어 일관성을 유지하는 규칙입니다.

 

 * 캐시일관성을 유지하는 프로토콜은 MSI, MESI, 시냅스, 버클리 프로토콜 등이 있다.

 

반응형

프로세서는 성능 향상을 위해 보폭 예측을 사용합니다. 보폭 예측은 많은 양의 상수를 생성하는 명령을 최적화합니다.

 

예를 들어 number를 십만번 더하는 코드가 수행된다고 가정해봅시다.

 

 

 

 

 

 

 

 

 

프로세서는 여러 개의 파이프라인으로 구성되어 고도의 병렬 연산을 수행하는데, number의 경우

 

이전 number에 1을 더해야 하기 때문에 dependency가 발생, 병렬 연산이 불가능하여 성능저하를 유발합니다.

 

이때 프로세서는 성능 향상을 위해 number를 일일이 더하지 않고 1씩 값이 증가하는 것을 예측하여 연산합니다.

 

[Stride]

stride는 값이 변화하는 보폭입니다. 예를 들어 수열 1,2,3,4,5,6 ~ 99, 100이 있습니다. 이 때 수열의 stride는 1입니다.

 

[Stride State Diagram]

value : 계산한 결과값

stride : 보폭, value1(선행 계산 결과) - value2(후행 계산 결과)

 

- Init state

처음 명령이 수행되었을 때의 상태. 해당 명령의 결과는 value에 저장됩니다.

 

- Transient state

Init 상태에서 다음 명령이 발생하면 결과를 value2에 저장. 이때, stride(value1 – value2)가 계산. 해당 상태를 transient(일시적 보폭) 라고 합니다.

transient상태에서 다음 명령이 수행되었을 때 stride값이 같다면 steady로 상태변화합니다.

 

- Steday state

보폭이 안정된 상태로 변수를 정확히 예측하여 수행 시간이 감소합니다.

새로운 명령을 수행한 뒤 stride가 같다면 steady state를 유지합니다. 만약 stride가 틀리면 transient상태로 변화합니다.

 

 

[참조]

"Data Value Prediction",  Jumnit Hong,  Elias Khair ... 

during "stride predicator".

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.86.8888&rep=rep1&type=pdf

 

반응형

'컴퓨터구조' 카테고리의 다른 글

[컴퓨터구조] mfence (Memory Fence)  (0) 2019.05.03
[컴퓨터구조] clflush instruction  (0) 2019.05.03

이어서 멀티 쓰레드 채팅프로그램의 chat_server.c 입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<pthread.h>
#include<time.h>
 
#define BUF_SIZE 100
#define MAX_CLNT 100
#define MAX_IP 30
 
void * handle_clnt(void *arg);
void send_msg(char *msg, int len);
void error_handling(char *msg);
char* serverState(int count);
void menu(char port[]);
 
 
/****************************/
 
int clnt_cnt=0;
int clnt_socks[MAX_CLNT];
pthread_mutex_t mutx;
 
int main(int argc, char *argv[])
{
    int serv_sock, clnt_sock;
    struct sockaddr_in serv_adr, clnt_adr;
    int clnt_adr_sz;
    pthread_t t_id;
 
    /** time log **/
    struct tm *t;
    time_t timer = time(NULL);
    t=localtime(&timer);
 
    if (argc != 2)
    {
        printf(" Usage : %s <port>\n", argv[0]);
        exit(1);
    }
 
    menu(argv[1]);
 
    pthread_mutex_init(&mutx, NULL);
    serv_sock=socket(PF_INET, SOCK_STREAM, 0);
    
    memset(&serv_adr, 0sizeof(serv_adr));
    serv_adr.sin_family=AF_INET;
    serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
    serv_adr.sin_port=htons(atoi(argv[1]));
 
    if (bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
        error_handling("bind() error");
    if (listen(serv_sock, 5)==-1)
        error_handling("listen() error");
 
    while(1)
    {
        t=localtime(&timer);
        clnt_adr_sz=sizeof(clnt_adr);
        clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);
 
        pthread_mutex_lock(&mutx);
        clnt_socks[clnt_cnt++]=clnt_sock;
        pthread_mutex_unlock(&mutx);
 
        pthread_create(&t_id, NULL, handle_clnt, (void*)&clnt_sock);
        pthread_detach(t_id);
        printf(" Connceted client IP : %s ", inet_ntoa(clnt_adr.sin_addr));
        printf("(%d-%d-%d %d:%d)\n", t->tm_year+1900, t->tm_mon+1, t->tm_mday,
        t->tm_hour, t->tm_min);
        printf(" chatter (%d/100)\n", clnt_cnt);
    }
    close(serv_sock);
    return 0;
}
 
void *handle_clnt(void *arg)
{
    int clnt_sock=*((int*)arg);
    int str_len=0, i;
    char msg[BUF_SIZE];
 
    while((str_len=read(clnt_sock, msg, sizeof(msg)))!=0)
        send_msg(msg, str_len);
 
    // remove disconnected client
    pthread_mutex_lock(&mutx);
    for (i=0; i<clnt_cnt; i++)
    {
        if (clnt_sock==clnt_socks[i])
        {
            while(i++<clnt_cnt-1)
                clnt_socks[i]=clnt_socks[i+1];
            break;
        }
    }
    clnt_cnt--;
    pthread_mutex_unlock(&mutx);
    close(clnt_sock);
    return NULL;
}
 
void send_msg(char* msg, int len)
{
    int i;
    pthread_mutex_lock(&mutx);
    for (i=0; i<clnt_cnt; i++)
        write(clnt_socks[i], msg, len);
    pthread_mutex_unlock(&mutx);
}
 
void error_handling(char *msg)
{
    fputs(msg, stderr);
    fputc('\n', stderr);
    exit(1);
}
 
char* serverState(int count)
{
    char* stateMsg = malloc(sizeof(char* 20);
    strcpy(stateMsg ,"None");
    
    if (count < 5)
        strcpy(stateMsg, "Good");
    else
        strcpy(stateMsg, "Bad");
    
    return stateMsg;
}        
 
void menu(char port[])
{
    system("clear");
    printf(" **** moon/sun chat server ****\n");
    printf(" server port    : %s\n", port);
    printf(" server state   : %s\n", serverState(clnt_cnt));
    printf(" max connection : %d\n", MAX_CLNT);
    printf(" ****          Log         ****\n\n");
}
cs


서버를 오픈하면 기본적으로 다음과 같은 화면을 출력해줍니다.


테스트한 port는 9190이고 최대 접속인원은 100명으로 제한을 두었습니다.


이 부분은 필요에 따라 변경해 사용하시면 됩니다.


* linux에서 포트를 사용할 때 한번 사용한 포트는 보안문제 때문에 당분간 사용할 수 없다고 합니다.

  서버를 오픈하실 때 마다 포트번호를 달리 하셔야 오류가 발생하지 않습니다.



log의 아래에는 접속한 클라이언트를 표시해 주는 부분입니다. 

반응형

+ Recent posts