SLAM Engineer

๐ŸŒˆ CUDA ํ”„๋กœ๊ทธ๋ž˜๋ฐ: Thrust ์‹ค์Šต 1ํŽธ


๋ชจ๋˜ํ•˜๊ฒŒ GPU ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ ํ•˜์ž

  • CUDA ์ง์ ‘ ์งœ๋Š” ๊ฒƒ๋„ ์ข‹์ง€๋งŒ
  • ์ข€ ๋” ํŽธํ•˜๊ณ  ์‹ถ๋‹ค.

๊ฐœ์š”

  • SLAM์„ ํ•˜๋‹ค๋ณด๋ฉด ์„ผ์„œ ๋ฐ์ดํ„ฐ๋กœ๋ถ€ํ„ฐ ์ˆ˜๋งŒ๊ฐœ์—์„œ ์ˆ˜๋ฐฑ๋งŒ๊ฐœ๊นŒ์ง€ raw data ๋“ค์„ ๋‹ค๋ฃฐ ์ผ์ด ๋งŽ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด์„œ, cleaned static point cloud map์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์ˆ˜ํ–‰ํ–ˆ๋˜ Removert (IROS 2020) ๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ, submap ์„ ๋งŒ๋“ค๊ณ  ์ด๋ฅผ ํ•œ ๋…ธ๋“œ์˜ viewpoint ์— projectionํ•ด์„œ projective range image๋ฅผ ์–ป์—ˆ์–ด์•ผ ํ–ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ 100m ์ •๋„๋งŒ ์Œ“์•„๋„ ์„œ๋ธŒ๋งต์˜ ํฌ์ธํŠธ ๊ฐœ์ˆ˜๋Š” 500๋งŒ๊ฐœ์—์„œ 1000๋งŒ๊ฐœ๊ฐ€ ๋œ๋‹ค. ์ด ๊ณผ์ •์„ ๋น ๋ฅด๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ OpenMP๋ฅผ ์‚ฌ์šฉํ•˜์˜€์ง€๋งŒ, ์—ฌ์ „ํžˆ ๋Š๋ฆฐ๊ฒŒ ์•„์‰ฌ์› ๋‹ค (removert ๋Š” ์—ฌ์ „ํžˆ ๋Š๋ฆฐ ์ฑ„๋กœ ๋‚จ์•„ ์žˆ๋‹ค).
  • ๊ทผ๋ณธ์ ์œผ๋กœ ์ด๋Ÿฌํ•œ ์ž‘์—…์—๋Š” CPU (๋ฅผ ์•„๋ฌด๋ฆฌ ์ˆ˜์‹ญ์ฝ”์–ด ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ํ•œ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„ ๋Š๋ฆฌ๋‹ค) ๊ฐ€ ์•„๋‹ˆ๋ผ GPU๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•จ์„ ๋Š๋ผ๊ณ  ์žˆ๋˜ ์ฐจ์—
  • Thrust ๋ผ๋Š” library๋ฅผ ์‹ค์Šตํ•ด๋ณด์•˜๋‹ค.
    • CUDA library๋ฅผ ํ•œ๋ฒˆ ๋” ํ•˜์ด๋ ˆ๋ฒจ๋กœ ๊ฐ์‹ผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.
    • Modern C++ (C++11 ์ด์ƒ) ์Šคํƒ€์ผ๋กœ ๊ตฌํ˜„๊ฐ€๋Šฅํ•œ ๊ฒƒ์ด ํŠน์ง•์ด๋‹ค. std::algorithm ์˜ ๋ฌธ๋ฒ•๊ณผ ์ƒ๋‹นํžˆ ๋‹ฎ์•„์žˆ๋‹ค.
      • ์ฝ”๋“œ ๋น„๊ต ์˜ˆ์‹œ (์•„๋ž˜ ์‹ค์Šต๋น„๋””์˜ค์—์„œ ์‚ฌ์šฉํ•œ): ์ˆซ์ž 10์–ต๊ฐœ ๋”ํ•˜๊ธฐ

        • ps. ๋ณด๋‹ค์‹œํ”ผ ์‚ฌ์šฉ๋ฒ•์€ ๋„ˆ๋ฌด ์‰ฝ๊ณ  ์ง๊ด€์ ์ด๋‹ค (๋นŒ๋“œํ•˜๋Š”๋ฐ ์‹œ๊ฐ„์ด ๋” ๊ฑธ๋ ธ๋‹ค ใ… ใ… ).
    • ๊ทธ๋ฆฌ๊ณ  CUDA ์˜ˆ์ œ๋“ค์—์„œ nvcc ๋กœ ์ปค๋งจ๋“œ๋ผ์ธ์—์„œ ๋นŒ๋“œํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์€๋ฐ, modern C++ ๋ฐ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค๊ณผ ํ•จ๊ป˜ thrust ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์•„๋ฌด๋ž˜๋„ cmake๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข€ ๋” ๊น”๋”ํ•˜๋‹ค. cmake ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์‹ค์Šต์„ ์ง„ํ–‰ํ•ด๋ณด์ž (== CMakeLists.txt ๋ฅผ ๋งŒ๋“ค์ž).

