Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make ADOL-C thread-save #36

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 65 additions & 11 deletions ADOL-C/src/tape_handling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <adolc/revolve.h>
#include <adolc/adalloc.h>

#include <mutex>

#ifdef ADOLC_MEDIPACK_SUPPORT
#include "medipacksupport_p.h"
#endif
Expand Down Expand Up @@ -341,10 +343,21 @@ vector<TapeInfos *> ADOLC_TAPE_INFOS_BUFFER_DECL;
stack<TapeInfos *> 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)
Expand Down Expand Up @@ -419,6 +432,10 @@ int initNewTape(short tapeID) {
ADOLC_OPENMP_THREAD_NUMBER;
ADOLC_OPENMP_GET_THREAD_NUMBER;

#if !defined(_OPENMP)
std::lock_guard<std::mutex> tape_lock(tape_mutex);
#endif

/* check if tape is in use */
vector<TapeInfos *>::iterator tiIter;
if (!ADOLC_TAPE_INFOS_BUFFER.empty()) {
Expand Down Expand Up @@ -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<std::mutex> tape_lock(tape_mutex);
#endif

/* check if tape information exist in memory */
vector<TapeInfos *>::iterator tiIter;
if (!ADOLC_TAPE_INFOS_BUFFER.empty()) {
Expand Down Expand Up @@ -617,6 +638,10 @@ void releaseTape() {
ADOLC_CURRENT_TAPE_INFOS.inUse = 0;
}

#if !defined(_OPENMP)
std::lock_guard<std::mutex> tape_lock(tape_mutex);
#endif

ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr->copy(
ADOLC_CURRENT_TAPE_INFOS);
ADOLC_GLOBAL_TAPE_VARS.currentTapeInfosPtr = ADOLC_TAPE_STACK.top();
Expand All @@ -636,6 +661,10 @@ TapeInfos *getTapeInfos(short tapeID) {
ADOLC_OPENMP_THREAD_NUMBER;
ADOLC_OPENMP_GET_THREAD_NUMBER;

#if !defined(_OPENMP)
std::lock_guard<std::mutex> tape_lock(tape_mutex);
#endif

/* check if TapeInfos for tapeID exist */
if (!ADOLC_TAPE_INFOS_BUFFER.empty()) {
for (tiIter=ADOLC_TAPE_INFOS_BUFFER.begin();
Expand Down Expand Up @@ -680,6 +709,10 @@ void cachedTraceTags(std::vector<short>& result) {
ADOLC_OPENMP_THREAD_NUMBER;
ADOLC_OPENMP_GET_THREAD_NUMBER;

#if !defined(_OPENMP)
std::lock_guard<std::mutex> 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();
Expand All @@ -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<std::mutex> tape_lock(tape_mutex);
#endif

/* check if TapeInfos for tapeID exist */
if (!ADOLC_TAPE_INFOS_BUFFER.empty()) {
for (tiIter=ADOLC_TAPE_INFOS_BUFFER.begin();
Expand Down Expand Up @@ -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<std::mutex> tape_lock(tape_mutex);
#endif

/* check if TapeInfos for tapeID exist */
if (!ADOLC_TAPE_INFOS_BUFFER.empty()) {
for (tiIter=ADOLC_TAPE_INFOS_BUFFER.begin();
Expand Down Expand Up @@ -830,6 +871,10 @@ void cleanUp() {
ADOLC_OPENMP_THREAD_NUMBER;
ADOLC_OPENMP_GET_THREAD_NUMBER;

#if !defined(_OPENMP)
std::lock_guard<std::mutex> tape_lock(tape_mutex);
#endif

TapeInfos** tiIter;
clearCurrentTape();
while (!ADOLC_TAPE_INFOS_BUFFER.empty()) {
Expand Down Expand Up @@ -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<std::mutex> 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);
Expand Down
14 changes: 10 additions & 4 deletions ADOL-C/src/taping_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

#ifdef __cplusplus
#include "storemanager.h"
#else
#include <threads.h>
#endif
#include <adolc/internal/common.h>
#include <adolc/taping.h>
Expand Down Expand Up @@ -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
Expand All @@ -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 */
/****************************************************************************/
Expand Down
9 changes: 7 additions & 2 deletions ADOL-C/test/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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@
Expand All @@ -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

96 changes: 96 additions & 0 deletions ADOL-C/test/parallel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include <adolc/adouble.h> // use of active doubles
#include <adolc/drivers/drivers.h> // use of "Easy to Use" drivers
// gradient(.) and hessian(.)
#include <adolc/taping.h> // use of taping

#include <iostream>
using namespace std;

#include <cstdlib>
#include <thread>

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<std::thread> 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;
}