[Optional] NVSHMEM (NVIDIA Shared Memory)

1. NVSHMEM ๊ฐœ์š”


1.1. NVSHMEM์ด๋ž€?

NVSHMEM(NVIDIA Shared Memory)์€ GPU ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค๊ฐ€ GPU ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง์ ‘ ๊ณต์œ ํ•˜๊ณ  ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํ†ต์‹  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๊ธฐ์กด OpenSHMEM์˜ ๊ฐœ๋…์„ GPU ํ™˜๊ฒฝ์œผ๋กœ ํ™•์žฅํ•œ ๊ฒƒ์œผ๋กœ, CUDA ์ปค๋„ ๋‚ด๋ถ€์—์„œ ์ง์ ‘ ์›๊ฒฉ GPU์˜ ๋ฉ”๋ชจ๋ฆฌ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ํ˜์‹ ์ ์ธ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์ค‘์š”ํ•œ ํŠน์ง•์€ CPU์˜ ๊ฐœ์ž… ์—†์ด GPU๊ฐ€ ์Šค์Šค๋กœ ๋‹ค๋ฅธ GPU์™€ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์ „ํ†ต์ ์ธ ๋ฐฉ์‹์—์„œ๋Š” GPU๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋ ค๋ฉด ๋จผ์ € CPU์—๊ฒŒ ์•Œ๋ฆฌ๊ณ , CPU๊ฐ€ ๋„คํŠธ์›Œํฌ ์ž‘์—…์„ ์‹œ์ž‘ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. NVSHMEM์€ ์ด๋Ÿฌํ•œ ๋ณ‘๋ชฉ์„ ์ œ๊ฑฐํ•˜์—ฌ GPU ๊ฐ„ ํ†ต์‹ ์˜ ์ง€์—ฐ ์‹œ๊ฐ„์„ ํš๊ธฐ์ ์œผ๋กœ ์ค„์ž…๋‹ˆ๋‹ค.

SPMD(Single Program Multiple Data) ์‹คํ–‰ ๋ชจ๋ธ

NVSHMEM ์ž‘์—…์€ ์—ฌ๋Ÿฌ ์šด์˜์ฒด์ œ ํ”„๋กœ์„ธ์Šค๋กœ ๊ตฌ์„ฑ๋˜๋ฉฐ, ๊ฐ ํ”„๋กœ์„ธ์Šค๋ฅผ Processing Element(PE)๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ๋ชจ๋“  PE๋Š” ๋™์ผํ•œ ์‹คํ–‰ ํŒŒ์ผ์˜ ๋ณต์‚ฌ๋ณธ์„ ์‹คํ–‰ํ•˜๋Š” SPMD(Single Program, Multiple Data) ํŒจ๋Ÿฌ๋‹ค์ž„์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. SPMD๋Š” ๋งˆ์น˜ ๊ฐ™์€ ๋ ˆ์‹œํ”ผ๋ฅผ ๊ฐ€์ง„ ์—ฌ๋Ÿฌ ์š”๋ฆฌ์‚ฌ๊ฐ€ ๊ฐ์ž ๋‹ค๋ฅธ ์žฌ๋ฃŒ๋กœ ์š”๋ฆฌํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  PE๊ฐ€ ๋™์ผํ•œ ์ฝ”๋“œ(๋ ˆ์‹œํ”ผ)๋ฅผ ์‹คํ–‰ํ•˜์ง€๋งŒ, ๊ฐ PE๋Š” ์ž์‹ ์˜ ๊ณ ์œ  ID๋ฅผ ํ†ตํ•ด ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ(์žฌ๋ฃŒ)๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ํ•„์š”์— ๋”ฐ๋ผ ์กฐ๊ฑด๋ฌธ์œผ๋กœ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด "if (my_id == 0)"์œผ๋กœ 0๋ฒˆ PE๋งŒ ํŠน์ • ์ž‘์—…์„ ํ•˜๊ฒŒ ํ•˜๊ฑฐ๋‚˜, "process_chunk(data[my_id])"๋กœ ๊ฐ PE๊ฐ€ ์ž์‹ ์—๊ฒŒ ํ• ๋‹น๋œ ๋ฐ์ดํ„ฐ ๋ถ€๋ถ„์„ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ PE์—๋Š” 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ๊ณ ์œ ํ•œ ์ •์ˆ˜ ์‹๋ณ„์ž(PE ID)๊ฐ€ ํ• ๋‹น๋ฉ๋‹ˆ๋‹ค. ์ด ID๋Š” ํ†ต์‹  ์ž‘์—…์—์„œ ์†Œ์Šค๋‚˜ ๋ชฉ์ ์ง€๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋ฉฐ, ๊ฐœ๋ฐœ์ž๊ฐ€ ํŠน์ • PE์— ์ž‘์—…์„ ํ• ๋‹นํ•  ๋•Œ๋„ ํ™œ์šฉ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด 8๊ฐœ์˜ GPU๋กœ ์ž‘์—…์„ ์‹คํ–‰ํ•œ๋‹ค๋ฉด, PE ID๋Š” 0๋ถ€ํ„ฐ 7๊นŒ์ง€ ํ• ๋‹น๋ฉ๋‹ˆ๋‹ค.

ํ”„๋กœ๊ทธ๋žจ ์‹œ์ž‘ ์‹œ ๋ชจ๋“  PE๋Š” ๋ฐ˜๋“œ์‹œ ๋™์‹œ์—, ์ฆ‰ ์ง‘ํ•ฉ์ ์œผ๋กœ(collectively) NVSHMEM ์ดˆ๊ธฐํ™” ๋ฃจํ‹ด์„ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ ์ „์—๋„ ๋ชจ๋“  PE๊ฐ€ ํ•จ๊ป˜ ์ข…๋ฃŒ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ดˆ๊ธฐํ™”๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด PE๋Š” ์ž์‹ ์˜ ID์™€ ์ „์ฒด PE ๊ฐœ์ˆ˜๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Symmetric Memory

NVSHMEM์˜ ํ•ต์‹ฌ์€ ๋Œ€์นญ ๋ฉ”๋ชจ๋ฆฌsymmetric memory ๊ฐœ๋…์ž…๋‹ˆ๋‹ค. ์ด๋Š” ๋ชจ๋“  PE์— ๋™์ผํ•œ ํฌ๊ธฐ์™€ ๋ ˆ์ด์•„์›ƒ์œผ๋กœ ํ• ๋‹น๋˜๋Š” GPU ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๊ฐ PE๋Š” ์ž์‹ ์˜ GPU ๋ฉ”๋ชจ๋ฆฌ์— symmetric heap์ด๋ผ๋Š” ํŠน๋ณ„ํ•œ ์˜์—ญ์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, NVSHMEM API๋ฅผ ํ†ตํ•ด ์ด ํž™์—์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹น๋ฐ›์Šต๋‹ˆ๋‹ค.

