从 java 运行本机 MPI 代码

Posted

技术标签:

【中文标题】从 java 运行本机 MPI 代码【英文标题】:Running Native MPI code from java 【发布时间】:2015-09-27 19:12:08 【问题描述】:

我正在尝试从 java 运行一个简单的本机 mpi 代码,稍后我的项目需要它。我正在使用 Ubuntu。 我有:

HelloJNI.java

public class HelloJNI 
 static 
   System.loadLibrary("hello");
 

 private native void sayHello();

 public static void main(String[] args) 
   new HelloJNI().sayHello();  // invoke the native method
 

头文件:

 JNIEXPORT void JNICALL Java_HelloJNI_sayHello (JNIEnv *, jobject);

C 源文件:

JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject     thisObj) 
printf("Hello World- MPI from C!\n");
MPI_Init(NULL, NULL);
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
char processor_name[MPI_MAX_PROCESSOR_NAME];
int name_len;
MPI_Get_processor_name(processor_name, &name_len);
printf("Hello world from processor %s, rank %d"
      " out of %d processors\n",
      processor_name, world_rank, world_size);
MPI_Finalize();

我已按照本教程进行操作: https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html

我可以通过 make 文件创建共享库:

INCLUDE1 = /usr/lib/java/jdk1.8.0_45/include
INCLUDE2 = /usr/lib/java/jdk1.8.0_45/include/linux
MPI_INCLUDE = /home/openmpi-1.8.5/ompi/include
JAVAHPATH = /usr/lib/java/jdk1.8.0_45/bin
MPICC = /home/openmpi-1.8.5/bin/mpicc
# Define a variable for classpath
CLASS_PATH = ../bin

# Define a virtual path for .class in the bin directory
vpath %.class $(CLASS_PATH)

all : libhello.so

# $@ matches the target, $< matches the first dependancy
libhello.so : HelloJNI.o
$MPICC $< -L/home/openmpi-1.8.5/lib -lmpi -shared -fpic -o $@ -Wl,-   rpath=/home/openmpi-1.8.5/lib 

# $@ matches the target, $< matches the first dependancy
HelloJNI.o : HelloJNI.c HelloJNI.h
$MPICC -fpic -I$(INCLUDE1) -I$(INCLUDE2) -I$(MPI_INCLUDE) -c $< -o $@

# $* matches the target filename without the extension
HelloJNI.h : HelloJNI.class     
    $(JAVAHPATH)/javah -classpath $(CLASS_PATH) $*


clean :
      rm HelloJNI.h HelloJNI.o libhello.so

问题是当我尝试运行它时,我遇到了这些 MPI 错误:

"mca: base: component_find: unable to open /home/openmpi-1.8.5/lib/openmpi/mca_shmem_sysv: /home/openmpi-1.8.5/lib/openmpi/mca_shmem_sysv.so: undefined symbol: opal_show_help (ignored)
mca: base: component_find: unable to open /home/openmpi-1.8.5/lib/openmpi/mca_shmem_mmap: /home/openmpi-1.8.5/lib/openmpi/mca_shmem_mmap.so: undefined symbol: opal_show_help (ignored)
mca: base: component_find: unable to open /home/openmpi-1.8.5/lib/openmpi/mca_shmem_posix: /home/openmpi-1.8.5/lib/openmpi/mca_shmem_posix.so: undefined symbol: opal_shmem_base_framework (ignored)
It looks like opal_init failed .....orte_init failed ..... mpi_init  failed"

到目前为止,我已经从命令行和使用 eclipse 尝试了各种方法,它们是: 使用 Eclipse:

在运行配置的 VM Argument 中通过 -Djava.library.path 添加了共享库路径 也可以通过 LD_LIBRARY_PATH 与 Environment 和 bashrc 一样 在 makefile 中我尝试使用 mpicc 编译共享库 我也已将 mpi.jar 添加到项目中

使用命令行:

javac -cp /home/s3050004/Downloads/openmpi-1.8.5/lib/mpi.jar HelloJNI.java java -Djava.library.path=/home/workspace/HelloJNI/jni:/home/openmpi-1.8.5/lib -cp /home/openmpi-1.8.5/lib/mpi.jar:/home/工作区/HelloJNI/src HelloJNI

在命令行中,我尝试执行与 eclipse 中相同的操作,即指定共享库的路径,mpi lib 也指定 mpi.jar 并尝试运行 HelloJNI,但我得到了相同的错误。我不确定为什么会收到这些错误,我想了解为什么会收到这些错误。我将非常感谢对此提出的任何建议或想法。

【问题讨论】:

【参考方案1】:

已修复,OpenMPI 有问题,我已重新安装并重新配置它并且它工作正常:

--enable-shared --enable-static 

【讨论】:

【参考方案2】:

看起来 java 未能加载 libhello.so 的所有依赖项

请检查 ldd 是否可以加载依赖项:

ldd libhello.so

如果没有,

    为 openmpi 库创建符号链接

    ldconfig -n 带有 openmpi .so 文件的文件夹

    将该路径添加到 LD_LIBRARY_PATH

    再试一次ldd libhello.so

一旦它开始被 ldd 加载,它就会从 java 中工作。

【讨论】:

感谢康斯坦丁的回复, 我已修复,OpenMPI 有问题,我已重新安装并重新配置: --enable-shared --enable-static

以上是关于从 java 运行本机 MPI 代码的主要内容,如果未能解决你的问题,请参考以下文章

OpenMPI:包 mpi 不存在

在 Intellij IDEA 中运行的 MPJ Express (Java MPI)

OpenMPI MPI_Send 与英特尔 MPI MPI_Send

java和native代码之间有啥方法可以实现并发吗?本机代码作为进程/线程运行

如何使用 MPI 和 OpenMP 运行并行循环

MPI_Init() 需要很长时间才能运行