검색결과 리스트
Programming/C/C++에 해당되는 글 12건
- 2016.03.31 rand() 알고리즘
- 2015.06.04 D3DXFX_LARGEADDRESS_HANDLE 1
- 2015.01.13 국가 코드 얻기 1
- 2014.11.10 StackWalk
- 2014.08.21 HeapValidate function 2
- 2014.07.22 CPUInfo
- 2014.06.30 Memory Bandwidth
- 2014.06.24 비디오 메모리 구하기
- 2014.06.22 [WinAPI] 컴퓨터 각종 부품 정보 알아내기 1
- 2014.06.22 GlobalMemoryStatusEx
글
rand() 알고리즘
http://codesafe.tistory.com/80
갑짜기 rand 함수의 내부에 대하여 궁금해 졌습니다.
그래서 여기 저기 수소문 하여 알아낸 자료를 정리 합니다. (문론 우리의 VC 기반으로)
우리는 VC기반에서 random 값을 얻기 위하여 srand() 그리고 rand()라는 두가지 함수를 사용합니다.
(예전 볼랜드 C / WATCOM C 에서는 randomize를 사용했던것 같은데 기억이 안나네요.)
그럼 우리가 사용하는 srand 와 rand 함수를 봅시다.
(불법으로 COPY 해온 VC 디버그 상태의 내용 -_-;)
void __cdecl srand (unsigned int seed)
{
holdrand = (long)seed;
}
int __cdecl rand (void)
{
return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
}
결국 srand() 함수에서는 seed(씨앗)이라는 일종의 Start Point value를 부여하고 rand() 함수에서 결과 값을 다시 seed로 사용하는 수식으로 불특정한 값을 얻는다.
역시 가장 중요한 것은 바로 이 공식!
이 공식을 보자니 수학적인 냄새가 폴폴 난다. 그럼 잘 알려져 있는 두가지 랜덤 생성 알고리즘을 보자.
1) 네 자리 숫자 X를 선택한다.
2) X^2 를 취한다.
3) 결과에서 첫번째 숫자와 마지막 숫자를 네 자리 숫자가 남을 때까지 제거한다.
4) 이것이 난수이다.
5) 이 난수를 X로 놓고 반복한다.
1) n->(n*m)+k
2) n->n MOD p
3) n은 난수이다.
4) n을 사용해서 반복한다.
* n, m, k, p는 실행 전에 선택된다.
* 이 알고리즘을 고안한 듀드니조차도 m, k, p가 조심스럽게 선택되지 않으면 결과는 형편없을 것이라고 말했다.
위의 내용을 근거로 VC의 rand() 함수를 보니 두번째 듀드니 알고리즘을 채택 했군뇨. (거의 붕어 빵입니다.)
허나 위에서 말한대로 m, k, p 값을 어떤 근거로 만든건지는 모르겠습니다.
----------------------------------------------------------------------------------------------
* _holdrand 초기값은 1L로 설정되며 srand()를 쓰래드마다 해주지 않으면 같은 rand값이 나옵니다.
----------------------------------------------------------------------------------------------
http://www.gamedevforever.com/114?fb_action_ids=713010812094866&fb_action_types=og.likes
안녕하세요. 알콜코더 민군입니다.
현재 제작 중인 게임에서, 랜덤 시드 값을 일치 시켜서, 랜덤 결과를 서로 다른 클라이언트끼리 동기화 시키는 작업을 진행 하였습니다. 랜덤 시드값만 서로 일치시키면, 이후에 생성되는 랜덤 함수의 결과값들은 모두 일치가 되기 때문에, 예전에 스타크래프트와 같은 패키지 게임에서 자주 사용했던 테크닉입니다. ^^; 서로 다른 클라이언트끼리 처음 시드값만 일치 시키면, 이후의 랜덤값은 정해져 있기 때문에, 그 랜덤값을 사용한 이벤트등의 동기화에 사용하는 것이죠.
이런 테크닉은 패키지 게임 시절에는 리플레이 저장이나 네트워크 동기화등에서 상당히 많이 사용하였습니다. 하지만 온라인 게임으로 넘어오면서, 대부분 서버에서 랜덤값을 직접 생성하여 넘겨주기 때문에, 이 테크닉 쓸일이 거의 없었는데… 이번 상황은 랜덤값이 게임의 결과에 전혀 영향을 끼치 않고, 단지 연출에만 영향을 끼치기 때문에 이 테크닉을 사용하기로 하였습니다. (서버 부담을 줄여달라는 서버쪽의 간절한 요청 때문에.. 아흑..OTL)
일반적으로 랜덤 함수라면 C++ 표준 rand() 함수를 사용하게 됩니다. 뭐.. 일반적인 랜덤값을 사용하는 경우에는 사실 이 표준 함수를 사용해도, 별 문제는 없습니다. ^^; 하지만 위와 같은 테크닉을 사용할 때는 rand() 함수를 사용하면 안됩니다!
왜냐하면, C++의 표준 rand() 함수는 아래와 같은 약간의 문제점을 가지고 있습니다.
|
< 즉 이런 기적의 확률이 나올수도 있는거임.. ㅠ.ㅠ >
저의 경우에 문제가 되는 것은 1번이 아니라, 2번입니다. 같은 랜덤 시드값으로 서로 다른 클라이언트에서, 싱크를 맞추기 위해서는 랜덤 호출 횟수가 정확히(!) 일치하여야 합니다! 내가 랜덤함수를 5번 호출했으면, 상대방도 5번 호출해야 같은 결과 값이 나와서 싱크가 일치하게 됩니다.
그런데 만약? 내가 작성한 코드가 아니라 어딘가 다른 코드에서 그것도 한쪽 클라이언트에서만 그 사이에 rand()를 호출하게 되면 어떻게 될까요? 넵. 당연히 그 다음부터는 모든 싱크가 아작이 나게됩니다…(그리고 이 경우에는 어디서부터 문제가 발생 했는지 찾는 것도 거의 불가능)
전역 함수라는 특징 때문에, 어디서 어떻게 불리울지 모르기 때문에, 언제 호출 횟수가 어긋날지 모른다는 문제가 발생하기 때문에, 랜덤 시드로 씽크를 맞추는 이 테크닉에서는 rand() 함수를 사용하는 것은 불가능 합니다. (내 코드에서는 절대 그럴리가 없어! 라고 해도… 다른 사람이 작성한 코드에서 과연 부르지 않는다는 보장이 있을까요…)
그래서 따로 랜덤 생성 클래스를 만들어 사용하게 됩니다. 랜덤 클래스를 만들고 그 인스턴스만을 사용하게 되면, 호출 횟수가 어긋나는 문제를 해결할 수 있으니까요. ^^
저의 경우가 바로 이런 경우라서, 랜덤 생성 알고리즘을 한번 찾아 봤습니다. 랜덤 생성 알고리즘은 "난수 생성기(Random Number Generator)", 혹은 "의사 난수 생성기" 등으로 불리웁니다. (그냥 저는 편의를 위해.. 이후 '랜덤 생성기'라고 칭하겠습니다. 이게 걍 편해요…)
이렇게 따로 랜덤 생성기를 이용해서, 랜덤 생성 클래스를 만들어 사용하면, 위와 같이 코드의 다른곳에서 랜덤값이 불리우는 경우를 제어할 수 있습니다. 물론 그렇다고 랜덤 생성 알고리즘을 혼자 고급 수학책이나 물리책 펴놓고 만들어서 쓰라는 이야기는 아닙니다. 친절하게도 이런 알고리즘은 전문 수학자 분들이 편하게 갖다 쓸수 있도록 편하고도 멋지게 만들어 두었습니다. (아이구~ 이런 감사할때가….)
이런 랜덤 생성기중에서 가장 유명하고 널리 쓰이는 알고리즘이 바로 [메르센 트위스터(MT.Mersenne Twister)]와 [WELL]이라는 랜덤 생성기입니다.
그리고 이 랜덤 생성기들은 위와 같은 테크닉에 사용할 수 있는 용도 외에도 다음과 같은 뛰어난 장점들을 가지고 있습니다
|
메르센 트위스터위키백과, 우리 모두의 백과사전. 메르센 트위스터(Mersenne Twister)는 1997년에 마츠모토 마코토(松本 眞)와 니시무라 다쿠지(西村拓士)가 개발한 유사난수 생성기이다.[1] 메르센 트위스터는 동일한 저자들이 개발한 TT800 생성기의 개선판으로, 기존 생성기들의 문제점들을 피하면서 매우 질이 좋은 난수를 빠르게 생성할 수 있도록 설계되었다. 메르센 트위스터의 이름은 난수의 반복 주기가 메르센 소수인 데에서 유래했다. 메르센 트위스터는 그 속도와 난수의 품질 때문에 점점 많은 곳에서 채택되고 있으며, 흔히 주기가 219937 − 1인 MT19937을 사용한다. MT19937과 같으나 생성해 내는 난수가 32비트가 아닌 64비트인MT19937-64도 쓰이며, 2006년에 동일한 저자들이 발표한 SIMD 기반 메르센 트위스터는 MT19937에 비해 대략두 배 정도 빠른 것으로 알려져 있다. 난수의 품질에도 불구하고, 메르센 트위스터는 암호학적으로 안전한 유사난수 생성기가 아니다. 즉 난수의 특성(주기, 난수 범위)을 알고 있을 때 유한한 수의 난수(이 경우 624개)만으로 현재 생성기의 상태를 알아 낼 수 있으며, 그 뒤에 나올 난수를 예측해 낼 수 있다. 암호학적으로안전한 유사난수 생성기를 얻기 위해서는 해시 함수를 사용해야 하지만 난수의 생성 속도가 낮아진다. 또는 블룸 블룸 슙(BBS)과 같이 암호학적으로 안전하게 설계된 생성기를 쓸 수도 있다. |
메르센 트위스터는 현재도 가장 널리 사용되고 있는 랜덤 생성기입니다. C++에서는 Boost에도 이 MT 랜덤 생성기가 구현 되어 있습니다. 또한 MATLAB, Ruby, Python등의 언어에서도 기본 난수 알고리즘으로 채택되어서 사용 되고 있습니다. 뭐 물론 단점이 없는 건 아니지만, 장점이 훨씬 더 크기 때문에 표준으로 채택이 되었겠죠. ^^
그리고 가장 큰 장점은 특별히 따로 구현하지 않아도, Boost에 포함되어 있기 때문에, Boost만 있다면 바로 사용이 가능하다는 장점이 있습니다. 사용 방법에 관해서는 하단의 참조 링크에서 확인하실 수 있습니다.
WELL
WELL은 위 MT의 디자이너가 10년후에 고안한 난수 발생 알고리즘 입니다. 그의 주장에 따르면 MT보다 40% 빠르고 코드도 더 간단합니다. WELL은 분포도에 따라서 WELL512, WELL1024, WELL19947, WELL44497의 종류가 있습니다. 숫자가 클수록 분포도가 높긴 하지만, 게임에서 사용하기엔 512나 1024만으로도 충분할 것 같습니다.
WELL의 구현 코드는 이곳에서 받을 수 있습니다. 실제로 보면 정말 구현은 간단합니다.
아래가 WELL512의 구현 코드입니다.
이게 다입니다. Period는 이름 그대로 2^512입니다. 그렇다 해도 일반 PC로 저걸 세는데 10^100년이 걸린다고 하는군요. 초나 분이 아니라 년 말입니다. (googol years라고 부른다고 하는군요)
사용법은 위의 state만 적절히 초기화 해주고, 함수를 호출하면 32비트 정수(난수)가 리턴됩니다.
간단한 시물레이터로 두 난수 발생기를 시뮬레이팅 해 보았을 때의 차이를 보여드리겠습니다.
일반적으로 게임 개발할때는 이런 랜덤 생성기까지 필요 하지 않을지도 모릅니다. 그러나 MMORPG와 같이 랜덤이 게임의 밸런스에 큰 영향을 끼치는 경우에는, 서버 측에서 이런 고성능의 랜덤 생성기가 필요한 경우가 많습니다. 유저나 해커가 랜덤값을 함부로 예측해서는 안되니까요. ^^; 그리고 저의 경우 처럼 랜덤 시드를 이용해서 이벤트 동기화를 맞추는 경우에는 전역 함수인 rand()를 사용할 수 없기 때문에 꼭 이런 랜덤 함수가 별도로 필요합니다. 그런 경우에 굳이 이런 좋은 난수 알고리즘들을 놔두고 새로 짜는 고생은 안하는게 낫겠죠.(그렇다고 내가 만든 알고리즘이 저것보다 좋을리는 택도 없을 테니…=ㅅ=;)
< 참고 자료 > 위키피디아 : 메르센 트위스터 [한글] Generating random numbers in game.[한글] |
'Programming > C/C++' 카테고리의 다른 글
D3DXFX_LARGEADDRESS_HANDLE (1) | 2015.06.04 |
---|---|
국가 코드 얻기 (1) | 2015.01.13 |
StackWalk (0) | 2014.11.10 |
HeapValidate function (2) | 2014.08.21 |
CPUInfo (0) | 2014.07.22 |
설정
트랙백
댓글
글
D3DXFX_LARGEADDRESS_HANDLE
-. 32bit 프로세스에서 최대 4G까지 메모리를 사용할 수 있는 링크 옵션.
-. 의외로 기존 개발자 중에 이 옵션을 모르는 개발자들이 많다.
-. 64bit가 가야 할 길이지만 현실은 그리 만만하지 않다.
1. 켜는 법
-. EXE 프로젝트 속성창/구성 속성/링커/시스템 항목에 큰 주소 처리를 켠다.
(DLL 프로젝트는 변경해도 의미가 없다.)
2. 추가 작업
-. 전처리기에 D3DXFX_LARGEADDRESS_HANDLE 매크로 정의
-. D3DXGetShaderConstantTable() => D3DXGetShaderConstantTableEx() 로 변경 후
플래그에 D3DXCONSTTABLE_LARGEADDRESSAWARE 추가.
-. 쉐이더 이펙트 생성시 D3DXFX_LARGEADDRESSAWARE 추가.
-. 이펙트 핸들 이름으로 스트링 사용 금지.
https://msdn.microsoft.com/ko-kr/library/windows/desktop/bb172855(v=vs.85).aspx
http://www.slideshare.net/devcatpublications/10ndc2012 <- 여기도 오타 있음
이펙트 핸들 이름으로 스트링 사용 금지
D3DXFX_LARGEADDRESSAWARE Enables the allocation of an effect resource into the uppder address space of a machine. One important limitation is that you cannot use strings and handles interchangeably. For example, the following would no longer work.
Copy
g_pEffect->SetMatrix( "g_mWorldViewProjection", &mWorldViewProjection );
Instead, a method such as GetParameterByName must be used to store the handle of the parameter, which is then used to pass variables to the effect.
위 링크 중 전형규님께서 알려주신 내용입니다.
'Programming > C/C++' 카테고리의 다른 글
rand() 알고리즘 (0) | 2016.03.31 |
---|---|
국가 코드 얻기 (1) | 2015.01.13 |
StackWalk (0) | 2014.11.10 |
HeapValidate function (2) | 2014.08.21 |
CPUInfo (0) | 2014.07.22 |
설정
트랙백
댓글
글
국가 코드 얻기
// OS 정보를 얻어 국가 코드를 얻는다.
char szNation[7];
if( 0 != GetLocaleInfo( LOCALE_SYSTEM_DEFAULT, LOCALE_ICOUNTRY, szNation, 7 ) )
{
iLang = atoi( szNation );
}
switch( iLang )
{
case 82: // KOR(대한민국)
case 1: // USA(미국)
case 7: // RUS(러시아)
case 81: // 일본
case 86: // 중국
...
break;
}
'Programming > C/C++' 카테고리의 다른 글
rand() 알고리즘 (0) | 2016.03.31 |
---|---|
D3DXFX_LARGEADDRESS_HANDLE (1) | 2015.06.04 |
StackWalk (0) | 2014.11.10 |
HeapValidate function (2) | 2014.08.21 |
CPUInfo (0) | 2014.07.22 |
설정
트랙백
댓글
글
StackWalk
http://msdn.microsoft.com/en-us/library/windows/desktop/ms680650%28v=vs.85%29.aspx
http://stackwalker.codeplex.com/
쓰래드 처리는 안되있네..
VS2013에서 (v90으로 빌드)_snprintf_s() 함수에서 에러나서 memcpy_s로 변경 사용권장
'Programming > C/C++' 카테고리의 다른 글
D3DXFX_LARGEADDRESS_HANDLE (1) | 2015.06.04 |
---|---|
국가 코드 얻기 (1) | 2015.01.13 |
HeapValidate function (2) | 2014.08.21 |
CPUInfo (0) | 2014.07.22 |
Memory Bandwidth (0) | 2014.06.30 |
설정
트랙백
댓글
글
HeapValidate function
'Programming > C/C++' 카테고리의 다른 글
국가 코드 얻기 (1) | 2015.01.13 |
---|---|
StackWalk (0) | 2014.11.10 |
CPUInfo (0) | 2014.07.22 |
Memory Bandwidth (0) | 2014.06.30 |
비디오 메모리 구하기 (0) | 2014.06.24 |
설정
트랙백
댓글
글
CPUInfo
'Programming > C/C++' 카테고리의 다른 글
StackWalk (0) | 2014.11.10 |
---|---|
HeapValidate function (2) | 2014.08.21 |
Memory Bandwidth (0) | 2014.06.30 |
비디오 메모리 구하기 (0) | 2014.06.24 |
[WinAPI] 컴퓨터 각종 부품 정보 알아내기 (1) | 2014.06.22 |
설정
트랙백
댓글
글
Memory Bandwidth
http://www.cs.virginia.edu/stream/
ATI의 경우 AMD Display Library (ADL) SDK 를 사용하면 바로 bandwidth를 구할 수 있다.
Nvidia의 경우 CUDA에서는 되는데 NxApi를 사용해서 구하는 방법은 찾지 못했다.
'Programming > C/C++' 카테고리의 다른 글
HeapValidate function (2) | 2014.08.21 |
---|---|
CPUInfo (0) | 2014.07.22 |
비디오 메모리 구하기 (0) | 2014.06.24 |
[WinAPI] 컴퓨터 각종 부품 정보 알아내기 (1) | 2014.06.22 |
GlobalMemoryStatusEx (0) | 2014.06.22 |
설정
트랙백
댓글
글
비디오 메모리 구하기
http://code.msdn.microsoft.com/windowsdesktop/DirectX-Video-Memory-ee7d8319
여기에 나온 방법으로 했어도 실시간으로 변화하는 GPU 메모리 사용량을 표시 할수는 없었다. 내가... 잘 못한건가?.. 어째든 실시간 비디오 메모리 사용량을 측정하기 위해 Nvidia를 떠돌며 삽질만 하다가 Nvapi.dll을 통하여 해결하였다.// KGpuMon.h 源代码 #pragma once #define MAX_GPU_NUM 4L // 监控的GPU个数(NVIDIA定义的最多GPU个数是64,这里最多只监控4个) #define MY_PROCESS_ERROR(Condition) do { if (!(Condition)) goto Exit0; } while (false) #define MAX_DISPLAY_CARDS 4 // 最多监控4块显卡(暂时应该够了吧) // 常量定义 #define MAX_PHYSICAL_GPUS 64 #define SHORT_STRING_MAX 64 #define MAX_THERMAL_SENSORS_PER_GPU 3 #define MAX_CLOCKS_PER_GPU 0x120 #define MAX_PSTATES_PER_GPU 8 #define MAX_USAGES_PER_GPU 33 #define MAX_COOLER_PER_GPU 20 #define MAX_MEMORY_VALUES_PER_GPU 5 // 接口ID值 #define ID_NvAPI_Initialize 0x0150E828 #define ID_NvAPI_GPU_GetFullName 0xCEEE8E9F #define ID_NvAPI_GPU_GetThermalSettings 0xE3640A56 #define ID_NvAPI_EnumNvidiaDisplayHandle 0x9ABDD40D #define ID_NvAPI_GetPhysicalGPUsFromDisplay 0x34EF9506 #define ID_NvAPI_EnumPhysicalGPUs 0xE5AC921F #define ID_NvAPI_GPU_GetTachReading 0x5F608315 #define ID_NvAPI_GPU_GetAllClocks 0x1BD69F49 #define ID_NvAPI_GPU_GetPStates 0x60DED2ED #define ID_NvAPI_GPU_GetUsages 0x189A1FDF #define ID_NvAPI_GPU_GetCoolerSettings 0xDA141340 #define ID_NvAPI_GPU_SetCoolerLevels 0x891FA0AE #define ID_NvAPI_GPU_GetMemoryInfo 0x774AA982 #define ID_NvAPI_GetDisplayDriverVersion 0xF951A4D1 #define ID_NvAPI_GetInterfaceVersionString 0x01053FA5 #define ID_NvAPI_GPU_GetPCIIdentifiers 0x2DDFB66E // 版本号参数定义 #define GPU_THERMAL_SETTINGS_VER (sizeof(NvGPUThermalSettings) | 0x10000) #define GPU_CLOCKS_VER (sizeof(NvClocks) | 0x20000) #define GPU_PSTATES_VER (sizeof(NvPStates) | 0x10000) #define GPU_USAGES_VER (sizeof(NvUsages) | 0x10000) #define GPU_COOLER_SETTINGS_VER (sizeof(NvGPUCoolerSettings) | 0x20000) #define GPU_MEMORY_INFO_VER (sizeof(NvMemoryInfo) | 0x20000) #define DISPLAY_DRIVER_VERSION_VER (sizeof(NvDisplayDriverVersion) | 0x10000) #define GPU_COOLER_LEVELS_VER (sizeof(NvGPUCoolerLevels) | 0x10000) enum NvStatus { enumNvStatus_OK = 0, enumNvStatus_ERROR = -1, enumNvStatus_LIBRARY_NOT_FOUND = -2, enumNvStatus_NO_IMPLEMENTATION = -3, enumNvStatus_API_NOT_INTIALIZED = -4, enumNvStatus_INVALID_ARGUMENT = -5, enumNvStatus_NVIDIA_DEVICE_NOT_FOUND = -6, enumNvStatus_END_ENUMERATION = -7, enumNvStatus_INVALID_HANDLE = -8, enumNvStatus_INCOMPATIBLE_STRUCT_VERSION = -9, enumNvStatus_HANDLE_INVALIDATED = -10, enumNvStatus_OPENGL_CONTEXT_NOT_CURRENT = -11, enumNvStatus_NO_GL_EXPERT = -12, enumNvStatus_INSTRUMENTATION_DISABLED = -13, enumNvStatus_EXPECTED_LOGICAL_GPU_HANDLE = -100, enumNvStatus_EXPECTED_PHYSICAL_GPU_HANDLE = -101, enumNvStatus_EXPECTED_DISPLAY_HANDLE = -102, enumNvStatus_INVALID_COMBINATION = -103, enumNvStatus_NOT_SUPPORTED = -104, enumNvStatus_PORTID_NOT_FOUND = -105, enumNvStatus_EXPECTED_UNATTACHED_DISPLAY_HANDLE = -106, enumNvStatus_INVALID_PERF_LEVEL = -107, enumNvStatus_DEVICE_BUSY = -108, enumNvStatus_NV_PERSIST_FILE_NOT_FOUND = -109, enumNvStatus_PERSIST_DATA_NOT_FOUND = -110, enumNvStatus_EXPECTED_TV_DISPLAY = -111, enumNvStatus_EXPECTED_TV_DISPLAY_ON_DCONNECTOR = -112, enumNvStatus_NO_ACTIVE_SLI_TOPOLOGY = -113, enumNvStatus_SLI_RENDERING_MODE_NOTALLOWED = -114, enumNvStatus_EXPECTED_DIGITAL_FLAT_PANEL = -115, enumNvStatus_ARGUMENT_EXCEED_MAX_SIZE = -116, enumNvStatus_DEVICE_SWITCHING_NOT_ALLOWED = -117, enumNvStatus_TESTING_CLOCKS_NOT_SUPPORTED = -118, enumNvStatus_UNKNOWN_UNDERSCAN_CONFIG = -119, enumNvStatus_TIMEOUT_RECONFIGURING_GPU_TOPO = -120, enumNvStatus_DATA_NOT_FOUND = -121, enumNvStatus_EXPECTED_ANALOG_DISPLAY = -122, enumNvStatus_NO_VIDLINK = -123, enumNvStatus_REQUIRES_REBOOT = -124, enumNvStatus_INVALID_HYBRID_MODE = -125, enumNvStatus_MIXED_TARGET_TYPES = -126, enumNvStatus_SYSWOW64_NOT_SUPPORTED = -127, enumNvStatus_IMPLICIT_SET_GPU_TOPOLOGY_CHANGE_NOT_ALLOWED = -128, enumNvStatus_REQUEST_USER_TO_CLOSE_NON_MIGRATABLE_APPS = -129, enumNvStatus_OUT_OF_MEMORY = -130, enumNvStatus_WAS_STILL_DRAWING = -131, enumNvStatus_FILE_NOT_FOUND = -132, enumNvStatus_TOO_MANY_UNIQUE_STATE_OBJECTS = -133, enumNvStatus_INVALID_CALL = -134, enumNvStatus_D3D10_1_LIBRARY_NOT_FOUND = -135, enumNvStatus_FUNCTION_NOT_FOUND = -136 }; enum NvThermalController { enumNvThermalController_NONE = 0, enumNvThermalController_GPU_INTERNAL, enumNvThermalController_ADM1032, enumNvThermalController_MAX6649, enumNvThermalController_MAX1617, enumNvThermalController_LM99, enumNvThermalController_LM89, enumNvThermalController_LM64, enumNvThermalController_ADT7473, enumNvThermalController_SBMAX6649, enumNvThermalController_VBIOSEVT, enumNvThermalController_OS, enumNvThermalController_UNKNOWN = -1, }; enum NvThermalTarget { enumNvThermalTarget_NONE = 0, enumNvThermalTarget_GPU = 1, enumNvThermalTarget_MEMORY = 2, enumNvThermalTarget_POWER_SUPPLY = 4, enumNvThermalTarget_BOARD = 8, enumNvThermalTarget_ALL = 15, enumNvThermalTarget_UNKNOWN = -1 }; typedef struct _NvSensor { NvThermalController Controller; unsigned int DefaultMinTemp; unsigned int DefaultMaxTemp; unsigned int CurrentTemp; NvThermalTarget Target; }NvSensor; typedef struct _NvGPUThermalSettings { unsigned int Version; unsigned int Count; NvSensor Sensor[MAX_THERMAL_SENSORS_PER_GPU]; }NvGPUThermalSettings; typedef struct _NvClocks { unsigned int Version; unsigned int Clock[MAX_CLOCKS_PER_GPU]; }NvClocks; typedef struct _NvPState { bool Present; int Percentage; }NvPState; typedef struct _NvPStates { unsigned int Version; unsigned int Flags; NvPState PStates[MAX_PSTATES_PER_GPU]; }NvPStates; typedef struct _NvUsages { unsigned int Version; unsigned int Usages[MAX_USAGES_PER_GPU]; }NvUsages; typedef struct _NvCooler { int Type; int Controller; int DefaultMin; int DefaultMax; int CurrentMin; int CurrentMax; int CurrentLevel; int DefaultPolicy; int CurrentPolicy; int Target; int ControlType; int Active; }NvCooler; typedef struct _NvGPUCoolerSettings { unsigned int Version; unsigned int Count; NvCooler Coolers[MAX_COOLER_PER_GPU]; }NvGPUCoolerSettings; typedef struct _NvLevel { int Level; int Policy; }NvLevel; typedef struct _NvGPUCoolerLevels { unsigned int Version; NvLevel Levels[MAX_COOLER_PER_GPU]; }NvGPUCoolerLevels; typedef struct _NvMemoryInfo { unsigned int Version; unsigned int Values[MAX_MEMORY_VALUES_PER_GPU]; }NvMemoryInfo; typedef struct _NvDisplayDriverVersion { unsigned int Version; unsigned int DriverVersion; unsigned int BldChangeListNum; char szBuildBranch[SHORT_STRING_MAX]; char szAdapter[SHORT_STRING_MAX]; }NvDisplayDriverVersion; typedef int NvPhysicalGpuHandle; typedef int NvDisplayHandle; // 函数定义 typedef void* (*nvapi_QueryInterfaceType)(unsigned int uiInterfaceID); typedef NvStatus (*NvAPI_InitializeType)(); typedef NvStatus (*NvAPI_GPU_GetFullNameType)(const NvPhysicalGpuHandle gpuHandle, char *pszName); typedef NvStatus (*NvAPI_GPU_GetThermalSettingsType)(const NvPhysicalGpuHandle gpuHandle, int sensorIndex, NvGPUThermalSettings *pnvGPUThermalSettings); typedef NvStatus (*NvAPI_EnumNvidiaDisplayHandleType)(const int thisEnum, NvDisplayHandle *pDisplayHandle); typedef NvStatus (*NvAPI_GetPhysicalGPUsFromDisplayType)(const NvDisplayHandle displayHandle, NvPhysicalGpuHandle *pGpuHandles, unsigned int *pGpuCount); typedef NvStatus (*NvAPI_EnumPhysicalGPUsType)(NvPhysicalGpuHandle *pGpuHandles, int *pGpuCount); typedef NvStatus (*NvAPI_GPU_GetTachReadingType)(const NvPhysicalGpuHandle gpuHandle, int *pnValue); typedef NvStatus (*NvAPI_GPU_GetAllClocksType)(const NvPhysicalGpuHandle gpuHandle, NvClocks *pnvClocks); typedef NvStatus (*NvAPI_GPU_GetPStatesType)(const NvPhysicalGpuHandle gpuHandle, NvPStates *pnvPStates); typedef NvStatus (*NvAPI_GPU_GetUsagesType)(const NvPhysicalGpuHandle gpuHandle, NvUsages *pnvUsages); typedef NvStatus (*NvAPI_GPU_GetCoolerSettingsType)(const NvPhysicalGpuHandle gpuHandle, int coolerIndex, NvGPUCoolerSettings *pnvGPUCoolerSettings); typedef NvStatus (*NvAPI_GPU_SetCoolerLevelsType)(const NvPhysicalGpuHandle gpuHandle, int coolerIndex, NvGPUCoolerLevels *pnvGPUCoolerLevels); typedef NvStatus (*NvAPI_GPU_GetMemoryInfoType)(const NvDisplayHandle displayHandle, NvMemoryInfo *pnvMemoryInfo); typedef NvStatus (*NvAPI_GetDisplayDriverVersionType)(const NvDisplayHandle displayHandle, NvDisplayDriverVersion *pnvDisplayDriverVersion); typedef NvStatus (*NvAPI_GetInterfaceVersionStringType)(char *pszVersion); typedef NvStatus (*NvAPI_GPU_GetPCIIdentifiersType)( const NvPhysicalGpuHandle gpuHandle, unsigned int *puiDeviceId, unsigned int *puiSubSystemId, unsigned int *puiRevisionId, unsigned int *puiExtDeviceId ); //*****************************以下是类内部使用的结构体************************************// /* * @brief GPU信息 */ typedef struct _GPU_INFO { NvPhysicalGpuHandle nvGpuHandle; // GPU句柄 int nUsage; // GPU占用率 }GPU_INFO; /* * @brief 显卡信息 */ typedef struct _DISPLAY_CARD_INFO { NvDisplayHandle nvDisplayHandle; // 显卡句柄 int nGpuCount; // Gpu个数 DWORD dwTotalMemory; // 总显存大小(KB) DWORD dwFreeMemory; // 空闲显存大小(KB) GPU_INFO sGpuInfo[MAX_GPU_NUM]; // GPU信息 }DISPLAY_CARD_INFO; //*****************************************************************************************// /* * @brief 显卡相关信息(可用于导出的结构体) */ typedef struct _DISPLAY_INFO { int nGpuCount; // Gpu个数 int nGpuUsages[MAX_GPU_NUM]; // Gpu占用率 DWORD dwTotalMemory; // 总显存大小(KB) DWORD dwFreeMemory; // 空闲显存大小(KB) }DISPLAY_INFO; class KGpuMon { public: KGpuMon(void); ~KGpuMon(void); BOOL Init(); BOOL Unit(); int GetDisplayCardCount(); BOOL GetDisplayInfo(const int nCardIndex, DISPLAY_INFO *pDisplayInfo); private: int EnumDisplayCards(); BOOL GetGpuHandles(const NvDisplayHandle nvDisplayHandle, DISPLAY_CARD_INFO *pCardInfo); BOOL GetDisplayCardGpuUsages(const NvDisplayHandle nvDisplayHandle, DISPLAY_CARD_INFO *pCardInfo); BOOL GetDisplayCardMemoryInfo(const NvDisplayHandle nvDisplayHandle, DISPLAY_CARD_INFO *pCardInfo); private: nvapi_QueryInterfaceType m_pfnNvapi_QueryInterface; NvAPI_InitializeType m_pfnNvAPI_Initialize; NvAPI_GPU_GetFullNameType m_pfnNvAPI_GPU_GetFullName; NvAPI_GPU_GetThermalSettingsType m_pfnNvAPI_GPU_GetThermalSettings; NvAPI_EnumNvidiaDisplayHandleType m_pfnNvAPI_EnumNvidiaDisplayHandle; NvAPI_GetPhysicalGPUsFromDisplayType m_pfnNvAPI_GetPhysicalGPUsFromDisplay; NvAPI_EnumPhysicalGPUsType m_pfnNvAPI_EnumPhysicalGPUs; NvAPI_GPU_GetTachReadingType m_pfnNvAPI_GPU_GetTachReading; NvAPI_GPU_GetAllClocksType m_pfnNvAPI_GPU_GetAllClocks; NvAPI_GPU_GetPStatesType m_pfnNvAPI_GPU_GetPStates; NvAPI_GPU_GetUsagesType m_pfnNvAPI_GPU_GetUsages; NvAPI_GPU_GetCoolerSettingsType m_pfnNvAPI_GPU_GetCoolerSettings; NvAPI_GPU_SetCoolerLevelsType m_pfnNvAPI_GPU_SetCoolerLevels; NvAPI_GPU_GetMemoryInfoType m_pfnNvAPI_GPU_GetMemoryInfo; NvAPI_GetDisplayDriverVersionType m_pfnNvAPI_GetDisplayDriverVersion; NvAPI_GetInterfaceVersionStringType m_pfnNvAPI_GetInterfaceVersionString; NvAPI_GPU_GetPCIIdentifiersType m_pfnNvAPI_GPU_GetPCIIdentifiers; int m_nDisplayCardCount; DISPLAY_CARD_INFO* m_pDisplayCards; HMODULE m_hNvApiDll; }; //**************************************************************************************************/ // KGpuMon.cpp 源代码 #include "StdAfx.h" #include "KGpuMon.h" KGpuMon::KGpuMon(void) { m_hNvApiDll = NULL; m_nDisplayCardCount = 0; m_pDisplayCards = NULL; } KGpuMon::~KGpuMon(void) { Unit(); } BOOL KGpuMon::Init() { BOOL bResult = FALSE; BOOL bRetCode = FALSE; int nIndex = 0; int nResult = 0; m_hNvApiDll = LoadLibrary(_T("nvapi.dll")); if (m_hNvApiDll) { m_pfnNvapi_QueryInterface = (nvapi_QueryInterfaceType)GetProcAddress(m_hNvApiDll, "nvapi_QueryInterface"); if (m_pfnNvapi_QueryInterface) { m_pfnNvAPI_Initialize = (NvAPI_InitializeType)m_pfnNvapi_QueryInterface(ID_NvAPI_Initialize); m_pfnNvAPI_GPU_GetFullName = (NvAPI_GPU_GetFullNameType)m_pfnNvapi_QueryInterface(ID_NvAPI_GPU_GetFullName); m_pfnNvAPI_GPU_GetThermalSettings = (NvAPI_GPU_GetThermalSettingsType)m_pfnNvapi_QueryInterface(ID_NvAPI_GPU_GetThermalSettings); m_pfnNvAPI_EnumNvidiaDisplayHandle = (NvAPI_EnumNvidiaDisplayHandleType)m_pfnNvapi_QueryInterface(ID_NvAPI_EnumNvidiaDisplayHandle); m_pfnNvAPI_GetPhysicalGPUsFromDisplay = (NvAPI_GetPhysicalGPUsFromDisplayType)m_pfnNvapi_QueryInterface(ID_NvAPI_GetPhysicalGPUsFromDisplay); m_pfnNvAPI_EnumPhysicalGPUs = (NvAPI_EnumPhysicalGPUsType)m_pfnNvapi_QueryInterface(ID_NvAPI_EnumPhysicalGPUs); m_pfnNvAPI_GPU_GetTachReading = (NvAPI_GPU_GetTachReadingType)m_pfnNvapi_QueryInterface(ID_NvAPI_GPU_GetTachReading); m_pfnNvAPI_GPU_GetAllClocks = (NvAPI_GPU_GetAllClocksType)m_pfnNvapi_QueryInterface(ID_NvAPI_GPU_GetAllClocks); m_pfnNvAPI_GPU_GetPStates = (NvAPI_GPU_GetPStatesType)m_pfnNvapi_QueryInterface(ID_NvAPI_GPU_GetPStates); m_pfnNvAPI_GPU_GetUsages = (NvAPI_GPU_GetUsagesType)m_pfnNvapi_QueryInterface(ID_NvAPI_GPU_GetUsages); m_pfnNvAPI_GPU_GetCoolerSettings = (NvAPI_GPU_GetCoolerSettingsType)m_pfnNvapi_QueryInterface(ID_NvAPI_GPU_GetCoolerSettings); m_pfnNvAPI_GPU_SetCoolerLevels = (NvAPI_GPU_SetCoolerLevelsType)m_pfnNvapi_QueryInterface(ID_NvAPI_GPU_SetCoolerLevels); m_pfnNvAPI_GPU_GetMemoryInfo = (NvAPI_GPU_GetMemoryInfoType)m_pfnNvapi_QueryInterface(ID_NvAPI_GPU_GetMemoryInfo); m_pfnNvAPI_GetDisplayDriverVersion = (NvAPI_GetDisplayDriverVersionType)m_pfnNvapi_QueryInterface(ID_NvAPI_GetDisplayDriverVersion); m_pfnNvAPI_GetInterfaceVersionString = (NvAPI_GetInterfaceVersionStringType)m_pfnNvapi_QueryInterface(ID_NvAPI_GetInterfaceVersionString); m_pfnNvAPI_GPU_GetPCIIdentifiers = (NvAPI_GPU_GetPCIIdentifiersType)m_pfnNvapi_QueryInterface(ID_NvAPI_GPU_GetPCIIdentifiers); if (m_pfnNvAPI_Initialize) { nResult = m_pfnNvAPI_Initialize(); if (enumNvStatus_OK == nResult) { m_pDisplayCards = new DISPLAY_CARD_INFO[MAX_DISPLAY_CARDS]; ZeroMemory(m_pDisplayCards, MAX_DISPLAY_CARDS * sizeof(DISPLAY_CARD_INFO)); // 获取显卡个数 nResult = EnumDisplayCards(); MY_PROCESS_ERROR(nResult > 0); // 获取每块显卡的GPU个数 for (nIndex = 0; nIndex < m_nDisplayCardCount; ++nIndex) { bRetCode = GetGpuHandles(m_pDisplayCards[nIndex].nvDisplayHandle, &m_pDisplayCards[nIndex]); MY_PROCESS_ERROR(bRetCode); } bResult = TRUE; } } } } Exit0: return bResult; } BOOL KGpuMon::Unit() { m_nDisplayCardCount = 0; if (m_pDisplayCards) { delete []m_pDisplayCards; m_pDisplayCards = NULL; } if (m_hNvApiDll) { FreeLibrary(m_hNvApiDll); m_hNvApiDll = NULL; } return TRUE; } BOOL KGpuMon::GetDisplayInfo(const int nCardIndex, DISPLAY_INFO *pDisplayInfo) { BOOL bResult = FALSE; int nIndex = 0; if (nCardIndex < m_nDisplayCardCount) { bResult = GetDisplayCardGpuUsages(m_pDisplayCards[nCardIndex].nvDisplayHandle, &m_pDisplayCards[nCardIndex]); MY_PROCESS_ERROR(bResult); pDisplayInfo->nGpuCount = m_pDisplayCards[nCardIndex].nGpuCount; for (nIndex = 0; nIndex < pDisplayInfo->nGpuCount; ++nIndex) { pDisplayInfo->nGpuUsages[nIndex] = m_pDisplayCards[nCardIndex].sGpuInfo[nIndex].nUsage; } bResult = GetDisplayCardMemoryInfo(m_pDisplayCards[nCardIndex].nvDisplayHandle, &m_pDisplayCards[nCardIndex]); MY_PROCESS_ERROR(bResult); pDisplayInfo->dwTotalMemory = m_pDisplayCards[nCardIndex].dwTotalMemory; pDisplayInfo->dwFreeMemory = m_pDisplayCards[nCardIndex].dwFreeMemory; } Exit0: return bResult; } int KGpuMon::GetDisplayCardCount() { return m_nDisplayCardCount; } int KGpuMon::EnumDisplayCards() { NvStatus nvResult; NvDisplayHandle nvDisplayCardHandle; int nIndex = 0; m_nDisplayCardCount = 0; if (m_pfnNvAPI_EnumNvidiaDisplayHandle) { for (nIndex = 0; nIndex < MAX_DISPLAY_CARDS; ++nIndex) { nvResult = m_pfnNvAPI_EnumNvidiaDisplayHandle(nIndex, &nvDisplayCardHandle); if (enumNvStatus_OK == nvResult) { m_pDisplayCards[m_nDisplayCardCount].nvDisplayHandle = nvDisplayCardHandle; ++m_nDisplayCardCount; } } } return m_nDisplayCardCount; } BOOL KGpuMon::GetGpuHandles(const NvDisplayHandle nvDisplayHandle, DISPLAY_CARD_INFO *pCardInfo) { BOOL bResult = FALSE; NvStatus nvStatus; NvPhysicalGpuHandle *pnvHandles = NULL; int nIndex = 0; unsigned int uiGpuCount = 0; if (m_pfnNvAPI_GetPhysicalGPUsFromDisplay) { pnvHandles = new NvPhysicalGpuHandle[MAX_PHYSICAL_GPUS]; nvStatus = m_pfnNvAPI_GetPhysicalGPUsFromDisplay(nvDisplayHandle, pnvHandles, &uiGpuCount); if (enumNvStatus_OK == nvStatus) { pCardInfo->nGpuCount = min(uiGpuCount, MAX_GPU_NUM); for (nIndex = 0; nIndex < pCardInfo->nGpuCount; ++nIndex) { pCardInfo->sGpuInfo[nIndex].nvGpuHandle = pnvHandles[nIndex]; } bResult = TRUE; } delete []pnvHandles; pnvHandles = NULL; } return bResult; } BOOL KGpuMon::GetDisplayCardGpuUsages(const NvDisplayHandle nvDisplayHandle, DISPLAY_CARD_INFO *pCardInfo) { BOOL bResult = FALSE; int nIndex = 0; NvStatus nvStatus = enumNvStatus_ERROR; NvUsages *pnvUsages = NULL; if (m_pfnNvAPI_GPU_GetUsages) { pnvUsages = new NvUsages; pnvUsages->Version = GPU_USAGES_VER; for (nIndex = 0; nIndex < pCardInfo->nGpuCount; ++nIndex) { nvStatus = m_pfnNvAPI_GPU_GetUsages(pCardInfo->sGpuInfo[nIndex].nvGpuHandle, pnvUsages); if (enumNvStatus_OK == nvStatus) { pCardInfo->sGpuInfo[nIndex].nUsage = pnvUsages->Usages[2]; } } delete pnvUsages; pnvUsages = NULL; bResult = (enumNvStatus_OK == nvStatus) ? TRUE : FALSE; } return bResult; } BOOL KGpuMon::GetDisplayCardMemoryInfo(const NvDisplayHandle nvDisplayHandle, DISPLAY_CARD_INFO *pCardInfo) { BOOL bResult = FALSE; int nIndex = 0; NvStatus nvStatus = enumNvStatus_ERROR; NvUsages *pnvUsages = NULL; NvMemoryInfo sMemoryInfo; if (m_pfnNvAPI_GPU_GetMemoryInfo) { sMemoryInfo.Version = GPU_MEMORY_INFO_VER; nvStatus = m_pfnNvAPI_GPU_GetMemoryInfo(nvDisplayHandle, &sMemoryInfo); if (enumNvStatus_OK == nvStatus) { pCardInfo->dwTotalMemory = (DWORD)(sMemoryInfo.Values[0]); pCardInfo->dwFreeMemory = (DWORD)(sMemoryInfo.Values[4]); bResult = TRUE; } } return bResult; }http://blog.csdn.net/paopaoc/article/details/9093125
'Programming > C/C++' 카테고리의 다른 글
CPUInfo (0) | 2014.07.22 |
---|---|
Memory Bandwidth (0) | 2014.06.30 |
[WinAPI] 컴퓨터 각종 부품 정보 알아내기 (1) | 2014.06.22 |
GlobalMemoryStatusEx (0) | 2014.06.22 |
stack overrun (0) | 2014.06.19 |
설정
트랙백
댓글
글
[WinAPI] 컴퓨터 각종 부품 정보 알아내기
// 컴퓨터 각종 부품 정보 알아내기 std::wstring GetProcessorName() { wchar_t Cpu_info[100]; HKEY hKey; int i = 0; long result = 0; DWORD c_size = sizeof(Cpu_info); //레지스트리를 조사하여 프로세서의 모델명을 얻어냅니다. RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Hardware\\Description\\System\\CentralProcessor\\0", 0, KEY_QUERY_VALUE, &hKey); RegQueryValueEx(hKey, L"ProcessorNameString", NULL, NULL, (LPBYTE)Cpu_info, &c_size); RegCloseKey(hKey); //GetSystemInfo 함수를 이용해 논리적 코어 개수를 얻어냅니다. wchar_t num[8]; SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); swprintf(num, 8, L" * %d", systemInfo.dwNumberOfProcessors); wcscat_s(Cpu_info, 100, num); return Cpu_info; } std::wstring GetOSName() { wchar_t ProductName[100]; wchar_t CSDVersion[100]; std::wstring Os_info; HKEY hKey; int i = 0; DWORD c_size = 100; //레지스트리를 조사하여 운영체제 이름을 조사합니다. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\", 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) { return L"Fail to Open OS_info"; } if(RegQueryValueEx(hKey, L"ProductName", NULL, NULL, (LPBYTE)ProductName, &c_size) != ERROR_SUCCESS) { return L"Fail to Load the ProductName"; } if(RegQueryValueEx(hKey, L"CSDVersion", NULL, NULL, (LPBYTE)CSDVersion, &c_size) != ERROR_SUCCESS) { RegCloseKey(hKey); return ProductName; } Os_info = ProductName; Os_info += L" "; Os_info += CSDVersion; RegCloseKey(hKey); return Os_info; } std::string GetMemoryInfo() { //GlobalMemoryStatusEX 함수를 이용해 물리적 메모리양을 조사합니다. MEMORYSTATUSEX ms; ms.dwLength = sizeof(MEMORYSTATUSEX); GlobalMemoryStatusEx(&ms); char mss[128]; sprintf_s(mss, 128, "%d MB", ms.ullTotalPhys / 1024 / 1024); return mss; } std::string GetGPUInfo(LPDIRECT3D9 d3d) { //IDirect3D9 인터페이스를 이용해 GPU모델명을 얻어냅니다. D3DADAPTER_IDENTIFIER9 id; d3d->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &id); return id.Description; }http://bab2min.tistory.com/358
'Programming > C/C++' 카테고리의 다른 글
Memory Bandwidth (0) | 2014.06.30 |
---|---|
비디오 메모리 구하기 (0) | 2014.06.24 |
GlobalMemoryStatusEx (0) | 2014.06.22 |
stack overrun (0) | 2014.06.19 |
operator new (0) | 2014.06.14 |
설정
트랙백
댓글
글
GlobalMemoryStatusEx
// Use to convert bytes to KB #define DIV 1024 // Specify the width of the field in which to print the numbers. // The asterisk in the format specifier "%*I64d" takes an integer // argument and uses it to pad and right justify the number. #define WIDTH 7 void _tmain() { MEMORYSTATUSEX statex; statex.dwLength = sizeof (statex); GlobalMemoryStatusEx (&statex); _tprintf (TEXT("There is %*ld percent of memory in use.\n"), WIDTH, statex.dwMemoryLoad); _tprintf (TEXT("There are %*I64d total KB of physical memory.\n"), WIDTH, statex.ullTotalPhys/DIV); _tprintf (TEXT("There are %*I64d free KB of physical memory.\n"), WIDTH, statex.ullAvailPhys/DIV); _tprintf (TEXT("There are %*I64d total KB of paging file.\n"), WIDTH, statex.ullTotalPageFile/DIV); _tprintf (TEXT("There are %*I64d free KB of paging file.\n"), WIDTH, statex.ullAvailPageFile/DIV); _tprintf (TEXT("There are %*I64d total KB of virtual memory.\n"), WIDTH, statex.ullTotalVirtual/DIV); _tprintf (TEXT("There are %*I64d free KB of virtual memory.\n"), WIDTH, statex.ullAvailVirtual/DIV); // Show the amount of extended memory available. _tprintf (TEXT("There are %*I64d free KB of extended memory.\n"), WIDTH, statex.ullAvailExtendedVirtual/DIV); }http://msdn.microsoft.com/en-us/library/windows/desktop/aa366589(v=vs.85).aspx
'Programming > C/C++' 카테고리의 다른 글
Memory Bandwidth (0) | 2014.06.30 |
---|---|
비디오 메모리 구하기 (0) | 2014.06.24 |
[WinAPI] 컴퓨터 각종 부품 정보 알아내기 (1) | 2014.06.22 |
stack overrun (0) | 2014.06.19 |
operator new (0) | 2014.06.14 |