2018년 2월 13일 화요일

IBM Java의 source code 수정없는 GPU 가속 기능

아래 Redbook의 "8.4.5 CUDA and IBM Java"라는 항목을 보면 IBM JDK에서는 "-Dcom.ibm.gpu.enable" 옵션을 제공하는 것으로 나옵니다.  이를 이용하면 GPU로 source code 변환없이도 java application을 쉽게 가속할 수 있습니다.

https://www.redbooks.ibm.com/redbooks/pdfs/sg248263.pdf

아래의 BuiltInSort.java은 위 redbook에 나오는 sample code입니다.  보시다시피 특별히 CUDA를 이용하는 구간은 없습니다.

root@45e1670c8bc9:/java# cat BuiltInSort.java
import java.util.Arrays;
import java.util.Random;
public class BuiltInSort {
public static void main(String[] args) {
int N = 128*512*256;
//int N = 128*1024*1024;  --> 원래의 N size는 이것인데, 이를 위줄 같이 줄이지 않으면 invalid argument error가 나더군요.
int[] toSort = new int[N];
Random rnd = new Random();
for (int i = 0; i < N; ++i) {
toSort[i] = rnd.nextInt();
}
long startTime = System.nanoTime();
Arrays.sort(toSort);
long estimatedTime = System.nanoTime() - startTime;
System.out.println("CPU\t" + N + '\t' + estimatedTime * 1e-9 + " seconds");
}
}

설치된 java 환경은 다음과 같은 IBM Java입니다.

root@45e1670c8bc9:/java# which java
/opt/ibm/java-ppc64le-80/bin/java

root@45e1670c8bc9:/java# java -fullversion
java full version JRE 1.8.0 IBM Linux build 8.0.5.7 - pxl6480sr5fp7-20171216_01(SR5 FP7)

IBM javac를 이용하여 위 code를 아래와 같이 compile 합니다.

root@45e1670c8bc9:/java# javac BuiltInSort.java

그리고 이제 수행합니다.  여기서는 그냥 평범하게 수행합니다.

root@45e1670c8bc9:/java# time java -Xmx12g BuiltInSort
CPU     16777216        2.6369640330000004 seconds

real    0m3.649s
user    0m5.066s
sys     0m0.101s

이번에는 GPU를 이용하도록 '-Dcom.ibm.gpu.enable=sort'라는 옵션을 주어 수행합니다.

root@45e1670c8bc9:/java# time java -Xmx12g -Dcom.ibm.gpu.verbose -Dcom.ibm.gpu.enable=sort BuiltInSort
[IBM GPU]: [time.ms=1518500997649]: Discovered 4 device(s)
[IBM GPU]: [time.ms=1518500997655]: Acquired device: 0
[IBM GPU]: [time.ms=1518500997656]: Using device: 0 to sort int array; elements 0 to 16777216
[IBM GPU]: [time.ms=1518500998115]: Sorted ints on device 0 successfully
[IBM GPU]: [time.ms=1518500998116]: Released device: 0
CPU     16777216        0.5533952480000001 seconds

real    0m1.587s
user    0m1.311s
sys     0m0.475s

보시다시피 빠르며, 특히 compute 구간만 측정하면 5배 정도로 매우 빠릅니다.  이때 nvidia-smi에서도 java가 GPU를 사용하는 모습이 관측됩니다.

다만, 이를 다른 heavy compute 용도에 사용할 수 없을까 다른 sample을 몇개 돌려보니, GPU를 사용하지 않습니다.  이는 그 정도의 연산은 JVM이 GPU를 이용하는 것이 더 이익이냐 아니냐 판단 기준이 되는 threshold를 못 넘기 때문에 GPU를 안 쓰는 것으로 판단됩니다.

위에 언급한 IBM Redbook site의 문서를 보면 IBM JVM이 GPU를 이용하는데는 다음과 같이 세가지 방법이 있습니다.  그런데, 2번째와 3번째 방법도 사실상 java sort() 에 대한 것 외에는 따로 usage가 없는 것으로 보입니다.

1) Let the Java virtual machine (JVM) decide when to offload processing to a GPU.
2) Use the com.ibm.gpu classes to offload specific tasks.
3) Use the CUDA4J API to specify in the application exactly when to use the GPU.

However, to benefit from this type of processing, the array must be of a sufficient size. This size is required to justify the time of data movement between the CPU and
the GPU.  JVM, which is shipped with IBM SDK, Java Technology Edition, is able to automatically offload certain Java functions. This offload happens when the JVM expects that the speed of data processing at the GPU outweighs the cost of data movement from main memory to the GPU.

특히 아래의 문서를 보면,  -Dcom.ibm.gpu.enable=[]에서 []에 들어갈 keyword는 sort와 all 두가지 밖에 없습니다.  그리고 all로 수행하면 뭐 딱히 잘 먹히는 경우를 아직 저는 못 찾았습니다.

https://www.ibm.com/support/knowledgecenter/SSYKE2_7.1.0/com.ibm.java.lnx.71.doc/diag/appendixes/cmdline/Dcomibmgpuenable.html

-Dcom.ibm.gpu.enable=[all|sort]
Where:
all      Turns on GPU processing for all possible Java functions.
sort    Turns on GPU processing only for the Java sort() function.

결론적으로, 아직 sort 외의 use case에는 제한이 있긴 합니다만, 그래도 IBM JDK에서는 source code 변경 없이도 일부 code의 GPU 가속이 가능합니다.

댓글 없음:

댓글 쓰기