cuda

[์›๋ณธ ๋งํฌ]

cuda๋Š” ํ˜„๋Œ€ ๋จธ์‹ ๋Ÿฌ๋‹ ํ™˜๊ฒฝ์˜ ํ•ต์‹ฌ์ด ๋˜๋Š” ๊ธฐ๋Šฅ์š”์†Œ ์ค‘ ํ•˜๋‚˜๋‹ค.




cuda๊ฐ€ ๋Œ€์ฒด ๋ญ”๊ฐ€?

๊ทธ๋ž˜ํ”ฝ์นด๋“œ, GPU๋Š” ์›๋ž˜ ์ง„์งœ ๊ทธ๋ž˜ํ”ฝ ์—ฐ์‚ฐ์„ ์œ„ํ•œ ์žฅ์น˜์˜€๋‹ค. ๋ชจ๋‹ˆํ„ฐ ๋ Œ๋”๋งํ•˜๊ณ  ๊ทธ๋Ÿฐ๊ฑฐ ๋ง์ด๋‹ค.
ํ•˜์ง€๋งŒ ๊ทผ๋ž˜์— ์™€์„œ GPU์˜ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ๋Šฅ๋ ฅ์ด ์ฃผ๋ชฉ๋ฐ›๊ฒŒ ๋˜์—ˆ๋‹ค.

GPU๋Š” ํ•˜๋“œ์›จ์–ด์ ์œผ๋กœ ์ˆ˜๋ฐฑ ์ˆ˜์ฒœ๊ฐœ์˜ ์ž‘์€ ์ฝ”์–ด๋กœ ๊ตฌ์„ฑ๋˜๋Š”๋ฐ, ์ฝ”์–ด ํ•˜๋‚˜ํ•˜๋‚˜์˜ ๋‹จ์ผ ์„ฑ๋Šฅ์€ CPU๋ณด๋‹ค ๋‚ฎ์•„์„œ ๋ฒ”์šฉ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ์—๋Š” ๋น„ํšจ์œจ์ ์ด๋‹ค.
ํ•˜์ง€๋งŒ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ˆซ์ž(ํŠนํžˆ float)๋กœ ๊ตฌ์„ฑ๋˜๋Š” ๋ฒกํ„ฐ/ํ–‰๋ ฌ๊ฐ„์˜ ์—ฐ์‚ฐ์— ๋Œ€ํ•ด์„œ๋Š” ๋งค์šฐ ๋›ฐ์–ด๋‚œ ์„ฑ๋Šฅ์„ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๋‹ค. CPU๋Š” ํ•˜๋‚˜ํ•˜๋‚˜ ๋ฃจํ”„ ๋Œ๋ฉด์„œ ์ฒ˜๋ฆฌํ•ด์•ผํ•˜๋Š” ๊ฒƒ์„ GPU๋Š” ํ•œ๋ฒˆ์— ๋ฐ€์–ด๋„ฃ๊ณ  ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๋ฅผ ํ•ด๋ฒ„๋ฆด ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

.PNG?type=w800) CUDA๋Š” GPU๋ฅผ ๊ทธ๋Ÿฐ ์—ฐ์‚ฐ๋“ค์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.
C/C++๋กœ ์ž‘์„ฑ๋˜์–ด์žˆ๋Š”๋ฐ, ์ด๊ฑฐ ์ž์ฒด๋Š” ๋„ˆ๋ฌด rawํ•˜๊ฒŒ ๋˜์–ด์žˆ์–ด์„œ ๋ณดํ†ต์€ torch ๊ฐ™์€ ์ถ”์ƒํ™”๋œ ํ™˜๊ฒฝ์„ ํ†ตํ•ด์„œ ๊ฐ„์ ‘ ํ˜ธ์ถœ์„ ํ•˜๋Š”๊ฒŒ ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ํ˜•ํƒœ๋‹ค.

