728x90

Linux 버전은 설치하는 방법이 인터넷에 많이 나오지만...


Windows에서 설치하고 테스트하려고 보니 공식 홈페이지에서 


(https://www.open-mpi.org/software/ompi/v1.6/ms-windows.php)


Due to lack of interest and anyone to maintain them, binary support for a Microsoft Windows Open MPI build has been discontinued.

Microsoft Windows Open MPI 빌드에 대한 바이너리 지원은 관심 부족과 유지 관리가 부족하기 때문에 중단되었습니다.


라고 하기에... 쭉 찾아보니 MS-MPI라는 것이 따로 있었다.


소스코드 부분을 보니 Linux나 Window나 코드가 동일해 보이기에 일단 진행해보려고 한다.


Windows 설치 : https://blogs.technet.microsoft.com/windowshpc/2015/02/02/how-to-compile-and-run-a-simple-ms-mpi-program/

728x90

'Parallel Programming > OpenMPI' 카테고리의 다른 글

OpenMPI - 강좌  (0) 2018.09.18
728x90

OpenMPI 교재 : http://k-atoms.ksc.re.kr/mpi/main.html

Parallel Programming, OpenMP, Win32 : http://himskim.egloos.com/3261640

728x90

'Parallel Programming > OpenMPI' 카테고리의 다른 글

OpenMPI - Windows 설치하기  (0) 2018.09.27
728x90

간단한 어셈블리만 알아두자.


1. 덧셈




2. 뺄셈



3. 곱셈

곱셈의 경우 피승수가 eax에 대입되고 승수는 다른 레지스터나 메모리를 사용하면 된다. 한 연산자가 2개의 인자를 동시에 사용할 수 없다. 항상 eax를 사용하여 곱셈을 연산해야하며, 결과도 eax에 들어가게 되는데 곱의 대상은 다른 레지스터나 메모리 변수를 사용하면 된다.



4. 나눗셈

나눗셈도 곱셈과 방법은 마찬가지이다. 피제수가 eax에 들어가게 되고, 다른 레지스터와 메모리 값을 제수로 사용하게 된다. 결과값의 몫은 eax에 들어가고, 나머지는 edx 레지스터에 들어가게 된다. 한번에 두개의 인자를 입력할 수 없으므로 나누어 계산해야 한다.



728x90

'Parallel Programming > SSE' 카테고리의 다른 글

SSE - SSE (Streaming SIMD Extensions)  (0) 2017.03.14
728x90

SSE (Streaming SIMD Extensions)는 실수 연산에 최적화된 명령어이다.


여기서 SIMD란 Single Instruction Multiple Data의 약자로써, 하나의 명령어를 수행할 때, 레지스터를 좀 더 효율적으로 활용하는 기법을 말한다.


MMX에 이은 Intel의 다음 세대 멀티미디어 명령어이다. CPU에는 참 많은 명령어가 있다. MMX 명령어 50여개를 비롯하여 SSE에서 SSE4 등등이 있다. 이러한 명령어는 부동 소수점 연산등에 탁월한 효과를 보이기 때문에 3D 게임 혹은 멀티미디어 분야에서 그 성능을 발휘한다. 




컴퓨터 시스템의 종류


SISD (Single Instruction Single Data) 

 - 한 번의 연산으로 한개의 데이터를 처리할 수 있는 컴퓨터 시스템


SIMD (Single Instruction Multiple Data) 

 - 한 번의 연산으로 여러 개의 데이터를 처리할 수 있는 컴퓨터 시스템


MISD (Multiple Instruction Single Data) 

 - 하나의 데이터를 처리하기 위해 여러개의 연산 명령이 필요한 컴퓨터 구조


MIMD (Multiple Instruction Multiple Data) 

 - 여러 개의 데이터를 처리하기 위해 여러 개의 연산 명령을 처리하는 컴퓨터 구조




728x90

'Parallel Programming > SSE' 카테고리의 다른 글

SSE - 어셈블리 덧셈, 뺄셈, 곱셈, 나눗셈  (0) 2017.03.14
728x90
  • DWORD_PTR WINAPI SetThreadAffinityMask( HANDLE hThread DWORD_PTR dwThreadAffinityMask );  


  • Thread Handle을 인수로 받아 특정 코어에서 해당 Thread를 실행하도록 지정해주는 함수.

    0x01 부터 순서대로 한비트씩 쉬프트 하면 원하는 코어를 결정할수 있다.

    주의할점은 하나의 Thread는 여러개의 코어가 모두 실행시킬수 있는데

    만약 첫번째 코어와 두번째 코어가 모두 실행 가능하도록 설정하고 싶다면

    01 과 10 의 OR 연산결과값인 0x03 을 설정하면 되는것이다.

    만약 코어 1,2,3 에서 실행가능하게 하고 싶다면

    001 , 010  그리고 100 를 OR 연산하여 호출해주면 된다.


    아래의 코드는

    SetThreadAffinityMask 를 테스트해보는 예제인데 

    주석처리된 부분을 그대로 두고 실행하면 재미있는 결과를 얻을수 있다.

    실행하면 Core의 수를 출력한뒤 코어의 갯수에 해당하는 Thread를 생성하고

    무한루프를 돌려서 CPU 점유율을 100%로 만들어 버린다.

    그리고 콘솔창에서 숫자키 1~9까지의 숫자를 사용해 원하는 번호의 Thread를 정상종료

    시킬수 있는데. 만약 듀얼코어에서 쓰레드 하나만 죽인다면 50%의 점유율을 차지하게 될것은

    당연한 이치이지만. SetThreadAffinityMask 를 사용하지 않았을 경우와 사용했을 경우의

    점유율 그래프를 본다면 이마를 탁 치게 될것이다. ( 벌써 알고 계셨다면.. 굳ㅋ )

    1. #include <iostream>  
    2. #include <conio.h>  
    3. #include <windows.h>  
    4.   
    5.   
    6.   
    7. using namespace std;  
    8.   
    9.   
    10. DWORD WINAPI ThreadProc(LPVOID arg)  
    11. {  
    12.  while( *((bool*)(arg))  )Sleep(0);  
    13.   
    14.   
    15.  return 0;  
    16. }  
    17.   
    18.   
    19. int main(int argc, char argv[])  
    20. {  
    21.  SYSTEM_INFO info;  
    22.  GetSystemInfo(&info);  
    23.   
    24.   
    25.  cout << info.dwNumberOfProcessors << endl;  
    26.   
    27.   
    28.  bool *flag = new bool[ info.dwNumberOfProcessors ];  
    29.   
    30.   
    31.  HANDLE *hTrhead = new HANDLE[info.dwNumberOfProcessors];  
    32.   
    33.   
    34.  for(int i = 0 ; i < info.dwNumberOfProcessors ; i++ )  
    35.  {  
    36.   flag[i] = true;  
    37.   hTrhead[i] = CreateThread(0,0,ThreadProc,&flag[i],0,0);  
    38.   //SetThreadAffinityMask( hTrhead[i]  , 1 << i );  
    39.  }  
    40.   
    41.   
    42.   
    43.  char c;  
    44.  while(1)  
    45.  {  
    46.   c = getch();  
    47.   
    48.   
    49.   if( c >= '1' && c <= '9' )  
    50.    flag[ c-'1' ] = false;  
    51.   
    52.   
    53.   if( c == 13 )  
    54.    break;  
    55.  }  
    56.   
    57.   
    58.  return 0;  
    59. }  


    사용자 삽입 이미지




    야래 사진이 SetThreadAffinityMask() 를 사용하지 않아서코어가 쓰레드의 삽질을같이 보듬어주고 있는경우고


    사용자 삽입 이미지



    아래의 사진은 SetThreadAffinityMask를 통해 하나의 코어가 하나의 쓰레드만 담당하여2번째 쓰레드를 죽이고나니 개미와 베짱이를 연출시킨 상황이다.


    사용자 삽입 이미지




    출처 : http://1stpasa.tistory.com/8

    728x90
    728x90
    // show memory usage of GPU

    size_t free_byte ;
    size_t total_byte ;

    cuda_status = cudaMemGetInfo( &free_byte, &total_byte ) ;

    if ( cudaSuccess != cuda_status )
    {
    printf("Error: cudaMemGetInfo fails, %s \n", cudaGetErrorString(cuda_status) );
    exit(1);
    }

    double free_db = (double)free_byte ;
    double total_db = (double)total_byte ;
    double used_db = total_db - free_db ;

    printf("GPU memory usage: used = %f, free = %f MB, total = %f MB\n",
    used_db/1024.0/1024.0, free_db/1024.0/1024.0, total_db/1024.0/1024.0);


    출처 : https://devtalk.nvidia.com/default/topic/487541/best-way-to-report-memory-consumption-in-cuda-/?offset=1

    728x90

    'Parallel Programming > CUDA' 카테고리의 다른 글

    CUDA - 스트림(stream)  (0) 2016.03.03
    CUDA - 고정 메모리(cudaHostAlloc())  (0) 2016.03.03
    CUDA - 원자적 연산  (0) 2016.03.03
    CUDA - 시간 측정  (0) 2016.02.26
    CUDA - 2차원 배열의 할당과 이용  (0) 2016.02.25
    728x90

    CUDA Stream은 어플리케이션을 가속시키는 데 중요한 역할을 한다. 하나의 CUDA Stream은 하나의 큐를 나타내며, 여기에는 특정 순서에 따라 실행될 GPU 작업들이 추가되어 있다. 커널의 실행, 메모리 복사 그리고 이벤트의 시작과 중지와 같은 작업들을 하나의 스트림에 추가할 수 있다. 스트림에 추가된 작업들의 순서가 곧 실행될 순서를 의미한다. 각 스트림을 GPU 상의 하나의 태스크로 여길 수 있으며, 이러한 태스크들은 병렬로 실행될 수 있다. 


    CUDA Stream을 사용하기 위해서는 디바이스 오버랩(Device Overlap)이라고 알려진 기능을 제공하는지 확인해야한다.


    CUDA Stream을 사용하는 방법은 다음과 같다.

    CUDA Stream은 정 메모리를 이용해야만 한다.



    728x90

    'Parallel Programming > CUDA' 카테고리의 다른 글

    CUDA - GPU Memory Usage Check  (0) 2016.11.22
    CUDA - 고정 메모리(cudaHostAlloc())  (0) 2016.03.03
    CUDA - 원자적 연산  (0) 2016.03.03
    CUDA - 시간 측정  (0) 2016.02.26
    CUDA - 2차원 배열의 할당과 이용  (0) 2016.02.25
    728x90

    CUDA 런타임은 cudaHostAlloc()이라는 CUDA만의 호스트 메모리를 할당하는 방법을 제공하고 있다.


    사실 malloc()과 cudaHostAlloc()으로 메모리를 할당하는 것에는 중요한 차이점이 존재한다. C 라이브러리 함수인 malloc()은 표준의 페이징(pageable)이 가능한 호스트 메모리를 할당하는 반면, cudaHostAlloc()은 잠긴 페이지의 호스트 메모리를 할당한다.


    때때로 고정 메모리(pinned memory)라고 불리는 잠긴 페이지의 메모리 버퍼들은 하나의 중요한 속성을 가지고 있다. 이는 운영 체제가 해당 메모리를 절대로 디스크로 페이징하여 내보내지 않는 것을 보장하며 실제 물리 메모리에 존재하도록 해준다.


    버퍼의 물리적인 주소를 알게됨으로써 GPU는 호스트로부터 또는 호스트로 데이터를 복사하기 위해 직접 메모리 접근(DMA) 방식을 이용할 수 있다. DMA 방식의 복사는 CPU의 개입 없이 진행되므로 복사 도중 CPU가 버퍼를 디스크로 페이징하여 내보내거나 운영체제의 페이지 테이블을 갱신하면서 버퍼의 물리적인 주소를 재위치시킬 수 있음을 의미하기도 한다.

    CPU는 페이징이 가능한 메모리의 데이터를 이동시킬 수 있으므로 DMA 방식의 복사를 위해서는 고정 메모리를 사용하는 것이 필수다. 


    하지만 주의 할 점이 있다.


    고정 메모리를 사용하는 것은 양날의 검이다. 고정 메모리를 사용하면 가상 메모리의 멋진 특징들을 효과적으로 이용하지 못한다. 구체적으로 말하면, 잠긴 페이지의 버퍼들은 디스크로 스왑(swap)될 수 없기 때문에 어플리케이션을 구동중인 컴퓨터는 잠긴 페이지의 모든 버퍼들에 대해 가용한 물리적인 메모리를 가져야만 한다. 이것은 시슽렘에서 표준 malloc()를 사용할 때보다 메모리 부족현상이 훨씬 빨리 발생할 수 있음을 의미한다. 이것은 어플리케이션이 더 적은 양의 물리적인 메모리로 인해 실패할 수 있음을 의미하며, 시스템에서 구동중인 다른 어플리케이션들의 성능에도 영향을 미칠 수 있음을 의미한다.





    728x90

    'Parallel Programming > CUDA' 카테고리의 다른 글

    CUDA - GPU Memory Usage Check  (0) 2016.11.22
    CUDA - 스트림(stream)  (0) 2016.03.03
    CUDA - 원자적 연산  (0) 2016.03.03
    CUDA - 시간 측정  (0) 2016.02.26
    CUDA - 2차원 배열의 할당과 이용  (0) 2016.02.25

    + Recent posts