๊ทธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ ์žฅ์น˜(GPU)์˜ ์ฒซ ๋ฒˆ์งธ ์‹ ๊ฒฝ๋ง์ž…๋‹ˆ๋‹ค. ์ดˆ๋ณด์ž ๊ฐ€์ด๋“œ

๊ทธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ ์žฅ์น˜(GPU)์˜ ์ฒซ ๋ฒˆ์งธ ์‹ ๊ฒฝ๋ง์ž…๋‹ˆ๋‹ค. ์ดˆ๋ณด์ž ๊ฐ€์ด๋“œ
์ด๋ฒˆ ๊ธ€์—์„œ๋Š” 30๋ถ„ ๋งŒ์— ๋จธ์‹ ๋Ÿฌ๋‹ ํ™˜๊ฒฝ์„ ์„ค์ •ํ•˜๊ณ , ์ด๋ฏธ์ง€ ์ธ์‹์„ ์œ„ํ•œ ์‹ ๊ฒฝ๋ง์„ ๋งŒ๋“  ๋’ค, ๋™์ผํ•œ ๋„คํŠธ์›Œํฌ๋ฅผ ๊ทธ๋ž˜ํ”ฝ ํ”„๋กœ์„ธ์„œ(GPU)์—์„œ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

๋จผ์ € ์‹ ๊ฒฝ๋ง์ด ๋ฌด์—‡์ธ์ง€ ์ •์˜ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ ์ด๊ฒƒ์€ ์ƒ๋ฌผํ•™์  ์‹ ๊ฒฝ ๋„คํŠธ์›Œํฌ, ์ฆ‰ ์‚ด์•„์žˆ๋Š” ์œ ๊ธฐ์ฒด์˜ ์‹ ๊ฒฝ ์„ธํฌ ๋„คํŠธ์›Œํฌ์˜ ์กฐ์ง ๋ฐ ๊ธฐ๋Šฅ ์›๋ฆฌ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋œ ์ˆ˜ํ•™์  ๋ชจ๋ธ์ด์ž ์†Œํ”„ํŠธ์›จ์–ด ๋˜๋Š” ํ•˜๋“œ์›จ์–ด ๊ตฌํ˜„์ž…๋‹ˆ๋‹ค. ์ด ๊ฐœ๋…์€ ๋‡Œ์—์„œ ์ผ์–ด๋‚˜๋Š” ๊ณผ์ •์„ ์—ฐ๊ตฌํ•˜๊ณ  ์ด๋Ÿฌํ•œ ๊ณผ์ •์„ ๋ชจ๋ธ๋งํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜๋Š” ๋™์•ˆ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

์‹ ๊ฒฝ๋ง์€ ์ผ๋ฐ˜์ ์ธ ์˜๋ฏธ๋กœ ํ”„๋กœ๊ทธ๋ž˜๋ฐ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํ›ˆ๋ จ๋ฉ๋‹ˆ๋‹ค. ํ•™์Šต ๋Šฅ๋ ฅ์€ ๊ธฐ์กด ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ๋น„ํ•ด ์‹ ๊ฒฝ๋ง์˜ ์ฃผ์š” ์žฅ์  ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ๊ธฐ์ˆ ์ ์œผ๋กœ ํ•™์Šต์€ ๋‰ด๋Ÿฐ ๊ฐ„์˜ ์—ฐ๊ฒฐ ๊ณ„์ˆ˜๋ฅผ ์ฐพ๋Š” ๊ฒƒ์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ํ›ˆ๋ จ ๊ณผ์ •์—์„œ ์‹ ๊ฒฝ๋ง์€ ์ž…๋ ฅ ๋ฐ์ดํ„ฐ์™€ ์ถœ๋ ฅ ๋ฐ์ดํ„ฐ ๊ฐ„์˜ ๋ณต์žกํ•œ ์ข…์†์„ฑ์„ ์‹๋ณ„ํ•˜๊ณ  ์ผ๋ฐ˜ํ™”๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๊ณ„ ํ•™์Šต์˜ ๊ด€์ ์—์„œ ๋ณผ ๋•Œ ์‹ ๊ฒฝ๋ง์€ ํŒจํ„ด ์ธ์‹ ๋ฐฉ๋ฒ•, ํŒ๋ณ„ ๋ถ„์„, ํด๋Ÿฌ์Šคํ„ฐ๋ง ๋ฐฉ๋ฒ• ๋ฐ ๊ธฐํƒ€ ๋ฐฉ๋ฒ•์˜ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