CUDA์™€, CUDA ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋œ ๊ฐœ๋ฐœํ™˜๊ฒฝ์ด์•ผ๋ง๋กœ ์—”๋น„๋””์•„์˜ ์ฃผ๊ฐ€๋ฅผ ์ง€ํƒฑํ•˜๋Š” ๊ฐ€์žฅ ํฐ ๊ธฐ๋‘ฅ์ด๋ผ ํ•  ์ˆ˜ ์žˆ๋‹ค.
๋‹ค๋ฅธ GPU ๊ฐœ๋ฐœ์‚ฌ๋“ค์ด ์„ฑ๋Šฅ์ด ๋–จ์–ด์ ธ์„œ ๋ฐ€๋ฆฌ๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ, ์ด ์†Œํ”„ํŠธ์›จ์–ด ํ™˜๊ฒฝ ๋•Œ๋ฌธ์— ๋ฐ€๋ฆฌ๋Š” ๊ฒƒ์ด๋‹ค.




์‚ฌ์šฉํ•ด๋ณด๊ธฐ

๋‹น์—ฐํžˆ ์—”๋น„๋””์•„ ๊ทธ๋ž˜ํ”ฝ์นด๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ์ด์–ด์•ผ ํ•œ๋‹ค.
๋‚ด ๊ฒฝ์šฐ์—๋Š” AWS EC2์˜ GPU ํƒ€์ž…์„ ์‚ฌ์šฉํ–ˆ๋‹ค.

์ •๋ณด๋ฅผ ์กฐํšŒํ•ด์„œ, ์ด๋Ÿฐ ์‹์œผ๋กœ ๋‚˜์˜ค๋ฉด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ™˜๊ฒฝ์ด๋‹ค.

lspci | grep -i nvidia

๋“œ๋ผ์ด๋ฒ„ ๊ตฌ์„ฑ์€ ๋ณ„๋„ ํฌ์ŠคํŠธ๋ฅผ ์ฐธ์กฐํ•œ๋‹ค.
https://blog.naver.com/sssang97/223867488688




Python torch๋กœ cuda ์จ๋ณด๊ธฐ

pytorch๋ฅผ ํ†ตํ•ด์„œ cuda๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์‚ฌ์šฉํ•ด๋ณด๊ฒ ๋‹ค.

์„ค์น˜ํ•˜๊ณ , importํ•ด์„œ ์‹คํ–‰ํ•ด๋ณธ๋‹ค.

import torch
torch.cuda.is_available()

๋“œ๋ผ์ด๋ฒ„ ๊ตฌ์„ฑ์ด ์ œ๋Œ€๋กœ ๋˜์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ False๊ฐ€ ๋‚  ๊ฒƒ์ด๋‹ค.


๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค๋ฉด True๊ฐ€ ๋‚˜์˜จ๋‹ค. ์ด๋ž˜์•ผ cuda๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

torch๋ฅผ ํ†ตํ•ด cuda ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋„ ์ด๊ฒƒ์ €๊ฒƒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

print(f"CUDA ๋ฒ„์ „: {torch.version.cuda}")
print(f"GPU ๊ฐœ์ˆ˜: {torch.cuda.device_count()}")

์‚ฌ์šฉ๋ฒ•์€ ๋Œ€๋žต ์ด๋ ‡๋‹ค. ๋‹ค์Œ ์ฝ”๋“œ๋Š” 1000x1000 ํ–‰๋ ฌ์„ ๋žœ๋ค์œผ๋กœ ๋งŒ๋“ค์–ด์„œ ํ–‰๋ ฌ๊ณฑ์„ ๋Œ๋ฆฌ๋Š” ์˜ˆ์ œ๋‹ค.

x = torch.randn(1000, 1000).cuda()
y = torch.randn(1000, 1000).cuda()
z = x @ y  # ํ–‰๋ ฌ ๊ณฑ์…ˆ
print("GPU ์—ฐ์‚ฐ ์„ฑ๊ณต")
print(z)

๊ทธ๋Ÿผ ์ด๋ ‡๊ฒŒ ์ž˜ ๋™์ž‘ํ•œ๋‹ค.

๊ฐ„๋‹จํ•œ ์„ฑ๋Šฅ ๋น„๊ต๋„ ํ•œ๋ฒˆ ํ•ด๋ณด์ž.

import torch
import time