๋Œ€์นญ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์€ ์ง‘ํ•ฉ ์—ฐ์‚ฐcollective operation์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  PE๋Š” ๋™์ผํ•œ ํฌ๊ธฐ ์ธ์ž๋ฅผ ์ „๋‹ฌํ•˜์—ฌ ํ• ๋‹น ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•˜๋ฉฐ, ๊ทธ ๊ฒฐ๊ณผ ๊ฐ PE์˜ ๋Œ€์นญ ํž™symmetric heap์—์„œ ์ง€์ •๋œ ํฌ๊ธฐ์˜ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ• ๋‹น๋ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋Š” ๋Œ€์นญ์ ์ด๋ผ๋Š” ํŠน๋ณ„ํ•œ ์†์„ฑ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. PE ID์™€ ๋Œ€์นญ ์ฃผ์†Œ์˜ ์กฐํ•ฉ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค๋ฅธ PE์—์„œ๋„ ์ด ๋ฉ”๋ชจ๋ฆฌ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ค‘์š”ํ•œ ์ ์€ NVSHMEM API๋ฅผ ํ†ตํ•˜์ง€ ์•Š๊ณ  ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋Š” ํ•ด๋‹น PE์˜ private memory๋กœ ๊ฐ„์ฃผ๋˜์–ด ๋‹ค๋ฅธ PE๊ฐ€ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ค์ง nvshmem_malloc ๊ฐ™์€ NVSHMEM ํ• ๋‹น ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์–ป์€ ๋ฉ”๋ชจ๋ฆฌ๋งŒ์ด ๋‹ค๋ฅธ PE์™€ ๊ณต์œ  ๊ฐ€๋Šฅํ•œ ๋Œ€์นญ ๋ฉ”๋ชจ๋ฆฌsymmetric memory๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

PGAS(Partitioned Global Address Space) ๋ชจ๋ธ: ์ „์—ญ ์ฃผ์†Œ ๊ณต๊ฐ„์˜ ํŒŒํ‹ฐ์…˜

๋ชจ๋“  PE์˜ ๋Œ€์นญ ๋ฉ”๋ชจ๋ฆฌ ์„ธ๊ทธ๋จผํŠธ๋ฅผ ํ•ฉ์นœ ๊ฒƒ์„ Partitioned Global Address Space(PGAS, ํŒŒํ‹ฐ์…˜๋œ ์ „์—ญ ์ฃผ์†Œ ๊ณต๊ฐ„)๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ์ด๋Š” ๋ถ„์‚ฐ ๋ฉ”๋ชจ๋ฆฌ ์‹œ์Šคํ…œ์„ ๋งˆ์น˜ ํ•˜๋‚˜์˜ ๊ฑฐ๋Œ€ํ•œ ์ „์—ญ ๋ฉ”๋ชจ๋ฆฌ์ฒ˜๋Ÿผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ์ถ”์ƒํ™”์ž…๋‹ˆ๋‹ค.

PGAS ๋ชจ๋ธ์—์„œ ๋ฐ์ดํ„ฐ์˜ ์œ„์น˜๋Š” ์ฃผ์†Œ ์ง€์ • ๋ชจ๋ธ์˜ ๋ณธ์งˆ์ ์ธ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. NVSHMEM ์—ฐ์‚ฐ์€ <symmetric_address, destination_PE> ํŠœํ”Œ๋กœ symmetric ๊ฐ์ฒด์— ์ ‘๊ทผํ•ฉ๋‹ˆ๋‹ค. symmetric address๋Š” NVSHMEM ํ• ๋‹น ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ์ฃผ์†Œ์— ํฌ์ธํ„ฐ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด &X[10]์ด๋‚˜ &ptr->x ๊ฐ™์€ ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์˜ํ•  ์ ์€ symmetric address๋Š” ํ• ๋‹น์„ ๋ฐ›์€ PE์—์„œ๋งŒ ์œ ํšจํ•˜๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ PE์™€ ์ด ์ฃผ์†Œ ๊ฐ’์„ ๊ณต์œ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. NVSHMEM ๋Ÿฐํƒ€์ž„์€ ๋‚ด๋ถ€์ ์œผ๋กœ symmetric address๋ฅผ ์‹ค์ œ ์›๊ฒฉ ์ฃผ์†Œ๋กœ ๋ณ€ํ™˜ํ•˜๋ฉฐ, ๊ณ ๊ธ‰ CUDA ๋ฉ”๋ชจ๋ฆฌ ๋งคํ•‘ ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด ๋ณ€ํ™˜ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ตœ์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค.

ํ†ต์‹  ๋ชจ๋ธ: Put, Get, ๊ทธ๋ฆฌ๊ณ  AMO

NVSHMEM์€ symmetric ๊ฐ์ฒด๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณต์‚ฌํ•˜๋Š” put API์™€ symmetric ๊ฐ์ฒด๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” get API๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋Ÿ‰ ์ „์†ก, ์Šค์นผ๋ผ ์ „์†ก, ๊ทธ๋ฆฌ๊ณ  ์ธํ„ฐ๋ฆฌ๋ธŒ ๋ฒ„์ „์˜ API๋“ค์ด ๋ชจ๋‘ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ Atomic Memory Operations(AMO)๋„ ์ œ๊ณต๋˜์–ด symmetric ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์›์ž์  ์—…๋ฐ์ดํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ API๋“ค์„ ํ†ตํ•ด NVSHMEM์€ CUDA ์ปค๋„๋กœ๋ถ€ํ„ฐ PGAS์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์„ธ๋ฐ€ํ•˜๊ณ  ๋‚ฎ์€ ์˜ค๋ฒ„ํ—ค๋“œ์˜ ์ ‘๊ทผ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ปค๋„ ๋‚ด๋ถ€์—์„œ ํ†ต์‹ ์„ ์ˆ˜ํ–‰ํ•จ์œผ๋กœ์จ, NVSHMEM์€ GPU ์›Œํ”„ ์Šค์ผ€์ค„๋ง ํ•˜๋“œ์›จ์–ด์˜ ๋ณธ์งˆ์ ์ธ ์ง€์—ฐ ์€๋‹‰ ๊ธฐ๋Šฅ์˜ ์ด์ ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

put, get, AMO ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฃจํ‹ด ์™ธ์—๋„, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ nvshmem_ptr ๋ฃจํ‹ด์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค๋ฅธ PE์˜ PGAS ํŒŒํ‹ฐ์…˜์— ์œ„์น˜ํ•œ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ง์ ‘ ํฌ์ธํ„ฐ๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ง€์ •๋œ PE์˜ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ง์ ‘ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ, ์ด ํ•จ์ˆ˜๋Š” ์œ ํšจํ•œ ํฌ์ธํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด null ํฌ์ธํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์ „์—ญ ๋ฉ”๋ชจ๋ฆฌ์— ์ง์ ‘ ๋กœ๋“œ์™€ ์Šคํ† ์–ด๋ฅผ ๋ฐœํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