์‹ค์Šต

์ค€๋น„๊ณผ์ •

  1. Thrust ๋นŒ๋“œ
    • ๊ณต์‹ github readme ์— ๋‚˜์™€์žˆ๋Š”๋Œ€๋กœ ํ•˜๋ฉด ๋œ๋‹ค.
      • ์ด ๋•Œ ํด๋ฆฐํ•œ ํ˜ธ์ŠคํŠธ ์œ ์ง€๋ฅผ ์œ„ํ•ด docker ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•˜๊ณ , ์•„๋ž˜ ์˜ˆ์ œ์—์„œ๋„ docker ๋กœ ์ˆ˜ํ–‰ํ•ด๋ณผ ๊ฒƒ์ด๋‹ค.
      • ์ฒซ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์ธ ci/local/build.bash ๋ฅผ ํ•˜๋‹ˆ๊นŒ ๋ญ”๊ฐ€ ์•ˆ๋˜์„œ ๊ทธ๋ƒฅ ์•„๋ž˜ ๋ฐฉ๋ฒ•๋Œ€๋กœ ์Šคํ…๋ฐ”์ด์Šคํ… (git clone ํ•˜๊ณ  cmake .. ํ•˜๊ณ  make install) ์œผ๋กœ ์ง์ ‘ ๋นŒ๋“œํ•˜์˜€๋‹ค.
      • ๋Œ€์ถฉ ์•„๋ฌด ์‹œ์ž‘ ์ด๋ฏธ์ง€ (e.g., docker pull ubuntu:jammy) ๋ฅผ ๋ฐ›์•„๋‘๊ณ  docker run ํ•ด์„œ ๋“ค์–ด๊ฐ€์ž.
        • ๊ทผ๋ฐ ๋„ˆ๋ฌด ์•„๋ฌด๊ฒƒ๋„ ์—†๋Š” ๋ฒ ์ด์Šค๋ฅผ ๋•ก๊ฒจ์˜ค๋ฉด ์ข€ ๊ท€์ฐฎ๊ณ , ๋‚˜๋Š” ci/local/build.bash ๋ฅผ ํ•˜๋‹ˆ ์ด๊ฒƒ์ €๊ฒƒ์ด ์ž˜ ์„ค์น˜๋˜์–ด์žˆ๋Š” ์ด๋ฏธ์ง€๊ฐ€ ํ•˜๋‚˜ ๋•ก๊ฒจ์™€์ ธ์„œ ๊ทธ๊ฒƒ์„ ๋ฒ ์ด์Šค๋กœ ์‚ฌ์šฉํ–ˆ๋‹ค.
      • runํ•  ๋•Œ gpu ๋ฅผ ์žก์•„์ฃผ๋ฉด์„œ ๋“ค์–ด๊ฐ€์•ผ ํ•œ๋‹ค. ์ฆ‰, ์˜ต์…˜์œผ๋กœ --gpus all ๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.
      • docker runํ•ด์„œ image ์•ˆ์œผ๋กœ ๋“ค์–ด๊ฐ„ ๋‹ค์Œ์—, ๋Š˜ ํ•˜๋“ฏ์ด git clone ํ•˜๊ณ  cmake .. ํ•˜๊ณ  make install ํ•œ๋‹ค.
        • ๊ทธ๋Ÿฐ๋ฐ compute_90์ด ์•ˆ๋œ๋‹ค๋Š” ์–ด๋–ค ์—๋Ÿฌ๊ฐ€ ๋‚˜์™€์„œ ccmake .. ์—์„œ config ๋ฅผ ๋“ค์–ด๊ฐ„ ๋‹ค์Œ์— 90 ์˜ต์…˜์„ OFFํ•ด์ฃผ์—ˆ๋‹ค. ์•„๋งˆ ๋‚ด๊ฐ€ ์˜›๋‚  ์•„ํ‚คํ…์ฒ˜(6.1)์ธ gtx1080ti ๋ฅผ ์“ฐ๊ณ  ์žˆ์–ด์„œ ์ตœ์‹  ์•„ํ‚คํ…์ฒ˜ (9๋ฒˆ๋Œ€?) ์—์„œ ์ง€์›ํ•˜๋Š” ๋ญ”๊ฐ€๊ฐ€ ๋นŒ๋“œ๊ฐ€ ์•ˆ๋˜๋Š” ๋Š๋‚Œ์ด ๋“ ๋‹ค.

      • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋นŒ๋“œํ•˜๋Š” ๋ฐ์— ๊ฝค๋‚˜ ๊ธด ์‹œ๊ฐ„ (i5 11gen์—์„œ 8core๋กœ 2-3์‹œ๊ฐ„ ๊ฑธ๋ฆฐ ๋“ฏํ•˜๋‹ค (example ๋“ค์„ ๋‹ค ๋นŒ๋“œํ•˜๋Š๋ผ..)) ์ด ์ง€๋‚œ ํ›„โ€ฆ ๋ญ”๊ฐ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ make install ์€ ๋‹ค ๋˜์—ˆ๋Š”๋ฐ, ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ (์•„๋ž˜ ์†Œ๊ฐœํ• ) ๋นŒ๋“œ๋ฅผ ํ•˜๊ณ  ์‹คํ–‰ํ•˜๋ ค๊ณ ๋ณด๋‹ˆ forward compatible ํ•œ HW๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค๋Š” ์—๋Ÿฌ๊ฐ€ ๋– ์„œ ์•ˆ๋˜์—ˆ๋‹ค.
        • cuda toolkit version๊ณผ ์ด์— ๋Œ€์‘๋˜๋Š” nvidia driver ๋ฅผ ๋‹ค์‹œ ์„ค์น˜ํ•ด์ฃผ๋‹ˆ ํ•ด๊ฒฐ๋˜์—ˆ๋‹ค. ๋‚ด ๊ฒฝ์šฐ gtx1080ti์— cuda 11.4, nvidia driver 470 ์„ ์‚ฌ์šฉํ•˜์˜€๋‹ค.
  2. CMake๋ฅผ ์‚ฌ์šฉํ•ด์„œ main code ๋นŒ๋“œ
    • ์ฒ˜์Œ ์จ๋ณด๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ CMakeLists.txt ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒŒ ๋‹ค ํ•˜๊ณ ๋‚˜์„œ ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ๊ฐ€ ์žˆ์œผ๋ฉด ์—„์ฒญ ์‰ฌ์šด๋ฐ, ์ฒ˜์Œ ํ•œ ๋ฒˆ ํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์ผ์ด๋‹ค.
    • ์—ญ์‹œ ์ด๋Ÿด ๋•Œ๋Š” ๊ณตํ™ˆ์— ํžŒํŠธ ๊ฐ€ ์žˆ๋‹ค. ์ด๊ฑธ ๋ณด๊ณ  ๋Œ€์ถฉ ๋”ฐ๋ผํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋œ๋‹ค.
    • code: CMakeLists.txt

      • ์ฒ˜์Œ์— ์ € thrust_creat_target ์˜ ๊ทœ์•ฝ์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•ด์„œ ์ข€ ํ—ค๋งค์—ˆ๋‹ค. DEVICE๋’ค์— CPP๋ฅผ ๋ถ™์ด๋ฉด thrust code ๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ cpu๋งŒ ์‚ฌ์šฉํ•œ๋‹ค (ps. DEVICE CUDA๋ฅผ DEVICE CPP๋กœ ๋ฐ”๊พธ๊ณ  main_gpu_thrust.cu๋ฅผ main_gpu_thrust.cpp ๋กœ ์ด๋ฆ„๋ฐ”๊ฟ”์„œ ์ง์ ‘ ๋นŒ๋“œ ํ•ด๋ณด๋ผ! ๋ถ„๋ช… thrust ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ–ˆ์ง€๋งŒ cpu๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๋™์ผํ•œ ์‹œ๊ฐ„์ด ์†Œ์š”๋จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค).
      • DEVICE CUDA์ธ src์— ๋Œ€ํ•ด์„œ๋Š”, Modern C++ ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜๊ณ  main์ด ๋“ค์–ด์žˆ๋Š” ํŒŒ์ผ์ด์ง€๋งŒ .cu ํ™•์žฅ์ž๋กœ ์ด๋ฆ„์„ ์ง€์–ด์ค€๋‹ค. ์™ ์ง€๋ชจ๋ฅด์ง€๋งŒ .cpp๋กœ ๋๋‚˜๊ฒŒ ํ•˜๋‹ˆ๊นŒ ์ปดํŒŒ์ผ์ด ์•ˆ๋˜์—ˆ๋‹ค.
        • ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ณต์‹ ๋ฆฌํฌ์˜ ์˜ˆ์ œ ์ฝ”๋“œ๋“ค ๋„ ๋ชจ๋‘ ๊ฐ๊ฐ main์„ ๊ฐ€์ง€๋Š” ๋…๋ฆฝ๋œ executables ๋“ค์ด์ง€๋งŒ ๋ชจ๋‘ .cu ํ™•์žฅ์ž๋ฅผ ๊ฐ€์ง์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
          • ps. ๋ฐฉ๊ธˆ ๊ตฌ์ถ•ํ•œ CMake project directory๋ฅผ ํ™œ์šฉํ•ด์„œ ๊ณตํ™ˆ์˜ ๋‹ค๋ฅธ ์˜ˆ์ œ๋“ค์„ ๋ณต์‚ฌํ•ด์™€์„œ main_gpu.cu ์•ˆ์— ๋‚ด์šฉ์„ ๋ฐ”๊ฟ”์„œ ์ถ”๊ฐ€์ ์œผ๋กœ ๋” ์‹ค์Šตํ•ด๋ณด๋ผ!