ะžะฑะพั€ัƒะดะพะฒะฐะฝะธะต

๋จผ์ € ์žฅ๋น„๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. Linux ์šด์˜ ์ฒด์ œ๊ฐ€ ์„ค์น˜๋œ ์„œ๋ฒ„๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๊ณ„ ํ•™์Šต ์‹œ์Šคํ…œ์„ ์ž‘๋™ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์žฅ๋น„๋Š” ๋งค์šฐ ๊ฐ•๋ ฅํ•˜๊ณ  ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋น„์šฉ์ด ๋งŽ์ด ๋“ญ๋‹ˆ๋‹ค. ์ข‹์€ ๋จธ์‹ ์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š์€ ๋ถ„๋“ค์€ ํด๋ผ์šฐ๋“œ ์ œ๊ณต ์—…์ฒด์˜ ์ œ์•ˆ์— ์ฃผ๋ชฉํ•  ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ์„œ๋ฒ„๋ฅผ ๋น ๋ฅด๊ฒŒ ์ž„๋Œ€ํ•˜๊ณ , ์‚ฌ์šฉํ•œ ์‹œ๊ฐ„๋งŒํผ๋งŒ ๋น„์šฉ์„ ์ง€๋ถˆํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์‹ ๊ฒฝ๋ง์„ ์ƒ์„ฑํ•ด์•ผ ํ•˜๋Š” ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋Ÿฌ์‹œ์•„ ํด๋ผ์šฐ๋“œ ์ œ๊ณต์—…์ฒด ์ค‘ ํ•˜๋‚˜์˜ ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ํšŒ์‚ฌ๋Š” NVIDIA์˜ ๊ฐ•๋ ฅํ•œ Tesla V100 ๊ทธ๋ž˜ํ”ฝ ํ”„๋กœ์„ธ์„œ(GPU)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๊ณ„ ํ•™์Šต์„ ์œ„ํ•œ ์ž„๋Œ€์šฉ ํด๋ผ์šฐ๋“œ ์„œ๋ฒ„๋ฅผ ํŠน๋ณ„ํžˆ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ, GPU๊ฐ€ ์žˆ๋Š” ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๊ณ„์‚ฐ์„ ์œ„ํ•ด CPU(์ž˜ ์•Œ๋ ค์ง„ ์ค‘์•™ ์ฒ˜๋ฆฌ ์žฅ์น˜)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์œ ์‚ฌํ•œ ๋น„์šฉ์˜ ์„œ๋ฒ„์— ๋น„ํ•ด ์ˆ˜์‹ญ ๋ฐฐ ๋” ํšจ์œจ์ (๋น ๋ฅผ ์ˆ˜ ์žˆ์Œ)์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ณ„์‚ฐ์— ๋” ๋น ๋ฅด๊ฒŒ ๋Œ€์ฒ˜ํ•˜๋Š” GPU ์•„ํ‚คํ…์ฒ˜์˜ ๊ธฐ๋Šฅ์œผ๋กœ ์ธํ•ด ๋‹ฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

์•„๋ž˜ ์„ค๋ช…๋œ ์˜ˆ์ œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ๋ฉฐ์น  ๋™์•ˆ ๋‹ค์Œ ์„œ๋ฒ„๋ฅผ ๊ตฌ์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค.

  • SSD ๋””์Šคํฌ 150GB
  • RAM 32GB
  • Tesla V100 16Gb ํ”„๋กœ์„ธ์„œ, 4์ฝ”์–ด

์šฐ๋ฆฌ ์ปดํ“จํ„ฐ์— Ubuntu 18.04๋ฅผ ์„ค์น˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ™˜๊ฒฝ ์„ค์ •