NVSHMEM API์™€ ํ•˜๋“œ์›จ์–ด๊ฐ€ ํ—ˆ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์˜ ๋กœ๋“œ/์Šคํ† ์–ด๋Š” ๋กœ์ปฌ ๋ฐ ์›๊ฒฉ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์–ด, ํ•˜๋‚˜์˜ ์ฝ”๋“œ ๊ฒฝ๋กœ๋กœ ๋กœ์ปฌ๊ณผ ์›๊ฒฉ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ Hopper ์•„ํ‚คํ…์ฒ˜์˜ ๋ฉ€ํ‹ฐ์บ์ŠคํŠธ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•˜๋Š” ํ”Œ๋žซํผ์—์„œ๋Š” nvshmemx_mc_ptr ๋ฃจํ‹ด์„ ์‚ฌ์šฉํ•˜์—ฌ ํŒ€์˜ PGAS ํŒŒํ‹ฐ์…˜์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ง์ ‘ ๋ฉ€ํ‹ฐ์บ์ŠคํŠธ ํฌ์ธํ„ฐ๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

OpenSHMEM๊ณผ์˜ ์ฐจ์ด์ 

NVSHMEM์€ OpenSHMEM์˜ GPU ํ™•์žฅ์ด์ง€๋งŒ ๋ช‡ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฒซ์งธ, NVSHMEM ํ• ๋‹น API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ• ๋‹น๋œ ๋ชจ๋“  symmetric ๋ฉ”๋ชจ๋ฆฌ๋Š” ํ•€๋œ(pinned) GPU ๋””๋ฐ”์ด์Šค ๋ฉ”๋ชจ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๋‘˜์งธ, NVSHMEM์€ GPU ์ธก๊ณผ CPU ์ธก ํ†ต์‹  ๋ฐ ๋™๊ธฐํ™” API๋ฅผ ๋ชจ๋‘ ์ง€์›ํ•˜๋ฉฐ, ๊ด€๋ จ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ NVSHMEM์— ์˜ํ•ด ํ• ๋‹น๋œ GPU ๋””๋ฐ”์ด์Šค ๋ฉ”๋ชจ๋ฆฌ์ด๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ OpenSHMEM ๊ตฌํ˜„์—์„œ๋Š” ์ด๋Ÿฌํ•œ API๋ฅผ CPU์—์„œ๋งŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

NVSHMEM์€ ์ƒํƒœ๋ฅผ ๊ฐ€์ง„stateful ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. PE๊ฐ€ NVSHMEM ์ดˆ๊ธฐํ™” ๋ฃจํ‹ด์„ ํ˜ธ์ถœํ•˜๋ฉด, ์–ด๋–ค GPU๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”์ง€ ๊ฐ์ง€ํ•˜๊ณ  ์ด ์ •๋ณด๋ฅผ ๋Ÿฐํƒ€์ž„์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. PE๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ชจ๋“  symmetric ํ• ๋‹น ํ˜ธ์ถœ์€ ์„ ํƒ๋œ GPU์˜ ๋””๋ฐ”์ด์Šค ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. PE๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ชจ๋“  NVSHMEM ํ˜ธ์ถœ์€ ์„ ํƒ๋œ GPU์— ๋Œ€ํ•ด ๋˜๋Š” ์ด GPU์—์„œ ์‹คํ–‰๋œ ์ปค๋„ ๋‚ด๋ถ€์—์„œ ์ด๋ฃจ์–ด์ง„ ๊ฒƒ์œผ๋กœ ๊ฐ€์ •๋ฉ๋‹ˆ๋‹ค.

NVSHMEM์˜ ์žฅ์ ๊ณผ ์œ ์Šค์ผ€์ด์Šค

NVSHMEM์€ GPU ๊ฐ€์† ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํ†ต์‹  ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ๊ทน์ ์œผ๋กœ ์ค„์ž…๋‹ˆ๋‹ค. CPU ๊ฐœ์ž… ์—†์ด GPU๊ฐ€ ์ง์ ‘ ํ†ต์‹ ์„ ์ œ์–ดํ•˜๋ฏ€๋กœ, ์ง€์—ฐ ์‹œ๊ฐ„์ด ๋งˆ์ดํฌ๋กœ์ดˆ ๋‹จ์œ„๋กœ ์ค„์–ด๋“ค๊ณ  CPU ์ž์›์„ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ์ž‘์€ ๋ฉ”์‹œ์ง€๋ฅผ ๋นˆ๋ฒˆํ•˜๊ฒŒ ์ฃผ๊ณ ๋ฐ›์•„์•ผ ํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ทธ ํšจ๊ณผ๊ฐ€ ๋‘๋“œ๋Ÿฌ์ง‘๋‹ˆ๋‹ค.

๊ฐ•ํ•œ ์Šค์ผ€์ผ๋ง์ด ํ•„์š”ํ•œ HPC ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ NVSHMEM์€ ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค. GPU ์ˆ˜๊ฐ€ ๋Š˜์–ด๋‚ ์ˆ˜๋ก ๊ฐ GPU๊ฐ€ ์ฒ˜๋ฆฌํ•˜๋Š” ์ž‘์—… ํฌ๊ธฐ๊ฐ€ ์ค„์–ด๋“ค๊ณ , ๋”ฐ๋ผ์„œ ํ†ต์‹  ๋ฉ”์‹œ์ง€ ํฌ๊ธฐ๋„ ์ž‘์•„์ง‘๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํ™˜๊ฒฝ์—์„œ NVSHMEM์˜ ์ €์ง€์—ฐ ํŠน์„ฑ์€ ์ „์ฒด ์‹œ์Šคํ…œ์˜ ํ™•์žฅ์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

๊ทธ๋ž˜ํ”„ ์•Œ๊ณ ๋ฆฌ์ฆ˜, ํฌ์†Œ ํ–‰๋ ฌ ์—ฐ์‚ฐ, ๋ถ„์ž ๋™์—ญํ•™ ์‹œ๋ฎฌ๋ ˆ์ด์…˜๊ณผ ๊ฐ™์ด ๋ถˆ๊ทœ์น™ํ•˜๊ณ  ๋™์ ์ธ ํ†ต์‹  ํŒจํ„ด์„ ๊ฐ€์ง„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋„ NVSHMEM์˜ ์ฃผ์š” ์‚ฌ์šฉ ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์‹คํ–‰ ์ค‘์— ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋А PE๋กœ๋ถ€ํ„ฐ ๊ฐ€์ ธ์™€์•ผ ํ•˜๋Š”์ง€๊ฐ€ ๋™์ ์œผ๋กœ ๊ฒฐ์ •๋˜๋Š”๋ฐ, NVSHMEM์˜ one-sided ํ†ต์‹  ๋ชจ๋ธ์ด ์ด๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

