diff --git a/ADOL-C/src/tape_handling.cpp b/ADOL-C/src/tape_handling.cpp index 4dd8a39ad..b907601ee 100644 --- a/ADOL-C/src/tape_handling.cpp +++ b/ADOL-C/src/tape_handling.cpp @@ -18,6 +18,8 @@ #include #include +#include + #ifdef ADOLC_MEDIPACK_SUPPORT #include "medipacksupport_p.h" #endif @@ -341,10 +343,21 @@ vector ADOLC_TAPE_INFOS_BUFFER_DECL; stack ADOLC_TAPE_STACK_DECL; /* the main tape info buffer and its fallback */ +#if defined(_OPENMP) + TapeInfos ADOLC_CURRENT_TAPE_INFOS_DECL; TapeInfos ADOLC_CURRENT_TAPE_INFOS_FALLBACK_DECL; -/* global taping variables */ +#else + +std::mutex tape_mutex; + +thread_local TapeInfos ADOLC_CURRENT_TAPE_INFOS_DECL; +thread_local TapeInfos ADOLC_CURRENT_TAPE_INFOS_FALLBACK_DECL; + +#endif + +/* global tapeing variables */ GlobalTapeVars ADOLC_GLOBAL_TAPE_VARS_DECL; #if defined(_OPENMP) @@ -419,6 +432,10 @@ int initNewTape(short tapeID) { ADOLC_OPENMP_THREAD_NUMBER; ADOLC_OPENMP_GET_THREAD_NUMBER; +#if !defined(_OPENMP) + std::lock_guard tape_lock(tape_mutex); +#endif + /* check if tape is in use */ vector::iterator tiIter; if (!ADOLC_TAPE_INFOS_BUFFER.empty()) { @@ -537,6 +554,10 @@ void openTape(short tapeID, char mode) { ADOLC_OPENMP_THREAD_NUMBER; ADOLC_OPENMP_GET_THREAD_NUMBER; +#if !defined(_OPENMP) + std::lock_guard tape_lock(tape_mutex); +#endif + /* check if tape information exist in memory */ vector::iterator tiIter; if (!ADOLC_TAPE_INFOS_BUFFER.empty()) { @@ -617,6 +638,10 @@ void releaseTape() { ADOLC_CURRENT_TAPE_INFOS.inUse = 0; } +#if !defined(_OPENMP) + std::lock_guard tape_lock(tape_mutex); +#endif + ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr->copy( ADOLC_CURRENT_TAPE_INFOS); ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr = ADOLC_TAPE_STACK.top(); @@ -636,6 +661,10 @@ TapeInfos *getTapeInfos(short tapeID) { ADOLC_OPENMP_THREAD_NUMBER; ADOLC_OPENMP_GET_THREAD_NUMBER; +#if !defined(_OPENMP) + std::lock_guard tape_lock(tape_mutex); +#endif + /* check if TapeInfos for tapeID exist */ if (!ADOLC_TAPE_INFOS_BUFFER.empty()) { for (tiIter=ADOLC_TAPE_INFOS_BUFFER.begin(); @@ -680,6 +709,10 @@ void cachedTraceTags(std::vector& result) { ADOLC_OPENMP_THREAD_NUMBER; ADOLC_OPENMP_GET_THREAD_NUMBER; +#if !defined(_OPENMP) + std::lock_guard tape_lock(tape_mutex); +#endif + result.resize(ADOLC_TAPE_INFOS_BUFFER.size()); if (!ADOLC_TAPE_INFOS_BUFFER.empty()) { for(tiIter=ADOLC_TAPE_INFOS_BUFFER.begin(), tIdIter=result.begin(); @@ -699,6 +732,10 @@ void setTapeInfoJacSparse(short tapeID, SparseJacInfos sJinfos) { ADOLC_OPENMP_THREAD_NUMBER; ADOLC_OPENMP_GET_THREAD_NUMBER; +#if !defined(_OPENMP) + std::lock_guard tape_lock(tape_mutex); +#endif + /* check if TapeInfos for tapeID exist */ if (!ADOLC_TAPE_INFOS_BUFFER.empty()) { for (tiIter=ADOLC_TAPE_INFOS_BUFFER.begin(); @@ -740,6 +777,10 @@ void setTapeInfoHessSparse(short tapeID, SparseHessInfos sHinfos) { ADOLC_OPENMP_THREAD_NUMBER; ADOLC_OPENMP_GET_THREAD_NUMBER; +#if !defined(_OPENMP) + std::lock_guard tape_lock(tape_mutex); +#endif + /* check if TapeInfos for tapeID exist */ if (!ADOLC_TAPE_INFOS_BUFFER.empty()) { for (tiIter=ADOLC_TAPE_INFOS_BUFFER.begin(); @@ -830,6 +871,10 @@ void cleanUp() { ADOLC_OPENMP_THREAD_NUMBER; ADOLC_OPENMP_GET_THREAD_NUMBER; +#if !defined(_OPENMP) + std::lock_guard tape_lock(tape_mutex); +#endif + TapeInfos** tiIter; clearCurrentTape(); while (!ADOLC_TAPE_INFOS_BUFFER.empty()) { @@ -981,20 +1026,29 @@ int removeTape(short tapeID, short type) { ADOLC_OPENMP_THREAD_NUMBER; ADOLC_OPENMP_GET_THREAD_NUMBER; - /* check if TapeInfos for tapeID exist */ - if (!ADOLC_TAPE_INFOS_BUFFER.empty()) { +#if !defined(_OPENMP) + { + std::lock_guard tape_lock(tape_mutex); +#endif + + /* check if TapeInfos for tapeID exist */ + if (!ADOLC_TAPE_INFOS_BUFFER.empty()) { for (tiIter = ADOLC_TAPE_INFOS_BUFFER.begin(); - tiIter != ADOLC_TAPE_INFOS_BUFFER.end(); - ++tiIter) + tiIter != ADOLC_TAPE_INFOS_BUFFER.end(); + ++tiIter) { - if ((*tiIter)->tapeID == tapeID) { - tapeInfos = *tiIter; - if (tapeInfos->tapingComplete == 0) return -1; - ADOLC_TAPE_INFOS_BUFFER.erase(tiIter); - break; - } + if ((*tiIter)->tapeID == tapeID) { + tapeInfos = *tiIter; + if (tapeInfos->tapingComplete == 0) return -1; + ADOLC_TAPE_INFOS_BUFFER.erase(tiIter); + break; + } } + } + +#if !defined(_OPENMP) } +#endif if (tapeInfos == NULL) { // might be on disk only tapeInfos = new TapeInfos(tapeID); diff --git a/ADOL-C/src/taping_p.h b/ADOL-C/src/taping_p.h index ada95ccc4..47a432427 100644 --- a/ADOL-C/src/taping_p.h +++ b/ADOL-C/src/taping_p.h @@ -16,6 +16,8 @@ #ifdef __cplusplus #include "storemanager.h" +#else +#include #endif #include #include @@ -378,6 +380,10 @@ extern int isParallel(); #define ADOLC_CHECKPOINTS_STACK ADOLC_checkpointsStack[ADOLC_threadNumber] #define REVOLVE_NUMBERS revolve_numbers[ADOLC_threadNumber] +extern TapeInfos ADOLC_CURRENT_TAPE_INFOS_DECL; +extern TapeInfos ADOLC_CURRENT_TAPE_INFOS_FALLBACK_DECL; +extern GlobalTapeVars ADOLC_GLOBAL_TAPE_VARS_DECL; + #else #define ADOLC_TAPE_INFOS_BUFFER_DECL tapeInfosBuffer @@ -401,12 +407,12 @@ extern int isParallel(); #define ADOLC_CHECKPOINTS_STACK ADOLC_checkpointsStack #define REVOLVE_NUMBERS revolve_numbers -#endif /* _OPENMP */ - -extern TapeInfos ADOLC_CURRENT_TAPE_INFOS_DECL; -extern TapeInfos ADOLC_CURRENT_TAPE_INFOS_FALLBACK_DECL; +extern thread_local TapeInfos ADOLC_CURRENT_TAPE_INFOS_DECL; +extern thread_local TapeInfos ADOLC_CURRENT_TAPE_INFOS_FALLBACK_DECL; extern GlobalTapeVars ADOLC_GLOBAL_TAPE_VARS_DECL; +#endif /* _OPENMP */ + /****************************************************************************/ /* C Function interfaces */ /****************************************************************************/ diff --git a/ADOL-C/test/Makefile.am b/ADOL-C/test/Makefile.am index 43d40a88d..1b02a1f61 100644 --- a/ADOL-C/test/Makefile.am +++ b/ADOL-C/test/Makefile.am @@ -10,17 +10,22 @@ ## ############################################################################## -noinst_PROGRAMS = powexam speelpenning fminmax +noinst_PROGRAMS = powexam speelpenning fminmax parallel speelpenning_SOURCES = speelpenning.cpp powexam_SOURCES = powexam.cpp +parallel_SOURCES = parallel.cpp + fminmax_SOURCES = fminmax.cpp powexam_LDADD = ../lib${adolclib}.la speelpenning_LDADD = ../lib${adolclib}.la fminmax_LDADD = ../lib${adolclib}.la +parallel_LDADD = ../lib${adolclib}.la + +parallel_CXXFLAGS = -pthread AM_CFLAGS = @ac_adolc_cflags@ AM_CXXFLAGS = @ac_adolc_cxxflags@ @@ -35,7 +40,7 @@ EXTRA_DIST = run_tests # on Cygwin DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/inc -test: powexam speelpenning +test: powexam speelpenning parallel chmod u+x $(srcdir)/run_tests $(srcdir)/run_tests diff --git a/ADOL-C/test/parallel.cpp b/ADOL-C/test/parallel.cpp new file mode 100644 index 000000000..b384b0d19 --- /dev/null +++ b/ADOL-C/test/parallel.cpp @@ -0,0 +1,96 @@ +#include // use of active doubles +#include // use of "Easy to Use" drivers +// gradient(.) and hessian(.) +#include // use of taping + +#include +using namespace std; + +#include +#include + +void derive(const short my_tape, double init) +{ + const int n = 100; + + double *xp = new double[n]; + double yp = 0.0; + adouble *x = new adouble[n]; + adouble y = 1; + + for(int i = 0; i < n; i++) + { + xp[i] = (i + init)/(2. + i); // some initialization + } + + trace_on(my_tape); + + for(int i = 0; i < n; i++) { + x[i] <<= xp[i]; + y *= x[i]; + } + + y >>= yp; + + delete[] x; + + trace_off(); + + double* g = new double[n]; + + gradient(my_tape, n, xp, g); + + double** H = new double*[n]; + + for(int i = 0; i < n; i++) + { + H[i] = (double*) new double[i + 1]; + } + + hessian(my_tape, n, xp, H); + + double errh = 0.; + + for(int i = 0; i < n; i++) + { + for(int j = 0; j < n; j++) + { + if (i>j) + { + errh += fabs(H[i][j] - g[i]/xp[j]); + } + } // end for + } // end for + + std::cout << "Computed Hessian in tape " << my_tape + << ", error = " + << errh + << std::endl; + + for(int i = 0; i < n; ++i) + { + delete[] H[i]; + } + + delete[] H; + delete[] g; +} + + +int main() +{ + std::vector threads; + + for(int i = 1; i <= 10; ++i) + { + threads.push_back(std::thread(derive, i, (double) i)); + } + + for(auto& thread: threads) + { + thread.join(); + } + + return 0; +} +