์ด์ œ ์„œ๋ฒ„ ์ž‘์—…์— ํ•„์š”ํ•œ ๋ชจ๋“  ๊ฒƒ์„ ์„ค์น˜ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ ๊ธฐ์‚ฌ๋Š” ์ฃผ๋กœ ์ดˆ๋ณด์ž๋ฅผ ๋Œ€์ƒ์œผ๋กœํ•˜๋ฏ€๋กœ ์ดˆ๋ณด์ž์—๊ฒŒ ์œ ์šฉํ•œ ๋ช‡ ๊ฐ€์ง€ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ™˜๊ฒฝ์„ ์„ค์ •ํ•  ๋•Œ ๋งŽ์€ ์ž‘์—…์ด ๋ช…๋ น์ค„์„ ํ†ตํ•ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ์ž๋Š” Windows๋ฅผ ์ž‘์—… OS๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด OS์˜ ํ‘œ์ค€ ์ฝ˜์†”์—๋Š” ๋ถ€์กฑํ•œ ์ ์ด ๋งŽ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํŽธ๋ฆฌํ•œ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ช…๋ น/. ๋ฏธ๋‹ˆ ๋ฒ„์ „์„ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  Cmder.exe๋ฅผ ์‹คํ–‰ํ•˜์„ธ์š”. ๋‹ค์Œ์œผ๋กœ SSH๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ssh root@server-ip-or-hostname

server-ip-or-hostname ๋Œ€์‹  ์„œ๋ฒ„์˜ IP ์ฃผ์†Œ๋‚˜ DNS ์ด๋ฆ„์„ ์ง€์ •ํ•˜์‹ญ์‹œ์˜ค. ๋‹ค์Œ์œผ๋กœ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ์—ฐ๊ฒฐ์— ์„ฑ๊ณตํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-74-generic x86_64)

ML ๋ชจ๋ธ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ์ฃผ์š” ์–ธ์–ด๋Š” Python์ž…๋‹ˆ๋‹ค. Linux์—์„œ ๊ฐ€์žฅ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ํ”Œ๋žซํผ์€ ์•„๋‚˜์ฝ˜๋‹ค.

์„œ๋ฒ„์— ์„ค์น˜ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋จผ์ € ๋กœ์ปฌ ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

sudo apt-get update

์ปฌ ์„ค์น˜(๋ช…๋ น์ค„ ์œ ํ‹ธ๋ฆฌํ‹ฐ):

sudo apt-get install curl

Anaconda ๋ฐฐํฌํŒ์˜ ์ตœ์‹  ๋ฒ„์ „์„ ๋‹ค์šด๋กœ๋“œํ•˜์„ธ์š”:

cd /tmp
curl โ€“O https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.sh

์„ค์น˜๋ฅผ ์‹œ์ž‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

bash Anaconda3-2019.10-Linux-x86_64.sh

์„ค์น˜ ๊ณผ์ •์—์„œ ๋ผ์ด์„ผ์Šค ๊ณ„์•ฝ์„ ํ™•์ธํ•˜๋ผ๋Š” ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์„ฑ๊ณต์ ์œผ๋กœ ์„ค์น˜๋˜๋ฉด ๋‹ค์Œ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Thank you for installing Anaconda3!

ํ˜„์žฌ ML ๋ชจ๋ธ ๊ฐœ๋ฐœ์„ ์œ„ํ•ด ๋งŽ์€ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ์œผ๋ฉฐ, ์šฐ๋ฆฌ๋Š” ๊ฐ€์žฅ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํŒŒ์ด ํ† ์น˜ ะธ ํ…์„œ ํ”Œ๋กœ์šฐ.

ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐœ๋ฐœ ์†๋„๋ฅผ ๋†’์ด๊ณ  ํ‘œ์ค€ ์ž‘์—…์— ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์ง„ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์˜ˆ์—์„œ๋Š” PyTorch๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์„ค์น˜ํ•ด ๋ด…์‹œ๋‹ค:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

