TigerCow.Door


최근 학교에서 데이터베이스 수업을 들으면서 실습을 진행하고 있습니다.

이번에 PHP에 관련된 내용을 공부하게 되어 관련 내용을 공부하면서 정리해서 포스팅하려합니다.

부족한 부분은 언제든지 댓글이나 이메일(doorbw@outlook.com)으로 피드백주시면 감사하겠습니다.


1. Web Server


php와 같은 것들을 server side script(technology) 라고 합니다.

한글로 한다면 서버 측면 언어(기술)라고 생각할 수 있기에 서버 측에서 동작하는 언어라고 할 수 있습니다.

서버(server)라는 개념안에는 Apache, PHP, MySQL 등이 있습니다.

그리고 클라이언트(client)는 서버(server)에게 요청을 하고, 서버는 클라이언트에게 응답 및 제공을 하게 되죠.



흔히들 사용하는 웹 브라우저는 웹 클라이언트로 볼 수 있습니다.

웹 브라우저에 도메인을 입력하면 웹 클라이언트는 웹 서버에 요청을 하게 됩니다.

그리고 그 요청에 대해서 응답하는 것이 웹 서버가 하는 일 입니다.

웹 브라우저에는 우리가 많이사용하는 크롬, IE, Firefox 등이 있습니다.

그리고 웹 서버에는 Apache, IIS, nginx 등이 있습니다.

다시 돌아와서 웹 클라이언트(웹 브라우저)가 요청을 하면 웹 서버가 응답 및 제공을 하게 되는데 이때 HTML을 제공하게 됩니다.

그런데 HTML은 정적인 문서입니다.

정적이다? 다시 말해서 HTML은 사람이 수작업으로 하나하나 만들어야 한다는 것입니다.

이 때문에 몇 가지 문제가 생기게 됩니다.

많은 변화들을 어떻게 반영할 것인가?

많은 것들을 어떻게 사람이 일일이 제작할 것인가? 등 입니다.

이러한 정적인 HTML에서 한계를 느끼면서 이것을 극복하고자 하는 움직임이 생겼고 그로인해 CGI(Common Gateway Interface)가 나왔습니다.

CGI 란 웹 서버와 PHP파일을 처리하는 PHP engine 사이의 통신할 수 있는 통신 규약입니다.

웹 서버가 처리할 수 없는 파일(ex. php, py, ...)을 처리할 수 있는 것(PHP engine, python, ... )에 전달합니다.

이때 그것이 가능하도록 하는 것이 CGI 입니다.


2. PHP


그 중 우리가 배울 PHP라는 것에 대해서 더 알아보도록 하겠습니다.

PHP는 Personal homepage tools의 줄임말로 시작해서 현재는 PHP:Hypertext preprocessor 라고 정의되어 있습니다.

여기서 Hypertext는 HTML이라고 생각하셔도 좋습니다. 과거에는 perl이라는 언어로 만들어졌지만 현재는 C언어로 대체되었습니다.

위에서 간략하게 알아보았지만 다시 확인해보면 PHP는 서버쪽에서 실행 되는 프로그래밍 언어입니다. 주로 HTML 코드를 프로그래밍적으로 생성하죠.


PHP의 장점으로는 무엇이 있을까요?

웹 개발에서 많이 사용되고 있는 php는 관련된 많은 기능을 제공합니다.

따라서 웹 개발에 최적화된 언어로써 과거부터 현재까지 많이 이용되고 있습니다.

또한 거의 모든 데이터베이스를 지원하고 현재 가장 많은 공개소프트웨어가 PHP로 만들어져 있습니다.


PHP를 초보자에게 많이 쉽고 전문가에게는 많은 기능을 제공하기 때문에 많이 이용하기도 합니다.


PHP를 설치하는데  있어서는 아래 URL을 참고하시길 바랍니다. (우분투 기준)

http://imitator.kr/Linux/1078


이후 포스팅부터는 직접적인 실습을 진행하며 정리해보도록 하겠습니다.




블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc



안녕하세요. 문범우입니다.