MoEMixture-of-Experts ๋ชจ๋ธ์ฒ˜๋Ÿผ ํ† ํฐ๋งˆ๋‹ค ๋‹ค๋ฅธ ์ „๋ฌธ๊ฐ€๋กœ ๋ผ์šฐํŒ…๋˜๋Š” ํ˜„๋Œ€์ ์ธ AI ์•„ํ‚คํ…์ฒ˜์—์„œ๋„ NVSHMEM์€ ํ•ต์‹ฌ์ ์ธ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. DeepEP ๊ฐ™์€ MoE ํŠนํ™” ํ†ต์‹  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ NVSHMEM์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋œ ๊ฒƒ์€ ์šฐ์—ฐ์ด ์•„๋‹™๋‹ˆ๋‹ค. GPU ์ปค๋„ ๋‚ด์—์„œ ์ฆ‰์‹œ ํ†ต์‹  ๊ฒฐ์ •์„ ๋‚ด๋ฆฌ๊ณ  ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” NVSHMEM์˜ ๋Šฅ๋ ฅ์ด MoE์˜ ๋™์ ์ด๊ณ  ๋ถˆ๊ทœ์น™ํ•œ ํ†ต์‹  ํŒจํ„ด์„ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์ด์ƒ์ ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

InfiniBand GPUDirect Async ์ „์†ก

NVSHMEM์€ InfiniBand ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์˜ ์ œ์–ด ํ”Œ๋ ˆ์ธ๊ณผ ๋ฐ์ดํ„ฐ ํ”Œ๋ ˆ์ธ์„ ๋ชจ๋‘ GPU์—์„œ ์™„์ „ํžˆ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋””๋ฐ”์ด์Šค๊ฐ€ ์‹œ์ž‘ํ•œ ํ†ต์‹ ์„ ์—ญ๋ฐฉํ–ฅ ํ”„๋ก์‹œํ•  ํ•„์š”๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์€ InfiniBand GPUDirect Async(IBGDA) ์›๊ฒฉ ์ „์†ก์œผ๋กœ ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

IBGDA ์ „์†ก์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ „์ œ ์กฐ๊ฑด์ด ์žˆ์Šต๋‹ˆ๋‹ค. Mellanox HCA์™€ NIC๋งŒ ์ง€์›๋˜๋ฉฐ, Mellanox OFED 5.0 ์ด์ƒ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ nvidia.ko ๋“œ๋ผ์ด๋ฒ„๋Š” 510.40.3 ์ด์ƒ์ด์–ด์•ผ ํ•˜๊ณ , nvidia_peermem 510.40.3 ์ด์ƒ ๋˜๋Š” nv_peer_mem 1.3 ์ด์ƒ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์š”๊ตฌ์‚ฌํ•ญ์ด ์ถฉ์กฑ๋˜๋ฉด GPU๊ฐ€ CPU ์—†์ด ์ง์ ‘ InfiniBand ๋„คํŠธ์›Œํฌ ์–ด๋Œ‘ํ„ฐ๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

1.2. ์‹ค์ œ ์‚ฌ์šฉ ์˜ˆ์ œ

๋ง ํ†ต์‹  ํŒจํ„ด

๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด NVSHMEM์˜ ์‚ฌ์šฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ PE๋“ค์ด ๋ง ๊ตฌ์กฐ๋กœ ํ†ต์‹ ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค.

__global__ void simple_shift(int *destination) {
    int mype = nvshmem_my_pe();
    int npes = nvshmem_n_pes();
    int peer = (mype + 1) % npes;
    
    nvshmem_int_p(destination, mype, peer);
}

int main(void) {
    int mype_node, msg;
    cudaStream_t stream;
    
    // NVSHMEM ์ดˆ๊ธฐํ™”
    nvshmem_init();
    
    // ๋…ธ๋“œ ๋‚ด PE ID ์กฐํšŒ ๋ฐ ๋””๋ฐ”์ด์Šค ์„ค์ •
    mype_node = nvshmem_team_my_pe(NVSHMEMX_TEAM_NODE);
    cudaSetDevice(mype_node);
    cudaStreamCreate(&stream);
    
    // Symmetric ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น
    int *destination = (int *) nvshmem_malloc(sizeof(int));
    
    // ์ปค๋„ ์‹คํ–‰
    simple_shift<<<1, 1, 0, stream>>>(destination);
    
    // ๋ชจ๋“  PE์˜ ์—…๋ฐ์ดํŠธ ์™„๋ฃŒ ๋Œ€๊ธฐ
    nvshmemx_barrier_all_on_stream(stream);
    
    // ๊ฒฐ๊ณผ๋ฅผ ํ˜ธ์ŠคํŠธ๋กœ ๋ณต์‚ฌ
    cudaMemcpyAsync(&msg, destination, sizeof(int), 
                    cudaMemcpyDeviceToHost, stream);
    cudaStreamSynchronize(stream);
    
    printf("%d: received message %d\n", nvshmem_my_pe(), msg);
    
    // ์ •๋ฆฌ
    nvshmem_free(destination);
    nvshmem_finalize();
    return 0;
}

์ด ํ”„๋กœ๊ทธ๋žจ์˜ ๋™์ž‘์„ ๋‹จ๊ณ„๋ณ„๋กœ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. main ํ•จ์ˆ˜๋Š” ๋จผ์ € nvshmem_init()์œผ๋กœ NVSHMEM ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ๋‹ค์Œ ๋…ธ๋“œ ๋‚ด ํŒ€์—์„œ์˜ PE ID๋ฅผ ์กฐํšŒํ•˜์—ฌ CUDA ๋””๋ฐ”์ด์Šค๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ๋””๋ฐ”์ด์Šค ์„ค์ •์€ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์ด๋‚˜ ์ปค๋„ ์‹คํ–‰ ์ „์— ๋ฐ˜๋“œ์‹œ ์ˆ˜ํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

nvshmem_malloc์„ ํ†ตํ•ด ๋ชจ๋“  PE์— symmetric integer ๋ณ€์ˆ˜ destination์„ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  simple_shift ์ปค๋„์„ ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋กœ ์‹คํ–‰ํ•˜๋Š”๋ฐ, ์ด ์ปค๋„์˜ ์ธ์ž๋กœ symmetric ๊ฐ์ฒด์˜ ํฌ์ธํ„ฐ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

