diff options
author | oparviai <oparviai@f3a24b6a-cf45-0410-b55a-8c22e2698227> | 2015-05-15 13:22:36 +0300 |
---|---|---|
committer | oparviai <oparviai@f3a24b6a-cf45-0410-b55a-8c22e2698227> | 2015-05-15 13:22:36 +0300 |
commit | 7655c8ba36657be51509aa05a5b9b1a1ca245ebb (patch) | |
tree | 2e713898e6301a06694fb20f8e1e8329924ae823 | |
parent | 2816202b12d5eee8d29a1b31e924bb393a2e3bc3 (diff) |
- OpenMP parallel processing disabled by default; can be enabled in compile-time
- Android: Workaround for threading issue to enable OpenMP parallel processing in Android
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | source/Android-lib/.classpath | 4 | ||||
-rw-r--r-- | source/Android-lib/jni/Android.mk | 16 | ||||
-rw-r--r-- | source/Android-lib/jni/Application.mk | 3 | ||||
-rw-r--r-- | source/Android-lib/jni/soundtouch-jni.cpp | 62 | ||||
-rw-r--r-- | source/Android-lib/res/layout/activity_example.xml | 6 | ||||
-rw-r--r-- | source/Android-lib/src/net/surina/ExampleActivity.java | 19 |
7 files changed, 96 insertions, 18 deletions
diff --git a/configure.ac b/configure.ac index e399dc5..aaa4028 100644 --- a/configure.ac +++ b/configure.ac @@ -85,8 +85,8 @@ AC_ARG_ENABLE(integer-samples, AC_ARG_ENABLE(openmp, [AC_HELP_STRING([--enable-openmp], - [use parallel multicore calculation through OpenMP [default=yes]])],, - [enable_openmp=yes]) + [use parallel multicore calculation through OpenMP [default=no]])],, + [enable_openmp=no]) # Let the user enable/disable the x86 optimizations. # Useful when compiling on non-x86 architectures. diff --git a/source/Android-lib/.classpath b/source/Android-lib/.classpath index 7bc01d9..5176974 100644 --- a/source/Android-lib/.classpath +++ b/source/Android-lib/.classpath @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> - <classpathentry kind="src" path="src"/> - <classpathentry kind="src" path="gen"/> <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="gen"/> <classpathentry kind="output" path="bin/classes"/> </classpath> diff --git a/source/Android-lib/jni/Android.mk b/source/Android-lib/jni/Android.mk index ef5cfef..98fbbf7 100644 --- a/source/Android-lib/jni/Android.mk +++ b/source/Android-lib/jni/Android.mk @@ -36,10 +36,16 @@ LOCAL_SHARED_LIBRARIES += -lgcc LOCAL_LDLIBS += -llog # for native asset manager #LOCAL_LDLIBS += -landroid -# don't export all symbols -# -# in ARM-only environment could add "-marm" switch to force arm instruction set instead -# of thumb for improved calculation performance. -LOCAL_CFLAGS += -fvisibility=hidden -I ../../../include -fdata-sections -ffunction-sections + +# Custom Flags: +# -fvisibility=hidden : don't export all symbols +# -fopenmp : enable these flags to allow using OpenMP for parallel computation +LOCAL_CFLAGS += -fvisibility=hidden -I ../../../include -fdata-sections -ffunction-sections #-fopenmp + +#LOCAL_LDFLAGS += -fopenmp + + +# Use ARM instruction set instead of Thumb for improved calculation performance in ARM CPUs +LOCAL_ARM_MODE := arm include $(BUILD_SHARED_LIBRARY) diff --git a/source/Android-lib/jni/Application.mk b/source/Android-lib/jni/Application.mk index 68ef2d0..9875799 100644 --- a/source/Android-lib/jni/Application.mk +++ b/source/Android-lib/jni/Application.mk @@ -6,4 +6,5 @@ APP_ABI := all #armeabi-v7a armeabi APP_OPTIM := release APP_STL := stlport_static -APP_CPPFLAGS := -fexceptions
\ No newline at end of file +APP_CPPFLAGS := -fexceptions # -D SOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS + diff --git a/source/Android-lib/jni/soundtouch-jni.cpp b/source/Android-lib/jni/soundtouch-jni.cpp index 15fb446..7922bb3 100644 --- a/source/Android-lib/jni/soundtouch-jni.cpp +++ b/source/Android-lib/jni/soundtouch-jni.cpp @@ -46,6 +46,54 @@ static void _setErrmsg(const char *msg) }
+#ifdef _OPENMP
+
+#include <pthread.h>
+extern pthread_key_t gomp_tls_key;
+static void * _p_gomp_tls = NULL;
+
+/// Function to initialize threading for OpenMP.
+///
+/// This is a workaround for bug in Android NDK v10 regarding OpenMP: OpenMP works only if
+/// called from the Android App main thread because in the main thread the gomp_tls storage is
+/// properly set, however, Android does not properly initialize gomp_tls storage for other threads.
+/// Thus if OpenMP routines are invoked from some other thread than the main thread,
+/// the OpenMP routine will crash the application due to NULL pointer access on uninitialized storage.
+///
+/// This workaround stores the gomp_tls storage from main thread, and copies to other threads.
+/// In order this to work, the Application main thread needws to call at least "getVersionString"
+/// routine.
+static int _init_threading(bool warn)
+{
+ void *ptr = pthread_getspecific(gomp_tls_key);
+ LOGV("JNI thread-specific TLS storage %ld", (long)ptr);
+ if (ptr == NULL)
+ {
+ LOGV("JNI set missing TLS storage to %ld", (long)_p_gomp_tls);
+ pthread_setspecific(gomp_tls_key, _p_gomp_tls);
+ }
+ else
+ {
+ LOGV("JNI store this TLS storage");
+ _p_gomp_tls = ptr;
+ }
+ // Where critical, show warning if storage still not properly initialized
+ if ((warn) && (_p_gomp_tls == NULL))
+ {
+ _setErrmsg("Error - OpenMP threading not properly initialized: Call SoundTouch.getVersionString() from the App main thread!");
+ return -1;
+ }
+ return 0;
+}
+
+#else
+static int _init_threading(bool warn)
+{
+ // do nothing if not OpenMP build
+ return 0;
+}
+#endif
+
// Processes the sound file
static void _processFile(SoundTouch *pSoundTouch, const char *inFileName, const char *outFileName)
@@ -118,6 +166,17 @@ extern "C" DLL_PUBLIC jstring Java_net_surina_soundtouch_SoundTouch_getVersionSt // Call example SoundTouch routine
verStr = SoundTouch::getVersionString();
+ /// gomp_tls storage bug workaround - see comments in _init_threading() function!
+ _init_threading(false);
+
+ int threads = 0;
+ #pragma omp parallel
+ {
+ #pragma omp atomic
+ threads ++;
+ }
+ LOGV("JNI thread count %d", threads);
+
// return version as string
return env->NewStringUTF(verStr);
}
@@ -176,6 +235,9 @@ extern "C" DLL_PUBLIC int Java_net_surina_soundtouch_SoundTouch_processFile(JNIE LOGV("JNI process file %s", inputFile);
+ /// gomp_tls storage bug workaround - see comments in _init_threading() function!
+ if (_init_threading(true)) return -1;
+
try
{
_processFile(ptr, inputFile, outputFile);
diff --git a/source/Android-lib/res/layout/activity_example.xml b/source/Android-lib/res/layout/activity_example.xml index b333511..c71c77d 100644 --- a/source/Android-lib/res/layout/activity_example.xml +++ b/source/Android-lib/res/layout/activity_example.xml @@ -25,7 +25,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="5" - android:inputType="numberDecimal" + android:inputType="text" android:text="100" > </EditText> </TableRow> @@ -46,8 +46,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="5" - android:inputType="numberSigned" - android:text="0" > + android:inputType="text" + android:text="-0.318" > </EditText> </TableRow> </TableLayout> diff --git a/source/Android-lib/src/net/surina/ExampleActivity.java b/source/Android-lib/src/net/surina/ExampleActivity.java index 465cb9d..1aae8d8 100644 --- a/source/Android-lib/src/net/surina/ExampleActivity.java +++ b/source/Android-lib/src/net/surina/ExampleActivity.java @@ -146,11 +146,10 @@ public class ExampleActivity extends Activity implements OnClickListener } - /// Processing routine - @Override - protected Long doInBackground(Parameters... aparams) + + /// Function that does the SoundTouch processing + public final long doSoundTouchProcessing(Parameters params) { - Parameters params = aparams[0]; SoundTouch st = new SoundTouch(); st.setTempo(params.tempo); @@ -177,6 +176,15 @@ public class ExampleActivity extends Activity implements OnClickListener } return 0L; } + + + + /// Overloaded function that get called by the system to perform the background processing + @Override + protected Long doInBackground(Parameters... aparams) + { + return doSoundTouchProcessing(aparams[0]); + } } @@ -202,8 +210,9 @@ public class ExampleActivity extends Activity implements OnClickListener Toast.makeText(this, "Starting to process file " + params.inFileName + "...", Toast.LENGTH_SHORT).show(); - // start processing task in background + // start SoundTouch processing in a background thread task.execute(params); +// task.doSoundTouchProcessing(params); // this would run processing in main thread } catch (Exception exp) |