이번 포스팅부터 Introduction to Algorithm (3rd Edition) 책의 15장. 동적 프로그래밍(ch15, dynamic programming)에 대해서 이야기하려 합니다.

매주 1~2번 정도 포스팅 될 예정이며, 공부를 하면서 내용을 정리해서 올리기 때문에 잘못된 정보나 지식이 포함되어 있을 수 있으니 참고용으로 확인해주시고, 잘못된 내용에 대해서는 피드백 주시면 감사하겠습니다.

오늘은 동적 프로그래밍에 대한 개요와 동적 프로그래밍의 막대 자르기(Rod Cut)에 대해서 알아보겠습니다.


1. 동적 프로그래밍(Dynamic programming)


동적 프로그래밍은 분할정복 기법과 같이 부분 문제의 해를 결합하여 문제를 해결합니다.

이때, 프로그래밍이란 것은 코딩을 하는 것이 아니라 테이블을 이용하여 문제를 해결하는 방법을 말합니다.

동적 프로그래밍은, 동적 계획법, Dynamic programming, DP 등으로 부르기도 합니다.


분할정복 알고리즘은 기본적으로, 하나의 문제를 겹치지 않는 부분 문제들로 분할(divide)하여 해당 부분 문제들을 재귀적으로 해결한 후, 각각의 결과를 다시 결합하여 원래의 문제를 해결합니다.

반면, 동적 프로그래밍에서는 부분 문제가 서로 중복될 떄, 즉 부분 문제가 다시 부분 문제를 공유할 때 적용됩니다.

동적 프로그래밍 알고리즘을 이용하여 부분 문제를 한번만 해결하고 그 해를 테이블에 저장함으로써 각 부분 문제를 풀 때마다 다시 계산하는 일을 피할 수 있습니다.


일반적으로 최적화 문제(Optimization problem)에서 동적 프로그래밍을 적용합니다.

최적화 문제에서는 대체적으로 다양한 해를 가질 수 있는데 우리는 다양한 해들 중에서 최적(최소 또는 최대)의 해를 찾기를 원합니다. 이러한 해를 그 문제에 대한 유일한 최적해라고 하지 않고, 한 개의 최적해라 합니다. 최적의 값을 가지는 해가 여러개 존재할 수 있기 때문이죠.

동적 프로그래밍 알고리즘을 개발할 때는 아래의 4단계를 따릅니다.


1. 최적해의 구조의 특징을 찾는다.

2. 최적해의 값을 재귀적으로 정의한다.

3. 최적해의 값을 일반적으로 상향식(bottom-up) 방법으로 계산한다.

4. 계산된 정보들로부터 최적해를 구성한다.


1~3 단계는 주어진 문제에 대한 동적 프로그래밍 해의 기초가 됩니다.

이어서 4 단계에서는 최적해의 값만 필요한 것이 아니라 최적해 자체가 필요할 때 수행하는 것으로써 값만 필요할때에는 생략할 수 있습니다.


2. 막대 자르기


막대 자르기 문제는 다음과 같습니다.

길이가 n인 막대와 i = 1,2,3,...,n에 대한 가격 p_i의 표가 주어지면 해당 막대를 잘라서 판매했을떄 얻을 수 있는 최대수익 r_n을 결정하는 것 입니다. 길이가 n인 막대의 가격 p_n이 충분히 비싸면 최적해는 자르지 않은 것일 수도 있습니다.


아래 표와 그림을 통해 확인해보겠습니다.


표에는 막대의 길이가 얼마일 때, 얼마의 가격인지가 나와 있습니다.

그리고 아래 그림에서 막대를 다양한 방법으로 잘라, 그 가격을 나타내고 있습니다.

(a) ~ (h)를 봤을 때 어떤 경우가 최적의 해 인가요?

막대를 2의 길이, 두 개로 자른 (c)의 경우의 수익이 10으로써 가장 최적의 해를 나타내고 있습니다.


위와 같이, 길이가 n인 막대는 개의 다른 방법으로 자를 수 있습니다.

제일 좌측에서 부터 i = 1,2,3,...,n-1 에 대한 모든 i길이마다 자르거나 자르지 않거나 하는 독립적인 선택이 가능하기 때문입니다.