์ปค๋„ ๋‚ด๋ถ€์—์„œ๋Š” ์ „์—ญ PE ID์™€ ์‹คํ–‰ ์ค‘์ธ PE์˜ ์ด ๊ฐœ์ˆ˜๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ nvshmem_int_p ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์ผ ์ •์ˆ˜ put ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด ์—ฐ์‚ฐ์€ ์ž์‹ ์˜ PE ID๋ฅผ ๋‹ค์Œ ๋ฒˆํ˜ธ์˜ PE(๋˜๋Š” ๋งˆ์ง€๋ง‰ PE์˜ ๊ฒฝ์šฐ 0๋ฒˆ PE)์˜ destination์— ์”๋‹ˆ๋‹ค. 8๊ฐœ์˜ PE๋กœ ์‹คํ–‰ํ•˜๋ฉด PE 0์€ PE 7๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๊ณ , PE 1์€ PE 0์œผ๋กœ๋ถ€ํ„ฐ ๋ฐ›๋Š” ์‹์œผ๋กœ ๋ง ํŒจํ„ด์ด ํ˜•์„ฑ๋ฉ๋‹ˆ๋‹ค.

์ปค๋„์ด ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰๋œ ํ›„, nvshmemx_barrier_all_on_stream์œผ๋กœ ์ŠคํŠธ๋ฆผ ์ƒ์—์„œ ๋ฐฐ๋ฆฌ์–ด๋ฅผ ์ˆ˜ํ–‰ํ•˜์—ฌ ๋ชจ๋“  ์—…๋ฐ์ดํŠธ๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ๋‹ค์Œ ์—…๋ฐ์ดํŠธ๋œ destination ๊ฐ’์„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ํ˜ธ์ŠคํŠธ๋กœ ๋ณต์‚ฌํ•˜๊ณ , ์ŠคํŠธ๋ฆผ์„ ๋™๊ธฐํ™”ํ•œ ํ›„ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ํ• ๋‹นํ•œ ๋ฒ„ํผ๋ฅผ ํ•ด์ œํ•˜๊ณ  NVSHMEM ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.

MPI์™€์˜ ํ†ตํ•ฉ: ์ ์ง„์  ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

๊ธฐ์กด MPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ NVSHMEM์œผ๋กœ ์ ์ง„์ ์œผ๋กœ ํฌํŒ…ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ, ๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์˜ˆ์ œ๋Š” MPI ํ”„๋กœ๊ทธ๋žจ์—์„œ NVSHMEM์„ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

#include <mpi.h>
#include <nvshmem.h>
#include <nvshmemx.h>

int main(int argc, char *argv[]) {
    int rank, ndevices;
    nvshmemx_init_attr_t attr;
    MPI_Comm comm = MPI_COMM_WORLD;
    
    attr.mpi_comm = &comm;
    
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    
    cudaGetDeviceCount(&ndevices);
    cudaSetDevice(rank % ndevices);
    
    nvshmemx_init_attr(NVSHMEMX_INIT_WITH_MPI_COMM, &attr);
    
    // ... NVSHMEM ์ž‘์—… ...
    
    nvshmem_finalize();
    MPI_Finalize();
    return 0;
}

์ด ์˜ˆ์ œ์—์„œ MPI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋จผ์ € ์ดˆ๊ธฐํ™”ํ•˜๊ณ , MPI ๋žญํฌ๋ฅผ ์กฐํšŒํ•˜์—ฌ CUDA ๋””๋ฐ”์ด์Šค๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. nvshmemx_init_attr_t ๊ตฌ์กฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  mpi_comm ํ•„๋“œ์— MPI ์ปค๋ฎค๋‹ˆ์ผ€์ดํ„ฐ ํ•ธ๋“ค์˜ ์ฐธ์กฐ๋ฅผ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค. MPI ํ˜ธํ™˜ ๋ชจ๋“œ๋ฅผ ํ™œ์„ฑํ™”ํ•˜๊ธฐ ์œ„ํ•ด nvshmem_init ๋Œ€์‹  nvshmemx_init_attr ์—ฐ์‚ฐ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฐ MPI ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋™์‹œ์— NVSHMEM PE๊ฐ€ ๋˜์–ด, MPI ๋žญํฌ์™€ NVSHMEM ๋žญํฌ๋ฅผ ๋ชจ๋‘ ๊ฐ€์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ปดํŒŒ์ผ๊ณผ ์‹คํ–‰

NVSHMEM ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ nvcc๋กœ ์ปดํŒŒ์ผํ•˜๊ณ  ๋งํฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. NVSHMEM์€ ๋‘ ๊ฐœ์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋นŒ๋“œ๋ฉ๋‹ˆ๋‹ค. ๊ณต์œ  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ libnvshmem_host.so์™€ ์ •์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ libnvshmem_device.a์ž…๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ํ˜ธ์ŠคํŠธ API๋งŒ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ๋””๋ฐ”์ด์Šค API๋งŒ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ชจ๋‘ ๋งํฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ปดํŒŒ์ผ ์˜ˆ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

nvcc -rdc=true -ccbin g++ -gencode=$NVCC_GENCODE \
     -I $NVSHMEM_HOME/include nvshmem_hello.cu \
     -o nvshmem_hello.out \
     -L $NVSHMEM_HOME/lib -lnvshmem_host -lnvshmem_device

NVSHMEM ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ mpirun ๋Ÿฐ์ฒ˜๋กœ ์ง์ ‘ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. NVSHMEM ํŠน์ • ์˜ต์…˜์ด๋‚˜ ๊ตฌ์„ฑ ํŒŒ์ผ์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด:

mpirun -n 4 -ppn 2 -hosts hostname1,hostname2 /path/to/nvshmem/app/binary

๋˜ํ•œ srun์œผ๋กœ๋„ ์ถ”๊ฐ€ ๊ตฌ์„ฑ ์—†์ด ์ง์ ‘ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ NVSHMEM ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ PMI-1์„ ์‚ฌ์šฉํ•˜์—ฌ ํ†ต์‹ ํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜์ง€๋งŒ, NVSHMEM_BOOTSTRAP_PMI ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜์—ฌ ๋Ÿฐํƒ€์ž„์— ์‚ฌ์šฉ๋˜๋Š” PMI ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

NVSHMEM์€ ๋…๋ฆฝ์ ์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด Hydra Process Manager ์„ค์น˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ scripts/install_hydra.sh์— ํŒจํ‚ค์ง•ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์™ธ๋ถ€ MPI ์„ค์น˜ ์—†์ด๋„ NVSHMEM์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์„ค์น˜๋œ Hydra ๋Ÿฐ์ฒ˜๋Š” nvshmrun.hydra๋กœ ๋ถˆ๋ฆฌ๋ฉฐ, ์‰ฌ์šด ์ ‘๊ทผ์„ ์œ„ํ•ด nvshmrun ์‹ฌ๋ณผ๋ฆญ ๋งํฌ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

