Kinetica는 GPU를 이용한 in-memory DB로서, 주로 OLTP용보다는 OLAP용으로 사용됩니다. 아래에 간단한 TPC-H data와 query를 이용하여 일반 DBMS(여기서는 postgresql)와의 성능 비교 및 그때 CPU-GPU간의 NVLink가 어떤 효과를 내는지 nvprof로 분석해보았습니다. 아래 test는 모두 POWER9 + V100 GPU의 IBM AC922 서버로 진행했습니다.
Postgresql과 Kinetica 모두 TPC-H에서 제공되는 dbgen으로 생성한 data를 사용했습니다. 여기서 DB 크기는 10GB로 했습니다. 이렇게 하면 delimeter가 '|'로 되어 있는 SAM file들이 만들어지는데, 실제로 DB에 load를 하려면 맨 끝에 붙은 '|'은 제거해야 하더군요.
[root@localhost dbgen]# nohup ./dbgen -s 10 &
[root@localhost dbgen]# ls -ltr *.tbl
-rw-r--r--. 1 root root 14176368 Oct 23 09:35 supplier.tbl
-rw-r--r--. 1 root root 389 Oct 23 09:35 region.tbl
-rw-r--r--. 1 root root 243336157 Oct 23 09:35 part.tbl
-rw-r--r--. 1 root root 1204850769 Oct 23 09:35 partsupp.tbl
-rw-r--r--. 1 root root 1749195031 Oct 23 09:35 orders.tbl
-rw-r--r--. 1 root root 2224 Oct 23 09:35 nation.tbl
-rw-r--r--. 1 root root 7775727688 Oct 23 09:35 lineitem.tbl
-rw-r--r--. 1 root root 244847642 Oct 23 09:35 customer.tbl
Postgres에서는 다음과 같이 dbgen에 포함된 dss.ddl script를 이용하여 필요한 table들을 생성했습니다.
[root@localhost dbgen]# su - postgres
Last login: Mon Oct 22 17:27:48 KST 2018 on pts/1
-bash-4.2$ createdb dss
-bash-4.2$ psql dss
psql (9.2.23)
Type "help" for help.
dss=# \i /home/data/2.17.3/dbgen/dss.ddl
dss=# \d ORDERS
Table "public.orders"
Column | Type | Modifiers
-----------------+-----------------------+-----------
o_orderkey | integer | not null
o_custkey | integer | not null
o_orderstatus | character(1) | not null
o_totalprice | numeric(15,2) | not null
o_orderdate | date | not null
o_orderpriority | character(15) | not null
o_clerk | character(15) | not null
o_shippriority | integer | not null
o_comment | character varying(79) | not null
그 다음에 다음과 같이 SAM file에서 postgresql table 안으로 loading을 합니다. 아래는 LINEITEM의 table 예만 들었습니다.
dss=# copy lineitem from '/home/data/2.17.3/dbgen/lineitem.csv' with (FORMAT csv, DELIMITER '|');
COPY 59986052
Kinetica에도 이 SAM file을 만들고 load 하기 위해서는 다음과 같은 menu를 이용하면 됩니다. 다만 Kinetica는 GPU를 이용한 분산 DB이기 때문에, shard key를 지정하는 등 추가적인 설정 과정을 거쳐야 합니다. (여기서는 상세히 표시하지 않았습니다. 저도 제가 직접 못하고 저희 파트너사인 Unione INC의 엔지니어 도움을 받았습니다.)
먼저, TPC-H의 query들 중 1개씩의 query를 수행해보겠습니다. 이 query는 join 등이 그렇게까지 크지 않은 query라서 GPUdb가 일반 RDBMS에 비해 그다지 더 유리하지도 않은 query입니다. 그런데도, 또 별다른 tuning 없이도, Kinetica가 20배 정도 빠른 것을 보실 수 있습니다. 모두 2번씩 돌린 것이므로, postgresql에서도 data는 이미 memory에 cache된 상태라서 disk 병목은 전혀 없다고 보셔도 됩니다.
-bash-4.2$ time psql -d dss -f /home/data/RunQuery/q16.sql > /tmp/ooo
real 1m1.267s
user 0m0.374s
sys 0m0.000s
[root@localhost ~]# time /opt/gpudb/bin/kisql -host 127.0.0.1 -f /home/data/RunQuery/q16.sql > /tmp/iii
real 0m3.046s
user 0m3.729s
sys 0m0.770s
특히 Kinetica의 경우는 아래처럼 query 결과에 Query Execution Time과 Data Transfer Time을 각각 명기합니다. GPUdb에서는 query execution보다 data를 transfer하는데 더 많은 시간이 걸린다는 것을 보실 수 있습니다. 이런 것 때문에 특히 CPU와 GPU간의 연결이 CPU냐 GPU냐가 매우 중요합니다.
| Brand#54 | ECONOMY PLATED BRASS | 14 | 4 |
| Brand#55 | STANDARD BURNISHED BRASS | 14 | 4 |
+------------+-----------------------------+----------+----------------+
Rows read = 27840
Query Execution Time: 0.495 s
Data Transfer Time: 2.283 s
이 시스템에 CPU core는 32개나 있지만 GPU는 딱 2장 뿐입니다. 이럴 경우 저런 query를 10개씩 병렬로 수행하면 CPU가 더 빠를 수도 있지 않을까요 ? 꼭 그렇지는 않습니다.
여기서는 TPC-H의 16번과 19번 query 2개를 5번씩, 총 10개를 한꺼번에 수행하는 방식으로 돌리겠습니다.
Postgres에서 돌릴 script는 다음과 같습니다.
-bash-4.2$ cat 1.sh
date
echo "Starting"
psql -d dss -f /home/data/RunQuery/q16.sql &
psql -d dss -f /home/data/RunQuery/q19.sql &
...(총 10줄)
wait
date
echo "Finished"
Kinetica에서 돌릴 script도 사실상 똑같은 내용입니다.
[root@localhost ~]# cat /tmp/1.sh
date
echo "Starting"
/opt/gpudb/bin/kisql -host 127.0.0.1 -f /home/data/RunQuery/q16.sql &
/opt/gpudb/bin/kisql -host 127.0.0.1 -f /home/data/RunQuery/q19.sql &
/opt/gpudb/bin/kisql -host 127.0.0.1 -f /home/data/RunQuery/q16.sql &
/opt/gpudb/bin/kisql -host 127.0.0.1 -f /home/data/RunQuery/q19.sql &
... (총 10줄)
wait
date
echo "Finished"
각각의 수행 결과는 다음과 같습니다. Kinetica도 GPU가 2장 뿐인 환경에서도 10개의 동시 query를 잘 수행해내며, 여전히 6배 정도 빠릅니다.
Postgresql는 다음과 같습니다.
-bash-4.2$ time ./1.sh > p.txt
real 1m6.947s
user 0m1.891s
sys 0m0.055s
Kinetica는 다음과 같습니다.
[root@localhost ~]# time /tmp/1.sh > /tmp/k.txt
real 0m8.545s
user 0m29.965s
sys 0m20.525s
Kinetica에서 이 query를 처리하기 전에, nvprof를 이용해 profile data를 받기 위해서 Kinetica의 구동 script 중 일부를 수정한 뒤 restart 해주어야 합니다. 수정은 다음과 같이 간단합니다. 아래 붉은 색 부분의 명령어를 삽입해주기만 하면 됩니다.
[root@localhost ~]# vi /opt/gpudb/core/bin/gpudb
...
# nohup $HOST_MANAGER_CMD >> $HOST_MANAGER_LOG_FILENAME 2>&1 &
nohup /usr/local/cuda-9.2/bin/nvprof --log-file /tmp/nvprof/%p.txt --export-profile /tmp/nvprof/%p.nvvp --print-gpu-trace --profile-child-processes $HOST_MANAGER_CMD >> $HOST_MANAGER_LOG_FILENAME 2>&1 &
...
이렇게 얻은 profile data를 분석해보면, GPUdb의 대표적인병목인 cuda memcpy HtoD (CPU to GPU) 및 DtoH (GPU to CPU)의 사용되는 대역폭을 보실 수 있습니다. 대략 35GB/sec에 달합니다. 참고로, POWER9과 V100 GPU 사이를 연결하는 NVLink는 3개의 port를 aggregate시킨 것이라서, 이론상 단방향 대역폭이 75GB/sec (양방향 150GB/sec)에 달합니다. PCIe Gen3 버스의 이론상 단방향 대역폭이 16GB/sec(양방향 32GB/sec)에 불과하다는 것을 생각하면, Kinetica와 같은 GPUdb를 사용할 경우 CPU와 GPU의 연결은 반드시 NVLink가 되어야 한다는 것을 쉽게 아실 수 있습니다.
2018년 10월 25일 목요일
2018년 1월 29일 월요일
IBM AC922의 2-socket 간의 대역폭은 얼마인가 ?
먼저, 이건 IBM의 공식 발표 수치가 아니라 현재까지 발표된 기술 자료들에 근거한 산술 계산임을 밝힙니다.
IBM AC922은 POWER9 processor와 NVIDIA V100 GPU를 PCIe 대신 NVLink 2.0으로 연결했다는, 업계 유일무이한 아키텍처 외에도 자랑할 만한 점이 있습니다. 즉, 6개의 NVLink를 3개씩묶어, NVLink의 50GB/s (25+25)가 아닌 150GB/s의 대역폭으로 GPU와 GPU, 그리고 CPU와 GPU를 연결한다는 점입니다.
같은 NVLink V100을 사용하는 x86 processor 기반의 다른 서버들에서는 CPU와 GPU는 고작 32GB/s의 PCIe로 연결하고, 또 GPU와 GPU 간도 NVLink 하나로 연결되기 때문에 고작 50GB/s로 연결되는 점과 비교되는 부분입니다.
하지만 AC922의 각 CPU 소켓에 연결된 2개의 GPU cluster간의 연결은 POWER 프로세서의 SMP 버스를 연결해야 한다는 점은 여전합니다. 기존 POWER8 + P100 구조인 Minsky 서버에서는 이 SMP X bus의 대역폭이 38.4 GB/s 였기 때문에, 40 GB/s인 NVLink 1.0에 비해 손색이 별로 없었습니다. 그런데, AC922에서는 이 SMP X bus의 대역폭이 얼마일까요 ? 아직 IBM에서 AC922의 아키텍처에 대한 상세 redbook이 나오지 않아 정식으로 발표된 자료가 없습니다.
(이 그림에서 왼쪽은 P100을 장착한 DGX-1의 아키텍처입니다. 이제 4개의 NVLink 1.0 port를 장착한 P100 대신 6개의 NVLink 2.0을 장착한 V100을 탑재했으니, 아마 GPU 간을 엮는 NVLink topology가 조금 바뀌었을 것 같은데, 그림을 못 찾겠네요. 대신 기존의 링크 당 40GB/s 대신 50GB/s로 올라간 것은 확실합니다.)
구글링을 해보니 답이 나옵니다. 아래 PDF 문서에, AC922의 두 processor socket을 연결하는 SMP X bus의 spec이 "X-Bus 4B @ 16GHz"라고 나온 것입니다. 기존 Minsky 서버의 SMP X bus의 spec은 "8B @ 4.8 GHz"였습니다.
(출처 : https://www.ibm.com/developerworks/community/wikis/form/anonymous/api/wiki/61ad9cf2-c6a3-4d2c-b779-61ff0266d32a/page/1cb956e8-4160-4bea-a956-e51490c2b920/attachment/9a8eabe8-10b8-4a8e-aebe-3a3845b71c0f/media/Power%20Systems%20AC922%20Intro%2011December2017%20.pdf )
이 spec을 대역폭(GB/s)으로 환산하는 것은 어떻게 하는 것일까요 ? 다음 문서에 나옵니다.
https://www.redbooks.ibm.com/redpapers/pdfs/redp5405.pdf
기존 Minsky 서버의 SMP X bus 대역폭 : 8 bytes * 4.8 GHz = 38.4 GB/s
AC922 서버의 SMP X bus 대역폭 : 4 bytes * 16 GHz = 64 GB/s
즉, AC922 서버는 NVLink 1.0 80GB/s에서 NVLink 2.0 150GB/s로의 비율만큼, SMP X bus의 속도도 끌어올린 것입니다. 이 64GB/s라는 속도는 NVLink 2.0 1개 link인 50GB/s보다 오히려 더 뛰어난 속도로서, 4개 GPU를 이용한 Deep Learning에 충분한 속도를 제공합니다.
한편, x86 서버 프로세서 중 최신인 Skylake Scalable Processor는 기존 Broadwell의 2 x QPI @ 9.6 GT/s를 3 x UPI @ 10.4 GT/s로 업그레이드했습니다. (출처 : https://www.servethehome.com/intel-xeon-scalable-processor-family-platform-level-overview/ ) 이 GT/s를 Gbps로 변환하면 PCIe Gen3 기준으로 대략 98%이므로 (출처 : https://paolozaino.wordpress.com/2013/05/21/converting-gts-to-gbps/ ) 대략 30.72 Gbps가 됩니다. ( 3 x 10.4 x 128/130 = 30.72 )
IBM AC922은 POWER9 processor와 NVIDIA V100 GPU를 PCIe 대신 NVLink 2.0으로 연결했다는, 업계 유일무이한 아키텍처 외에도 자랑할 만한 점이 있습니다. 즉, 6개의 NVLink를 3개씩묶어, NVLink의 50GB/s (25+25)가 아닌 150GB/s의 대역폭으로 GPU와 GPU, 그리고 CPU와 GPU를 연결한다는 점입니다.
같은 NVLink V100을 사용하는 x86 processor 기반의 다른 서버들에서는 CPU와 GPU는 고작 32GB/s의 PCIe로 연결하고, 또 GPU와 GPU 간도 NVLink 하나로 연결되기 때문에 고작 50GB/s로 연결되는 점과 비교되는 부분입니다.
하지만 AC922의 각 CPU 소켓에 연결된 2개의 GPU cluster간의 연결은 POWER 프로세서의 SMP 버스를 연결해야 한다는 점은 여전합니다. 기존 POWER8 + P100 구조인 Minsky 서버에서는 이 SMP X bus의 대역폭이 38.4 GB/s 였기 때문에, 40 GB/s인 NVLink 1.0에 비해 손색이 별로 없었습니다. 그런데, AC922에서는 이 SMP X bus의 대역폭이 얼마일까요 ? 아직 IBM에서 AC922의 아키텍처에 대한 상세 redbook이 나오지 않아 정식으로 발표된 자료가 없습니다.
(이 그림에서 왼쪽은 P100을 장착한 DGX-1의 아키텍처입니다. 이제 4개의 NVLink 1.0 port를 장착한 P100 대신 6개의 NVLink 2.0을 장착한 V100을 탑재했으니, 아마 GPU 간을 엮는 NVLink topology가 조금 바뀌었을 것 같은데, 그림을 못 찾겠네요. 대신 기존의 링크 당 40GB/s 대신 50GB/s로 올라간 것은 확실합니다.)
구글링을 해보니 답이 나옵니다. 아래 PDF 문서에, AC922의 두 processor socket을 연결하는 SMP X bus의 spec이 "X-Bus 4B @ 16GHz"라고 나온 것입니다. 기존 Minsky 서버의 SMP X bus의 spec은 "8B @ 4.8 GHz"였습니다.
(출처 : https://www.ibm.com/developerworks/community/wikis/form/anonymous/api/wiki/61ad9cf2-c6a3-4d2c-b779-61ff0266d32a/page/1cb956e8-4160-4bea-a956-e51490c2b920/attachment/9a8eabe8-10b8-4a8e-aebe-3a3845b71c0f/media/Power%20Systems%20AC922%20Intro%2011December2017%20.pdf )
이 spec을 대역폭(GB/s)으로 환산하는 것은 어떻게 하는 것일까요 ? 다음 문서에 나옵니다.
https://www.redbooks.ibm.com/redpapers/pdfs/redp5405.pdf
기존 Minsky 서버의 SMP X bus 대역폭 : 8 bytes * 4.8 GHz = 38.4 GB/s
AC922 서버의 SMP X bus 대역폭 : 4 bytes * 16 GHz = 64 GB/s
즉, AC922 서버는 NVLink 1.0 80GB/s에서 NVLink 2.0 150GB/s로의 비율만큼, SMP X bus의 속도도 끌어올린 것입니다. 이 64GB/s라는 속도는 NVLink 2.0 1개 link인 50GB/s보다 오히려 더 뛰어난 속도로서, 4개 GPU를 이용한 Deep Learning에 충분한 속도를 제공합니다.
한편, x86 서버 프로세서 중 최신인 Skylake Scalable Processor는 기존 Broadwell의 2 x QPI @ 9.6 GT/s를 3 x UPI @ 10.4 GT/s로 업그레이드했습니다. (출처 : https://www.servethehome.com/intel-xeon-scalable-processor-family-platform-level-overview/ ) 이 GT/s를 Gbps로 변환하면 PCIe Gen3 기준으로 대략 98%이므로 (출처 : https://paolozaino.wordpress.com/2013/05/21/converting-gts-to-gbps/ ) 대략 30.72 Gbps가 됩니다. ( 3 x 10.4 x 128/130 = 30.72 )
피드 구독하기:
글 (Atom)