만약 최적해가 막대를 에 대해 k의 조각으로 나누면,

막대를 조각 길이 로 나누는 다음의 최적의 분해는

 이며,

다음과 같은 최대의 해당 수익을 제공합니다.


좀 더 일반적으로 말하면, 에 대한  값을 더 작은 막대로부터의 최대 수익을 이용해 나타낼 수 있습니다.



첫 번째 인자 은 자르지 않고 길이가 n인 막대를 그대로 파는 것에 해당합니다.()

max 함수에 대한 다른 인자는 막대를 처음에 i와 n-i의 길이가 되도록 둘로 나누고 두 조각을 더 최적으로 잘라서 두 조각으로부터 최적의 이익을 얻습니다. 그런데 어떤 i의 값이 최대의 수익을 가져오는지 미리 알 수 없기 때문에 i에 대한 모든 가능한 값을 고려해야 합니다.


다시말해서, 크기가 n인 원래 문제를 풀기 위해서 종류가 같은 더 작은 크기의 문제를 풉니다.

처음에 자르기를 진행하여 도출된 두 가지의 문제는 서로 독립적인 예로 생각해도 됩니다.

전체적인 최적해는 두 부분 문제의 각각에 대해 수익을 최대화하는 해를 이용합니다.

이에 따라 막대 자르기 문제는 최적 부분구조(Optimal substructure)를 가졌다고 말합니다.

따라서 길이가 n인 막대의 모든 분해를 첫 번째 조각과 나머지 조각의 어떤 분해로 볼 수 있습니다. 그렇게 할 때는 막대를 전혀 자르지 않는 방법의 해를 포함하여 좀 더 간단한, 아래와 같은 식을 얻을 수 있습니다.



우리는 위의 식을 토대로 몇 가지 알고리즘을 구현해보도록 하겠습니다.


2-1. 하향식 재귀의 표현


알고리즘의 의사코드는 아래와 같습니다.



위의 CUT-ROD 의사코드에 대해 간략히 확인해볼까요?

길이 n이 0인 막대기는 당연히 0을 반환합니다.

그리고 그것이 아닐때에, 최대 수익 q를 음의 무한대로 초기화를 진행하고 i가 1부터 n까지 값으로 재귀 함수를 호출합니다.

이러한 알고리즘의 총 수행시간은,

   

입니다.


CUT-ROD 알고리즘이 위와 같은 수행시간을 보이듯, 비효율적인 이유는 무엇일까요?

그것은 CUT-ROD 알고리즘이 같은 인자를 똑같이 반복해서 계산하려고 하기 때문입니다.

아래의 트리를 보면 이해하기 쉬울 것 입니다.

n=4 일때를 보여주는 위의 트리에서, 재귀적으로 호출되는 함수 때문에 n=1 일때, n=2일때의 경우가 반복되서 호출되고 있습니다. 

즉 CUT-ROD 함수에서는 길이가 n인 막대를 자르는 데 가능한 개의 경우의 수를 모두 고려하고 있는 것 입니다.



3. 동적 프로그래밍을 이용한 최적의 막대 자르기


이제 1에서 알아보았던 동적 프로그래밍을 이용하여 막대 자르기 문제를 효율적으로 해결해보록 하겠습니다.

동적 프로그래밍은 위에서 알아본 바와 같이, 각 부분 문제를 단 한번만 풀고 그 해를 저장하도록 처리합니다.

그렇게 함으로써 반복되는 부분 문제의 해를 구할 떄 다시 계산하지 않고 저장된 값을 참조만 함으로써 시간소요를 줄일 수 있습니다. 하지만 이렇게 동적 프로그래밍은 시간을 절약하기 위해 부가적인 메모리를 사용합니다.

이것은 시간-메모리 트레이드 오프(Time-memory trade-off)의 한가지 예로써 작용합니다.


막대자르기 문제를 동적 프로그래밍 방법으로 해결하는데 있어서 크게 두 가지 방법이 존재합니다.

하나는 메모하기를 이용한 하향식 방법, 다른 하나는 상향식 방법입니다.