์‹ค์Šต ์˜์ƒ

  • ์•„๋ฌดํŠผ ์œ„์˜ ๊ณผ์ •์„ ๊ฑฐ์ณ์„œ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ์ธ, 10์–ต๊ฐœ ์ˆซ์ž ๋”ํ•˜๊ธฐ๋ฅผ ํ•ด๋ณด์•˜๋‹ค.
    • std::uniform_int_distribution<> dist(0, 9999) ์™€ ๊ฐ™์ด 0์—์„œ 9999 ์‚ฌ์ด์˜ int ๋“ค์ด 10์–ต๊ฐœ ์žˆ๋‹ค.

๊ฒฐ๊ณผ

  • ํ•  ๋•Œ๋งˆ๋‹ค ๋‹ค๋ฅด์ง€๋งŒ, ๋Œ€์ถฉ ์ด์ •๋„ ๋‚˜์˜จ๋‹ค. GPU๋กœ ๋Œ๋ฆด ๋•Œ 20๋ฐฐ ์ •๋„ ๋น ๋ฅด๋‹ค.

    • ์œ„ ์˜์ƒ์—์„œ ๋‚˜์˜ค์ง€๋งŒ, ๊ผญ ์ƒ˜ํ”Œ์ด 10์–ต๊ฐœ์”ฉ ์žˆ์ง€ ์•Š๋”๋ผ๋„, ์ฆ‰ 1์–ต๊ฐœ ์ •๋„์—์„œ๋„ ์—ฌ์ „ํžˆ 20-30๋ฐฐ ๋น ๋ฅธ ๋ชจ์Šต์„ ๋ณด์—ฌ์ค€๋‹ค.

