现在的位置: 首页 > 综合 > 正文

AMD兼容图像处理器(GPU)代码生成用于Java:案例分析

2013年02月08日 ⁄ 综合 ⁄ 共 2540字 ⁄ 字号 评论关闭

GPU卸载是加速并行程序的一种知名技术,但由于当前的Java 虚拟机(JVMs)缺乏GPU代码生成的支持,因此其嵌入Java空间的速度较慢。Sumatra是首个开源项目,旨在将GPU卸载能力直接集成到Java 虚拟机中。

AMD运行时间(Runtimes)团队已向OpenJDK社区提交了一个补丁,该补丁可扩展Java虚拟机以生成可在GPU/APU上执行的代码。这一项目对一个叫做Graal的OpenJDK项目产生了有利作用(http://openjdk.java.net/projects/graal/)。Graal是一个用于热点Java
虚拟机、可扩展性极高的即时编译器(JIT),其特点是拥有用于不同信息搜索与分析技能(ISA)的后端(x86, Sparc)。

AMD提交的补丁扩展了Graal,使其拥有一个生成HSA中间语言(HSAIL)代码的后端,一种HSA(异构系统架构)基金会定义的中间格式(http://hsafoundation.com/standards/)。这一特性使许多Java程序可在兼容GPU/APU的设备上编译及执行。虽然目前仍处于原型阶段,但我们已加入了几个工作单元(workingunit)测试用例,包括曼德博(Mandelbrot)和NBody。

此编译方法的参数可以是基元或对象,但当这些参数是阵列时,数据和阵列对象可被编译器编译。

该测试用例(除基本HSAIL测试外)要求一个HSAIL模拟器或硬件进行执行,但如果使用其他代替模拟器或硬件,测试用例将输出生成的HSAIL代码,这些代码可用于调试。用于HSAIL的开源模拟器将在近期发布。

此外,基本HSAIL测试还为添加Java代码段及查看HSAIL生成的代码而无需执行该代码提供了一个模板。

示例:平方数的HSAIL代码生成


为了说明HSAIL代码生成的原理,以下是一个简单的JUnit测试示例,求两个整型数组中所有元素的平方。

packagecom.oracle.graal.compiler.hsail.test;

importorg.junit.Test;

importjava.util.logging.*;

publicclass IntSquaredTest extends StaticMethodTwoIntArrays {

publicstatic void run(int[] out, int[] in, int gid) {

out[gid] =in[gid] * in[gid];

}

 

@Test

publicvoid test() {

super.testGeneratedHsail();

}

}

为了单独运行这一测试用例(IntSquaredTest),需执行以下命令:

./mx.sh –vm  server  unittest  hsail.test.IntSquaredTest

该测试将生成以下HSAIL代码

Version0:95: $full : $large;

// staticmethodHotSpotMethod<com.oracle.graal.compiler.hsail.test.IntSquaredTest.run(int[],int[], int)>

kernel&run (

kernarg_u64%_arg0,

kernarg_u64%_arg1

) {

Parameters loaded into registers

d6 = int[] out

d2= int[] in

s1 = gid

ld_kernarg_u64 $d6, [%_arg0];

ld_kernarg_u64 $d2, [%_arg1];

workitemabsid_u32$s1, 0;

align 4 spill_u8%spillseg[   400];

Array index out of bounds checks for in[] and out[]

@L0:

ld_global_s32$s0, [$d2 + 16];

cmp_ge_b1_s32$c0, $s1, $s0;

cbr $c0,@L1;

@L2:

ld_global_s32$s0, [$d6 + 16];

cmp_ge_b1_s32$c0, $s1, $s0;

cbr $c0,@L3;

@L4:

Load in[gid] into $s0

cvt_s64_s32$d0, $s1;

mul_s64$d0, $d0, 4;

add_u64$d2, $d2, $d0;

ld_global_s32 $s0, [$d2 + 24];

$s3 = in[gid]*in[gid]

mul_s32$s3, $s0, $s0;

cvt_s64_s32 $d1, $s1;

Store result in out[gid]

mul_s64$d1, $d1, 4;

add_u64$d6, $d6, $d1;

st_global_s32$s3, [$d6 + 24];

ret;

@L1:

ret;

@L3:

ret;

};

很不错吧?你也可以用以下方式编写你的测试用例(用JDK8 lambda语法)并生成与以上相同的代码:

packagecom.oracle.graal.compiler.hsail.test.lambda;

importcom.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;

importcom.amd.okra.sample.utils.KernelTester;

importorg.junit.Test;

publicclass IntSquaredStaticTest extends GraalKernelTester {

staticfinal int NUM = 20;

@Result

publicint[] outArray = new int[NUM];

publicint[] inArray = new int[NUM];

@Override

publicvoid runTest() {

int[] out= outArray;

int[] in= inArray;

dispatchLambdaKernel(NUM,(gid)->{

out[gid]= in[gid] * in[gid] + 1;

});

}

@Test

publicvoid testUsingLambdaMethod() {

testGeneratedHsailUsingLambdaMethod();

}

}

抱歉!评论已关闭.