3-1. 메모하기를 이용한 하향식


메모하기를 이용한 하향식의 기본 개념은 2-1에서 진행한 하향식 재귀와 비슷합니다.

하지만 특정 부분 문제를 해결하였을때 해당 부분 문제의 해를 배열이나 해시 테이블에 저장해놓도록 수정하여 이후 같은 부분 문제가 반복되었을때 다시 계산하지 않고 배열이나 해시 테이블을 참조하여 이용할 수 있도록 함으로써 시간을 절약합니다.

아래는 메모하기가 더해진 하향식 CUT-ROD 의 의사코드입니다.

메인 알고리즘, MEMOIZED-CUT-ROD는 새로운 배열 r[]을 선언하고 음의 무한대로 초기화 합니다.

배열 r의 구성은, 특정 길이 n'에 대한 최적의 해를 r[n']에 저장합니다.

그리고 길이 n에 대해서 MEMOIZED-CUT-ROD-AUX 함수가 호출이 됩니다.

그리고 1행에서 길이 n에 대한 최적의 해가 존재하다면 그것을 리턴하게 됩니다.

(초기에 배열 r[]을 음의 무한대로 초기화 하였으니 특정 길이 n'에 대하여 r[n']의 값이 0보다 크거나 같다면 길이 n'에 대한 최적의 해가 저장되어 있다는 것을 알 수 있습니다.)

계산되어 있지 않다면 이후 3행부터는 2-1에서 진행한 하향식 재귀함수와 동일합니다.



3-2. 상향식 방법


상향식 방법은 보다 간단합니다.

상향식 방법에서는 동적 프로그래밍 방법에서 부분 문제의 자연스러운 순서를 사용합니다.

만약 i > j 이라면 크기 i의 부분 문제는 크기 j 의 부분 문제보다 작습니다. 그러므로 해당 상향식 방법에서는 크기가 0부터 n으로 커지는 부분 문제의 크기 순으로 해결합니다.


수도코드의 1행에서 배열 r[]에 대해서 선언하고 이후 우리는 r[] 배열에 부분 문제의 결과를 저장할 것 입니다.

그리고 길이가 0인 막대에 대한 최대 수익은 0 이므로 2행에서 r[0]=0 으로 저장합니다.

3행에서부터는 길이가 1부터 j까지 하나씩 증가하는 각 부분 문제를 해결하여 값을 구하고 그것의 값을 7행에서 배열 r[]에 저장합니다.

마지막 8행에서 우리가 얻고자 하는 길이 n에 대한 최대 수익값을 리턴하게 됩니다.

이러한 상향식 방법의 수행시간은 을 가집니다.



3-3. 해의 재구성


우리가 위에서 공부한 두가지 알고리즘에서는 최적 해의 대한 값만 도출합니다.

즉, 길이가 n에 대한 막대를 통해 얻을 수 있는 최대 수익만을 반환할 뿐이지 해당 막대를 어떻게 잘라야 하는지는 리턴하지 않습니다.

이러한 동적 프로그래밍 방법을 각각의 부분 문제에 대한 계산된 최적 값 뿐만 아니라, 그 최적 값에 이르는 선택도 기록하도록 확장할 수 있습니다. 즉 이러한 정보와 함께 최적 값 뿐 아니라 최적해 자체를 쉽게 출력할 수 있습니다.



위의 수도코드에서는 그 전과 다르게 1행에서 배열 s[]를 선언합니다. 그리고 8행을 확인하시면 잘라내는 첫번째 조각의 최적크기 i를 보관하는 것을 알 수 있습니다.

그리고 최적 해를 가지는 r과 최적의 첫 번째 막대 크기들의 배열 s[]을 반환합니다.

아래 수도코드는 길이 n의 막대의 최적 분할에서의 모든 조각 크기의 리스트를 함께 출력합니다.





이렇게 해서 동적프로그래밍에 대한 개요와 하나의 예제인 막대 자르기(Rod-cutting) 에 대해서 공부해보았습니다.

추가적으로 궁금하신 점이나 피드백해주실 점은 댓글 또는 이메일(doorbw@outlook.com)을 이용해주세요 :)



