Java 数组快速转换为 NumPy 数组 (Py4J)
Fast conversion of Java array to NumPy array (Py4J)
有一些很好的示例如何将 NumPy 数组转换为 Java 数组,但反之亦然 - 如何将数据从 Java 对象转换回 NumPy 数组。我有一个这样的 Python 脚本:
from py4j.java_gateway import JavaGateway
gateway = JavaGateway() # connect to the JVM
my_java = gateway.jvm.JavaClass(); # my Java object
....
int_array=my_java.doSomething(int_array); # do something
my_numpy=np.zeros((size_y,size_x));
for jj in range(size_y):
for ii in range(size_x):
my_numpy[jj,ii]=int_array[jj][ii];
my_numpy
是 Numpy 数组,int_array
是 Java 整数数组 - int[ ][ ]
类型的数组。在 Python 脚本中初始化为:
int_class=gateway.jvm.int # make int class
double_class=gateway.jvm.double # make double class
int_array = gateway.new_array(int_class,size_y,size_x)
double_array = gateway.new_array(double_class,size_y,size_x)
尽管它按原样工作,但它不是最快的方法并且工作速度相当慢 - 对于 ~1000x1000 数组,转换需要 5 分钟以上。
有什么方法可以在合理的时间内完成吗?
如果我尝试:
test=np.array(int_array)
我得到:
ValueError: invalid __array_struct__
我遇到了类似的问题,只是试图绘制我通过 py4j 从 Java 端获得的光谱向量(Java 数组)。
这里,从 Java 数组到 Python 列表的转换是通过 list() 函数实现的。这可能会提供一些关于如何使用它来填充 NumPy 数组的线索...
vectors = space.getVectorsAsArray(); # Java array (MxN)
wvl = space.getAverageWavelengths(); # Java array (N)
wavelengths = list(wvl)
import matplotlib.pyplot as mp
mp.hold
for i, dataset in enumerate(vectors):
mp.plot(wavelengths, list(dataset))
我不能说这是否比您使用的嵌套 for 循环更快,但它也有作用:
import numpy
from numpy import array
x = array(wavelengths)
v = array(list(vectors))
mp.plot(x, numpy.rot90(v))
我有一个类似的问题,并找到了一个解决方案,对于我测试的案例来说,它的速度快了大约 220 倍:为了将一个 1628x120 的短整数数组从 Java 传输到 Numpy,运行时间从 11 减少了秒到 0.05 秒。感谢 , I started looking into py4j byte arrays,事实证明 py4j 有效地将 Java 字节数组转换为 Python 字节对象,反之亦然(按值传递,而不是按引用传递)。这是一种相当迂回的做事方式,但并不难。
因此,如果您要传输尺寸为 iMax
xjMax
的整数数组 intArray
(为了示例,我假设这些都存储为对象中的实例变量),您可以先编写一个 Java 函数将其转换为 byte[],如下所示:
public byte[] getByteArray() {
// Set up a ByteBuffer called intBuffer
ByteBuffer intBuffer = ByteBuffer.allocate(4*iMax*jMax); // 4 bytes in an int
intBuffer.order(ByteOrder.LITTLE_ENDIAN); // Java's default is big-endian
// Copy ints from intArray into intBuffer as bytes
for (int i = 0; i < iMax; i++) {
for (int j = 0; j < jMax; j++){
intBuffer.putInt(intArray[i][j]);
}
}
// Convert the ByteBuffer to a byte array and return it
byte[] byteArray = intBuffer.array();
return byteArray;
}
然后,您可以编写Python 3 代码来接收字节数组并将其转换为正确形状的numpy 数组:
byteArray = gateway.entry_point.getByteArray()
intArray = np.frombuffer(byteArray, dtype=np.int32)
intArray = intArray.reshape((iMax, jMax))
有一些很好的示例如何将 NumPy 数组转换为 Java 数组,但反之亦然 - 如何将数据从 Java 对象转换回 NumPy 数组。我有一个这样的 Python 脚本:
from py4j.java_gateway import JavaGateway
gateway = JavaGateway() # connect to the JVM
my_java = gateway.jvm.JavaClass(); # my Java object
....
int_array=my_java.doSomething(int_array); # do something
my_numpy=np.zeros((size_y,size_x));
for jj in range(size_y):
for ii in range(size_x):
my_numpy[jj,ii]=int_array[jj][ii];
my_numpy
是 Numpy 数组,int_array
是 Java 整数数组 - int[ ][ ]
类型的数组。在 Python 脚本中初始化为:
int_class=gateway.jvm.int # make int class
double_class=gateway.jvm.double # make double class
int_array = gateway.new_array(int_class,size_y,size_x)
double_array = gateway.new_array(double_class,size_y,size_x)
尽管它按原样工作,但它不是最快的方法并且工作速度相当慢 - 对于 ~1000x1000 数组,转换需要 5 分钟以上。
有什么方法可以在合理的时间内完成吗?
如果我尝试:
test=np.array(int_array)
我得到:
ValueError: invalid __array_struct__
我遇到了类似的问题,只是试图绘制我通过 py4j 从 Java 端获得的光谱向量(Java 数组)。 这里,从 Java 数组到 Python 列表的转换是通过 list() 函数实现的。这可能会提供一些关于如何使用它来填充 NumPy 数组的线索...
vectors = space.getVectorsAsArray(); # Java array (MxN)
wvl = space.getAverageWavelengths(); # Java array (N)
wavelengths = list(wvl)
import matplotlib.pyplot as mp
mp.hold
for i, dataset in enumerate(vectors):
mp.plot(wavelengths, list(dataset))
我不能说这是否比您使用的嵌套 for 循环更快,但它也有作用:
import numpy
from numpy import array
x = array(wavelengths)
v = array(list(vectors))
mp.plot(x, numpy.rot90(v))
我有一个类似的问题,并找到了一个解决方案,对于我测试的案例来说,它的速度快了大约 220 倍:为了将一个 1628x120 的短整数数组从 Java 传输到 Numpy,运行时间从 11 减少了秒到 0.05 秒。感谢
因此,如果您要传输尺寸为 iMax
xjMax
的整数数组 intArray
(为了示例,我假设这些都存储为对象中的实例变量),您可以先编写一个 Java 函数将其转换为 byte[],如下所示:
public byte[] getByteArray() {
// Set up a ByteBuffer called intBuffer
ByteBuffer intBuffer = ByteBuffer.allocate(4*iMax*jMax); // 4 bytes in an int
intBuffer.order(ByteOrder.LITTLE_ENDIAN); // Java's default is big-endian
// Copy ints from intArray into intBuffer as bytes
for (int i = 0; i < iMax; i++) {
for (int j = 0; j < jMax; j++){
intBuffer.putInt(intArray[i][j]);
}
}
// Convert the ByteBuffer to a byte array and return it
byte[] byteArray = intBuffer.array();
return byteArray;
}
然后,您可以编写Python 3 代码来接收字节数组并将其转换为正确形状的numpy 数组:
byteArray = gateway.entry_point.getByteArray()
intArray = np.frombuffer(byteArray, dtype=np.int32)
intArray = intArray.reshape((iMax, jMax))