์ด์ œ ML ์ „๋ฌธ๊ฐ€๋ฅผ ์œ„ํ•œ ์ธ๊ธฐ ์žˆ๋Š” ๊ฐœ๋ฐœ ๋„๊ตฌ์ธ Jupyter Notebook์„ ์ถœ์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์ฆ‰์‹œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Jupyter Notebook์€ Anaconda์— ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉฐ ์ด๋ฏธ ์„œ๋ฒ„์— ์„ค์น˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์Šคํฌํƒ‘ ์‹œ์Šคํ…œ์—์„œ ์—ฐ๊ฒฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฅผ ์œ„ํ•ด ๋จผ์ € ํฌํŠธ 8080์„ ์ง€์ •ํ•˜๋Š” ์„œ๋ฒ„์—์„œ Jupyter๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

jupyter notebook --no-browser --port=8080 --allow-root

๋‹ค์Œ์œผ๋กœ Cmder ์ฝ˜์†”(์ƒ์œ„ ๋ฉ”๋‰ด - ์ƒˆ ์ฝ˜์†” ๋Œ€ํ™” ์ƒ์ž)์—์„œ ๋‹ค๋ฅธ ํƒญ์„ ์—ด๋ฉด SSH๋ฅผ ํ†ตํ•ด ํฌํŠธ 8080์„ ํ†ตํ•ด ์„œ๋ฒ„์— ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

ssh -L 8080:localhost:8080 root@server-ip-or-hostname

์ฒซ ๋ฒˆ์งธ ๋ช…๋ น์„ ์ž…๋ ฅํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €์—์„œ Jupyter๋ฅผ ์—ด ์ˆ˜ ์žˆ๋Š” ๋งํฌ๊ฐ€ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

To access the notebook, open this file in a browser:
        file:///root/.local/share/jupyter/runtime/nbserver-18788-open.html
    Or copy and paste one of these URLs:
        http://localhost:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311
     or http://127.0.0.1:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311

localhost:8080์— ๋Œ€ํ•œ ๋งํฌ๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ „์ฒด ๊ฒฝ๋กœ๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ PC ๋กœ์ปฌ ๋ธŒ๋ผ์šฐ์ €์˜ ์ฃผ์†Œ ํ‘œ์‹œ์ค„์— ๋ถ™์—ฌ๋„ฃ์œผ์„ธ์š”. Jupyter Notebook์ด ์—ด๋ฆฝ๋‹ˆ๋‹ค.

์ƒˆ ๋…ธํŠธ๋ถ์„ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. New - Notebook - Python 3.

์šฐ๋ฆฌ๊ฐ€ ์„ค์น˜ํ•œ ๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์˜ˆ์‹œ PyTorch ์ฝ”๋“œ๋ฅผ Jupyter์— ์ž…๋ ฅํ•˜๊ณ  ์‹คํ–‰์„ ์‹คํ–‰ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค(์‹คํ–‰ ๋ฒ„ํŠผ).

from __future__ import print_function
import torch
x = torch.rand(5, 3)
print(x)

๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ ์žฅ์น˜(GPU)์˜ ์ฒซ ๋ฒˆ์งธ ์‹ ๊ฒฝ๋ง์ž…๋‹ˆ๋‹ค. ์ดˆ๋ณด์ž ๊ฐ€์ด๋“œ

๋น„์Šทํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๋ฉด ๋ชจ๋“  ๊ฒƒ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌ์„ฑ๋œ ๊ฒƒ์ด๋ฉฐ ์‹ ๊ฒฝ๋ง ๊ฐœ๋ฐœ์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

์‹ ๊ฒฝ๋ง ๋งŒ๋“ค๊ธฐ

์ด๋ฏธ์ง€ ์ธ์‹์„ ์œ„ํ•œ ์‹ ๊ฒฝ๋ง์„ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ๊ธฐ์ดˆ๋กœ ์‚ผ์ž ์ง€๋„๋ ฅ.

์šฐ๋ฆฌ๋Š” ๊ณต๊ฐœ์ ์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ CIFAR10 ๋ฐ์ดํ„ฐ ์„ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋„คํŠธ์›Œํฌ๋ฅผ ํ›ˆ๋ จํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” "๋น„ํ–‰๊ธฐ", "์ž๋™์ฐจ", "์ƒˆ", "๊ณ ์–‘์ด", "์‚ฌ์Šด", "๊ฐœ", "๊ฐœ๊ตฌ๋ฆฌ", "๋ง", "๋ฐฐ", "ํŠธ๋Ÿญ" ํด๋ž˜์Šค๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. CIFAR10์˜ ์ด๋ฏธ์ง€๋Š” 3x32x32, ์ฆ‰ 3x32 ํ”ฝ์…€์˜ 32์ฑ„๋„ ์ปฌ๋Ÿฌ ์ด๋ฏธ์ง€์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ ์žฅ์น˜(GPU)์˜ ์ฒซ ๋ฒˆ์งธ ์‹ ๊ฒฝ๋ง์ž…๋‹ˆ๋‹ค. ์ดˆ๋ณด์ž ๊ฐ€์ด๋“œ
์ž‘์—…์—์„œ๋Š” ์ด๋ฏธ์ง€ ์ž‘์—…์„ ์œ„ํ•ด PyTorch์—์„œ ๋งŒ๋“  ํŒจํ‚ค์ง€์ธ torchvision์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ์ˆ˜ํ–‰ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

  • ํ•™์Šต ๋ฐ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ ์„ธํŠธ ๋กœ๋“œ ๋ฐ ์ •๊ทœํ™”
  • ์‹ ๊ฒฝ๋ง ์ •์˜
  • ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๋„คํŠธ์›Œํฌ ํ›ˆ๋ จ
  • ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๋„คํŠธ์›Œํฌ ํ…Œ์ŠคํŠธ
  • GPU๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ›ˆ๋ จ๊ณผ ํ…Œ์ŠคํŠธ๋ฅผ ๋ฐ˜๋ณตํ•˜์ž

Jupyter Notebook์—์„œ ์•„๋ž˜์˜ ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

CIFAR10 ๋กœ๋“œ ๋ฐ ์ •๊ทœํ™”

Jupyter์—์„œ ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌํ•˜๊ณ  ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.


import torch
import torchvision
import torchvision.transforms as transforms

transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                        download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
                                          shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root='./data', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
                                         shuffle=False, num_workers=2)

classes = ('plane', 'car', 'bird', 'cat',
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

๋Œ€๋‹ต์€ ๋‹ค์Œ๊ณผ ๊ฐ™์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz
Extracting ./data/cifar-10-python.tar.gz to ./data
Files already downloaded and verified

ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ์—ฌ๋Ÿฌ ํ›ˆ๋ จ ์ด๋ฏธ์ง€๋ฅผ ํ‘œ์‹œํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


import matplotlib.pyplot as plt
import numpy as np

# functions to show an image

def imshow(img):
    img = img / 2 + 0.5     # unnormalize
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))
    plt.show()

# get some random training images
dataiter = iter(trainloader)
images, labels = dataiter.next()

# show images
imshow(torchvision.utils.make_grid(images))
# print labels
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))

๊ทธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ ์žฅ์น˜(GPU)์˜ ์ฒซ ๋ฒˆ์งธ ์‹ ๊ฒฝ๋ง์ž…๋‹ˆ๋‹ค. ์ดˆ๋ณด์ž ๊ฐ€์ด๋“œ

์‹ ๊ฒฝ๋ง ์ •์˜

๋จผ์ € ์ด๋ฏธ์ง€ ์ธ์‹์„ ์œ„ํ•œ ์‹ ๊ฒฝ๋ง์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ฐ„๋‹จํ•œ ์ง€์  ๊ฐ„ ๋„คํŠธ์›Œํฌ์ž…๋‹ˆ๋‹ค. ์ž…๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ์—ฌ๋Ÿฌ ๋ ˆ์ด์–ด๋ฅผ ํ•˜๋‚˜์”ฉ ํ†ต๊ณผํ•œ ๋‹ค์Œ ์ตœ์ข…์ ์œผ๋กœ ์ถœ๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ ์žฅ์น˜(GPU)์˜ ์ฒซ ๋ฒˆ์งธ ์‹ ๊ฒฝ๋ง์ž…๋‹ˆ๋‹ค. ์ดˆ๋ณด์ž ๊ฐ€์ด๋“œ

์šฐ๋ฆฌ ํ™˜๊ฒฝ์—์„œ ์œ ์‚ฌํ•œ ๋„คํŠธ์›Œํฌ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

net = Net()

๋˜ํ•œ ์†์‹ค ํ•จ์ˆ˜์™€ ์ตœ์ ํ™” ํ”„๋กœ๊ทธ๋žจ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.


import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๋„คํŠธ์›Œํฌ ํ›ˆ๋ จ

์‹ ๊ฒฝ๋ง ํ›ˆ๋ จ์„ ์‹œ์ž‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•œ ํ›„ ์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ์ž ์‹œ ๊ธฐ๋‹ค๋ ค์•ผ ํ•œ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. 5๋ถ„ ์ •๋„ ๊ฑธ๋ ธ์–ด์š”. ๋„คํŠธ์›Œํฌ๋ฅผ ํ›ˆ๋ จ์‹œํ‚ค๋Š” ๋ฐ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค.

 for epoch in range(2):  # loop over the dataset multiple times

    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # get the inputs; data is a list of [inputs, labels]
        inputs, labels = data

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()
        if i % 2000 == 1999:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

๋‹ค์Œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ ์žฅ์น˜(GPU)์˜ ์ฒซ ๋ฒˆ์งธ ์‹ ๊ฒฝ๋ง์ž…๋‹ˆ๋‹ค. ์ดˆ๋ณด์ž ๊ฐ€์ด๋“œ

ํ›ˆ๋ จ๋œ ๋ชจ๋ธ์„ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

PATH = './cifar_net.pth'
torch.save(net.state_dict(), PATH)

ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๋„คํŠธ์›Œํฌ ํ…Œ์ŠคํŠธ

์šฐ๋ฆฌ๋Š” ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ ์„ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋„คํŠธ์›Œํฌ๋ฅผ ํ›ˆ๋ จํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ๋„คํŠธ์›Œํฌ๊ฐ€ ์ „ํ˜€ ํ•™์Šตํ•œ ๊ฒƒ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์‹ ๊ฒฝ๋ง์ด ์ถœ๋ ฅํ•˜๋Š” ํด๋ž˜์Šค ๋ผ๋ฒจ์„ ์˜ˆ์ธกํ•˜๊ณ  ๊ทธ๊ฒƒ์ด ์‚ฌ์‹ค์ธ์ง€ ํ…Œ์ŠคํŠธํ•จ์œผ๋กœ์จ ์ด๋ฅผ ํ…Œ์ŠคํŠธํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ์ธก์ด ์ •ํ™•ํ•˜๋ฉด ์ƒ˜ํ”Œ์„ ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ์ธก ๋ชฉ๋ก์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
ํ…Œ์ŠคํŠธ ์„ธํŠธ์˜ ์ด๋ฏธ์ง€๋ฅผ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

dataiter = iter(testloader)
images, labels = dataiter.next()

# print images
imshow(torchvision.utils.make_grid(images))
print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))

๊ทธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ ์žฅ์น˜(GPU)์˜ ์ฒซ ๋ฒˆ์งธ ์‹ ๊ฒฝ๋ง์ž…๋‹ˆ๋‹ค. ์ดˆ๋ณด์ž ๊ฐ€์ด๋“œ

์ด์ œ ์‹ ๊ฒฝ๋ง์— ์ด ๊ทธ๋ฆผ์— ๋ฌด์—‡์ด ์žˆ๋Š”์ง€ ๋งํ•ด๋‹ฌ๋ผ๊ณ  ์š”์ฒญํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


net = Net()
net.load_state_dict(torch.load(PATH))

outputs = net(images)

_, predicted = torch.max(outputs, 1)

print('Predicted: ', ' '.join('%5s' % classes[predicted[j]]
                              for j in range(4)))

๊ทธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ ์žฅ์น˜(GPU)์˜ ์ฒซ ๋ฒˆ์งธ ์‹ ๊ฒฝ๋ง์ž…๋‹ˆ๋‹ค. ์ดˆ๋ณด์ž ๊ฐ€์ด๋“œ

๊ฒฐ๊ณผ๋Š” ๊ฝค ์ข‹์•„ ๋ณด์ž…๋‹ˆ๋‹ค. ๋„คํŠธ์›Œํฌ๋Š” ์‚ฌ์ง„ 4์žฅ ์ค‘ 3์žฅ์„ ์ •ํ™•ํ•˜๊ฒŒ ์‹๋ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ „์ฒด ๋ฐ์ดํ„ฐ ์„ธํŠธ์—์„œ ๋„คํŠธ์›Œํฌ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


correct = 0
total = 0
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print('Accuracy of the network on the 10000 test images: %d %%' % (
    100 * correct / total))

๊ทธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ ์žฅ์น˜(GPU)์˜ ์ฒซ ๋ฒˆ์งธ ์‹ ๊ฒฝ๋ง์ž…๋‹ˆ๋‹ค. ์ดˆ๋ณด์ž ๊ฐ€์ด๋“œ

๋„คํŠธ์›Œํฌ๊ฐ€ ๋ญ”๊ฐ€๋ฅผ ์•Œ๊ณ  ์ž‘๋™ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฐ€ ๋ฌด์ž‘์œ„๋กœ ํด๋ž˜์Šค๋ฅผ ๊ฒฐ์ •ํ–ˆ๋‹ค๋ฉด ์ •ํ™•๋„๋Š” 10%๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด์ œ ๋„คํŠธ์›Œํฌ๊ฐ€ ์–ด๋–ค ํด๋ž˜์Šค๋ฅผ ๋” ์ž˜ ์‹๋ณ„ํ•˜๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs, 1)
        c = (predicted == labels).squeeze()
        for i in range(4):
            label = labels[i]
            class_correct[label] += c[i].item()
            class_total[label] += 1


for i in range(10):
    print('Accuracy of %5s : %2d %%' % (
        classes[i], 100 * class_correct[i] / class_total[i]))

๊ทธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ ์žฅ์น˜(GPU)์˜ ์ฒซ ๋ฒˆ์งธ ์‹ ๊ฒฝ๋ง์ž…๋‹ˆ๋‹ค. ์ดˆ๋ณด์ž ๊ฐ€์ด๋“œ

๋„คํŠธ์›Œํฌ๋Š” ์ž๋™์ฐจ์™€ ์„ ๋ฐ•์„ ์‹๋ณ„ํ•˜๋Š” ๋ฐ ๊ฐ€์žฅ ์ข‹์€ ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค. ์ •ํ™•๋„๋Š” 71%์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋„คํŠธ์›Œํฌ๊ฐ€ ์ž‘๋™ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ์ž‘์—…์„ ๊ทธ๋ž˜ํ”ฝ ํ”„๋กœ์„ธ์„œ(GPU)๋กœ ์ „์†กํ•˜๊ณ  ์–ด๋–ค ๋ณ€ํ™”๊ฐ€ ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

GPU์—์„œ ์‹ ๊ฒฝ๋ง ํ›ˆ๋ จ

๋จผ์ € CUDA๊ฐ€ ๋ฌด์—‡์ธ์ง€ ๊ฐ„๋žตํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. CUDA(Compute Unified Device Architecture)๋Š” GPU(๊ทธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ ์žฅ์น˜)์˜ ์ผ๋ฐ˜ ์ปดํ“จํŒ…์„ ์œ„ํ•ด NVIDIA๊ฐ€ ๊ฐœ๋ฐœํ•œ ๋ณ‘๋ ฌ ์ปดํ“จํŒ… ํ”Œ๋žซํผ์ž…๋‹ˆ๋‹ค. CUDA๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐœ๋ฐœ์ž๋Š” GPU์˜ ์„ฑ๋Šฅ์„ ํ™œ์šฉํ•˜์—ฌ ์ปดํ“จํŒ… ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํš๊ธฐ์ ์œผ๋กœ ๊ฐ€์†ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ”Œ๋žซํผ์€ ์šฐ๋ฆฌ๊ฐ€ ๊ตฌ๋งคํ•œ ์„œ๋ฒ„์— ์ด๋ฏธ ์„ค์น˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋จผ์ € GPU๋ฅผ ์ตœ์ดˆ์˜ ๊ฐ€์‹œ์  cuda ์žฅ์น˜๋กœ ์ •์˜ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

device = torch . device ( "cuda:0" if torch . cuda . is_available () else "cpu" )
# Assuming that we are on a CUDA machine, this should print a CUDA device:
print ( device )

๊ทธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ ์žฅ์น˜(GPU)์˜ ์ฒซ ๋ฒˆ์งธ ์‹ ๊ฒฝ๋ง์ž…๋‹ˆ๋‹ค. ์ดˆ๋ณด์ž ๊ฐ€์ด๋“œ

๋„คํŠธ์›Œํฌ๋ฅผ GPU๋กœ ๋ณด๋‚ด๊ธฐ:

net.to(device)

๋˜ํ•œ ๊ฐ ๋‹จ๊ณ„์—์„œ ์ž…๋ ฅ๊ณผ ๋ชฉํ‘œ๋ฅผ GPU๋กœ ๋ณด๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

inputs, labels = data[0].to(device), data[1].to(device)

GPU์—์„œ ๋„คํŠธ์›Œํฌ๋ฅผ ๋‹ค์‹œ ํ›ˆ๋ จ์‹œ์ผœ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
for epoch in range(2):  # loop over the dataset multiple times

    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # get the inputs; data is a list of [inputs, labels]
    inputs, labels = data[0].to(device), data[1].to(device)

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()
        if i % 2000 == 1999:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

์ด๋ฒˆ์— ๋„คํŠธ์›Œํฌ ํ›ˆ๋ จ์€ ์•ฝ 3๋ถ„ ์ •๋„ ์ง„ํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ์กด ํ”„๋กœ์„ธ์„œ์—์„œ ๋™์ผํ•œ ๋‹จ๊ณ„๊ฐ€ 5๋ถ„ ๋™์•ˆ ์ง€์†๋˜์—ˆ๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ฐจ์ด๋Š” ํฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋„คํŠธ์›Œํฌ๊ฐ€ ๊ทธ๋‹ค์ง€ ํฌ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ํ›ˆ๋ จ์— ๋Œ€๊ทœ๋ชจ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜๋ฉด GPU ์†๋„์™€ ๊ธฐ์กด ํ”„๋กœ์„ธ์„œ์˜ ์†๋„ ์ฐจ์ด๊ฐ€ ์ปค์ง‘๋‹ˆ๋‹ค.

๊ทธ๊ฒŒ ์ „๋ถ€์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ํ•ด๋‚ธ ์ผ:

  • GPU๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์‚ดํŽด๋ณด๊ณ  GPU๊ฐ€ ์„ค์น˜๋œ ์„œ๋ฒ„๋ฅผ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์šฐ๋ฆฌ๋Š” ์‹ ๊ฒฝ๋ง์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์†Œํ”„ํŠธ์›จ์–ด ํ™˜๊ฒฝ์„ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์šฐ๋ฆฌ๋Š” ์ด๋ฏธ์ง€ ์ธ์‹์„ ์œ„ํ•œ ์‹ ๊ฒฝ๋ง์„ ๋งŒ๋“ค๊ณ  ํ›ˆ๋ จ์‹œ์ผฐ์Šต๋‹ˆ๋‹ค.
  • GPU๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋„คํŠธ์›Œํฌ ํ›ˆ๋ จ์„ ๋ฐ˜๋ณตํ•˜๊ณ  ์†๋„๊ฐ€ ํ–ฅ์ƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋Œ“๊ธ€๋กœ ์งˆ๋ฌธ์— ๋‹ต๋ณ€ํ•ด ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€