블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc



안녕하세요. 문범우입니다.

지난 포스팅에서 프로세스 및 스레드에 대한 개념을 정리해보았습니다.

이번에는 스레드를 직접적으로 만들어서 확인해보도록 하겠습니다.

실습은 C언어로 진행합니다.


1. 싱글 스레드(Single-Thread)

먼저 싱글 스레드를 만들어서 확인해보도록 하죠.

코드는 아래와 같습니다.

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
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
 
DWORD WINAPI ThreadFunc(LPVOID);
// DWORD는 더블워드 = long
// WINAPI : Windows의 API
// LPVOID : ms에서 사용하는 void* 
 
int global = 1;
 
int main()
{
    HANDLE hThrd; //스레드를 접근하기 위한 손잡이 개념
    DWORD threadId; 
    int i;
    // for 루프문
    for (i=0; i<5; i++)
    {
        ThreadFunc( (LPVOID) i); // single thread
    }
    // Wait for the threads to complete.
    Sleep(3000);
 
    return EXIT_SUCCESS;
}
 
DWORD WINAPI ThreadFunc(LPVOID n)
{
    int i;
    for (i=0;i<100;i++){
        printf("%d%d%d%d%d%d%d%d global = %d\n",n,n,n,n,n,n,n,n,global++);
    }
    return 0;
}
cs


11번 라인은 추후 멀티 스레드에서 확인하기 위한 변수입니다.

21번 라인을 보시면 ThreadFunc 함수를 호출 하도록 되어 있습니다.

그리고 해당 함수에 대해서는 코드 하단에 나와 있습니다.

24번 라인은 결과를 끝까지 확인하기 위해 일시적으로 추가한 코드입니다.


해당 코드에서는 스레드를 추가적으로 만들지 않습니다.

따라서 프로세스에는 Primary thread 하나만 존재함으로써 단일 스레드를 유지합니다.

코드에 대한 결과는 어떻게 될까요?

싱글스레드 실행결과 중간


싱글스레드 실행결과 끝


위의 실행결과를 확인하면 코드에서 for문에 의해서 ThreadFunc 함수가 5번 호출되는 것을 알 수 있습니다.

처음에 ThreadFunc함수가 호출되고 100번 반복될때 까지 다음 코드를 실행하지 않고 함수가 리턴될때 까지 기다립니다.

이것은 출력되는 결과를 보면 알 수 있죠.

함수가 for문의 i를 인자로 받아서 이를 출력하기 때문에 몇번째로 호출된 함수인지를 확인할 수 있습니다.


2. 멀티 스레드(Multi-Thread)

그럼 해당 코드를 약간 바꿔서 단일스레드가 아닌 멀티스레드로 확인해보겠습니다.


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
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
 
DWORD WINAPI ThreadFunc(LPVOID);
// DWORD는 더블워드 = long
// WINAPI : Windows의 API
// LPVOID : ms에서 사용하는 void* 
 
int global = 1;
 
int main()
{
    HANDLE hThrd; //스레드를 접근하기 위한 손잡이 개념
    DWORD threadId; 
    int i;
    // for 루프문
    for (i=0; i<5; i++)
    {
        //ThreadFunc( (LPVOID) i); // single thread 
        //CreateThread함수를 5번 호출
        hThrd = CreateThread(NULL,
            0
            ThreadFunc, //함수포인터: 함수가 시작하는 메모리 주소
                        //아래에서 함수 확인!
            (LPVOID)i, //
            0,
            &threadId ); //
        if (hThrd)
        {
            printf("Thread launched %d\n", i);
            CloseHandle(hThrd);
        }
    }
    // Wait for the threads to complete.
    Sleep(1000);
 
    return EXIT_SUCCESS;
}
 
DWORD WINAPI ThreadFunc(LPVOID n)
{
    int i;
    for (i=0;i<100;i++){
        printf("%d%d%d%d%d%d%d%d global = %d\n",n,n,n,n,n,n,n,n,global++);
    }
    return 0;
}
 
cs


해당 코드를 보면 단순히 ThreadFunc 함수를 호출하는 것이 아니고,

CreateThread 함수를 통해 스레드를 만들고 해당 스레드가 ThreadFunc 함수를 호출하게 합니다.

그럼 그 결과가 어떻게 바뀔까요?


멀티스레드 실행결과 중간


멀티스레드 실행결과 끝


좀 전에 확인한 싱글스레드와의 차이가 보이시나요?

각각의 스레드가 각자 실행되면서 global 변수의 값을 증가시키고 있습니다.


3. 싱글 스레드와 멀티 스레드 시간 차이

이러한 차이가 어떤 결과를 보여줄까요?

각각의 코드에 시간측정함수를 더해 확인해보도록 하겠습니다.

먼저 싱글 스레드의 코드입니다.


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
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#define MAXTHREAD 5
 
DWORD WINAPI ThreadFunc(LPVOID n);
int main () {
    clock_t start, finish;
    double duration;
    DWORD threadId; 
    HANDLE hThrd[MAXTHREAD];
 
    int i;
    start = clock();//현재 시간 반환
 
    for (i=0; i<MAXTHREAD; i++){
        ThreadFunc((LPVOID)i);
    }
    WaitForMultipleObjects(MAXTHREAD, hThrd, TRUE, INFINITE);
    for (i=0; i<MAXTHREAD; i++){
        CloseHandle(hThrd[i]);
    }
    //종료
    finish = clock();
    duration = (double) (finish-start) / CLOCKS_PER_SEC;
    printf("%f 초입니다\n", duration);
    return 0;
}
DWORD WINAPI ThreadFunc(LPVOID n)
{
    for (int i = 0; i<1000000000; i++){
        3+5+8*24;
    }
    return 0;
}
cs


위의 코드를 보면 18번 for문을 통해 ThreadFunc 함수가 총 5번 실행됩니다.

ThreadFunc에서는 단일 연산을 1억번 수행하게됩니다.

그러므로, 해당 싱글스레드에서는 단일 연산을 총 5억번 수행합니다.

21번 라인은 멀티스레드가 종료할때까지 기다려라 라는 함수인데 이에 대한 것은 추후에 설명드리도록 하겠습니다.

해당 코드에 대한 결과는 아래와 같습니다.



대략적으로 12초가 걸렸습니다.

그럼 멀티스레드에서는 어떨까요? 먼저 코드를 확인해보겠습니다.


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
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#define MAXTHREAD 5
 
DWORD WINAPI ThreadFunc(LPVOID n);
int main () {
    clock_t start, finish;
    double duration;
    DWORD threadId; 
    HANDLE hThrd[MAXTHREAD];
 
    int i;
    start = clock();//현재 시간 반환
 
    for (i=0; i<MAXTHREAD; i++){
        hThrd[i] = CreateThread(NULL
            0,        
            ThreadFunc, 
            (LPVOID)i, 
            0,            
            &threadId    
            ); 
    }
    WaitForMultipleObjects(MAXTHREAD, hThrd, TRUE, INFINITE);
    for (i=0; i<MAXTHREAD; i++){
        CloseHandle(hThrd[i]);
    }
    //종료
    finish = clock();
    duration = (double) (finish-start) / CLOCKS_PER_SEC;
    printf("%f 초입니다\n", duration);
    return 0;
}
DWORD WINAPI ThreadFunc(LPVOID n)
{
    for (int i = 0; i<1000000000; i++){
        3+5+8*24;
    }
    return 0;
}
cs


19번~25번 라인을 통해 각각 스레드를 만듭니다.

각각의 스레드가 1억번 단일연산을 수행하므로 위와 동일하게 총 5억번의 연산을 수행합니다.

이러한 멀티스레딩에서의 시간 결과는 어떻게 나올까요?



싱글스레드에서는 약 12초가 소요되었던 5억번의 단일연산이 멀티스레드에서는 3.6초로 줄어들었습니다.

물론 개인 컴퓨터 사양에 따라 시간은 변동될 수 있지만, 그런 점들을 감안해도

싱글스레드와 멀티스레드에 대한 시간효율 차이는 너무나 명백하게 확인할 수 있습니다.




블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc