通过MPI发送java对象

时间:2015-03-05 07:42:31

标签: java performance data-structures mpi

我的故事

我开始在mpiJava编写一个mpi程序并设法编写一个工作程序,但由于其中一个或另一个原因它不想在平台上运行我需要它运行(I没有任何权限安装任何东西)。我不确定是否有必要(考虑到我现在遇到同样的问题),但我开始使用open-mpi和它的java绑定。关键是在平台上,open-mpi可用,因此我认为它会自动运行。它没有工作,我仍然试图找出原因(它可能与信用系统有关),但这不是我希望在这里解决的问题

我的问题

真正的问题是我需要通过MPI发送java对象,我不知道如何以正确的方式执行它。在mpiJava我有优势,有一个MPI.Object数据类型可用(它只是序列化对象),但open-mpi没有这样的东西。我已经访问了post on BigIntegerpost actually providing some answers,当然还有the open-mpi reference,但我现在还不完全确定在我的案例中哪种方法最好。

我想通过MPI发送3个不同的对象:

  1. 经典BigInteger
  2. 一个经典的Object[],里面有3个不同的对象
  3. 一个不太经典的自编类,包含对另一个自编类的引用
  4. 自编类看起来像这样:

    public class AC implements Iterable<BS>, Comparable<AC>, LE, Serializable {
    
        private static final long serialVersionUID = -530910801257060853L;
        private static AC emptyAC = new AC();
        private static AC emptySetAC = new AC();
        static {emptySetAC.theAC.set(0);}
    
        private BitSet theAC = new BitSet();
        private BS universe = BS.universe();
        ...
        //methods
    }
    
    public class BS implements Iterable<Integer>, Comparable<BS>, Serializable {
    
        private static final long serialVersionUID = 4240724082500295998L;
        private static BS theEmptySet = new BS();
        private static long[] bits;
    
        private long theSet;
        ...
        //methods
    }
    

    到目前为止发送的open-mpi代码(省略了我的列表中的&#39; BigInteger)看起来像:

    public static void main(String[] args) {
    
        ...
    
        //master code
    
        SortedMap<AC, Long> functions = new TreeMap<>();
        AC u = AC.oneSetAC(BS.universe(n));
        SortedMap<AC, BigInteger> leftIntervalSize = new TreeMap<>();
        MPI.COMM_WORLD.bcast(new Object[]{functions, leftIntervalSize, u}, 3, MPI.Object, 0);
    
        ...
    
        AC[] sendbuf = new AC[1];
        while(iterator.hasnext()) {
            MPI.COMM_WORLD.send(sendbuf, 1, MPI.OBJECT, i, 0);
        }
    
        ...
    
        //worker code
        Object[] buf = new Object[3];
        MPI.COMM_WORLD.bcast(buf, 3, MPI.OBJECT, 0);
    
        ...
    
        AC[] func = new AC[1];
        Status stat = MPI.COMM_WORLD.recv(func, 1, MPI.OBJECT, 0, MPI.ANY_TAG);
    
        ...
    }
    

    请注意,MPI.Object只是我的mpiJava实现的继承,这些是我需要正确更改的行。

    提议的解决方案

    我已经对它有了一些想法,我认为如果有人能给我一个如何正确使用MPI结构的例子,我可以使用the post actually providing some answersBigInteger的答案。 (我真的不完全从the open-mpi reference了解它。对于我自己的课程和另一方面Object[],我可以做以下任何一种情况:

    1. 只是序列化血腥物体。
    2. 使用MPI结构(在我使用它之后)。
    3. 对所需的字节数进行赌博并将其作为字节发送。 (如果这样做会让我感到惊讶)。
    4. 使用我即将听到的其他一些功能。
    5. 我的问题

      1. 有人能举例说明如何在java中使用MPI结构吗? (也许适用于我的一个例子?)
      2. 任何人都可以告诉我在任何情况下的优选策略(在序列化的情况下,指出陷阱)?
      3. 我很抱歉这篇长篇文章,但我希望从第一次开始就明白。

        提前致谢

2 个答案:

答案 0 :(得分:1)

如果您控制通信的两个方面,并且两者都在Java 中,您不太关心性能,那么您可以执行以下操作:

MyClass someObject = ...
serialized = ""
try {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(someObject);
    oos.flush();
    serialized = baos.toString();
} 
catch (Exception e) {
    System.out.println(e);    
}
char [] message = serialized.toCharArray() ;
MPI.COMM_WORLD.Send(message, 0, message.length, MPI.CHAR, 1, 99) ;

另一方面,您只是接收并基本上反向执行相同的步骤以反序列化。

try {
    byte b[] = serializedObject.getBytes(); 
    ByteArrayInputStream bis = new ByteArrayInputStream(b);
    ObjectInputStream ois = new ObjectInputStream(bis);
    MyClass obj = (MyClass) ois.readObject();
} catch (Exception e) {
    System.out.println(e);
}

这种方法的优点是简单,让你快速前进。如果您不打算发送很多物品,我认为这是完全可以接受的。

答案 1 :(得分:1)

最后,我决定使用sdotdi的答案序列化Object[]。因为广播只发生过一次,所以这不应该太糟糕 对于BigInteger,我使用toByteArray()方法并首先发送数组的长度,然后发送字节数组本身。我怀疑它几乎与使用MPI结构一样快,但我不太确定。因此代码如下:

byte[] bigintbuf = result.toByteArray();
MPI.COMM_WORLD.send(new int[]{bigintbuf.length}, 1, MPI.INT, 0, NUMTAG);
MPI.COMM_WORLD.send(bigintbuf, bigintbuf.length, MPI.BYTE, 0, 0);

对于AC类,我通过实现toLongArray()方法应用了类似的技巧,因此代码变为:

long[] acbuf = next.toLongArray();
MPI.COMM_WORLD.send(new int[]{acbuf.length}, 1, MPI.INT, i, NUMTAG);
MPI.COMM_WORLD.send(acbuf, acbuf.length, MPI.LONG, i, 0);

这可能仍然不是最佳方式,但我认为它会达到最佳性能。