1.3. ์„ฑ๋Šฅ ์ตœ์ ํ™” ๋ฐ ๋””๋ฒ„๊น…

์„ฑ๋Šฅ ์ตœ์ ํ™”

NVSHMEM์˜ ์„ฑ๋Šฅ์„ ์ตœ๋Œ€ํ™”ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” CUDA ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ชจ๋ฒ” ์‚ฌ๋ก€๋ฅผ ๋”ฐ๋ผ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ๋ฐ์ดํ„ฐ ๋ณ‘ํ•ฉdata coalescing์„ ์ด‰์ง„ํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. GPU ํ•˜๋“œ์›จ์–ด์˜ ๋ฐ์ดํ„ฐ ๋ณ‘ํ•ฉ ๊ธฐ๋Šฅ์— ์˜์กดํ•˜์—ฌ ๋„คํŠธ์›Œํฌ ์ƒ์—์„œ ํšจ์œจ์„ฑ์„ ๋‹ฌ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์›Œํ”„ ๋‚ด์˜ ์Šค๋ ˆ๋“œ๋“ค์ด ์—ฐ์†๋œ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ์— ์ ‘๊ทผํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ๊ตฌ์„ฑํ•˜๋ฉด, NVSHMEM์ด ์ด๋Ÿฌํ•œ ์ ‘๊ทผ์„ ํ•˜๋‚˜์˜ ํšจ์œจ์ ์ธ ๋„คํŠธ์›Œํฌ ์ „์†ก์œผ๋กœ ๋ณ‘ํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋Œ€๋กœ ๋ฌด์ž‘์œ„์ ์ด๊ฑฐ๋‚˜ ์ŠคํŠธ๋ผ์ด๋“œ๊ฐ€ ํฐ ์ ‘๊ทผ ํŒจํ„ด์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž‘์€ ๋„คํŠธ์›Œํฌ ์ „์†ก์„ ๋ฐœ์ƒ์‹œ์ผœ ์„ฑ๋Šฅ์„ ์ €ํ•˜์‹œํ‚ต๋‹ˆ๋‹ค.

๋Œ€์นญ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น ํฌ๊ธฐ๋„ ์‹ ์ค‘ํ•˜๊ฒŒ ์„ ํƒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋„ˆ๋ฌด ์ž‘์€ ํ• ๋‹น์€ ๊ด€๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๊ณ , ๋„ˆ๋ฌด ํฐ ํ• ๋‹น์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋‚ญ๋น„ํ•ฉ๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ†ต์‹  ํŒจํ„ด์„ ๋ถ„์„ํ•˜์—ฌ ์ ์ ˆํ•œ ํ• ๋‹น ๋‹จ์œ„๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

fence์™€ quiet ์—ฐ์‚ฐ์€ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. fence๋Š” ํŠน์ • PE์— ๋Œ€ํ•œ ์ˆœ์„œ๋งŒ ๋ณด์žฅํ•˜๋ฏ€๋กœ quiet๋ณด๋‹ค ๊ฐ€๋ฒผ์šฐ๋ฉฐ, ์ ๋Œ€์  ํ†ต์‹  ์ˆœ์„œ๋งŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋Š” fence๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค. quiet๋Š” ๋ชจ๋“  PE์— ๋Œ€ํ•œ ์ „์—ญ ์ˆœ์„œ๋ฅผ ๋ณด์žฅํ•˜๋ฏ€๋กœ ๋” ๋ฌด๊ฑฐ์šด ์—ฐ์‚ฐ์ž…๋‹ˆ๋‹ค.

๋””๋ฒ„๊น…

NVSHMEM ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋””๋ฒ„๊น…ํ•  ๋•Œ๋Š” ๋ช‡ ๊ฐ€์ง€ ์ผ๋ฐ˜์ ์ธ ํ•จ์ •์„ ํ”ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€์žฅ ํ”ํ•œ ๋ฌธ์ œ๋Š” ๋Œ€์นญ ์ฃผ์†Œsymmetric address๋ฅผ ๋‹ค๋ฅธ PE์™€ ๊ณต์œ ํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋Œ€์นญ ์ฃผ์†Œ๋Š” ํ• ๋‹น๋ฐ›์€ PE์—์„œ๋งŒ ์œ ํšจํ•˜๋ฉฐ, ๋‹ค๋ฅธ PE์—๊ฒŒ ์ด ์ฃผ์†Œ ๊ฐ’์„ ์ „๋‹ฌํ•ด๋„ ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  ๋ฐ์ดํ„ฐ ์ž์ฒด๋ฅผ ์ „์†กํ•˜๊ฑฐ๋‚˜, ๋ชจ๋“  PE๊ฐ€ ๋™์ผํ•œ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ symmetric ๋ฐฐ์—ด์— ์ ‘๊ทผํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ๊ตฌ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ดˆ๊ธฐํ™”์™€ ์ข…๋ฃŒ ์ˆœ์„œ๋„ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. nvshmem_init()์€ ๋ชจ๋“  NVSHMEM ์—ฐ์‚ฐ๋ณด๋‹ค ๋จผ์ € ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•˜๋ฉฐ, nvshmem_finalize()๋Š” ๋ชจ๋“  PE๊ฐ€ NVSHMEM ์‚ฌ์šฉ์„ ์™„๋ฃŒํ•œ ํ›„์—๋งŒ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํ˜ธ์ถœ๋“ค์€ ์ง‘ํ•ฉ ์—ฐ์‚ฐ์ด๋ฏ€๋กœ ๋ชจ๋“  PE๊ฐ€ ๋™์‹œ์— ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ถ€ PE๋งŒ ์ดˆ๊ธฐํ™”ํ•˜๊ฑฐ๋‚˜ ์ข…๋ฃŒํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ์ด ๋ฉˆ์ถ”๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋™๊ธฐํ™” API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ปค๋„์—์„œ ๋ฐ๋“œ๋ฝ์ด ๋ฐœ์ƒํ•œ๋‹ค๋ฉด, ์ง‘ํ•ฉ ์ปค๋„ ์‹คํ–‰ API๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ชจ๋“  PE๊ฐ€ ๋™์ผํ•œ ๋™๊ธฐํ™” ์ง€์ ์— ๋„๋‹ฌํ•˜๋Š”์ง€, GPU ์˜ค๋ฒ„์„œ๋ธŒ์Šคํฌ๋ฆฝ์…˜์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”์ง€ ์ ๊ฒ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ™˜๊ฒฝ ๋ณ€์ˆ˜ NVSHMEM_DEBUG๋ฅผ ์„ค์ •ํ•˜๋ฉด ๋” ์ž์„ธํ•œ ๋””๋ฒ„๊ทธ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. NVSHMEM๊ณผ NCCL: ๊ทผ๋ณธ์ ์œผ๋กœ ๋‹ค๋ฅธ ๋‘ ๊ฐ€์ง€ ์ฒ ํ•™


