PyTorch๊ฐ ๋นํธ ๊ฒฐ์ ์ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ๋๋ก ํ๋ ค๋ฉด ์ ์ญ ๋ณ์๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค. Soumith๋ ์ผ๋ถ ์ธ๋ถ ์ ๋ณด๊ฐ ํ์คํ์ง ์๊ธฐ ๋๋ฌธ์ torch.experimental
ํ์ ํจํค์ง์ ํ๋๊ทธ๋ฅผ ์ถ๊ฐํ ๊ฒ์ ์ ์ํฉ๋๋ค.
์คํ ๊ฐ์ ๋นํธ ๋จ์ ๊ฒฐ์ ์ฑ์ ๋๋ฒ๊น ์ ์ ์ฉํ ๋๊ฐ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ผ๋ถ ์์ ์ ๋ํด ํจ์จ์ ์ธ ๊ฒฐ์ ๋ก ์ ์๊ณ ๋ฆฌ์ฆ์ ์์ฑํ๋ ๊ฒ์ ์ด๋ ต์ต๋๋ค.
torch.experimental.deterministic
๊ฐ False
(๊ธฐ๋ณธ๊ฐ)์ธ ๊ฒฝ์ฐ PyTorch๋ ์ฃผ์ด์ง ์์
์ ์ฌ์ฉํ ์ ์๋ ๊ฐ์ฅ ๋น ๋ฅธ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. torch.experimental.deterministic
๊ฐ True
์ด๋ฉด PyTorch๋ ๊ฒฐ์ ์ ์๊ณ ๋ฆฌ์ฆ๋ง ์ฌ์ฉํด์ผ ํฉ๋๋ค. PyTorch๋ ์ฃผ์ด์ง ์์
์ ์ฌ์ฉํ ์ ์๋ ๊ฒฐ์ ์ ์๊ณ ๋ฆฌ์ฆ์ด ์๊ณ torch.experimental.deterministic
๊ฐ True
๊ฒฝ์ฐ ๊ฒฝ๊ณ ๋ฅผ ๋ฐํํด์ผ ํฉ๋๋ค.
cuDNN ์๊ณ ๋ฆฌ์ฆ ์ ํ์ ์ ์ดํ๊ธฐ ์ํ torch.backends.cudnn.deterministic
ํ๋๊ทธ๊ฐ ์ด๋ฏธ ์์ต๋๋ค. ์ง๊ธ์ ์ด ํ๋๊ทธ๋ฅผ ์ ์งํ๊ณ torch.backends.cudnn.deterministic
๋๋ torch.experimental.deterministic
๊ฐ True์ธ ๊ฒฝ์ฐ cuDNN์ ๊ฒฐ์ ์ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ ํํด์ผ ํฉ๋๋ค.
์ฐ๋ฆฌ๋ ๋์ผํ ์ํคํ
์ฒ์ ๊ตฌ์ฑ์ ๊ฐ์ง ๋จธ์ ์์ ์คํ๋๋ ๋นํธ ๋จ์ ๊ฒฐ์ ๋ก ๋ง์ ๋ชฉํ๋ก ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, torch.experimental.deterministic
๊ฐ True์ธ ๊ฒฝ์ฐ์๋ ๋ค์ ์ค ํ๋๋ผ๋ ๋ค๋ฅผ ๋ ๋นํธ ๊ฒฐ์ ๋ก ์ ๋ชฉํ๋ก ํ์ง ์์ต๋๋ค .
์ด ๊ธฐ๋ฅ์ ๋ ๋จ๊ณ๋ก ์ถ๊ฐํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ฒซ ๋ฒ์งธ ๋จ๊ณ๋ torch.backends.cudnn.deterministic
ํ๋๊ทธ๋ฅผ ์ถ๊ฐํ๊ณ ๋น๊ฒฐ์ ์ ์์
์ ๊ฒฝ๊ณ ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์
๋๋ค. ๋ ๋ฒ์งธ ๋จ๊ณ๋ ๋น๊ฒฐ์ ์ ์์
์ ๋ํ ๊ฒฐ์ ์ ๊ตฌํ์ โโ์ถ๊ฐํ๋ ๊ฒ์
๋๋ค.
PyTorch ๋ฌธ์ ์ ๋น๊ฒฐ์ ์ ์์ ์ ์ผ๋ถ ๋ชฉ๋ก์ด ์์ต๋๋ค.
torch.experimental.deterministic
๋ RNG ์๋์ ์ด๋ป๊ฒ ์ํธ ์์ฉํด์ผ ํฉ๋๊น? ์๋ ์๋๊ฐ ์ค์ ๋์ง ์์ ๊ฒฝ์ฐ ๊ธฐ๋ณธ ์๋๋ฅผ ์ค์ ํด์ผ ํฉ๋๊น? ์๋ ์๋๊ฐ ์ค์ ๋์ง ์์ ๊ฒฝ์ฐ ๊ฒฝ๊ณ ๋ฅผ ๋ฐํํด์ผ ํฉ๋๊น?
cc @ezyang @gchanan @zou3519
์ด๊ฒ์ ๋์๊ฒ์ ์๋ก ์์ง์๊ฐ๋ฝ์ด๋ค. ๋ฌธ์ ๋ ์ฃผ๋ก ์ด๊ฒ์ ์ฝ๋๋ฒ ์ด์ค์ ๋ชจ๋ ๊ณณ์์ ์ค์ ๋ก ๋กค์์ํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ๋ ๋์ ๊ฒ์ ์ฐ๋ฆฌ๊ฐ ๊ฒฐ์ ๋ก ์ ์ด๋ผ๊ณ ์ฃผ์ฅํ๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ๋น๋ฐ๋ฆฌ์ ๊ทธ๊ฒ์ ์๋๋๋ค :)
๋๋ ๊ทธ๊ฒ์ ์ฐฌ์ฑํ๊ณ ๋ด ์ ๊ทผ ๋ฐฉ์์ ๊ฒฐ์ ๋ก ์ด ์ผ์ ธ ์๊ณ ๊ทธ๋ ์ง ์๋ค๋ ๊ฒ์ ์๊ณ ์์ ๋ ์์ ๋ฐ ์ค๋ฅ์ ํ๋๊ทธ๋ฅผ ์ง์ ํ๋ ๊ฒ์ ๋๋ค.
๋น๊ฒฐ์ ์ ์ฐ์ฐ์์ ์ค๋ฅ๋ฅผ ๋ฒํ๋ ๊ฒ์ ๋๋ฌด ๊ฐํนํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ฒฝ๊ณ ๋ ๋ ๋ถ๋๋ฌ์ด ๊ฒฝํ์ฒ๋ผ ๋ณด์ ๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก throw๊ฐ ๋์ด์ผ ํ๋ค๊ณ ์๊ฐํ์ง๋ง ๋ค์ค ๊ฐ ์์ฑ์ ์ง์ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค(๋น๊ฒฐ์ ์ ์ ๊ด์ฐฎ์, ๊ฒฝ๊ณ , throw).
๋๋ ๊ฒฝ๊ณ ์ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ์ค์ ๋ก ๋ณด์ง ๋ชปํ๋ค๋ ๊ฒ์ ์ธ์ ํด์ผ ํฉ๋๋ค. ์ฌ๋๋ค์ด ๊ทธ๊ฒ์ ์ผค ๋งํผ ์ถฉ๋ถํ ๊ฒฐ์ ์ ์ธ ๊ฒ์ ๊ด์ฌ์ ๊ฐ์ง ๋ ๊ทธ๋ค์ ์๋ง๋ ์ค๋ฅ๋ฅผ ์์ํ ๊ฒ์ ๋๋ค. ์ด๋ค ๋น๊ฒฐ์ ๋ก ์ด ์์ด๋ ๊ด์ฐฎ๋ค๊ณ ๋งํ๋ ํน์ ํธ์ถ์ ๋ํด์๋ ํญ์ ์ด ๊ธฐ๋ฅ์ ๋ ์ ์์ต๋๋ค.
์ค๋ฅ, ๊ฒฝ๊ณ , ์ ์ ํ ๋ฌธ์...
ํ์๋ ํ์์
๋๋ค.
๊ฒฝ๊ณ ๋๋ ์ค๋ฅ? ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
๋์ง๋ ๊ฒ์ ๋๋จํ ๊ฒ ๊ฐ๋ค. ๋์ง๋ ๋์ ๊ฒฝ๊ณ ํ๋ ์ต์ ์ ์ ๊ณตํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ผ๋ก ๋ณด์ธ๋ค๋ Adam์ ์๊ฒฌ์ ๋์ํฉ๋๋ค.
์๋ ค์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค. ๊ฒฐ๊ตญ ์ผํญ ํ๋๊ทธ๋ฅผ ์ํ ์ฃผ์ ๋
ธ๋ ฅ์ ํ๋๊ทธ ์์ฒด์ด๋ฉฐ ์ด๋ ต์ง ์์ต๋๋ค.
Context.h์ ํ๋๊ทธ๋ฅผ ์ถ๊ฐํ๊ณ (์ ํธ๋ฆฌํฐ ํจ์๋ฅผ ํตํด) AT_ERROR ๋ฐ AT_CHECK๋ฅผ ๋ฟ๋ฆด ๊ฒ์
๋๋ค.
์๋
ํ์ธ์,
์ด ๊น๋ฐ์ ์ด๋ค ์์์ด ์์ต๋๊น?
๊ฒฐ์ ๋ก ์ด ์ค์ํฉ๋๋ค.
๋ด ๊ฒฝํ์ ๋ฐ๋ฅด๋ฉด ํ์ฌ ๋ฒ์ ์ ๊ณ ์ ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ต๋ ์ ๋ฐ๋ 1e-16
๊น์ง ํ๋์ GPU์ ๋ํ ๊ฒฐ์ ์ฑ์ ํ์ฉํฉ๋๋ค. ๊ทน๋ฏธํ ์ฐจ์ด๊ฐ ์ฆํญ๋์ด ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ฐํ ์ ์๋ค๋ ์ ์ ์ ์ํ์ญ์์ค.
multigpu์ ๊ฒฝ์ฐ๋ ๊ณ ๋ คํ์ญ์์ค(์ ์ด๋ ๊ณ ์ ๋ K
GPU์ ๊ฒฝ์ฐ ๋์์ ๊ฒฐ์ ์ ์ด์ด์ผ ํฉ๋๋ค. ์ ๋ ๋ค์๊ณผ ๊ฐ์ ์ด์ ๋ก ๋๋๋ก ๋ถํด๋๋ ์ผ์ข
์ ๊ฒฐ์ ๋ก ์ ๋ฌ์ฑํ ์ ์์ต๋๋ค. ์ง๊ธ์ ์ดํดํ์ง ๋ชปํฉ๋๋ค(nightly build 1.2.0.dev20190616
). ๋๋ ์ง๊ธ ๊ทธ๊ฒ ๋๋ฌธ์ ๊ณ ๊ตฐ๋ถํฌํ๊ณ ์๋ค( 1 , 2 ).
๊ฐ์ฌํฉ๋๋ค!
@t-vi ์ด ์ผ์ ํ๋ฐํ ํ๊ณ ์๋์?
๋๋ ๋น์ ์ด ๊ทธ๊ฒ์ ํ๋ ๊ฒ์ ๋ง๊ณ ์ถ์ง ์์ต๋๋ค.
@t-vi ๋ช ํํ์ง ์์ ๊ฒฝ์ฐ ์ฃ์กํฉ๋๋ค. ์์ ํ ๊ณํ์ด ์์ต๋๋ค. :) . ๋๊ตฐ๊ฐ๊ฐ ์ ๊ทน์ ์ผ๋ก ๊ทธ๋ ๊ฒํ๊ณ ์๋์ง ์ดํดํ๋ ค๊ณ ํ์ต๋๋ค.
๊ฑฐ์ 1๋ ์ด ์ง๋ ํ์๋ ๋น๊ฒฐ์ ์ ๋ณด๊ฐ ๋ฌธ์ ๋ ์ฌ์ ํ ํด๊ฒฐ๋์ง ์๊ณ ์์ต๋๋ค.
์ปค๋ฎค๋ํฐ์์ ์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. :)
๊ฒฐ์ ๋ก ์ ๋ณด๊ฐ์ ์ฌ์ฉ์์๊ฒ ํฐ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
~์์ง ๊ด๊ณ ํ์ง ์์์ง๋ง ํ ๋น๋ ๊ฐ๋ฐ์ ๋ฆฌ์์ค๋ณด๋ค ์ฌ์ฉ์ ๊ด์ฌ์ด ๋ ๋ง์ ๊ฒ ๊ฐ์์ ์ค์ ํ ๋ ๋ด github ํ์ ํ์ด์ง ์์ ํฌํํ ์ ์๋ ํ๋ก์ ํธ๋ก ๋์ดํ์ต๋๋ค.
๋๋ ์ฐ๋ฆฌ๊ฐ ์ฌํด ๋ง๊น์ง ์ข์ ์ง์ ์ ์ด๋ฃฐ ์ ์๋ค๊ณ ํ์ ํ๊ณ ๋ณด๊ฐ๋ฒ์ ํ์คํ ์์ ๋ฐฉ๋ฒ์ ๋ํ ๊ณํ์ด ์๋ ๊ฒ ์ค ํ๋์
๋๋ค(๋ด๊ฐ ๋ฌธ์ ์ ์ด๋๊ฐ์ ์๋ fold์ ๋ํ ์์ฌ ์ฝ๋์ ์ ์ฌ). ๋ด ์์ ์ ์ฐ์ ์์ ๋ชฉ๋ก์ ๋์ง ์์ต๋๋ค.~
ํฅ๋ฏธ๋กญ์ง ์์ ๊ฒ์ผ๋ก ๋ํ๋ฌ์ต๋๋ค.
๊ฒฐ์ ๋ก ์ ๋ณด๊ฐ์ ํฐ ๋์์ด ๋ ๊ฒ์ ๋๋ค. ๋งํฌ
๋ฒํ ์ฐ์ ์์, ํนํ CUDA์ ๊ฒฝ์ฐ ์ฌ์ฉ์ ํผ๋๋ฐฑ์ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค.
๊ณ ์ณ์ง๊ณ ์์ด์ ๋คํ์ ๋๋ค, ๊ฐ์ฌํฉ๋๋ค!
@t-vi๋ ๊ณต์ ํ๊ธฐ ์ํด "์ฐ์ ์์ ์ถฉ๋"์ด "๊ณ ์ ์ค"๊ณผ ๋์ผํ๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค. :).
์๋ฃจ์ ์ ๊ธฐ๋ํฉ๋๋ค!
colesbury๋ ๊ฒฐ์ ๋ก ์ ์๊ณ ๋ฆฌ์ฆ์ ํฌ๋ฌ ์ด์ ์ค ํ๋๋ ๊ฒฐ์ ๋ก ์ด ์ค์ ๋ก ๋ฌธ์ ์ด๊ธฐ ๋๋ฌธ์ด ์๋๋ผ ์ด ๊ธฐ๋ฅ์ ์ผค ๋ ์ด๋ฅผ ๋ฐฐ์ ํ ์ ์๋ค๊ณ ์ธ๊ธํ์ต๋๋ค. ;)
torch.experimental.deterministic
๋ RNG ์๋์ ์ด๋ป๊ฒ ์ํธ ์์ฉํด์ผ ํฉ๋๊น? ์๋ ์๋๊ฐ ์ค์ ๋์ง ์์ ๊ฒฝ์ฐ ๊ธฐ๋ณธ ์๋๋ฅผ ์ค์ ํด์ผ ํฉ๋๊น? ์๋ ์๋๊ฐ ์ค์ ๋์ง ์์ ๊ฒฝ์ฐ ๊ฒฝ๊ณ ๋ฅผ ๋ฐํํด์ผ ํฉ๋๊น?
์ฌ์ฉ์๊ฐ ์๋๋ฅผ ์ค์ ํ์ง ์์ ๊ฒฝ์ฐ ์๋๋ฅผ ์ค์ ํ์ง ์๋ ๊ฒ์ด ์ข์ต๋๋ค. ํ๋๋ ํ์ํ์ง ์์ ๋ ๊ฐ์ ์ธํฐํ์ด์ค๋ฅผ ์ฐ๊ฒฐํ๊ธฐ ๋๋ฌธ์
๋๋ค(๊ฒฐ์ ๋ก ์ ๊ด์ฌ์ด ์๋ ์ฌ์ฉ์๋ RNG๋ฅผ ๋งค์ฐ ์ ์ดํดํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค). ๋ ์ค์ํ ๊ฒ์ ์ด ์์
์ ์์ ์ ์ผ๋ก ์ํํ๊ธฐ๊ฐ ๋งค์ฐ ์ด๋ ต๋ค๋ ๊ฒ์
๋๋ค. ๋ค์ค ํ๋ก์ธ์ค/์ค๋ ๋ ์์ฉ ํ๋ก๊ทธ๋จ์์ RNG๋ฅผ ์ฌ์ฉํ ์ ์๊ณ , ๋ค๋ฅธ torch.Generator
ํ์ ํด๋์ค๊ฐ ์๊ณ , numpy.random
๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๊ฒฝ๊ณ ๋ฅผ ์ค์ ํ ์ ์๋ ์ ์ ํ ์์น๊ฐ ์๋ ๊ฒฝ์ฐ์๋ง ๊ฒฝ๊ณ ์ ๋ํด ํ์ ํ ์ ์์ต๋๋ค(์: RNG๊ฐ ์ฌ์ฉ๋๋ ๋์ผํ ๋ชจ๋/ํจ์๊ฐ ์๋๋ผ determinism=True
์ด์ ์ ๊ฐ์ ๋ก ์๋ํ์๊ฒ ์ต๋๊น?).
torch.backends.cudnn.deterministic=True
์ค์ ํ ๋ ๋ณด๊ฐ ์ฐ์ฐ์๊ฐ ์ฌ์ ํ ๊ฒฐ์ ์ ์ผ ์ ์๋ค๋ ์ ์ด ๊ถ๊ธํฉ๋๋ค. pytorch ๋ณด๊ฐ์ cudnn์ ์ฌ์ฉํ์ง ์์ต๋๊น?
๊ทธ๋ ์ง ์์ ์๋ ์์ต๋๋ค. ๋ณด๊ฐ ์คํ์ nvprofํ์ฌ ํ์คํ๊ฒ ํ์ธํ ์ ์์ต๋๋ค.
torch.experimental.deterministic
๊ฐ ๊ตฌํ๋๋ฉด ํจ์ ํธ์ถ์์ deterministic
์ธ์๋ฅผ ๊ณ์ ์ ๊ณตํด์ผ ํ๋์ง ์ฌ๋ถ๊ฐ ๊ถ๊ธํฉ๋๋ค. ์ฌ์ฉ์๊ฐ ์ผ๋ถ ์์
์๋ ๊ฒฐ์ ์ฑ์ ์ ํธํ๊ณ ๋ค๋ฅธ ์์
์๋ ์๋๋ฅผ ์ ํธํ ์ ์๊ธฐ ๋๋ฌธ์ ๊ทธ๋ ๊ฒ ํด์ผ ํ ์๋ ์์ต๋๋ค.
์ธ์๋ฅผ ์ ์งํ๋ฉด torch.experimental.deterministic
์ ํจ์์ deterministic
ํ๋๊ทธ๊ฐ ์๋ก ๋ฐ๋๋๋ ๊ฒฝ์ฐ ์ด๋ป๊ฒ ๋ฉ๋๊น? torch.experimental.deterministic = True
๊ฐ "๋ฌด์จ ์ผ์ด ์์ด๋ ๋ชจ๋ ๊ฒฝ์ฐ์ ๊ฒฐ์ ๋ก ์ ์ฌ์ฉ"์ ์๋ฏธํด์ผ ํ๊ฑฐ๋ "๊ฒฐ์ ๋ก ์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ฌ์ฉํ์ง๋ง deterministic
์ธ์๊ฐ ํจ์ ํธ์ถ์ ์ง์ ๋ ๊ฒฝ์ฐ์๋ ๋ค์์ ์ฌ์ฉํ์ญ์์ค. ํน์ ๊ธฐ๋ฅ ํธ์ถ์ ๋ํ ์ค์ ์
๋๋ค." ์ฆ, ์๋ ์ฝ๋๋ฅผ ์ด๋ป๊ฒ ์ฒ๋ฆฌํด์ผ ํ ๊น์? ๋น์ทํ ์ํฉ์์ torch.backends.cudnn.deterministic
ํ๋๊ทธ๊ฐ ์ด๋ป๊ฒ ์๋ํ๋์ง ์๋ ์ฌ๋์ด ์์ต๋๊น?
torch.experimental.deterministic = True
torch.some_operation(deterministic=False)
@kurtamohler ์ข์ ์ง๋ฌธ์
๋๋ค. ๊ฐ์ฅ ์ฌ์ด ์์ ์ bool? deterministic=None
๋ก ๋ง๋ ๋ค์ None
๋ฅผ " torch.experimental.deterministic
์กด์ค"์ ์๋ฏธํ๋๋ก ํด์ํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด ์ฌ์ฉ์๊ฐ ์์ฒญํ ๊ฒ์ ์ ํํ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค.
์ฐ๋ฆฌ๋ ์ข
๋ฅ์ ํ์ ๊ณผ ๋น์ทํ ์ํฉ์ ๊ฐ์ง๊ณ ์์ง๋ง ๊ทธ๊ฒ์ ์ํ ๋ ๋ฐฉ๋ฒ์ด ์๋ค๋ ๊ฒ์์ด์ด์๋ค convolution
์๋์ค benchmark
๋ค์ ์ธ์ ๋ฐ _convolution
๋ช
์ ์ ์ผ๋ก ๊ธฐ์ค.
์ด ์๋ฃจ์
์ค ํ๋๊ฐ ํ์ฉ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ปจ๋ณผ๋ฃจ์
์ ๊ทผ ๋ฐฉ์์ ๋ด๋ถ deterministic
ํ๋๊ทธ๋ฅผ ์ฌ์ฉ์๊ฐ ๋ณผ ์ ์๋ API๋ก ๋์ถํ์ง ์๋๋ค๋ ์ถ๊ฐ ์ด์ ์ด ์์ต๋๋ค(๋ด๋ถ API๋ฅผ ์ฌ์ฉํ์ง ์๋ ํ).
"๋๋ ๋ชจ๋ ๊ณณ์์ ๊ฒฐ์ ๋ก ์ ์ด ๋๊ณ ์ถ์ง๋ง _์ด ํน์ ์ฐ์ฐ์์์๋ _ ํ์ง ์๊ธฐ๋ฅผ ์ํฉ๋๋ค."์ ๋ํ ๊ทผ๊ฑฐ๋ ๋ฌด์์ ๋๊น? ์ด๊ฒ์ด ์ฐ๋ฆฌ์ ๋ง์ ์ฐ์ฐ์(๊ทธ๋ฆฌ๊ณ ๋๋ถ๋ถ์ ๋ณต์กํ ์ฐ์ฐ์)์ ์ถ๊ฐ ์ ๋ ฅ์ ์ถ๊ฐํ๋ ๊ฒ์ ๋ณด์ฆํ ๋งํผ ์ถฉ๋ถํ ์ผ๋ฐ์ ์ธ ์ฌ์ฉ ์ฌ๋ก๋ผ๊ณ ํด์ผ ํ ๊น์? IMO์์๋ ๊ฒฐ์ ์ฑ์ ํ ๊ธํ๊ธฐ ์ํ ์ปจํ ์คํธ ๊ด๋ฆฌ์๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
@apaszke , ๋ค, ์ปจํ
์คํธ ๊ด๋ฆฌ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒฐ์ ๋ก ์ ํ ๊ธํ๋ ๊ฒ์ด ๋ ๋ซ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ด๋ค ์ฐ์ฐ์์๋ deterministic
์ธ์๋ฅผ ์ถ๊ฐํด์ผ ํ๋ค๊ณ ๋งํ์ง๋ ์์ง๋ง ์ผ๋ถ ์ฐ์ฐ์์๋ ์ด๋ฏธ ์์ต๋๋ค. ๊ทธ๊ฒ๋ค์ ๋ชจ๋ ์ ๊ฑฐํ๊ณ BC๋ฅผ ์ค๋จํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ต๋๊น, ์๋๋ฉด ๊ณ์ ์ ์งํ๊ณ torch.experimental.deterministic
๋ฅผ ์ฌ์ ์ํ๋๋ก ํ์ฉํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ต๋๊น?
๋๋ ๊ทธ๊ฒ์ ์ ๊ฑฐํ๊ฑฐ๋ ์ต์ํ ๋น๊ณต๊ฐ๋ก ๋ง๋ค์ด์ผ ํ๋ค๊ณ ๋งํ๊ณ ์ถ์ต๋๋ค(์ฆ, ๋ฐ์ค ์ ๋์ฌ ๋๋ sth).
๋ณด๊ฐ ๊ธฐ๋ฅ์ ๋ํ ๊ฒฐ์ ์ ๊ธฐ๋ฅ์ด ๋ซํ ์๊ณ ๊ตฌํ๋์ง ์๋์ง ๊ถ๊ธํฉ๋๋ค.
์๋์, ์ฐ๋ฆฌ๋ PyTorch์ ๋ชจ๋ ๊ธฐ๋ฅ์ ๋ํ ๊ฒฐ์ ๋ก ์ ๋ฒ์ ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
@ezyang ์ด๋ค pytorch ๋ฒ์ ์ ๊ฒฐ์ ์ F.interpolate ๊ธฐ๋ฅ์ด ์์ต๋๊น? pytorch 1.6๋ถํฐ ์์ํฉ๋๊น? ์๋๋ฉด ์ต์ ์์ ๋ฒ์ (1.5)์์ ์ฌ์ฉํ ์ ์์ต๋๊น? ์๋๋ฉด ์์ค์์ Pytorch๋ฅผ ๋ค์ด๋ก๋ํ์ฌ ์ค์นํด์ผ ํฉ๋๊น?
์ด ์์ ์ ์์ํ๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค.
์์ ์ปค๋ฐ์ ํ๋๊ทธ๋ง ์ถ๊ฐํ ๋ฟ ์์ง ์์
์๋ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค. ๋๊ตฐ๊ฐ ์๊ฐ์ ๋ด์ด ์ดํด๋ณด๊ณ ๋ด๊ฐ ์๋ชปํ ๊ฒ์ด ์๊ฑฐ๋ ์ง๊ธ๊น์ง ๊ฐ์ ํ ์ ์๋ ๊ฒ์ด ์์ผ๋ฉด ์๋ ค์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค. torch.backends.cudnn.deterministic
๊ตฌํ ๋ฐฉ๋ฒ์ ๊ธฐ๋ฐ์ผ๋ก ํ์ต๋๋ค.
์ด๊ฒ์ ๊ด์ฐฎ์ ๋ณด์ด์ง๋ง ๋ด๋ถ ์ด๋ฆ ์ง์ ์๋ ์คํ์ ํญ๋ชฉ์ด ํฌํจ๋์ด์๋ ์ ๋๋ค๊ณ ์๊ฐํฉ๋๋ค.
@ezyang , ๋ค ์ดํด๊ฐ ๋ฉ๋๋ค. ์ด๋ฆ์ ๋ฐ๊พธ๊ฒ ์ต๋๋ค.
@t-vi๊ฐ ์ด ๋ฌธ์ ์ ๋ํ ์ด์ ์์
์์ ํ๋ ๊ฒ๊ณผ ์ ์ฌํ torch.experimental.deterministic_error_level
์ถ๊ฐํ์ต๋๋ค. deterministic_error_level
๋ deterministic == True
์ด๊ณ ์ฃผ์ด์ง ํจ์์ ๊ฒฐ์ ์ ๊ตฌํ์ด ์๋ ๊ฒฝ์ฐ ์ค๋ฅ/๊ฒฝ๊ณ ๋์์ ์ ์ดํฉ๋๋ค. 2(์ค๋ฅ), 1(๊ฒฝ๊ณ ) ๋๋ 0(๋ฌด์)์ผ๋ก ์ค์ ํ ์ ์์ต๋๋ค.
์ฌ์ฉ์๊ฐ ๋ค๋ฅธ ๊ฐ์ผ๋ก ์ค์ ํ๋ฉด ์ก์ ์ ์๋ ํ์ด์ฌ ๋ฐํ์ ์์ธ๋ฅผ ๋์ง๊ณ ์ถ์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ด๋ฌํ ์ข
๋ฅ์ ๋์์ TORCH_CHECK()
๋ฅผ ์ฌ์ฉํ์ง๋ง ์ด ๊ฒฝ์ฐ ์์ธ๋ฅผ ํฌ์ฐฉํ ์ ์๊ณ ์ด์ ๋ฅผ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. TORCH_CHECK()
ํธ์ถ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ๋งํฌ
๊ฒ์ฌ๊ฐ ์คํจํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ฉ๋๋ค.
>>> import torch
>>> try:
... torch.experimental.deterministic_error_level=50
... except:
... print('exception caught')
...
terminate called after throwing an instance of 'c10::Error'
what(): error level 50 is invalid, must be one of 0: None, 1: Warn, or 2: Error
Exception raised from longToErrorLevel at ../aten/src/ATen/Context.cpp:85 (most recent call first):
frame #0: c10::Error::Error(c10::SourceLocation, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) + 0x58 (0x7f53e2cc0878 in /work/kurtamohler/development/pytorch-deterministic-flag/torch/lib/libc10.so)
frame #1: at::Context::longToErrorLevel(long) + 0x122 (0x7f53f6d61a82 in /work/kurtamohler/development/pytorch-deterministic-flag/torch/lib/libtorch_cpu.so)
frame #2: THPModule_setDeterministicErrorLevel(_object*, _object*) + 0x31 (0x7f53fb5625d1 in /work/kurtamohler/development/pytorch-deterministic-flag/torch/lib/libtorch_python.so)
<omitting python frames>
frame #23: __libc_start_main + 0xe7 (0x7f5432d62b97 in /lib/x86_64-linux-gnu/libc.so.6)
Aborted (core dumped)
๋๊ตฌ๋ ์ง ๋ด๊ฐ ๊ทธ๊ฒ์ ๊ณ ์น ์์๋ ๋ฐฉ๋ฒ์ ์๊ณ ์๋ค๋ฉด ์๋ ค์ฃผ์ญ์์ค.
@kurtamohler ์ THPModule_setDeterministicErrorLevel
HANDLE_TH_ERRORS / END_ HANDLE_TH_ERRORS ๋งคํฌ๋ก๊ฐ ๋๋ฝ๋์์ต๋๊น? C++ ์์ธ๋ฅผ ์ก์์ ํ์ด์ฌ ์ค๋ฅ ๋ฐํ์ผ๋ก ๋ณํํ๋ ๋ฐ ํ์ํฉ๋๋ค.
์ ๊ทธ๋ฌ์ต๋๋ค, @colesbury์๊ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค!
atomicAdd
์ ๋ชจ๋ ํธ์ถ์์๊ฒ ๋น๊ฒฐ์ ์ ๊ฒฝ๊ณ ๋ฅผ ์ถ๊ฐํ๊ธฐ ์์ํ์ต๋๋ค. ์ผ๋ถ ๋ฐ์ ์๋ ํน์ ๊ฒฝ์ฐ์๋ง atomicAdd
๋ฅผ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ์์์ต๋๋ค. ์๋ฅผ ๋ค์ด adaptive_avg_pool3d_backward
๋ (isizeW%osizeW != 0) || (isizeH%osizeH != 0) || (isizeT%osizeT != 0)
๊ฐ true์ธ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํฉ๋๋ค. ์ด๋ฌํ ๊ฒฝ์ฐ์๋ง ๊ฒฝ๊ณ ํ๊ณ ์ค๋ฅ ๋ฉ์์ง๋ก ์ ๋ฌํด์ผ ํฉ๋๊น, ์๋๋ฉด atomicAdd
๊ฐ ์ฌ์ฉ๋๋์ง ์ฌ๋ถ์ ๊ด๊ณ์์ด ์ด๋ฌํ ํจ์๊ฐ ํธ์ถ๋ ๋๋ง๋ค ๊ฒฝ๊ณ ํ๋ ๊ฒ์ด ๊ด์ฐฎ์ต๋๊น?
๋ฌด์กฐ๊ฑด ๊ฒฝ๊ณ ํ๋ฉด ๊ตฌํํ๊ธฐ ์ฝ๊ณ ์ดํดํ๊ธฐ ์ฌ์ธ ๊ฒ์ ๋๋ค.
@ngimel , ์ ๋ CUBLAS_WORKSPACE_CONFIG
๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒฐ์ ์ ์ธ ์คํธ๋ฆผ ์ฌ์ฉ์ ๋ณด์ฅํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์๊ฐํด ์์ผ๋ฉฐ ๊ณ ๋ คํด์ผ ํ ๋ ๊ฐ์ง ์ฃผ์ ์ ๊ทผ ๋ฐฉ์์ด ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋๊ตฐ๊ฐ๊ฐ ์ํฅ์ ๋ฐ๋ CUDA ๋ฒ์ (ํ์ฌ 10.2 ์ด์) ์ค ํ๋๋ฅผ ์ฌ์ฉํ๊ณ ์๊ณ torch.set_deterministic(True)
๊ฐ ํธ์ถ๋๋ฉด std::getenv
๋ฅผ ์ฌ์ฉํ์ฌ CUBLAS_WORKSPACE_CONFIG
๊ฐ :16:8
๋๋ :4096:8
. ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ (1) ๋๋ (2)๋ฅผ ์ํํฉ๋๋ค.
์ฌ์ฉ์์๊ฒ ๋ณ์๋ฅผ ์ ์ ํ๊ฒ ์ค์ ํ๋ผ๋ ์ค๋ฅ๋ฅผ ๋์ง๋๋ค.
putenv
(Windows์ ๊ฒฝ์ฐ _putenv
)๋ก ๋ณ์๋ฅผ ์๋์ผ๋ก ์ค์ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด์ ๊ด๋ จ๋ ๋ช ๊ฐ์ง ์ถ๊ฐ ์ค๊ณ ๊ฒฐ์ ์ด ์์ต๋๋ค. :16:8
(์ฑ๋ฅ์ ๋ฎ์ง๋ง ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ ์) ๋๋ :4096:8
(์ฑ๋ฅ์ ๋์ง๋ง ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ๋ง์)๋ฅผ ์ ํํด์ผ ํฉ๋๊น? ๋ํ ์ฌ์ฉ์๊ฐ ๋ณ์๋ฅผ ๋ค๋ฅธ ๋น๊ฒฐ์ ์ ๊ฐ์ผ๋ก ์ค์ ํ๋ฉด torch.set_deterministic(False)
๊ฐ ํธ์ถ๋๋ฉด ์๋ ๊ฐ์ ์ถ์ ํ๊ณ ๋ณต์ํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์ฌ์ฉ์์๊ฒ ๋ค์๊ณผ ๊ฐ์ด ์๋ฆฌ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ๋ณ์ ๋๋ ๋ค๋ฅธ ๊ตฌ์ฑํ๋ฅผ ์ค์ ํด์ ํด์ผ ํฉ๋๋ค.
๋ํ ์ด๋ฏธ ์คํ ์ค์ธ ์์ฉ ํ๋ก๊ทธ๋จ์์ ๋ณ์๋ฅผ ์ค์ ํ๋ ๊ฒ์ด ์ค์ ๋ก ์ด๋ค ์ํฅ์ ๋ฏธ์น ์ง ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ ์ต์ (2)๊ฐ ๊ฐ๋ฅํ์ง ํ์คํ์ง ์์ต๋๋ค. ๋ณ์๋ CUDA ๋ฐํ์์ด ์์๋๊ฑฐ๋ cuBLAS ํธ๋ค์ด ์์ฑ๋ ๋ ํ ๋ฒ๋ง ํ์ธํ ์ ์์ต๋๋ค. ์ด์ ๋ํ ์ ๋ณด๋ฅผ ์ฐพ์ ์ ์์์ผ๋ฏ๋ก ์๋ง๋ ์คํ์ ์ผ๋ก ์์๋ด์ผ ํ ๊ฒ์ ๋๋ค(์ด๋ ์ชฝ์ด๋ ํ ์คํธ๋ฅผ ์์ฑํ๋ ค๋ฉด ๋น๊ฒฐ์ ์ ์คํธ๋ฆผ ์ฌ์ฉ๋ ์ฌ์๊ธฐ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ฏ๋ก ์ด์ ๋ํด ์กฐ์ฌํ๊ฒ ์ต๋๋ค) . ๋ํ ํ๊ฒฝ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ ๋์ API ํธ์ถ์ ์ฐพ์์ง๋ง CUDA์์๋ ์ ๊ณตํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ด๋ค ์ต์ ์ด ๋ ์ข์์ง์ ๋ํ ๊ฐ๋ ฅํ ์๊ฒฌ์ด ์์ต๋๊น? ์ต์ (2)๋ ์๋ง๋ ๋ ์ฌ์ฉ์ ์นํ์ ์ด์ง๋ง ์ต์ (1)๋ณด๋ค ๋ ํฌ๋ช ํ ์ ์์ต๋๋ค.
์์ฉ ํ๋ก๊ทธ๋จ์ด ์ด๋ฏธ ์คํ ์ค์ธ ๋์ ๋ณ์๋ฅผ ์ค์ ํ๋ ๊ฒ์ด ์ค์ ๋ก ์ด๋ค ์ํฅ์ ๋ฏธ์น ์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
์ด ์ง๋ฌธ์ ๋ํ ํ์ ์กฐ์น๋ก pytorch ์คํฌ๋ฆฝํธ ๋ด์์ ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํด๋ CUDA ์คํธ๋ฆผ์ ๊ฒฐ์ ์ฑ์ ์ํฅ์ ๋ฏธ์น์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค. https://github.com/pytorch/pytorch/issues/39849 ์์ ์คํฌ๋ฆฝํธ๋ฅผ ์์ ํ์ฌ ์ฌ๋ฌ ๋ฒ ์คํํ๊ณ ํ๋ จ ํต๊ณ๋ฅผ ๋น๊ตํ์ฌ ๋น๊ฒฐ์ ์ ๋์์ ํ์ธํ์ต๋๋ค. ๊ฒฐ์ ์ ์คํธ๋ฆผ ์ฌ์ฉ์ ๋ณด์ฅํ๊ธฐ ์ํด CUBLAS_WORKSPACE_CONFIG=:4096:8
์ค์ ์ ์๋ํฉ๋๋ค. https://github.com/kurtamohler/pytorch-perf-test-scripts/blob/master/nondeterministic_alert/cuda_stream_nondeterminism.py
๊ทธ๊ฒ์ ์คํํ๋ฉด ์คํฌ๋ฆฝํธ ๋ด์์ ๋ณ์๋ฅผ ์ค์ ํ๋ ๊ฒ์ผ๋ก๋ถํฐ ๊ฒฐ์ ์ ์ธ ๋์์ ์ป์ง ๋ชปํ๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
$ python cuda_stream_nondeterminism.py
Before setting var: not deterministic
After setting var: not deterministic
After restoring old var: not deterministic
๊ทธ๋ฌ๋ ์คํฌ๋ฆฝํธ ์ธ๋ถ์ ์ค์ ๋ ํ๊ฒฝ ๋ณ์๋ก ์คํํ๋ฉด ๊ฒฐ์ ์ ์ ๋๋ค.
$ CUBLAS_WORKSPACE_CONFIG=:4096:8 python cuda_stream_nondeterminism.py
Before setting var: possibly deterministic
After setting var: possibly deterministic
After restoring old var: possibly deterministic
ํ๋ จ ๊ธฐ๋ฅ์ 5๋ฒ๋ง ์คํํ๊ธฐ ๋๋ฌธ์ "possably deterministic"์ด ์ธ์๋๋ฉฐ ๋์์ด ์ค์ ๋ก ๊ฒฐ์ ์ ์ด์ง ์๋๋ผ๋ ์ด์ด ์ข์ ์ ์์ต๋๋ค.
์๋ง๋ cuda ์คํธ๋ฆผ์ ๋ค์ ์ด๊ธฐํํ ์ ์๋ค๋ฉด ๋ณ๊ฒฝ๋ CUBLAS_WORKSPACE_CONFIG
๋ณ์๋ฅผ ์ ์ฉํ๋๋ก ๊ฐ์ ํ ๊ฒ์
๋๋ค. ๋๋ ๊ทธ๊ฒ์ ์๋ํ๊ณ ์ถ์ง๋ง ์ด๋ป๊ฒ ๋๋ ๊ทธ๊ฒ์ด ๋ฐํ์์ ๊ฐ๋ฅํ์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ์์๋ ๋ถ ๊ณ์๋ฉด ์๋ ค์ฃผ์ธ์.
๋ค์์ ์ฌ์ฉํ์ฌ ์ ์คํธ๋ฆผ์ ๋ง๋ค๊ณ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ ์์์ต๋๋ค.
with torch.cuda.stream(torch.cuda.Stream()):
๊ทธ๋ฌ๋ ์ ์คํธ๋ฆผ์ ๋ณ๊ฒฝ๋ ํ๊ฒฝ ๋ณ์ ์ค์ ์ ์ ์ฉํ์ง ์์ต๋๋ค. torch.cuda.init()
๋ ์ฐพ์์ง๋ง ๋ถํํ๋ cuda๊ฐ ์ด๋ฏธ ์ด๊ธฐํ๋ ๊ฒฝ์ฐ์๋ ์๋ํ์ง ์์ต๋๋ค.
๋ฐ๋ผ์ ์๋ํ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด ์๊ฐ๋์ง ์์ผ๋ฉด ์์ ๊ณต๊ฐ ๊ตฌ์ฑ์ ์๋์ผ๋ก ๋ณ๊ฒฝํ ์ ์๋ ๊ฒ ๊ฐ์ผ๋ฏ๋ก ์ฌ์ฉ์์๊ฒ ์ค์ ํ๋ผ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํด์ผ ํ ์ ์์ต๋๋ค.
๋ค, cuda ์ปจํ ์คํธ๊ฐ ์ด๊ธฐํ๋ ํ ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํด๋ ์๋ฌด๋ฐ ํจ๊ณผ๊ฐ ์์ผ๋ฏ๋ก ๋ถํํ๋ ๊ทธ๊ฒ์ ์ ๋ถ ์๋๋ฉด ์ ๋ฌด(all or nothing) ์๋ฃจ์ ์ ๋๋ค. ์ฌ์ฉ์์๊ฒ ์ค์ ํ๋ผ๋ ์ค๋ฅ๋ฅผ ๋์ง๋ ๊ฒ์ ํฉ๋ฆฌ์ ์ผ๋ก ๋ค๋ฆฝ๋๋ค.
ํ์ฌ nvcc๊ฐ ์๋ ์ปดํ์ผ๋ ํ์ผ์์ CUDA ๋ฒ์ ์ ํ์ธํ ์ ์๋ ๊ฒ ๊ฐ์์ aten/src/ATen/cuda/detail/CUDAHooks.h
์ ์ถ๊ฐํด์ผ ํ ๊ฒ ๊ฐ์ต๋๋ค(cuDNN ๋ฒ์ ํ์ธ์ ํด๋น ์ธํฐํ์ด์ค์ ์ผ๋ถ์) . ๋ ์ ์์๋ ๋ถ ๊ณ์๋ฉด ์๋ ค์ฃผ์ธ์.
์์ ์ปค๋ฐ์ ์ค๋ฅ๋ฅผ ์ถ๊ฐํฉ๋๋ค. ํ์ง๋ง ์ง๊ธ ๋จ์ ํ ์คํธ๋ก ๋ฌด์์ ํด์ผ ํ๋์ง ์์๋ด์ผ ํฉ๋๋ค. ๋ ๊ฐ์ง ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
CUBLAS_WORKSPACE_CONFIG
๊ฐ ์ ๋๋ก ์ค์ ๋์ง ์์) ํ
์คํธ ์ธํ๋ผ๋ ํ
์คํธ๋ฅผ ์คํํ๊ธฐ ์ ์ ํ๊ฒฝ ๋ณ์๋ฅผ ์๋์ผ๋ก ๋ณ๊ฒฝํ ์ ์์ด์ผ ํฉ๋๋ค.torch.set_deterministic
ํ
์คํธ๊ฐ ์ค๋จ๋์ง ์๋๋ก ํ๋ ค๋ฉด CUBLAS_WORKSPACE_CONFIG
๋ฅผ ์๋์ผ๋ก ์ ์ ํ๊ฒ ์ค์ ํด์ผ ํฉ๋๋ค. cuda >= 10.2๋ฅผ ์ฌ์ฉํ๋ ๋ชจ๋ CI ์์
์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ด ๋ณ์๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.๋๋ ํ์ด์ฌ ์คํฌ๋ฆฝํธ์์ ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ ์ ์๋ค๋ ๊ฒ์ ์๊ฒ ๋์๊ณ , ์ ๊ฐ์ ์กด์คํ๋๋ก ํ ์น ๋ชจ๋์ ๋ค์ ๋ก๋ํ ์ ์๋ค๋ ๊ฒ์ ์๊ฒ ๋์์ต๋๋ค:
>>> import torch
>>> torch.set_deterministic(True)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/work/kurtamohler/development/pytorch-deterministic-flag-cuda-env-var/torch/__init__.py", line 306, in set_deterministic
_C._set_deterministic(d)
RuntimeError: To enable deterministic behavior with CUDA >= 10.2, you must set environment variable CUBLAS_WORKSPACE_CONFIG=:4096:8 or CUBLAS_WORKSPACE_CONFIG=:16:8. For more information, go to https://docs.nvidia.com/cuda/cublas/index.html#cublasApi_reproducibility
>>> import os
>>> os.environ['CUBLAS_WORKSPACE_CONFIG'] = ':4096:8'
>>> from importlib import reload
>>> torch = reload(torch)
>>> torch.set_deterministic(True)
ํ ์น๋ฅผ ์ฌ์ฅ์ ํ๋ฉด CUDA๊ฐ ์ด ๋ณ๊ฒฝ ์ฌํญ์ ์ค์ํ๊ฒ ๋ ์ง ๋ชจ๋ฅด๊ฒ ์ง๋ง ์ ์ด๋ ์ด๊ฒ์ ์ฐ๋ฆฌ์๊ฒ ์ค๋ฅ ๋ฉ์์ง์ ๋ํ ๋จ์ ํ ์คํธ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ๋ฌป๊ณ ์ถ์ง๋ง ๋จ์ ํ ์คํธ ๋ด์์ ํ ์น ๋ชจ๋์ ๋ค์ ๋ก๋ํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์์ต๋๊น?
ํธ์ง: ๋ณ๊ฒฝ๋ ํ๊ฒฝ ๋ณ์๋ฅผ ๋ณด๊ธฐ ์ํด ํ ์น๋ฅผ ๋ค์ ๋ก๋ํ ํ์๊ฐ ์๋ ๊ฒ์ผ๋ก ๋ํ๋ฌ์ต๋๋ค. ๋ํ ๋ณ์๋ฅผ ๋ณ๊ฒฝํ ํ ๋ค์ ๋ก๋ํด๋ CUDA ๋ฐํ์์๋ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค.
์์ ์ปค๋ฐ์ ์ด์ ์๊ฒฌ์์ ์ธ๊ธํ ๋ชจ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค. torch.set_deterministic()
๋ฅผ ํธ์ถํ๋ API ํ
์คํธ๋ฅผ ๋ํํ๊ธฐ ์ํด ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ถ๊ฐํ๊ณ ํ์ํ ๋๋ง ์์๋ก CUBLAS_WORKSPACE_CONFIG=:4096:8
์ค์ ํ์ต๋๋ค. ๋ํ ๊ฒฐ์ ์ ํ๋๊ทธ์ CUBLAS_WORKSPACE_CONFIG ์ค์ ์ ํ
์คํธ๊ฐ ์คํ๋๊ธฐ ์ ์ ์ํ๋ก ๋ณต์ํฉ๋๋ค.
์ฌํ์ฑ ๋ฌธ์์์ ๊ฒฐ์ ์ CuDNN ๋์์ด ํ์ํ๋ค๊ณ ์ธ๊ธํ๋ค๋ ๊ฒ์ ๊นจ๋ฌ์์ต๋๋ค.
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
์ด ์ค๋ ๋์ ๋๊ตฐ๊ฐ๊ฐ benchmark
๊ฐ ์ ํํ ๋ฌด์์ธ์ง ์๊ณ ์์ผ๋ฉฐ torch.backends.cudnn.deterministic = True
์์ฒด๋ก๋ ์ถฉ๋ถํ์ง ์์ ์ด์ ๋ ๋ฌด์์
๋๊น?
torch.is_deterministic() == True
์ด๋ฉด benchmark
๋ฅผ ๊ฐ์ ๋ก ๋ ์ ์์ต๋๋ค. ์ฆ, ctx.benchmarkCuDNN()
๋ฅผ at::_convolution()
์ง์ ์ ๋ฌํ๋ ๋์ https://github.com/pytorch/pytorch/blob/ ๋ผ์ธ์์ ctx.benchmarkCuDNN() && !ctx.deterministic()
์ฌ์ผ ํฉ๋๋ค. master/aten/src/ATen/native/Convolution.cpp#L602
์ด ๋ณ๊ฒฝ์ ์ํํ์ง ์์ผ๋ฉด set_deterministic
๋ฐ CuDNN์ ์ฌ์ฉํ๋ ์ฌ๋๋ค์ด ๋ค์์ ์ํํด์ผ ํ ๊ฒ ๊ฐ์ต๋๋ค.
torch.set_deterministic(True)
torch.backends.cudnn.benchmark = False
set_deterministic()
๋ง์ผ๋ก๋ ๋ชจ๋ ๊ฒ์ ๋ค๋ฃจ์ง ๋ชปํ๋ฏ๋ก ์ ์๊ฐ์๋ ํผ๋์ค๋ฝ์ต๋๋ค.
cc @ezyang @colesbury @t-vi @ngimel
์๋ก์ด ์ปจ๋ณผ๋ฃจ์
๊ตฌ์ฑ์ด ๋ฐ์ํ๋ฉด benchmark=True
๋ ์ฌ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ cudnn ๊ตฌํ์ ์คํํ๊ณ ๊ฐ์ฅ ๋น ๋ฅธ ๊ตฌํ์ ์ ํํ์ฌ ์ ํํ ๊ตฌํ์ ์บ์ฑํ๋ฏ๋ก ๋์ผํ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ๋ ์ปจ๋ณผ๋ฃจ์
์ ๋ํ ๋ชจ๋ ํ์ ํธ์ถ์์ ์ด๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋ฐ๋ผ์ deterministic
๋ True
์ค์ ๋์ด ์์ผ๋ฉด ์ด ์บ์๊ฐ ์ง์๋๋ ํ, ์ฆ ๋์ผํ ํ๋ก์ธ์ค์ ์๋ ํ ๊ฒฐ๊ณผ๊ฐ ๊ฒฐ์ ์ ์
๋๋ค. ๊ฐ๊น์ด ๋ฐํ์์ด ์๋ ๊ตฌํ์ด ์๋ ๊ฒฝ์ฐ ๋ค์์ ํ๋ก์ธ์ค๋ฅผ ์์ํ๊ณ ๋ฒค์น๋งํน์ ๋ค์ ์คํํ ๋ ๋ค๋ฅธ ๊ตฌํ์ด ์น๋ฆฌํ ์ ์์ผ๋ฉฐ ๊ฒฐ๊ณผ(์์ ์ค๋ช
๋ ์๋ฏธ์์ ์ฌ์ ํ ๊ฒฐ์ ์ ์ด์ง๋ง)๋ ์ด์ ์คํ๊ณผ ๋ค๋ฆ
๋๋ค. ๋ฐ๋ผ์ ์คํ ๊ฐ์ ๊ฒฐ์ ์ฑ์ ๋ณด์ฅํ๋ ค๋ฉด ๋ฒค์น๋งํน์ ๊บผ์ผ ํฉ๋๋ค.
๋ด๊ฐ ์ฐธ์กฐ. ๋ฐ๋ผ์ ์๋ง๋ ์ผ๋ถ ์ ํ๋ฆฌ์ผ์ด์
์์๋ ํ๋ก์ธ์ค ๊ฐ ๊ฒฐ์ ๋ก ์ด ์๋ ํ๋ก์ธ์ค ๋ด ๊ฒฐ์ ๋ก ๋ง ์ค์ํ๋ฏ๋ก ์ฌ๋๋ค์ด torch.set_deterministic(True)
๋ฅผ ์ค์ ํ๋ฉด ๋ฒค์น๋งํน์ ๊ณ์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ด ์ ์ฉํ๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ ํ์ฌ ๋์์ ๋ณ๊ฒฝํ์ง ์์์ผ ํฉ๋๋ค. ๋ถ๋ช
ํ ํ๊ธฐ ์ํด ๋ฌธ์๋ฅผ ์
๋ฐ์ดํธํ๋ ํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์์ต๋๋ค.
PyTorch ๊ธฐ๊ณ ์๊ฐ torch.set_deterministic()
๋ํ ์ง์์ ์ถ๊ฐํ ์ ์๋๋ก ์ํค ํ์ด์ง๋ฅผ ๋ง๋ค์์ต๋๋ค. https://github.com/pytorch/pytorch/wiki/How-to-support-%60torch.set_deterministic ()%60-in- PyTorch ์ด์์
๋ชจ๋ ๊ฐ์ ์ฌํญ์ ํ์ํฉ๋๋ค.
๋ํ "ํ์ฌ ์ง์๋์ง ์๋ ๊ธฐ๋ฅ" ์น์ ์ด ์ด ์ํค์ ์์ด์ผ ํ๋์ง ์๋๋ฉด ์๋ก์ด github ๋ฌธ์ ๋ก ๋ ์ข์์ง(์ํค ํ์ด์ง์์ ๋งํฌํ ์ ์์) ํ์คํ์ง ์์์ต๋๋ค. ์ ํธํ๋ ์ฌ๋์ด ์์ต๋๊น?
์๋
ํ์ธ์, ์์ผ๋ก torch.deterministic
์ ๋ํ ๊ณํ์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์ถ์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋๋ตํด์ผ ํ ๋ช ๊ฐ์ง ๋์ ์์ค์ ์ง๋ฌธ์ด ์์ต๋๋ค.
torch.deterministic
์ ์๋ฏธ๋ ๋ฌด์์
๋๊น? ์ฌ์ฉ์๋ ๋ฌด์์ ๊ธฐ๋ํฉ๋๊น? ์ต์ ์ ๋
ธ๋ ฅ์ด ์ค์ ๋ก ์ฌ์ฉ์์๊ฒ ์ ์ฉํ๊ฐ? ์ ์ฉํ์ง ์์ ๊ฒฝ์ฐ torch.deterministic
๋ฅผ ์ ์ด ํ๋ ์์
์ ๊ด์ ์์ ์ ์ํ๋ ๊ฒ์ด ๋ ๋ซ์ต๋๊น?torch.deterministic
ํ๋๊ทธ๊ฐ ์์ผ๋ฏ๋ก ๊ณต๊ฐ API( bmm
, ๋ณด๊ณ ์์ต๋๋ค)์์ deterministic=
ํค์๋ ์ธ์๋ฅผ ์์ ํ ์ ๊ฑฐํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์
๋๊น?(1)๋ถํฐ ์์ํ์ฌ torch.deterministic์ ๋ํ ํ์ฌ ๋ฌธ์๋ ๋ค์๊ณผ ๊ฐ์ด ๋งํฉ๋๋ค.
r"""Sets a global flag to force all operations to use a deterministic
implementation if available. If an operation that does not have a
deterministic implementation is called while this setting is True, the
operation will throw a RuntimeError.
Note that deterministic operations tend to have worse performance than
non-deterministic operations.
์ด๋ ์ต์ข
์ํ์ ๋ํด ์ฌ์ค์ผ ์ ์์ง๋ง ์ด๋ ๋ง์ ์์
์ด ๊ฐ์ฌ๋์ง ์๊ณ ์ฃผ์ด์ง ๋ชจ๋ธ์ ๋ํด torch.deterministic
๊ฐ ์ค์ ๋ก ์ํํ ์์
์ ์ ์ ์๋ ํ์ฌ ์ํฉ์ ๋ถ์ ํํ๊ฒ ๋ํ๋
๋๋ค. ์ฃผ์์ ๋งํ๊ณ ๋ชจ๋ธ์ ๊ฒฐ์ ์ ์ผ๋ก ๋ง๋ค๊ฑฐ๋ nondet์ ์น ๋ ์ค๋ฅ๋ฅผ ๋ฐ์์ํต๋๋ค. ๋ฐ๋ผ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฐ๋ฆฌ์ ๊ตฌํ์ ์ด๋ฌํ ์๋ฏธ๋ก ๊ณผ ๊ด๋ จํ์ฌ ๋ฒ๊ทธ๊ฐ ์์ผ๋ฉฐ ๊ฐ๊น์ด ๋ฏธ๋์๋ ๊ณ์ ๋ฒ๊ทธ๊ฐ ์์ ๊ฒ์
๋๋ค. ์ด๊ฒ์ ์ข์ ์ํ๊ฐ ์๋๋๋ค.
์ด๋ฅผ ๊ฐ์ ํ๊ธฐ ์ํด torch.deterministic์ ๋ฌธ์๋ฅผ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค. ๋ช ๊ฐ์ง ๊ฐ๋ฅํ ๋ณ๊ฒฝ ์ฌํญ:
๋ ๋ฒ์งธ ๊ธ๋จธ๋ฆฌ ๊ธฐํธ๋ (2)๋ก ์ด์ด์ง๋๋ค. ์ด์ torch.deterministic์ด ๊ฒฐ์ ๋ก ์ ํ ๊ธํ๋ ๋ฐฉ๋ฒ์ผ๋ก ์กด์ฌํ๋ค๋ฉด ์ฌ์ฉ์ API์์ ์ง์ ๊ฒฐ์ ๋ก ์ ์ง์ํ๋ ๊ฒ์ด ํจ์ฌ ๋ ์ค์ํฉ๋๋ค. ๋ฐ๋ผ์ bmm์ deterministic
์ธ์๋ฅผ ์ถ๊ฐํด์๋ ์ ๋ฉ๋๋ค. ๋ฌด์ธ๊ฐ๋ฅผ ์ง์ ํ ๊ธํ๋ ค๋ ๊ฒฝ์ฐ ๋ด๋ถ ํจ์๋ฅผ ๋
ธ์ถํ๋ ๊ฒ์ ๊ณ ๋ คํ ์ ์์ง๋ง deterministic
๋ ํจ์ ์์ฒด์์ ์ง์ ์ฌ์ฉํ ์ ์์ด์ผ ํฉ๋๋ค.
์ด๋ป๊ฒ ์๊ฐํด? ๋ฌธ์๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฒ์ด ์ง์ ๊ฐ๋ฅํ ๊ฒฝ๋ก๋ก ๊ฐ๋ ๊ฐ์ฅ ์ฌ์ด ๋ฐฉ๋ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ ์ฒด ๋ชฉ๋ก์ ์ฑ์ฐ๋ ๋ฐฉ๋ฒ๊ณผ ๊ฐ์ ๋ช ๊ฐ์ง ๋ค๋ฅธ ์ธ๋ถ ์ฌํญ์ด ์์ง๋ง ์ด๋ฌํ ์๋ฏธ ์ฒด๊ณ๋ ์ค์ ๋ก๋ ์ฌ์ค์ด ์๋ "์ด์์ ์ธ" ์๋ฏธ ์ฒด๊ณ๋ณด๋ค ๋ ํฉ๋ฆฌ์ ์ผ ์ ์์ต๋๋ค.
cc @gchanan @mruberry
@zou3519 ๋ https://github.com/pytorch/pytorch/pull/38683#issuecomment -662590937์์๋ Q์ ๊ต์ฐจํ์ต๋๋ค.
@ezyang , @zou3519 , ํด์ฃผ์ ์ ๊ธฐ์ฉ๋๋ค. ๋ด๊ฐ ์์ฑํ ๋ฌธ์๊ฐ ํ์ฌ ์ํ์ ๋ํ ์๋ชป๋ ํํ์ด๋ผ๋ ๋ฐ ๋์ํฉ๋๋ค.
๋๋ torch.set_deterministic()
์ํฅ์ ๋ฏธ์น๋ ๋ชจ๋ ๊ธฐ๋ฅ์ ์ฒ ์ ํ๊ฒ ๋์ดํ์ฌ ์ฌ์ฉ์์๊ฒ ๊ฑฐ์ง๋ง์ ํ์ง ์๋๋ค๋ ์์ด๋์ด๋ฅผ ์ข์ํฉ๋๋ค. @zou3519, 1.6.0์ ์ถ๊ฐํด์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค.
deterministic
์ค์ ์ ์ง์ ํจ์ ์ธ์๋ก ์ ๊ณตํด์๋ ์ ๋๋ค๋ ๋ฐ ๋์ํฉ๋๋ค.
์ต์ข ๊ฒ์์ ๊ฒฝ์ฐ ํ์ํ ๊ธฐ๊ฐ ๋์ ๊ณ์ ์ด ์์ ์ ์ํํ๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค. ํ์ง๋ง ๋๊ตฌ๋ ๋น ๋ฅด๊ฒ ๋์์ ๋ฐ์ ์ ์๋๋ก ์ค์ ํด์ผ ํฉ๋๋ค.
์ฅ๊ธฐ์ ์ผ๋ก ์ํฅ์ ๋ฐ๋ ๊ธฐ๋ฅ์ ์ ์ฒด ๋ชฉ๋ก์ ์ ๊ณตํ๋ ๊ฒ์ด ์ ํจํ ๊ฒฐ์ ์ด๋ผ๊ณ ์๊ฐํ์ง๋ง ์ ๋ต๋ง์ผ๋ก๋ ๊ฒฐ์ ์ ํ๋๊ทธ์ ์ ์ฉ์ฑ์ ๊ทน๋ํํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ค์๊ณผ ๊ฐ์ด (ํ๋์ ํน์ ํ๊ฒฝ์์) ๊ธฐ๋ฅ์ ๋ถ๋ฅํ ์ ์์ต๋๋ค.
๋ฌผ๋ก ์ด์์ ์ธ ๊ฒฝ์ฐ๋ ๋ฒ์ฃผ 3์ ์์ ํ ์ ๊ฑฐํ ๋ค์ ๋ฒ์ฃผ 2 ๊ธฐ๋ฅ ๋ชฉ๋ก์ผ๋ก ์ถฉ๋ถํฉ๋๋ค. ๊ทธ๋ฌ๋ ์นดํ
๊ณ ๋ฆฌ 3 ๊ธฐ๋ฅ์ ์๋นํ ๊ธฐ๊ฐ ๋์ ๊ณ์ ์กด์ฌํ ๊ฒ์
๋๋ค(๋๋ ๋ชจ๋ ๊ธฐ์ฌ์๊ฐ ๊ฒฐ์ ๋ก ์ ๋ํ ๋ฌธ์ ๋ฅผ ์ธ์ํ์ง ๋ชปํ๊ฑฐ๋ ์ปค๋ฐ์ด ์ค์๋ก ํจ์์ ๋ํ ๊ฒฐ์ ๋ก ์ ์ ๊ฑฐํ๋ ๊ฒฝ์ฐ ๋ฑ). ๋ฐ๋ผ์ ๋ชจ๋ ๋ฒ์ฃผ 2 ๊ธฐ๋ฅ์ ์์ ํ ๋ชฉ๋ก์ด ์๋๋ผ๋ ์ฌ์ฉ์๋ ๋ชฉ๋ก์ ๋ํ๋์ง ์๋ ๊ธฐ๋ฅ์ด ๊ฒฐ์ ์ ์ธ์ง ์ฌ๋ถ(๋ฒ์ฃผ 1 ๋๋ 3์ผ ์ ์์)๋ฅผ ์ ์ ์๋ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, torch.add
๋ ๋ชฉ๋ก์ ๋ํ๋์ง ์๋๋ฐ ์ฌ์ฉ์๊ฐ ๊ทธ๊ฒ์ด ๊ฒฐ์ ์ ์ด๋ผ๋ ๊ฒ์ ์ด๋ป๊ฒ ์ ์ ์์ต๋๊น?
์นดํ ๊ณ ๋ฆฌ 3 ๊ธฐ๋ฅ ๋ชฉ๋ก์ ์ ์ง ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ๋ ์๊ฐํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฌํ ๋ชฉ๋ก์ ์๋์ผ๋ก ์ ์ง ๊ด๋ฆฌํ๋ ๊ฒ์ ์ฌ๋ฌ ๊ฐ์ง ์ด์ ๋ก ๋งค์ฐ ์ด๋ ค์ธ ์ ์์ผ๋ฏ๋ก ์ด๋ ์ ๋ ์๋ํํ ์ ์๋์ง ๊ถ๊ธํฉ๋๋ค. ๋ชจ๋ ๊ธฐ๋ฅ์ ๋ํด ๊ฒฐ์ ์ฑ ํ ์คํธ๋ฅผ ์คํํ๋ CI ์์ ์ ์ ์ฌ์ ์ผ๋ก ์ค์ ํ ์ ์์ต๋๋ค. ํจ์๊ฐ ๊ฒฐ์ ์ ์ด๋ผ๋ ๊ฒ์ ๊ท๋ฉ์ ์ผ๋ก 100% ์ฆ๋ช ํ ์๋ ์์ผ๋ฉฐ ์ด์ด ์ข์ง ์์ผ๋ฉด ๋น๊ฒฐ์ ์ ํจ์๊ฐ ๋์ผํ ๊ฒฐ๊ณผ๋ฅผ ์ฌ๋ฌ ๋ฒ ์ ๊ณตํ ์๋ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฌํ ํ ์คํธ๋ฅผ ๋ ์์ฃผ ์คํํ ์๋ก ๊ฐ ๊ธฐ๋ฅ์ด ์ํ ๋ฒ์ฃผ์ ๋ํด ๋ ํ์ ํ ์ ์์ต๋๋ค.
๋ํ ๊ฐ ๊ธฐ๋ฅ๊ณผ ํ๋ซํผ์ ๋ํด ์ฐ๋ฆฌ๊ฐ ์๊ณ ์๋ ๊ฒ๊ณผ ๋ชจ๋ฅด๋ ๋ชจ๋ ๊ฒ์ ์ฌ์ฉ์์๊ฒ ๊ฐ์ฅ ํจ์จ์ ์ผ๋ก ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์ง๋ฌธ๋ ์์ต๋๋ค. ๊ฐ ํ๋ซํผ์์ ๋ชจ๋ ๋ฒ์ฃผ 2 ๋ฐ 3 ๊ธฐ๋ฅ์ ๋ํ ํ ์ด๋ธ์ ๋ง๋ค ์ ์์ต๋๋ค. ๊ฒฐ์ ์ฑ ํ ์คํธ๊ฐ ์ด ํ ์ด๋ธ์ด ์ฌ๋ฐ๋ฅธ์ง ์๋์ผ๋ก ํ์ธํ ์ ์๋ค๋ฉด ์ข์ ๊ฒ์ ๋๋ค.
๋ธ๋ ์ธ์คํ ๋ฐ์ ํด๋ณด๋ฉด ์ด๋ฌํ ์์ด๋์ด๊ฐ ๊ฐ์น๋ณด๋ค ๋ ์ด๋ ค์ธ ์ ์์ต๋๋ค. ๋ ์ค์ฉ์ ์ธ ๊ณํ์ ๋น๋ก ๋ ์ด์์ ์ด๋๋ผ๋ ํจ์ฌ ๋ ์ง์ ๊ฐ๋ฅํฉ๋๋ค.
torch.add
๊ฒฐ์ ์ ์
๋๊น?
import torch
n = 512
device = 'cuda'
a = torch.arange(n**3, device=device, dtype=torch.float32)
a = a.reshape((n, n, n))
b = torch.arange(n**3, device=device, dtype=torch.float32)
b = b.reshape((n, n, n))
out_zero = torch.zeros((n, n, n), device=device)
out_zero = out_zero.set_(out_zero.storage(), storage_offset=0, size=a.size(), stride=(1,1,1))
out_one = torch.zeros((n, n, n), device=device)
out_one = out_one.set_(out_one.storage(), storage_offset=0, size=a.size(), stride=(1,1,1))
torch.add(a, b, out=out_zero)
torch.add(a, b, out=out_one)
(out_zero == out_one).all()
: tensor(False, device='cuda:0')
๊ฒน์น ํ ์๊ฐ ์ฐ๋ฆฌ๊ฐ ์ถ๊ตฌํ๋ ๊ฒฐ์ ๋ก ๊ณ์ฝ์ ์๋ฐํ๋ค๋ ๊ฒ์ ๋ฌธ์ํํด์ผ ํฉ๋๋ค.
"๊ฒฐ์ ๋ก " ํ๋๊ทธ์ ์ํฅ์ ๋ฐ๋ ์์ ์ ๋์ดํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฝ๊ฐ ๋ค๋ก ๋ฌผ๋ฌ์๋ฉด ์ฐ๋ฆฌ๊ฐ ์ค์ ๋ก ๋ ๊ฐ์ง์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
use_deterministic
?)๋จผ์ ํ๋๊ทธ๋ ๊ฐ๋จํด ๋ณด์ ๋๋ค. ๊ทธ๋ฌ๋ ๋ ๋ฒ์งธ๋ ์กฐ๊ธ ๋ ๊น๋ค๋กญ์ต๋๋ค. oneDNN, cuDNN ๋ฐ MAGMA์ ๊ฐ์ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์์ ์ด ํนํ ๋ฒ์ ๋ฐ ํ๋์จ์ด ์ ๋ฐ์ ๊ฑธ์ณ ๊ฒฐ์ ์ ์ธ์ง ์ฌ๋ถ๋ฅผ ๋งํ๊ธฐ๊ฐ ์ด๋ ต๋ค๋ ์ ์ด ๊ฑฑ์ ๋ฉ๋๋ค. @kurtamohler, ์ด ๋ฌธ์ ๋ฅผ ๊ฐ์ฅ ์ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์์ด๋์ด๊ฐ ์์ต๋๊น? ์ด์ฉ๋ฉด ์ฐ๋ฆฌ๋ ๋ชจ๋ ๋ค์ดํฐ๋ธ ๋น๊ฒฐ์ ์ ์ฐ์ฐ์ ๋ํด ๊ฒฝ๊ณ ํ๊ณ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํธ์ถ๋ ๋๋ ๊ฒฝ๊ณ ํ ์ ์์๊น์? ํ๋ก์ธ์ค๋น ํ ๋ฒ ๊ฒฝ๊ณ ๊ฐ ๊ทธ๋ ๊ฒ ๋ฐฉํด๊ฐ ๋์ด์๋ ์ ๋ฉ๋๋ค.
๊ฒฝ๊ณ ์ ๋ํ ์ด๋ฌํ ์ ๊ทผ ๋ฐฉ์์ ์คํ๋๊ธฐ ์ ์ ๋ง์ ์๊ณ ๋ฆฌ์ฆ์ ๊ฒํ ํ๊ณ ์ฌ์ดํธ๋ฅผ ํธ์ถํด์ผ ํ์ง๋ง ์ฌ์ฉ ๊ฐ๋ฅํ ๊ฒฝ์ฐ ๊ฒฐ์ ์ ์๊ณ ๋ฆฌ์ฆ์ ์ ํํ๊ธฐ ์ํด ํ๋๊ทธ๋ฅผ ์ฐจ๋จํ ํ์๋ ์์ต๋๋ค.
(์ธ ๋ฒ์งธ ๋ ผ์ ์ค์ธ ๊ฒ์ ๊ฒฐ์ ๋ก ์ ์๊ณ ๋ฆฌ์ฆ ์ ํ์ ์ ์ํ๋ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ด์ง๋ง(๊ธ๋ก๋ฒ ํ๋๊ทธ๋ฅผ ํตํด ๋๋ ํจ์์ ๋ํ kwargs๋ก) ํ๋๊ทธ์ ๋ํ ๊ณํ์ ๊ฒฐ์ ํ ๋๊น์ง ๋ ผ์๋ฅผ ์ฐ๊ธฐํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.)
๋๋ ์ฌ๊ธฐ์์ ์์ ํ ๊ฒ์ ์ ์ ์ ์ผ๋ก ๋์ด์๋ ์ ๋๋ค๊ณ ์๊ฐํฉ๋๋ค. PyTorch์์ self-overlapping tensor๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ธ์ 100% ์์ ํ์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ์ ์ธ์์ ๋ณดํต ์ฌ๋๋ค์ด ์ฌ์ฉํ์ง ์๋๋ค๋ ๊ฒ์ ๋๋ค.
ํฌ๋ผ์์ ๋ด๊ฐ ๋ฐ์ ์ธ์์ ๋๋ถ๋ถ์ ์ฌ๋๋ค์ด ๋ฌด์ธ๊ฐ๋ฅผ ๋ ๋ฒ ์คํํ๊ณ ๋ค๋ฅธ ๊ทธ๋ผ๋์ธํธ๋ฅผ ์ป๋๋ค๋ ์ฌ์ค์ ๋๋๋ค๋ ๊ฒ์
๋๋ค. ๊ฐ์ฅ ํํ ์ด์ ๋ PyTorch์ ๊ธฐ๋ณธ ๊ธฐ๋ฅ ์ค ํ๋๊ฐ atomicAdd๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์
๋๋ค.
์ด์ ๋ํ ๊ฒฝ๊ณ ๋ฅผ ๋ฐ์ผ๋ฉด ์ฌ๋๋ค์ด ๊ถ๊ธํดํ๋ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ๋ฅผ ๋ค๋ฃน๋๋ค. ์ ๋ฐ์ฒ๋ผ ๋๊ปด์ง๋ ๊ฒ์ด ์ค์ ๋ก๋ ๋ค๋ก ์
์ค์ผ์ผ๋งํ ๊ฒ์
๋๋ค.
๋๋ ์ด๊ฒ์ด ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ดํ ํ ์ต์ ์ ๋ ธ๋ ฅ์ด๋ฉฐ ๋ฌธ์ ๋ฅผ ์๊ฒ ๋๋ฉด ๊ฒฝ๊ณ ๋ฅผ ์ถ๊ฐํ๋ค๊ณ ๋ถ๋ช ํ ๋ช ์ํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ด ์ธ์์ ์ฐ๋ฆฌ์ ๊ธฐ๋ณธ ์ปค๋์ด ์ค์ ๋ก ๊ฐ์ฅ ์ค์ํ๋ค๋ ๊ฒ์ ๋๋ค.
PyTorch์์ self-overlapping tensor๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ธ์ 100% ์์ ํ์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ์ ์ธ์์ ๋ณดํต ์ฌ๋๋ค์ด ์ฌ์ฉํ์ง ์๋๋ค๋ ๊ฒ์ ๋๋ค.
์, ๊ทธ๋ฆฌ๊ณ ํฉ๋ฆฌ์ ์ผ๋ก ์ค๋ฅ๊ฐ ์๋ ๊ฒ์ผ๋ก ๋ถ๋ฅ๋ ์ ์๋ ๋ชจ๋ ํ๋ก๊ทธ๋จ. ๋๋ ๋จ์ง ์ฐ๋ฆฌ๊ฐ ์ด ํ๋๊ทธ์ ๋ํด ์ ์ํ ๊ณ์ฝ์ ๋ฌธ์ํํ๋ ๋ฐ ์ฃผ์ํด์ผ ํ๋ค๋ ์๋ฏธ์์ต๋๋ค.
์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ดํ ํ ์ด๊ฒ์ด ์ต์ ์ ๋ ธ๋ ฅ์ด๋ฉฐ ๋ฌธ์ ๋ฅผ ์๊ฒ ๋๋ฉด ๊ฒฝ๊ณ ๋ฅผ ์ถ๊ฐํ๋ค๋ ์ ์ ๋ถ๋ช ํ ๋ฐํ์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค...
๋ฌธ์๋ "๋น๊ฒฐ์ ์ ์ด๋ผ๊ณ ์๋ ค์ง ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํธ์ถ..."๊ณผ ๊ฐ์ด ๋งํ ์ ์์ต๋๋ค.
@t-vi์ ๋์ํฉ๋๋ค(๋ณด๊ณ ๋ ๋น๊ฒฐ์ ๋ก ์ ์ ๋ฐ์ด ์ญ๋ฐฉํฅ์ผ๋ก ์ ์ค์ผ์ผ๋ง๋๋ค๋ ๊ด์ฐฐ์ด ์ ๋ง ๋ง์์ ๋ญ๋๋ค). ํนํ, ๋น๊ฒฐ์ ์ ์ด๋ผ๊ณ ์๋ ค์ง ํจ์๋ฅผ ๋ถ๋ถ์ ์ผ๋ก ๋ฌธ์ํํ ์ํ(๋๋ ์ผ๋ถ ํจ์๊ฐ ๊ฒฐ์ ๋ก ์ ์ด๋ผ๊ณ ๋ถ๋ถ์ ์ผ๋ก ๋ฌธ์ํํ ์ํ)๊ฐ ์๋ฌด๋ฐ ํ์๋ ํ์ง ์๋ ์ํ๋ณด๋ค ์๊ฒฉํ๊ฒ ๋ ๋ซ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ฐ๋ฆฌ๊ฐํ์ง ์๋ ๊ฒ์ ์ง์ํ๋ค๊ณ ์ฃผ์ฅํ์ง ์๋ ๊ฒ์ ๋๋ค! ๋๋ ๊ฒฐ์ ๋ก ์ ํ ์คํธํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์๊ฐํ๋ ๊ฒ์ด ์ ์ฉํ ํ๋์ด๋ผ๋ ๋ฐ ๋์ํ์ง๋ง ์ด๊ฒ์ ๋ถ๋ช ํ ๋น๊ฒฐ์ ์ API์ ํ๋๊ทธ๋ฅผ ์ง์ ํ๋ ์ง๊ต ํ๋์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
๋ง์ ์์ด๋์ด๊ฐ ๋ ๋์๊ธฐ ๋๋ฌธ์ ๊ทธ ์ค ์ผ๋ถ์ ๋ํ ๊ตฌ์ฒด์ ์ธ ์๊ฐ์ ๋ง์๋๋ฆฌ๊ฒ ์ต๋๋ค.
๋๋ ์ฐ๋ฆฌ๊ฐ ๊ต์ฐจ ๋ฒ์ /ํ๋์จ์ด ๊ฒฐ์ ๋ก ์ ๋ํด ๊ฑฑ์ ํ ํ์๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ํ์ด์ ๋น๋๋ค.
์ฐ๋ฆฌ๊ฐ ๋น๊ฒฐ์ ๋ก ์ ๋ํด ๊ฒฝ๊ณ ํ ๋, ๊ทธ๊ฒ์ ๋น๊ฒฐ์ ๋ก ์ด ์ผ์ด๋๊ณ ์๊ธฐ ๋๋ฌธ์ด ์๋๋ผ ์ผ์ด๋ ์๋ ์๊ธฐ ๋๋ฌธ์ด์ด์ผ ํฉ๋๋ค. ๋น์ ์ด ์ง๋์น๊ฒ ๊ฒฝ๊ณ ํ๋ฉด ์ฌ๋๋ค์ ๊ฒฝ๊ณ ๋ฅผ ๋ฌด์ํ๊ธฐ ์์ํ ๊ฒ์ ๋๋ค.
๊น๋ค๋ก์ ๋ณด์ ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ด๊ฐ ์ด๋ค ์ฐ์ฐ์ ์คํ ์ค์ด๊ณ PyTorch ๊ตฌํ์ด ๊ฒฐ์ ์ ์ด์ง๋ง ์ผ๋ถ ํ์ฅ์ด (๋์คํจ์น ํค, ํ ์น ๊ธฐ๋ฅ ๋ฑ์ ํตํด) ๋ฌด์์ธ๊ฐ๋ฅผ ์ฌ์ ์ํ๊ณ ์ง๊ธ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๊ทธ๊ฒ์ด ์ค์ ๋ก ๋ด ๋น๊ฒฐ์ ๋ก ์ ๊ทผ์์ด๋ผ๋ฉด ๊ฒฝ๊ณ ๋ฅผ ๋ฐ์ง ์๋ ๊ฒ์ ์ด๋ฆฌ์์ ์ผ์ธ ๊ฒ ๊ฐ์ต๋๋ค.
๊ทธ๊ฒ์ด ์ค์ ๋ก ๋ด ๋น๊ฒฐ์ ๋ก ์ ๊ทผ์์ด๋ผ๋ฉด ๊ฒฝ๊ณ ๋ฅผ ๋ฐ์ง ์๋ ๊ฒ์ ์ด๋ฆฌ์์ ์ผ์ธ ๊ฒ ๊ฐ์ต๋๋ค.
๋ฌผ๋ก , ํ์ง๋ง ์ฌ์ฉ์๋ ๋ํ ์ฐ๋ฆฌ๋ฅผ ๊ทธ๋ค์ ๋น๊ฒฐ์ ์ ์์์์ ์ฐ๋ฃจ์ํค์ง ์์ ์ ์์ผ๋ฉฐ, ๊ทธ๋ฌ๋ฉด ๋น์ฐํ ๊ฒฝ๊ณ ๋ฅผ ๊ธฐ๋ํ์ง๋ ์์ ๊ฒ์ ๋๋ค ;)
ํ๋๊ทธ API๊ฐ ์กด์ฌํ๊ณ ๋ฌธ์ํ๋์ด ์์ผ๋ฏ๋ก ์ง๊ธ ์ด ๋ฌธ์ ๋ฅผ ์ข ๋ฃํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
@kurtamohler ๋ฉ์ง ์ํ์ ๋๋ค. ๊ฐ์ฌํฉ๋๋ค.
torch.manual_seed(111)
๋ฅผ ์ฌ์ฉํ์ฌ interpolation
์์
์ ํฌํจํ์ฌ ๋ชจ๋ ๊ฒ์ ๊ฒฐ์ ์ ์ผ๋ก ์ค์ ํ ์ ์๋ค๋ ๋ป์
๋๊น?
์๋์. ์ฌํ์ฑ/์์์ฑ ์ฐธ๊ณ ์ฌํญ์ ์ดํด๋ณด์ญ์์ค.
์ง๊ธ๊น์ง ์ฐ๋ฆฌ๋ ์ธํ๋ผ๊ฐ ์๊ณ , ๋น๊ฒฐ์ ๋ก ์ ๋ํ ์๋ ค์ง ์์ค๋ฅผ ํ์ํ๊ณ , ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ์ ์ ์๋๋ก ๋ฌธ์๋ฅผ ํฌ๊ฒ ๊ฐ์ ํ์ต๋๋ค.
๋น๊ฒฐ์ ์ ์์
์ ๋๋ฌํ๋ฉด ์ฌ์ ํ ์ด์ด ์์ง๋ง ์ด์ ์์
ํ๋ ๊ฒ์ด ๋ ํฉ๋ฆฌ์ ์
๋๋ค.
ํนํ ๋ณด๊ฐ์ ์ญ๋ฐฉํฅ์ ๋ํด ๊ทธ๋ค์ง ๋ณต์กํ์ง ์์ ์ปค๋์ ์์ฑํ์ฌ ๊ฒฐ์ ๋ก ์ ์ผ๋ก ๋ง๋ค ์ ์๋ ๊ฒ์ผ๋ก ๋ณด์ ๋๋ค.
@t-vi ์๋ ํ์ธ์, ์ด์ pytorch 1.7์ด ์ถ์๋๊ณ ๋ณด๊ฐ ์ญ๋ฐฉํฅ ์ปค๋์ด ์ ๋ฐ์ดํธ ๋์์ต๋๊น?
๋ฐ๋ผ์ CUDA ์
์ํ๋ง ์ปค๋๊ณผ ์ญ๋ฐฉํฅ์ aten/src/ATen/native/cuda/UpSample*
์์ต๋๋ค. grep์ ์ ํ, ์์ ํ, 3์ฐจํ์ด ์ญ๋ฐฉํฅ์ผ๋ก ๋น๊ฒฐ์ ์ (๊ฒฝ๊ณ ํ์๊ฐ ์์)์ ๊ฐ์ง๋ง ๊ฐ์ฅ ๊ฐ๊น์ด ๊ฒ์ ๊ทธ๋ ์ง ์์์ ๋ํ๋
๋๋ค.
@kurtamohler ๊ฐ ํจ์ฌ ๋ ๋์ ์ฌ๋์ด ๋ ๊ฒ์
๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
์๋ ํ์ธ์, ์์ผ๋ก
torch.deterministic
์ ๋ํ ๊ณํ์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์ถ์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋๋ตํด์ผ ํ ๋ช ๊ฐ์ง ๋์ ์์ค์ ์ง๋ฌธ์ด ์์ต๋๋ค.torch.deterministic
์ ์๋ฏธ๋ ๋ฌด์์ ๋๊น? ์ฌ์ฉ์๋ ๋ฌด์์ ๊ธฐ๋ํฉ๋๊น? ์ต์ ์ ๋ ธ๋ ฅ์ด ์ค์ ๋ก ์ฌ์ฉ์์๊ฒ ์ ์ฉํ๊ฐ? ์ ์ฉํ์ง ์์ ๊ฒฝ์ฐtorch.deterministic
๋ฅผ ์ ์ด ํ๋ ์์ ์ ๊ด์ ์์ ์ ์ํ๋ ๊ฒ์ด ๋ ๋ซ์ต๋๊น?torch.deterministic
ํ๋๊ทธ๊ฐ ์์ผ๋ฏ๋ก ๊ณต๊ฐ API(bmm
, ๋ณด๊ณ ์์ต๋๋ค)์์deterministic=
ํค์๋ ์ธ์๋ฅผ ์์ ํ ์ ๊ฑฐํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ ๋๊น?(1)๋ถํฐ ์์ํ์ฌ torch.deterministic์ ๋ํ ํ์ฌ ๋ฌธ์๋ ๋ค์๊ณผ ๊ฐ์ด ๋งํฉ๋๋ค.
์ด๋ ์ต์ข ์ํ์ ๋ํด ์ฌ์ค์ผ ์ ์์ง๋ง ์ด๋ ๋ง์ ์์ ์ด ๊ฐ์ฌ๋์ง ์๊ณ ์ฃผ์ด์ง ๋ชจ๋ธ์ ๋ํด
torch.deterministic
๊ฐ ์ค์ ๋ก ์ํํ ์์ ์ ์ ์ ์๋ ํ์ฌ ์ํฉ์ ๋ถ์ ํํ๊ฒ ๋ํ๋ ๋๋ค. ์ฃผ์์ ๋งํ๊ณ ๋ชจ๋ธ์ ๊ฒฐ์ ์ ์ผ๋ก ๋ง๋ค๊ฑฐ๋ nondet์ ์น ๋ ์ค๋ฅ๋ฅผ ๋ฐ์์ํต๋๋ค. ๋ฐ๋ผ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฐ๋ฆฌ์ ๊ตฌํ์ ์ด๋ฌํ ์๋ฏธ๋ก ๊ณผ ๊ด๋ จํ์ฌ ๋ฒ๊ทธ๊ฐ ์์ผ๋ฉฐ ๊ฐ๊น์ด ๋ฏธ๋์๋ ๊ณ์ ๋ฒ๊ทธ๊ฐ ์์ ๊ฒ์ ๋๋ค. ์ด๊ฒ์ ์ข์ ์ํ๊ฐ ์๋๋๋ค.์ด๋ฅผ ๊ฐ์ ํ๊ธฐ ์ํด torch.deterministic์ ๋ฌธ์๋ฅผ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค. ๋ช ๊ฐ์ง ๊ฐ๋ฅํ ๋ณ๊ฒฝ ์ฌํญ:
๋ ๋ฒ์งธ ๊ธ๋จธ๋ฆฌ ๊ธฐํธ๋ (2)๋ก ์ด์ด์ง๋๋ค. ์ด์ torch.deterministic์ด ๊ฒฐ์ ๋ก ์ ํ ๊ธํ๋ ๋ฐฉ๋ฒ์ผ๋ก ์กด์ฌํ๋ค๋ฉด ์ฌ์ฉ์ API์์ ์ง์ ๊ฒฐ์ ๋ก ์ ์ง์ํ๋ ๊ฒ์ด ํจ์ฌ ๋ ์ค์ํฉ๋๋ค. ๋ฐ๋ผ์ bmm์
deterministic
์ธ์๋ฅผ ์ถ๊ฐํด์๋ ์ ๋ฉ๋๋ค. ๋ฌด์ธ๊ฐ๋ฅผ ์ง์ ํ ๊ธํ๋ ค๋ ๊ฒฝ์ฐ ๋ด๋ถ ํจ์๋ฅผ ๋ ธ์ถํ๋ ๊ฒ์ ๊ณ ๋ คํ ์ ์์ง๋งdeterministic
๋ ํจ์ ์์ฒด์์ ์ง์ ์ฌ์ฉํ ์ ์์ด์ผ ํฉ๋๋ค.์ด๋ป๊ฒ ์๊ฐํด? ๋ฌธ์๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฒ์ด ์ง์ ๊ฐ๋ฅํ ๊ฒฝ๋ก๋ก ๊ฐ๋ ๊ฐ์ฅ ์ฌ์ด ๋ฐฉ๋ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ ์ฒด ๋ชฉ๋ก์ ์ฑ์ฐ๋ ๋ฐฉ๋ฒ๊ณผ ๊ฐ์ ๋ช ๊ฐ์ง ๋ค๋ฅธ ์ธ๋ถ ์ฌํญ์ด ์์ง๋ง ์ด๋ฌํ ์๋ฏธ ์ฒด๊ณ๋ ์ค์ ๋ก๋ ์ฌ์ค์ด ์๋ "์ด์์ ์ธ" ์๋ฏธ ์ฒด๊ณ๋ณด๋ค ๋ ํฉ๋ฆฌ์ ์ผ ์ ์์ต๋๋ค.
cc @gchanan @mruberry