def bench():
    # CPU์—์„œ ํ…์„œ ์ƒ์„ฑ
    print("\n=== CPU vs GPU ์„ฑ๋Šฅ ๋น„๊ต ===")
    size = 5000
    print(f"{size}x{size} ํ–‰๋ ฌ ๊ณฑ์…ˆ ์ˆ˜ํ–‰ ์ค‘...")

    # CPU ์—ฐ์‚ฐ ์ˆ˜ํ–‰ ๋ฐ ์‹œ๊ฐ„ ์ธก์ •
    start_time = time.time()
    a_cpu = torch.randn(size, size)
    b_cpu = torch.randn(size, size)
    c_cpu = torch.matmul(a_cpu, b_cpu)
    cpu_time = time.time() - start_time
    print(f"CPU ์—ฐ์‚ฐ ์™„๋ฃŒ: {cpu_time:.4f}์ดˆ")

    # GPU ์—ฐ์‚ฐ ์ˆ˜ํ–‰ ๋ฐ ์‹œ๊ฐ„ ์ธก์ •
    start_time = time.time()
    a_gpu = torch.randn(size, size, device='cuda')
    b_gpu = torch.randn(size, size, device='cuda')
    c_gpu = torch.matmul(a_gpu, b_gpu)
    # GPU ์—ฐ์‚ฐ์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ
    torch.cuda.synchronize()
    gpu_time = time.time() - start_time
    print(f"GPU ์—ฐ์‚ฐ ์™„๋ฃŒ: {gpu_time:.4f}์ดˆ")

    # ๊ฒฐ๊ณผ ๊ฒ€์ฆ (CPU์™€ GPU ๊ฒฐ๊ณผ๊ฐ€ ์ผ์น˜ํ•˜๋Š”์ง€)
    c_gpu_cpu = c_gpu.cpu()  # GPU ํ…์„œ๋ฅผ CPU๋กœ ์ด๋™
    is_close = torch.allclose(c_cpu, c_gpu_cpu, rtol=1e-3, atol=1e-3)
    print(f"CPU/GPU ๊ฒฐ๊ณผ ์ผ์น˜: {is_close}")

    # ์†๋„ ๋น„๊ต
    speedup = cpu_time / gpu_time
    print(f"GPU ์†๋„ ํ–ฅ์ƒ: {speedup:.2f}๋ฐฐ ๋น ๋ฆ„")

    print("\n=== ๊ฐ„๋‹จํ•œ GPU ๋ฉ”๋ชจ๋ฆฌ ํ…Œ์ŠคํŠธ ===")
    # GPU ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ํ˜„ํ™ฉ ํ™•์ธ
    print(f"๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น ์ „ ์‚ฌ์šฉ๋Ÿ‰: {torch.cuda.memory_allocated() / 1e6:.2f} MB")

    # ํฐ ํ…์„œ ์ƒ์„ฑ์œผ๋กœ GPU ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ
    large_tensor = torch.ones((1000, 1000, 100), device='cuda')
    print(f"๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น ํ›„ ์‚ฌ์šฉ๋Ÿ‰: {torch.cuda.memory_allocated() / 1e6:.2f} MB")

    # ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ
    del large_tensor
    torch.cuda.empty_cache()
    print(f"๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ ํ›„ ์‚ฌ์šฉ๋Ÿ‰: {torch.cuda.memory_allocated() / 1e6:.2f} MB")

    print("\nCUDA Hello World ์™„๋ฃŒ!")

bench()

5000x5000์„ ๋Œ๋ ธ์„ ๋•Œ๋Š” CPU๋กœ ๋Œ๋ฆด ๋•Œ๋ณด๋‹ค 4๋ฐฐ ์ •๋„ ๋นจ๋ž๋‹ค.
์‹ค์ œ ์‚ฌ์šฉ์‚ฌ๋ก€์—์„œ๋Š” ๋” ํฌ๊ณ  ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๊ธฐ ๋•Œ๋ฌธ์—, ์ด๊ฒƒ๋ณด๋‹ค ๋” ๋ฒŒ์–ด์ง€๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์„ ๊ฒƒ์ด๋‹ค.