您的位置:首页 > 编程语言 > Java开发

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

2013-08-15 11:15 363 查看
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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