简单的ByteBuffer调用和使用MPI交换参数
程序设计:用ByteBuffer.allocateDirect() 接口分配两个等长的内存空间(addr1和addr2),在JNI中使用GetDirectBufferAddress接口获得两个内存空间的地址,通过MPI的MPI_Isend/MPI_Recv接口,将addr1中的数据传递到addr2中。整个MPI在单进程中执行。
ByteBuff.java
View Code
1 import java.nio.ByteBuffer; 2 3 public class ByteBuff { 4 5 static { 6 System.loadLibrary("buff"); 7 } 8 9 public native void printBuff(ByteBuffer sbf, ByteBuffer rbf); 10 11 public static void main(String[] args) { 12 ByteBuffer bf = ByteBuffer.allocateDirect(10); 13 ByteBuffer rbf = ByteBuffer.allocateDirect(10); 14 byte bbs[] = "abc".getBytes(); 15 bf.put(bbs); 16 System.out.println("Before swap " + (char) (rbf).get()); 17 (new ByteBuff()).printBuff(bf, rbf); 18 System.out.println("Before swap " + (char) (rbf).get()); 19 } 20 }
ByteBuff.c
View Code
1 #include "ByteBuff.h" 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <mpi.h> 5 6 JNIEXPORT void JNICALL Java_ByteBuff_printBuff (JNIEnv *env, jobject jobj, jobject sbuf,jobject rbuf) { 7 jbyte* sbufp=(*env)->GetDirectBufferAddress(env,sbuf); 8 jbyte* rbufp=(*env)->GetDirectBufferAddress(env,rbuf); 9 10 MPI_Request sreq,rreq; 11 MPI_Status sstatus,rstatus; 12 MPI_Init(NULL,NULL); 13 MPI_Isend(sbufp,3,MPI_BYTE,0,0,MPI_COMM_WORLD,&sreq); 14 MPI_Recv(rbufp,3,MPI_BYTE,0,0,MPI_COMM_WORLD,&rstatus); 15 MPI_Wait(&sreq,&sstatus); 16 MPI_Finalize(); 17 18 (*env)->ReleasePrimitiveArrayCritical(env,sbuf,sbufp,0); 19 (*env)->ReleasePrimitiveArrayCritical(env,rbuf,rbufp,0); 20 }
编译动态库的时候需要链接MPI的静态库(本文使用MVAPICH 1.8.x),编译命令为
gcc -std=c99 -shared -fPIC -I /usr/local/mvapich/include/ -I /usr/local/jdk1.6.0_30/include/ -I /usr/local/jdk1.6.0_30/include/linux/ -I /usr/local/ ByteBuff.c -o libbuff.so -lpthread /usr/local/mvapich/lib/libmpich.a /usr/local/mvapich/lib/libopa.a /usr/local/mvapich/lib/libmpl.a -lrt -lpthread /usr/local/mvapich/lib/libmpich.a /usr/local/mvapich/lib/libopa.a /usr/local/mvapich/lib/libmpl.a -lrt
执行结果
1 $ mpiexec -n 1 java -Djava.library.path=. ByteBuff 2 Before swap 3 Before swap b