ps. ์‹ค์Šต2

  • ์ฐธ๊ณ ๋กœ cpp17๋ถ€ํ„ฐ ๋“ค์–ด์˜จ execution policy๋ฅผ ํ†ตํ•ด์„œ cpu ์ƒ์—์„œ ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•ด๋ณด์•˜๋‹ค.
  • ๋‹ค๋งŒ, ์ด ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” compiler ๊ฐ€ ์ƒ๊ฐํ•˜๊ธฐ์— ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋ฉด ์ตœ์„ ์„ ๋‹คํ•ด์ฃผ๊ฒ ๊ณ , ์•„๋‹ˆ๋ฉด ์•ˆํ•ด์ค„ ์ˆ˜๋„ ์žˆ๋‹ค, ๋ผ๋Š” โ€˜๊ณ ๋ ค๋Š” ํ•ด๋ณด๊ฒ ๋‹คโ€™ ์ •๋„์˜ ์˜๋ฏธ๋กœ ์ƒ๊ฐํ•ด์•ผ ํ•œ๋‹ค.
    • ๋ฉ”์ธ ๋ธ”๋ก์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
            auto do_sum = [&]() {
                Number init = 0;
                Number sum = std::transform_reduce(
                    std::execution::par, vec.begin(), vec.end(), init,
                    std::plus<Number>(), [](const Number& num) { return num; });
                return sum;
            };
      
      
    • ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์•˜๋‹ค. 3๋ฒˆ์”ฉ ์ˆ˜ํ–‰ํ–ˆ์„ ๋•Œ,

      • ์ด๋“์ด ๊ทธ๋ฆฌ ํฌ์ง€ ์•Š์Œ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
        • ์—ญ์‹œ (๋‹น์—ฐํžˆ) GPU๋ฅผ ์‚ฌ์šฉํ•ด์•ผ๋งŒ ์œ ๋ฆฌํ•œ ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๊ฐ€ ์žˆ๋‹ค. ์ฟ ๋‹ค ์„ค์น˜์˜ ๋งˆ์Œ์˜ ์žฅ๋ฒฝ(๊ท€์ฐฎ์Œ)์„ ์ด์ œ๋Š” ํ—ˆ๋ฌผ์ž!
          • ps. ๊ทธ๋‚˜์ €๋‚˜ ChatGPT์—๊ฒŒ ๊ถ๊ธˆํ•œ ๊ฑธ ๋ฌผ์–ด๋ณด์•˜๋‹ค.

๊ฒฐ๋ก 

  • ๋”ฅ๋Ÿฌ๋‹ ์•ˆํ•ด๋„ GPU ์ž˜ ์“ฐ๋ฉด ์ข‹๋‹ค.
  • ps. ์š”์ฆ˜์€ (2018๋…„ ์ด๋Ÿด ๋•Œ ๋Œ€๋น„ โ€ฆ) nvidia driver ์‚ญ์ œ ๋ฐ ์žฌ์„ค์น˜๋„ ๊ธˆ๋ฐฉ ํŽธํ•˜๊ฒŒ ๋˜๋”๋ผ.

TODO

  • ๋‹ค๋ฅธ ๊ณต์‹ ์˜ˆ์ œ๋“ค๋„ ๋Œ๋ ค๋ณด์ž.
  • Robotics ์—์„œ ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์— ๊ด€ํ•œ ํŠœํ† ๋ฆฌ์–ผ์„ ๋งŒ๋“ค์–ด ๋ณด์ž.