2016-07-25 4 views
1

Я пытаюсь получить доступ к встроенной (fortran) библиотеке (mylib.so), загруженной JNA. Доступ к библиотеке осуществляется в параллале с помощью Spark-Job. До сих пор я не синхронизировал вызовы методов (или библиотеки), поскольку вызов общей библиотеки является узким местом в моих вычислениях, и они должны выполняться параллельно.Проблемы параллелизма JNA

Я получаю следующую ошибку:

# A fatal error has been detected by the Java Runtime Environment: 
# 
# SIGSEGV (0xb) at pc=0x00007ffbcb5f8dcd, pid=58569, tid=140708155152128 
# 
# JRE version: Java(TM) SE Runtime Environment (8.0_60-b27) (build 1.8.0_60-b27) 
*** Error in `/usr/java/jdk1.8.0_60/jre/bin/java': double free or corruption (!prev): 0x0000000001b756d0 *** 
*** Error in `/usr/java/jdk1.8.0_60/jre/bin/java': free(): corrupted unsorted chunks: 0x0000000001b75010 *** 
*** Error in `/usr/java/jdk1.8.0_60/jre/bin/java': double free or corruption (!prev): 0x0000000001b756d0 *** 
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.60-b23 mixed mode linux-amd64 compressed oops) 
# Problematic frame: 
# C [libc.so.6+0x38dcd]======= Backtrace: ========= 
======= Backtrace: ========= 
======= Backtrace: ========= 
/lib64/libc.so.6(+0x7d053)[0x7ffbcb63d053] 
/lib64/libc.so.6(+0x7d053)[0x7ffbcb63d053] 
/lib64/libc.so.6(+0x7d053)[0x7ffbcb63d053] 
/lib64/libc.so.6(+0x38e90)[0x7ffbcb5f8e90] 
/usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so(+0x5d43f9)[0x7ffbcabba3f9] 
/lib64/libc.so.6(+0x38e90)[0x7ffbcb5f8e90] 
/lib64/libc.so.6(+0x38eb5)[0x7ffbcb5f8eb5] 
/lib64/libc.so.6(+0x38e69)[0x7ffbcb5f8e69] 
/lib64/libc.so.6(+0x38eb5)[0x7ffbcb5f8eb5] 
    __run_exit_handlers+0x3d 
# 
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again 
# 
/opt/usr/local/lib/mylib.so(for_exit+0x19)[0x7ff9285b0fa9] 
/lib64/libc.so.6(+0x38eb5)[0x7ffbcb5f8eb5] 
/opt/usr/local/lib/mylib.so(for_exit+0x19)[0x7ff9285b0fa9] 
/opt/usr/local/lib/mylib.so(for__once_private+0x27)[0x7ff9285660b7] 
/opt/usr/local/lib/mylib.so(for__once_private+0x27)[0x7ff9285660b7] 
/opt/usr/local/lib/mylib.so(for__acquire_lun+0x814)[0x7ff92855ea04] 
/opt/usr/local/lib/mylib.so(for__acquire_lun+0x814)[0x7ff92855ea04] 
/opt/usr/local/lib/mylib.so(for_write_int_fmt+0x9c)[0x7ff92857f83c] 
/opt/usr/local/lib/mylib.so(for__acquire_lun+0x814)[0x7ff92855ea04] 
/opt/usr/local/lib/mylib.so(for_write_int_fmt+0x9c)[0x7ff92857f83c] 
/opt/usr/local/lib/mylib.so(seterr_+0x1c8)[0x7ff928515328] 
/opt/usr/local/lib/mylib.so(for_write_int_fmt+0x9c)[0x7ff92857f83c] 
/opt/usr/local/lib/mylib.so(seterr_+0x1c8)[0x7ff928515328] 
/opt/usr/local/lib/mylib.so(ddl2sf_+0x322)[0x7ff92850eb02] 
/opt/usr/local/lib/mylib.so(seterr_+0x1c8)[0x7ff928515328] 
/opt/usr/local/lib/mylib.so(entsrc_+0x80)[0x7ff92850edb0] 
/opt/usr/local/lib/mylib.so(bspline_+0x52c)[0x7ff92850d66c] 
/opt/usr/local/lib/mylib.so(ddl2sf_+0x2e7)[0x7ff92850eac7] 
/opt/usr/local/lib/mylib.so(enter_+0x55)[0x7ff92850ecd5] 
/opt/usr/local/lib/mylib.so(rspbsp_+0x4a)[0x7ff928523cda] 
/opt/usr/local/lib/mylib.so(bspline_+0x52c)[0x7ff92850d66c] 
/opt/usr/local/lib/mylib.so(ddl2sf_+0x16d)[0x7ff92850e94d] 
/tmp/jna--1845237309/jna4302334124297214663.tmp(ffi_call_unix64+0x4c)[0x7ff92909465c] 
/tmp/jna--1845237309/jna4302334124297214663.tmp(ffi_call+0x1d4)[0x7ff929094164] 
/opt/usr/local/lib/mylib.so(bspline_+0x52c)[0x7ff92850d66c] 
/opt/usr/local/lib/mylib.so(rspbsp_+0x4a)[0x7ff928523cda] 
/tmp/jna--1845237309/jna4302334124297214663.tmp(+0x5870)[0x7ff929087870] 
/tmp/jna--1845237309/jna4302334124297214663.tmp(Java_com_sun_jna_Native_invokeVoid+0x22)[0x7ff92908a462] 
[0x7ffbb5015994] 

AFAIK это имеет к тому, что родная библиотека не поточно-? Из stacktracke мне кажется, что фактическая проблема libc.so, или это моя собственная библиотека mylib.so?

Случаем, что проблема в моей собственной библиотеке, можно ли решить эту проблему, сделав несколько физических копий общего объекта, например, для каждого потока?

+0

Вы _can_ создаете несколько копий своей библиотеки; каждый должен иметь уникальное изображение на диске (и, следовательно, уникальное имя). Это стоит попробовать только с двумя потоками. – technomage

+0

, хотя это правда, я бы вообще не считал его жизнеспособным подходом - он действительно не масштабируется и довольно взломан. –

+0

@technomage Я действительно смущен сейчас. Я сделал несколько копий своей библиотеки с уникальными именами, оба загрузили их с использованием JNA в разных переменных. Изображение загружается дважды, но они все еще, похоже, разделяют память. То есть Я изменяю одну глобальную переменную в одной lib, она также принимает это значение во второй lib (с глобальным, я имею в виду, что они находятся в общем блоке). Этого можно ожидать? –

ответ

0

Это обычно указывает на проблему в вашей общей библиотеке или ее использование. Если вы не создали библиотеку для обеспечения безопасности потоков, то, скорее всего, нет. Один процесс не может загружать собственную библиотеку несколько раз, поэтому нет простого решения. Существует несколько способов:

  • Выделите несколько объектов из своей родной библиотеки и разных для каждой нити java. Это может быть невозможно, если ваша собственная библиотека внутренне использует статические структуры данных.
  • Синхронизируйте доступ к собственной библиотеке через классы/методы, которые ее раскрывают. Таким образом, только один поток Java может обращаться к ним за раз. Однако, в зависимости от вашей библиотеки и прецедента, это может не помочь производительности - все действия все равно могут быть в одном месте.
  • Сделайте библиотеку потокобезопасной. Это может быть намного сложнее на родных языках, чем на Java. Кроме того, некоторые алгоритмы плохо подходят для распараллеливания.
+0

Я уже делаю первый пункт. Второй момент, конечно, приводит к блокировкам, поэтому потоки больше не работают параллельно ... –

+0

JNA предоставляет оболочку 'Native.synchronizedLibrary()', которая эффективно реализует # 2. – technomage

+0

, если вы создаете несколько объектов из вашей общей библиотеки (вместо того, чтобы использовать один и тот же из нескольких потоков), то у вас действительно нет решения, которое можно распараллеливать. Если это так, я бы посмотрел на код fortran, чтобы проверить, может ли код с использованием статических общих данных быть реорганизован. если это невозможно, то вы застряли в подходах с несколькими копиями, предложенных technomage –

Смежные вопросы