2.1. NVSHMEM vs. NCCL

ํŠน์ง•
NVSHMEM
NCCL

์ œ์–ด

GPU ์ปค๋„์—์„œ ์ง์ ‘

CPU๊ฐ€ ๋ช…๋ น

๋ฐฉ์‹

One-sided (put/get)

Two-sided (์ง‘ํ•ฉ ์—ฐ์‚ฐ)

ํฌ๊ธฐ

์ž‘์€ ๋ฉ”์‹œ์ง€ ์ตœ์ ํ™”

๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ตœ์ ํ™”

์šฉ๋„

๋น„์ •ํ˜•, ์ฆ‰๊ฐ ํ†ต์‹ 

ํ‘œ์ค€ ์ง‘ํ•ฉ ํ†ต์‹ 

๋ ˆ๋ฒจ

์ €์ˆ˜์ค€, ์„ธ๋ฐ€ํ•œ ์ œ์–ด

๊ณ ์ˆ˜์ค€, ์‚ฌ์šฉ ํŽธ๋ฆฌ

ํ†ต์‹ ์˜ ์ฃผ์ฒด

NVSHMEM๊ณผ NCCL์˜ ๊ฐ€์žฅ ๊ทผ๋ณธ์ ์ธ ์ฐจ์ด๋Š” ํ†ต์‹ ์„ ๋ˆ„๊ฐ€ ์‹œ์ž‘ํ•˜๊ณ  ์ œ์–ดํ•˜๋А๋ƒ์ž…๋‹ˆ๋‹ค. NVSHMEM์€ GPU๊ฐ€ ์ง์ ‘ ํ†ต์‹ ์„ ์ฃผ๋„ํ•˜๋Š” ์ €์ˆ˜์ค€ API์ž…๋‹ˆ๋‹ค. CUDA ์ปค๋„ ์•ˆ์—์„œ ์‹คํ–‰๋˜๋Š” GPU ์Šค๋ ˆ๋“œ๊ฐ€ "๋‚˜๋Š” ์ง€๊ธˆ 3๋ฒˆ GPU์˜ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ด ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด์˜ฌ ๊ฒƒ"์ด๋ผ๊ณ  ๊ฒฐ์ •ํ•˜๊ณ  ์ฆ‰์‹œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. CPU๋Š” ์ด ๊ณผ์ •์— ์ „ํ˜€ ๊ด€์—ฌํ•˜์ง€ ์•Š์œผ๋ฉฐ, GPU๊ฐ€ ์™„์ „ํžˆ ์ž์œจ์ ์œผ๋กœ ํ†ต์‹ ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด NCCL์€ CPU๊ฐ€ ํ†ต์‹ ์„ ์ง€ํœ˜ํ•˜๋Š” ๊ณ ์ˆ˜์ค€ API์ž…๋‹ˆ๋‹ค. ํ˜ธ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ์‹คํ–‰๋˜๋Š” CPU๊ฐ€ "๋ชจ๋“  GPU๋“ค์ด์—ฌ, ์ง€๊ธˆ๋ถ€ํ„ฐ AllReduce ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋ผ"๊ณ  ๋ช…๋ น์„ ๋‚ด๋ฆฌ๋ฉด, GPU๋“ค์ด ์ด์— ์‘๋‹ตํ•˜์—ฌ ์ง‘ํ•ฉ ํ†ต์‹ ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ํ†ต์‹ ์˜ ์‹œ์ž‘๊ณผ ์กฐ์œจ์€ ์—ฌ์ „ํžˆ CPU์˜ ์˜์—ญ์— ๋‚จ์•„์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

One-sided vs Two-sided: ํ†ต์‹  ๋ชจ๋ธ์˜ ์ฐจ์ด

NVSHMEM์€ one-sided ํ†ต์‹  ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํ•œ์ชฝ์ด ์ผ๋ฐฉ์ ์œผ๋กœ ํ†ต์‹ ์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. nvshmem_put ์—ฐ์‚ฐ์„ ์‚ฌ์šฉํ•˜๋ฉด "๋‚ด๊ฐ€ ๋„ˆํ•œํ…Œ ์ด ๋ฐ์ดํ„ฐ๋ฅผ ์ค„๊ฒŒ"๋ผ๊ณ  ์ผ๋ฐฉ์ ์œผ๋กœ ์ƒ๋Œ€๋ฐฉ ๋ฉ”๋ชจ๋ฆฌ์— ๋ฐ์ดํ„ฐ๋ฅผ ์“ธ ์ˆ˜ ์žˆ๊ณ , nvshmem_get ์—ฐ์‚ฐ์œผ๋กœ๋Š” "๋‚ด๊ฐ€ ๋„ˆํ•œํ…Œ์„œ ์ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ๊ฒŒ"๋ผ๊ณ  ์ƒ๋Œ€๋ฐฉ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ค‘์š”ํ•œ ์ ์€ ๋ฐ›๋Š” ์ชฝ์ด๋‚˜ ์ฃผ๋Š” ์ชฝ์ด ์ด ํ†ต์‹ ์ด ์ผ์–ด๋‚˜๋Š” ๊ฒƒ์„ ๋ช…์‹œ์ ์œผ๋กœ ์•Œ ํ•„์š”๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋งˆ์น˜ ๊ณต์œ  ์‚ฌ๋ฌผํ•จ์— ๋ฌผ๊ฑด์„ ๋„ฃ๊ฑฐ๋‚˜ ๊บผ๋‚ด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

NCCL์€ two-sided ํ†ต์‹  ๋ชจ๋ธ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. AllReduce, Broadcast, AllGather์™€ ๊ฐ™์€ ์ง‘ํ•ฉ ํ†ต์‹  ์—ฐ์‚ฐ์—์„œ๋Š” ๋ชจ๋“  ์ฐธ์—ฌ์ž๊ฐ€ "์šฐ๋ฆฌ๋Š” ์ง€๊ธˆ ํ•จ๊ป˜ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ๊ฒƒ์ด๋‹ค"๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  GPU๊ฐ€ ๋™์‹œ์— ํ†ต์‹ ์— ์ฐธ์—ฌํ•˜๋ฉฐ, ์„œ๋กœ ํ˜‘๋ ฅํ•˜์—ฌ ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํšŒ์˜์‹ค์— ๋ชจ๋‘ ๋ชจ์—ฌ์„œ ์ •๋ณด๋ฅผ ๊ณต์œ ํ•˜๋Š” ๊ฒƒ๊ณผ ์œ ์‚ฌํ•œ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ํฌ๊ธฐ์™€ ์ตœ์ ํ™” ์˜์—ญ

