来自JNI的错误对齐数组的性能方面

时间:2013-07-09 16:52:28

标签: java c++ java-native-interface memory-alignment

当通过JNI将两个数组从java传递到c ++时,使用c ++内在函数(或asm-inline)来提高性能有三个障碍。

1)JNI调用有一个开销(正如预期的那样,20个周期到100个周期)

2)数组传递为错误对齐(需要32B或16B对齐),因此需要移动整个两个数组以使它们对齐,然后在最终移位回到旧位置。

3)创建一个新数组以将结果发送到java(例如:向量乘法C = A * B)如果我们从java提供一个数组,那么它也会被错误对齐!所以我们需要在c ++中创建一个新的对齐数组,这会减慢整个过程。

我们可以创建一个更大的数组来连接两个数组,而不是移动两个数组,但这也会很慢。

如果我们只能使用(数据量少,计算量更大)的结构,那么使用JNI的性能有什么意义呢?

- 在JNI中使用纯c ++(无内在)只比纯java快10% - 20%。

- 使用内在函数将乘法/ s增加了%70但缓慢的数组复制仍然有效。只有%50%的机会将java的阵列移动到32B对齐的位置。

- 使用GetPrimitiveArrayCritical而非GetArrayElements()为大型向量(256k元素)的点积提供了另外的%250性能。这必须是在JNI工作和非拷贝访问时关闭gc-down的结果。

- 在我的机器上使用直接字节缓冲区而不是原始数组是%40(在纯java之上5x-6x)。还允许我在原生地址选择器的帮助下选择其中的自定义偏移量,使其与32B对齐。所以我们可以有32B对齐的直接缓冲区子集(在“C”空间中)但不是原始数组。

- 将一个大缓冲区划分为8个部分并分成8个java线程,与单个directbytebuffer相比,计算速度提高了40%(这可能接近我的ram限制,因为我只对每个元素进行一次乘法)< / p>

单个线程的最新案例与java的循环展开乘法的总速度比率接近6倍,在我应用多线程之后,它增加到8x(因为内存带宽而不是计算上限,不是很多)。

您可以添加什么来克服上述三个难题?

我们如何通过JNI将32B对齐的数组从java传递到c ++?

0 个答案:

没有答案