JuliaGPU/CUDAnative로 이징 모델 계산

소개


JuliaGPU / CUDAnative 를 시험해 보아 매우 좋았으므로, 우선 개요를 소개한다.
쓸 수 없었던 것은 다른 기사로 만들어질지도 모른다.
CUDAnativeCuArrays 에 비해
  • 로우 레벨 코딩 필요
  • 최적화되고 고속

  • 개발자의 최적화에 대한 언급
    htps : // ぢs 이렇게 r세. 주아아 g. 오 rg / t / 쿠다 나치
    JuliaGPU / ArrayFire 에서 이징 모델 계산
    htps : // 이 m / ㄴ ri / / ms / 3에 cb550 a f79 ~ c674에 480
    ArrayFireCuArrays 와 같은 정도로 높은 추상도의 외부 라이브러리
    CUDAnative 의 상세한 사용법은 보이지 않지만
    htps : // 기주 b. 코 m/쥬아아 G푸/쿠다나치ゔぇ. jl / t ree / ma s r / e mp ぇ s
    도움이되었습니다.

    이 기사의 노트북
    htps://응 b비에웨r. 나무 py 손 r. 오 rg / 의 st / ぃ理 my / c825 A B9 C45C45 A 2173C52254D4802C9

    이징 모델 병렬 처리



    GPU 계산에서는, 다수의 코어를 이용한 병렬화에 의해 퍼포먼스를 올리고 있다.

    한편, 이징 모델에서는 스핀이 인접한 스핀의 영향을 받기 때문에 인접한 스핀을 동시에 평가할 수 없다.

    영향이 직접 미치지 않는 스핀이면 병렬로 평가할 수 있습니다.
    스핀 전체를 격자 모양으로 칠해 색마다 교대로 평가하면 된다.



    Simulation of Ising spin model using CUDA
    h tp // w w.ゔぃこゔぃ c. rg/P 로지ぇcts/모두 ぇrせせ s/라d ンジぇ/2011_주리시 c. pdf

    ※ GPU의 성능은 CPU에 비해 ​​50-200배의 기술 있음

    CUDA 프로그래밍



    GPU에서 처리 설명



    GPU에서 호출되는 함수, 소위 커널을 써 갑니다.

    병렬 처리 이외의 부분에 대해서는, 쿠로키현에 의한 CPU 실장을 거의 그대로 답습했다.
    htps : /// b ゔぃ에우ぇr. Jupy r. 오 rg / 기 st / 겐쿠로키 / 4 46c68c56 예 0f3b1 아 6f88 c628b9d7
    using CUDAnative
    
    function _update!(s, rnd, m, n, β, white=false)
    
        i = (blockIdx().x-1) * blockDim().x + threadIdx().x
        j = (blockIdx().y-1) * blockDim().y + threadIdx().y
    
        if i  m && j  n && iseven(i+j) == white
    
            @inbounds ajs = (
                s[ifelse(i+1  m, i+1, 1), j] +
                s[ifelse(i-1  1, i-1, m), j] +
                s[i, ifelse(j+1  n, j+1, 1)] +
                s[i, ifelse(j-1  1, j-1, n)]
            )
            @inbounds prob = CUDAnative.exp_fast(-β * s[i, j] * ajs)
            @inbounds s[i, j] = ifelse(rnd[i, j] < prob, -s[i, j], s[i, j])
        end
    
        return
    end
    
  • CPU에서 계산할 때 For 루프의 내용 만 추출했다고 생각하면됩니다.
  • 함수 내에서 스레드 번호 등에서 자신이 할당 된 인덱스를 찾습니다.
  • 인덱스에 해당하는 스핀이 없으면 처리를 건너 뜁니다 (스핀 수가 32의 배수가 아닌 경우)
  • 격자 무늬에 의한 마스킹도 마찬가지로 처리 건너 뛰기로 대응합니다 (다른 방법도있다).

    GPU로 스레드 시작


    @cuda 매크로로 커널을 호출한다.
    using Random: rand!
    using CuArrays.CURAND
    
    m = 3072
    n = 4096
    
    rnd = curand(m, n)
    s = @. Int32(2 * (rnd < 0.5f0) - 1)
    βc = Float32(log(1+sqrt(2)))
    threads = (32, 32)
    blocks = @. ceil(Int, (m, n) / threads)
    
    # Main
    for _ in 1:100
        rand!(rnd)
        @cuda blocks=blocks threads=threads _update!(s, rnd, m, n, βc, true)
        @cuda blocks=blocks threads=threads _update!(s, rnd, m, n, βc, false)
    end
    
  • GPU는 32 스레드 (Warp)를 단위로 처리합니다.
  • thread의 정합을 블록이라고 한다
  • 블록 당 스레드 수에는 제한이 있습니다 (GTX 980이면 1024).
  • CuArrays에서 얻은 서열은 CUDAnative 커널에서 사용할 수 있습니다
  • 커널에서 난수를 얻는 것은 어려울 것입니다. 설명이 길어질 것입니다.

    갤러리



    임계 온도에서의 정상 상태(정지 화상)





    전체를 약 100000회 평가한 후
    $4096\times3072$ 를 1/8로 축소

    임계 온도에서의 정상 상태(동영상)





    $4096\times3072$ 를 1/16 로 축소
    전체 16회 평가/프레임
    30 프레임

    벤치마크




  • GPU는 CPU와 비교하여 적절한 조건에서 약 80 배 빠릅니다
  • 모델 크기가 작 으면 CPU와 성능이 변하지 않습니다
  • 반대로 너무 커도 ($32768\times32768$) 메모리가 부족하다
  • 최소한 $512\times512$ , 가능하면 $4096\times4096$ 를 원합니다
  • 좋은 웹페이지 즐겨찾기