Commit 0873ffe7 authored by W. David Dagenhart's avatar W. David Dagenhart
Browse files

Improve thread safety in the Random package

There are three different changes to static
and global variables. Where possible they are
made const. Variables used to generate default
seeds are made atomic so different threads will
get different seeds. Others are made thread local.
The only exceptions are ones in single thread
tests that are left as is. I also left the ones
in the classes that use rand and drand48 as is
because those classes are inherently thread unsafe
for other reasons.
parent 8299b82e
2014-03-04 W. David Dagenhart <wdd@fnal.gov>
* In Random package convert statics and globals to const, thread
local or atomic to improve thread safety.
2014-02-24 Lynn Garren <garren@fnal.gov>
......
......@@ -15,6 +15,9 @@
// extracted from the GNU C Library 2.0.1 and adapted for the native
// types.
// Copy constructor and operator= are private for objects of this class.
//
// WARNING: drand48 is not thread safe. If you need to use multiple
// engine objects on different threads concurrently, do not use DRand48Engine
// =======================================================================
// G.Cosmo - Created: 5th September 1995
......@@ -106,7 +109,7 @@ public:
private:
static int numEngines;
static int maxIndex;
static const int maxIndex;
};
......
......@@ -4,6 +4,7 @@
#include <string>
#include <vector>
#include <exception>
#include "CLHEP/Utility/thread_local.h"
namespace CLHEP {
......@@ -47,8 +48,8 @@ private:
double d;
};
static void fill_byte_order ();
static bool byte_order_known;
static int byte_order[8];
static CLHEP_THREAD_LOCAL bool byte_order_known;
static CLHEP_THREAD_LOCAL int byte_order[8];
// Meaning of byte_order: The first (high-order in IEEE 754) byte to
// output (or the high-order byte of the first unsigned long)
// is of db.b[byte_order[0]]. Thus the index INTO byte_order
......
......@@ -104,8 +104,6 @@ public:
private:
static int numEngines;
// This generator is composed of two others combined:
class Tausworthe {
......@@ -135,6 +133,7 @@ private:
unsigned int state, multiplier, addend;
}; // IntegerCong
int numEngines;
Tausworthe tausworthe;
IntegerCong integerCong;
......
......@@ -90,8 +90,6 @@ public:
static const unsigned int VECTOR_STATE_SIZE = 7;
private:
static int numEngines;
static int maxIndex;
void advance();
......
......@@ -89,8 +89,6 @@ public:
static const unsigned int VECTOR_STATE_SIZE = 11;
private:
static int numEngines;
static int maxIndex;
void advance();
......
......@@ -100,8 +100,6 @@ private:
double u[97];
double c, cd, cm;
int i97, j97;
static int numEngines;
static int maxIndex;
};
} // namespace CLHEP
......
......@@ -89,8 +89,6 @@ private:
int count624;
enum{ NminusM = 227, M = 397, N = 624};
static int numEngines;
static int maxIndex;
}; // MTwistEngine
......
......@@ -12,6 +12,9 @@
// library to implement the flat() basic distribution and for setting
// seeds.
// Copy constructor and operator= are private for objects of this class.
//
// WARNING: rand is not thread safe. If you need to use multiple
// engine objects on different threads concurrently, do not use RandEngine
// =======================================================================
// Gabriele Cosmo - Created: 5th September 1995
......@@ -113,7 +116,7 @@ private:
long seq;
static int numEngines;
static int maxIndex;
static const int maxIndex;
};
......
......@@ -25,6 +25,7 @@ for generating random variables", Journ. Statistical Software.
#include "CLHEP/Random/defs.h"
#include "CLHEP/Random/Random.h"
#include "CLHEP/Utility/thread_local.h"
namespace CLHEP {
......@@ -126,14 +127,15 @@ protected:
//#define RNOR (hz=SHR3, iz=hz&127, (fabs(hz)<kn[iz])? hz*wn[iz] : nfix())
//#define REXP (jz=SHR3, iz=jz&255, ( jz <ke[iz])? jz*we[iz] : efix())
static unsigned long kn[128], ke[256];
static float wn[128],fn[128], we[256],fe[256];
static CLHEP_THREAD_LOCAL unsigned long kn[128], ke[256];
static CLHEP_THREAD_LOCAL float wn[128],fn[128], we[256],fe[256];
static bool ziggurat_is_init;
static CLHEP_THREAD_LOCAL bool ziggurat_is_init;
static inline unsigned long ziggurat_SHR3(HepRandomEngine* anEngine) {return (unsigned int)(*anEngine);};
static inline float ziggurat_UNI(HepRandomEngine* anEngine) {return anEngine->flat();};
static inline float ziggurat_REXP(HepRandomEngine* anEngine) {
if(!ziggurat_is_init) ziggurat_init();
unsigned long jz=ziggurat_SHR3(anEngine);
unsigned long iz=jz&255;
return (jz<ke[iz]) ? jz*we[iz] : ziggurat_efix(jz,anEngine);
......@@ -161,12 +163,10 @@ namespace CLHEP {
inline RandExpZiggurat::RandExpZiggurat(HepRandomEngine & anEngine, double mean ) : localEngine(&anEngine), deleteEngine(false), defaultMean(mean)
{
if(!ziggurat_is_init) ziggurat_init();
}
inline RandExpZiggurat::RandExpZiggurat(HepRandomEngine * anEngine, double mean ) : localEngine(anEngine), deleteEngine(true), defaultMean(mean)
{
if(!ziggurat_is_init) ziggurat_init();
}
} // namespace CLHEP
......
......@@ -32,6 +32,7 @@
#include "CLHEP/Random/defs.h"
#include "CLHEP/Random/Random.h"
#include "CLHEP/Utility/memory.h"
#include "CLHEP/Utility/thread_local.h"
namespace CLHEP {
......@@ -194,8 +195,8 @@ private:
unsigned long randomInt;
unsigned long firstUnusedBit;
static unsigned long staticRandomInt;
static unsigned long staticFirstUnusedBit;
static CLHEP_THREAD_LOCAL unsigned long staticRandomInt;
static CLHEP_THREAD_LOCAL unsigned long staticFirstUnusedBit;
shared_ptr<HepRandomEngine> localEngine;
double defaultWidth;
......
......@@ -32,6 +32,7 @@
#include "CLHEP/Random/defs.h"
#include "CLHEP/Random/Random.h"
#include "CLHEP/Utility/memory.h"
#include "CLHEP/Utility/thread_local.h"
namespace CLHEP {
......@@ -160,8 +161,8 @@ private:
double nextGauss;
// static data
static bool set_st;
static double nextGauss_st;
static CLHEP_THREAD_LOCAL bool set_st;
static CLHEP_THREAD_LOCAL double nextGauss_st;
};
......
......@@ -27,6 +27,7 @@ for generating random variables", Journ. Statistical Software.
#include "cmath"
#include "CLHEP/Random/defs.h"
#include "CLHEP/Random/RandGauss.h"
#include "CLHEP/Utility/thread_local.h"
namespace CLHEP {
......@@ -105,14 +106,15 @@ protected:
//#define RNOR (hz=SHR3, iz=hz&127, (fabs(hz)<kn[iz])? hz*wn[iz] : nfix())
//#define REXP (jz=SHR3, iz=jz&255, ( jz <ke[iz])? jz*we[iz] : efix())
static unsigned long kn[128], ke[256];
static float wn[128],fn[128], we[256],fe[256];
static CLHEP_THREAD_LOCAL unsigned long kn[128], ke[256];
static CLHEP_THREAD_LOCAL float wn[128],fn[128], we[256],fe[256];
static bool ziggurat_is_init;
static CLHEP_THREAD_LOCAL bool ziggurat_is_init;
static inline unsigned long ziggurat_SHR3(HepRandomEngine* anEngine) {return (unsigned int)(*anEngine);};
static inline float ziggurat_UNI(HepRandomEngine* anEngine) {return anEngine->flat();};
static inline float ziggurat_RNOR(HepRandomEngine* anEngine) {
if(!ziggurat_is_init) ziggurat_init();
long hz=(signed)ziggurat_SHR3(anEngine);
unsigned long iz=hz&127;
return ((unsigned long)abs(hz)<kn[iz]) ? hz*wn[iz] : ziggurat_nfix(hz,anEngine);
......@@ -140,12 +142,10 @@ namespace CLHEP {
RandGaussZiggurat::RandGaussZiggurat(HepRandomEngine & anEngine, double mean,double stdDev ): RandGauss(anEngine, mean, stdDev)
{
if(!ziggurat_is_init) ziggurat_init();
}
RandGaussZiggurat::RandGaussZiggurat(HepRandomEngine * anEngine, double mean,double stdDev ): RandGauss(anEngine, mean, stdDev)
{
if(!ziggurat_is_init) ziggurat_init();
}
} // namespace CLHEP
......
......@@ -32,6 +32,7 @@
#include "CLHEP/Random/defs.h"
#include "CLHEP/Random/Random.h"
#include "CLHEP/Utility/memory.h"
#include "CLHEP/Utility/thread_local.h"
namespace CLHEP {
......@@ -119,8 +120,8 @@ private:
double status[3], oldm;
// static data
static double status_st[3];
static double oldm_st;
static CLHEP_THREAD_LOCAL double status_st[3];
static CLHEP_THREAD_LOCAL double oldm_st;
static const double meanMax_st;
};
......
......@@ -27,42 +27,42 @@ inline bool HepRandomEngine::operator!=(const HepRandomEngine& engine) {
}
inline double HepRandomEngine::exponent_bit_32() {
static double exponent_bit_32 = std::pow(2.0, 32.0);
static const double exponent_bit_32 = std::pow(2.0, 32.0);
return exponent_bit_32;
}
inline double HepRandomEngine::mantissa_bit_12() {
static double mantissa_bit_12 = std::pow(0.5, 12.0);
static const double mantissa_bit_12 = std::pow(0.5, 12.0);
return mantissa_bit_12;
}
inline double HepRandomEngine::mantissa_bit_24() {
static double mantissa_bit_24 = std::pow(0.5, 24.0);
static const double mantissa_bit_24 = std::pow(0.5, 24.0);
return mantissa_bit_24;
}
inline double HepRandomEngine::twoToMinus_32() {
static double twoToMinus_32 = std::ldexp(1.0, -32);
static const double twoToMinus_32 = std::ldexp(1.0, -32);
return twoToMinus_32;
}
inline double HepRandomEngine::twoToMinus_48() {
static double twoToMinus_48 = std::ldexp(1.0, -48);
static const double twoToMinus_48 = std::ldexp(1.0, -48);
return twoToMinus_48;
}
inline double HepRandomEngine::twoToMinus_49() {
static double twoToMinus_49 = std::ldexp(1.0, -49);
static const double twoToMinus_49 = std::ldexp(1.0, -49);
return twoToMinus_49;
}
inline double HepRandomEngine::twoToMinus_53() {
static double twoToMinus_53 = std::ldexp(1.0, -53);
static const double twoToMinus_53 = std::ldexp(1.0, -53);
return twoToMinus_53;
}
inline double HepRandomEngine::nearlyTwoToMinus_54() {
static double nearlyTwoToMinus_54 = std::ldexp(1.0, -54)
static const double nearlyTwoToMinus_54 = std::ldexp(1.0, -54)
- std::ldexp(1.0, -100);
return nearlyTwoToMinus_54;
}
......
......@@ -67,7 +67,7 @@ namespace CLHEP {
// On some compilers the static instance of the HepRandom generator
// needs to be created explicitly in the client code (i.e. here).
static int HepRandomGenActive = HepRandom::createInstance();
static const int HepRandomGenActive = HepRandom::createInstance();
} // namespace CLHEP
......
......@@ -125,7 +125,6 @@ private:
static const int maxSeq = 215;
long table[215][2];
int seq;
static int numEngines;
};
......
......@@ -112,9 +112,6 @@ private:
double randoms[12]; // randoms [i] is the x[n-i] of Luscher's note
double carry;
static int numEngines;
static int maxIndex;
}; // Ranlux64Engine
} // namespace CLHEP
......
......@@ -116,8 +116,6 @@ private:
float carry;
int count24;
static const int int_modulus = 0x1000000;
static int numEngines;
static int maxIndex;
};
} // namespace CLHEP
......
......@@ -100,7 +100,6 @@ public:
bool getState (const std::vector<unsigned long> & v);
private:
static int numEngines;
enum {numBuff = 512};
unsigned int halfBuff, numFlats;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment