반응형

게임 개발자나 유저들에게 항상 밀접한 관련이 있는 랜덤값에 대해서 알아보자.

 

개발자 입장에서 가장 처음 접하는 랜덤값과 관련된 함수는 아마도 C++의 rand()함수가 아닐까 싶다.

 

msdn의 함수 설명에서는 이렇게 설명하고 있다.

 

rand() 함수는 int 형의 무작위값을 반환하며 error는 반환하지 않는다.

 

더불어 srand()함수를 통해서 rand에 사용할 seed값을 미리 지정해줘야한다

 

다만, rand() 함수는 0 ~ RAND_MAX(32767) 까지의 값만 반환한다고 되어 있다.

 

위 간단하고 굳이 정밀도를 따지지 않는 확률이 요구될 때에는 해당 함수를 사용해도 문제가 생기진 않을것이다.

 

하지만 위 함수를 사용하면 문제가 발생할 수 있는 경우가 많은데 아래의 상황들이다.

 

우선 첫째로는 해당 함수는 의사난수[Pseudo Random] 이기 때문에 동일한 seed값에 대해서는 항상 동일간 결과가 나온다는 점이다.

[ 물론 이 경우 적용하는 곳에 따라 장점이 될 수 있다. ]

 

두번째로는 아래의 예시에 관한 상황이다.

 

우선 내가 원하는 아이템의 id가 70이라고 할 때 0~100000까지의 item들 중 랜덤으로 아이템을 드롭한다고 생각해보자.

 

rand 함수를 사용할때 우선 발생하는 문제는 랜덤값이 32767까지라는 점이다.

 

위의 예를 통해서 본다면 itemid가 32767보다 큰 경우에는 드롭조차 되지 않는다.

 

두번째 문제는 특정 item에 대한 확률이 미묘하게 달라질 수 있다는 것이다.

 

이번에는 itemid가 1~10000까지있다고 가정하고 itemid를 랜덤으로 얻는 방법이 아래와 같다고 생각해보자.

 

itemid = ((rand()+1)%1000 + 1);

 

위 코드의 경우 itemid 는 1~768 / 768 ~ 1000 구간에서의 itemid가 나올 확률이 미묘하게 다르다.

 

A구간[0 ~ 767]과 B구간[768 ~ 999] 구간의 값의 확률 기대값이 다르기 때문이다

 

A구간의 경우 총 33번 나올 수 있다. (ex : 0~767, 1000~767, ...... 32000 ~ 32767)

 

B구간의 경우 총 32번 나올수 있다. (ex :  768 ~ 999, 1768 ~ 1999, ..... 31768 ~ 31999)

 

즉, A구간에 속한 itemId의 경우  미묘하게 드랍될 확률이 높은 것이다.

 

따라서 정밀도, 기대값에 따라 rand()함수의 사용을 잘 고려해야한다.

 

다른 방식의 랜덤값 추출은 어떤게 있을까

 

중앙제곱법, 선형 합동법, XOR-SHIFT 등 여러 방법이 있지만 우선은 메르센 트위스터라는 방법에 대해서 알아보자.

 

메르센 트위스터란?

 

Mersenne-twister [흔히 mt_rand()] 라고 불린다.

 

이 방법은 메르센 소수라는 값을 사용하며 효율이 좋아 C++11 버전에서 mt19937이 표준으로 채택되었다.

 

사용하는 방법도 매우 간단하다.

int main()
{
	auto randSeed;
    std::mt19937 engine(randSeed);
    std::uniform_int_distribution<int> distibution(0, 100);
    auto gen = distribution(engine);
}

위 코드를 보면 우선 하드웨어 리소스를 사용하여 난수를 생성한 후에 0 ~ 100까지 숫자중 임의의 수를 반환한다.

 

난수엔진에 주는 seed값은 필요에 따라 다른값으로 부여하면 된다.

 

이 메르센 트위스터 방식의 경우 기존 rand() 함수보다 랜덤값의 범위가 더 광범위하므로 특정구간에서의 값이 나올 확률차이는 미미하다.

 

기타 다른방식의 랜덤값 추출의 경우 아래의 출처를 읽어보면 좋을것 같다.

https://namu.wiki/w/%EB%82%9C%EC%88%98%EC%83%9D%EC%84%B1

 

난수생성 - 나무위키

Xn+1=(aXn+c) mod mX_{n+1} = (a X_n + c)\ \text{mod}\ mXn+1​=(aXn​+c) mod m static UINT32 next = 1; int __cdecl rand(void) { next = next * 1103515245 + 12345; return (UINT32)(next>>16) & RAND_MAX; } void __cdecl srand(unsigned int seed) { next = seed; } X는

namu.wiki

 

반응형

'기타 상식' 카테고리의 다른 글

프로그램에서 CPU 시간정보 얻는법  (0) 2019.09.20
함수 호출 정보에 관하여  (0) 2019.09.05
FirebaseMessage 란?  (0) 2019.07.31
멀티 스레드에 관해서  (0) 2019.07.14
ORM이란?  (0) 2019.06.23
Posted by Sweetmeats_boy
반응형

Dead reckoning이란?

1. 서버에서 특정 객체 혹은 Data에 대해서 과도하게 보내지 않게 하기 위한 방법

2. 주로 실시간 시뮬레이션이 요구되는 게임에 적용한다.

 

Dead Reckoning 예시

1. 간단한 물리 공식을 통한 위치 계산

 -> 현재 위치 = 이전 위치 + (속도 * 시간)

 

이해한 바로는 서버가 매 순간마다 특정 Data의 최신 정보를 보내서 갱신하는 것이 아니라

해당 Data가 따르는 혹은 속한 규칙을 통해 최신정보를 어느정도 유추함으로써 패킷 송수신을 줄이는 방법이다.

즉, 일종의 보간 기법을 서버에 적용하는 개념이다.

이 방법의 장점은 단순히 패킷수를 줄인다는 측면도 있지만 좀 더 자연스러운 시뮬레이션을 보여줄 수 있다는 것이다.

클라이언트는 특정 행동이나 키입력 패킷을 받은 후 시뮬레이션을 하며 추가 패킷을 받기전까지

지연없는 시뮬레이션을 수행할 수 있기때문에 패킷 손실등에서 발생할 수 있는 시뮬레이션 오차가 줄어든다.

 

 

 

 

 

반응형

'용어 관련' 카테고리의 다른 글

Process에 대해서  (0) 2023.12.13
proxy server , reverse proxy server  (0) 2021.07.18
Zero Trust Model  (0) 2021.07.18
DeadLock, Live Lock  (0) 2021.06.20
SPOF란  (0) 2021.06.20
Posted by Sweetmeats_boy
반응형

참고자료 : https://developstudy.tistory.com/45

 

C++ IOCP 서버 3. IOCP 구현 (초기화)

* 아직 배우고 있는 학생이라 틀린 내용이 있을 수도 있습니다. 틀린 내용이 있다면 알려주시면 감사하겠습니다. IOCP 이론 : https://developstudy.tistory.com/43?category=836040 C++ IOCP 서버 2. IOCP 이론 *..

developstudy.tistory.com

IOCP는 I/O 처리를 하기 위해서 우선 등록을 한다.

 

우선 CreateIoCompletionPort 함수를 통해서 디바이스와 CompletionPort를 바인딩 할 필요가 있다.

 

이 때 IOCP는 Overlapped를 사용하여 통보를 받아서 처리를 한다.

 

 

Overlapped IO[중첩 입출력 모델]란?

1. NonBlocking, Async 적으로 IO를 처리하는 방법이다.

2. IO를 요청 한 후 별도의 대기시간 없이 리턴 후 다음 작업을 수행한다.

3. 해당 작업의 완료여부를 IOCP를 통해 알 수 있다.

4. 단순 Network만이 아닌 File IO에도 사용이 가능하다.

 

Overlapped IO의 장점

1. IO Blocking이 일어나지 않는다.

2. 버퍼링 오버헤드가 줄어든다.

 - Overlapped IO는 IO 작업 시 OS에서 제공한 버퍼를 사용하지 않고 사용자가 지정한 버퍼를 사용한다.

 -> 단, Overlapped IO 호출을 미리하지 않으면 TCP 수신버퍼로 들어오는 Data가 사용자 버퍼보다 커서 

   TCP 수신 버퍼가 금방 고갈되어 상대에게 Data를 전송하지 못하는 경우가 생길 수 있다.

 -> 단, 해당 이점을 얻기위해서는 별도의 설정값을 지정해줘야 한다.

3. FIFO으로 IO을 처리하는 것이 아닌 SCAN 방식으로 IO을 처리한다.

 * SCAN 방식 찾아볼 것.

 

Overlapped IO 사용 시 주의할 점.

1. Data 전송 시 Data 송신 작업이 완료될 때까지 Data가 있는 사용자 버퍼를 삭제하면 안된다.

 

 

반응형

'Server' 카테고리의 다른 글

서버 Socket 설정하는 방법들  (0) 2019.09.06
게임 서버에서의 Log 구성  (0) 2019.09.04
게임 서버에서의 Log의 분류  (0) 2019.09.04
IOCP에 대하여  (0) 2019.08.26
메세지 큐[Message Queue]  (0) 2019.07.14
Posted by Sweetmeats_boy

블로그 이미지
Sweetmeats_boy

태그목록

Yesterday
Today
Total

달력

 « |  » 2024.11
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

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함