NVSHMEM์€ ์ž‘์€ ๋ฉ”์‹œ์ง€ ์ „์†ก์— ํŠนํžˆ ๊ฐ•์ ์„ ๋ณด์ž…๋‹ˆ๋‹ค. ๋ช‡ ๋ฐ”์ดํŠธ์—์„œ ์ˆ˜ ํ‚ฌ๋กœ๋ฐ”์ดํŠธ ๋ฒ”์œ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋นˆ๋ฒˆํ•˜๊ฒŒ ์ฃผ๊ณ ๋ฐ›๋Š” ์ƒํ™ฉ์—์„œ ๋›ฐ์–ด๋‚œ ์„ฑ๋Šฅ์„ ๋ฐœํœ˜ํ•ฉ๋‹ˆ๋‹ค. GPU ์ปค๋„์ด ์‹คํ–‰๋˜๋Š” ๋„์ค‘์— ํ•„์š”ํ•œ ์ž‘์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฆ‰์‹œ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ง€์—ฐ ์‹œ๊ฐ„์ด ๋งค์šฐ ์ค‘์š”ํ•œ ์ž‘์—…์— ์ด์ƒ์ ์ž…๋‹ˆ๋‹ค. ๊ฐ•ํ•œ ์Šค์ผ€์ผ๋ง(strong scaling)์ด ํ•„์š”ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ GPU ์ˆ˜๊ฐ€ ๋Š˜์–ด๋‚ ์ˆ˜๋ก ๋ฉ”์‹œ์ง€ ํฌ๊ธฐ๊ฐ€ ์ž‘์•„์ง€๋Š” ๊ฒฝํ–ฅ์ด ์žˆ๋Š”๋ฐ, ์ด๋Ÿฌํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ NVSHMEM์˜ ์žฅ์ ์ด ๊ทน๋Œ€ํ™”๋ฉ๋‹ˆ๋‹ค.

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

API ๋ ˆ๋ฒจ๊ณผ ์‚ฌ์šฉ ๋ฐฉ์‹

NVSHMEM์€ ์ €์ˆ˜์ค€ API๋กœ์„œ ๋งค์šฐ ์„ธ๋ฐ€ํ•œ ์ œ์–ด๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. CUDA ์ปค๋„ ์ฝ”๋“œ ์•ˆ์—์„œ ์ง์ ‘ ํ˜ธ์ถœ๋˜๋ฉฐ, GPU ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ํŒจํ„ด์„ ์ •ํ™•ํ•˜๊ฒŒ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด __global__ void my_kernel() ํ•จ์ˆ˜ ์•ˆ์—์„œ int data = nvshmem_int_g(&remote_data, target_pe);์™€ ๊ฐ™์ด ์›๊ฒฉ GPU์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋งˆ์น˜ ๋กœ์ปฌ ๋ฉ”๋ชจ๋ฆฌ์ฒ˜๋Ÿผ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ €์ˆ˜์ค€ ์ ‘๊ทผ์€ ๋ณต์žกํ•œ ํ†ต์‹  ํŒจํ„ด์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์—ฐ์„ฑ์„ ์ œ๊ณตํ•˜์ง€๋งŒ, ๋™์‹œ์— ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ๋” ๋งŽ์€ ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

// CUDA ์ปค๋„ ์•ˆ์—์„œ ์ง์ ‘ ์ œ์–ด
__global__ void my_kernel() {
    int data = nvshmem_int_g(&remote_data, target_pe);
    // GPU๊ฐ€ ์ง์ ‘ ์›๊ฒฉ ๋ฉ”๋ชจ๋ฆฌ ์ฝ๊ธฐ
}

NCCL์€ ๊ณ ์ˆ˜์ค€ API๋กœ์„œ ์‚ฌ์šฉ์ด ๊ฐ„ํŽธํ•ฉ๋‹ˆ๋‹ค. CPU ํ˜ธ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ncclAllReduce(sendbuff, recvbuff, count, ncclFloat, ncclSum, comm, stream);์™€ ๊ฐ™์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, ๋ณต์žกํ•œ ์ง‘ํ•ฉ ํ†ต์‹ ์ด ์ž๋™์œผ๋กœ ์ตœ์ ํ™”๋˜์–ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ ๋ง ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‚˜ ํŠธ๋ฆฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ฐ™์€ ์ตœ์ ํ™”๋œ ํ†ต์‹  ํŒจํ„ด์ด ์ ์šฉ๋˜์ง€๋งŒ, ์‚ฌ์šฉ์ž๋Š” ์ด๋Ÿฌํ•œ ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ์‹ ๊ฒฝ ์“ธ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ถ”์ƒํ™” ๋•๋ถ„์— ๋ถ„์‚ฐ ํ•™์Šต ์ฝ”๋“œ๋ฅผ ๋น ๋ฅด๊ฒŒ ์ž‘์„ฑํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// CPU ํ˜ธ์ŠคํŠธ ์ฝ”๋“œ์—์„œ
ncclAllReduce(sendbuff, recvbuff, count, 
              ncclFloat, ncclSum, comm, stream);
// CPU๊ฐ€ ์ง‘ํ•ฉ ํ†ต์‹  ์‹œ์ž‘

2.2. ์œ ์Šค์ผ€์ด์Šค๋ณ„ ์„ ํƒ ๊ฐ€์ด๋“œ

NVSHMEM์ด ์ ํ•ฉํ•œ ๊ฒฝ์šฐ

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

NCCL์ด ์ ํ•ฉํ•œ ๊ฒฝ์šฐ

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

GPU ๊ฐ„ ํ†ต์‹ ์€ ๋” ์ด์ƒ ๋‹จ์ˆœํ•œ ๋ฐ์ดํ„ฐ ์ด๋™์˜ ๋ฌธ์ œ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. NVSHMEM๊ณผ NCCL์€ ๊ฐ๊ฐ ๋‹ค๋ฅธ ์ฒ ํ•™๊ณผ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, ํ˜„๋Œ€์˜ ๋ณต์žกํ•œ AI ์‹œ์Šคํ…œ์—์„œ๋Š” ๋‘ ๊ฐ€์ง€ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์ ์ ˆํžˆ ์กฐํ•ฉํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. Megatron-Core๋Š” ํฌ๊ด„์ ์ธ ํ•™์Šต ํ”„๋ ˆ์ž„์›Œํฌ๋กœ์„œ ๋‹ค์–‘ํ•œ ๋ณ‘๋ ฌํ™” ์ „๋žต์„ ์ œ๊ณตํ•˜๋ฉฐ, DeepEP๋Š” MoE ํŠน์œ ์˜ ํ†ต์‹  ํŒจํ„ด์„ ์œ„ํ•ด NVSHMEM๊ณผ GPUDirect Async๋ฅผ ํ™œ์šฉํ•œ ์ „๋ฌธํ™”๋œ ์†”๋ฃจ์…˜์„ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค.

References

Last updated