Revision 08285dff

View differences:

include/ccomponent.h
293 293
     * Returns the global RNG mapped to local RNG number k. For large indices
294 294
     * (k >= map size) the global RNG k is returned, provided it exists.
295 295
     */
296
    cRNG *getRNG(int k) const  {return ev.getRNG(k<rngmapsize ? rngmap[k] : k);}
296
    cRNG* getRNG(int k) const;
297 297
    //@}
298 298

  
299 299
    /** @name Interface for calling initialize()/finish().
include/cenvir.h
521 521
     * Returns the number of RNGs available for the simulation
522 522
     * ("num-rngs=" omnetpp.ini setting).
523 523
     */
524
    virtual int getNumRNGs() const = 0;
524
    virtual int getNumRNGsPerModule() const = 0;
525 525

  
526 526
    /**
527 527
     * Returns pointer to "physical" RNG k (0 <= k < getNumRNGs()).
......
655 655
     * abort waiting (e.g. pushed the Stop button).
656 656
     */
657 657
    virtual bool idle() = 0;
658

  
659
	virtual void createRNGs() = 0;
658 660
    //@}
659 661
};
660 662

  
include/csimplemodule.h
25 25
#include <semaphore.h>
26 26

  
27 27
#include "cmodule.h"
28
#include "cnumgen.h"
29 28

  
30 29
#ifdef ATOMIC_OPS_DEBUG
31 30
	#include "catomicopsdebug.h"
......
72 71
 *
73 72
 * @ingroup SimCore
74 73
 */
75
class SIM_API cSimpleModule : public cModule, public cNumberGenerator //implies noncopyable
74
class SIM_API cSimpleModule : public cModule //implies noncopyable
76 75
{
77 76
    friend class cModule;
78 77
    friend class cSimulation;
......
564 563
    {
565 564
        return duration == SimTime::simTimeZero ? parZeroDur : true;
566 565
    }
567
    /*
568
     * Initializes the local RNGs according to config options read from ini
569
     */
570
    void initLocalRNGs();
571 566
    //}@
572 567

  
573 568

  
include/csimulation.h
161 161
     */
162 162
    void setupThreadPool();
163 163

  
164
    /*
165
     * setup the local Random Number Generators for each module
166
     */
167
    void setupLocalRNGs();
168

  
169 164
  public:
170 165
    /** @name Constructor, destructor. */
171 166
    //@{
src/envir/envirbase.cc
202 202
    outscalarmgr = NULL;
203 203
    snapshotmgr = NULL;
204 204

  
205
    num_rngs = 0;
206
    rngs = NULL;
205
    num_rngs_per_module = 0;
207 206

  
208 207
#ifdef WITH_PARSIM
209 208
    parsimcomm = NULL;
......
223 222
    delete outscalarmgr;
224 223
    delete snapshotmgr;
225 224

  
226
    for (int i = 0; i < num_rngs; i++)
225
    for (int i = 0; i < rngs.size(); i++)
227 226
         delete rngs[i];
228
    delete [] rngs;
229 227

  
230 228
#ifdef WITH_PARSIM
231 229
    delete parsimcomm;
......
1447 1445
    delete testrng;
1448 1446

  
1449 1447
    // set up RNGs
1450
    int i;
1451
    for (i=0; i<num_rngs; i++)
1448
    for (int i = 0; i < rngs.size(); i++)
1452 1449
         delete rngs[i];
1453
    delete [] rngs;
1454 1450

  
1455
    num_rngs = opt_num_rngs;
1456
    rngs = new cRNG *[num_rngs];
1457
    for (i=0; i<num_rngs; i++)
1458
    {
1459
        cRNG *rng;
1460
        CREATE_BY_CLASSNAME(rng, opt_rng_class.c_str(), cRNG, "random number generator");
1461
        rngs[i] = rng;
1462
        rngs[i]->initialize(opt_seedset, i, num_rngs, getParsimProcId(), getParsimNumPartitions(), getConfig());
1463
    }
1464

  
1465
    // and  finally the private seed generator for all local generators of simple modules
1466
 	CREATE_BY_CLASSNAME(seedGenerator, opt_rng_class.c_str(), cRNG, "random number generator");
1467
 	seedGenerator->initializeAsMaster(opt_seedset, num_rngs+1, num_rngs, getParsimProcId(), getParsimNumPartitions(), getConfig());
1451
    num_rngs_per_module = opt_num_rngs;
1452
	createRNGs();
1468 1453

  
1469 1454
    // init nextuniquenumber -- startRun() is too late because simple module ctors have run by then
1470 1455
    nextuniquenumber = 0;
......
1483 1468
    }
1484 1469
}
1485 1470

  
1471
void EnvirBase::createRNGs()
1472
{
1473
	int offset=rngs.size();
1474
	int moduleId=offset/num_rngs_per_module;
1475
	for(int i=0;i<num_rngs_per_module;i++)
1476
	{
1477
		int pos=i+offset;
1478
		cRNG *rng;
1479
		CREATE_BY_CLASSNAME(rng, opt_rng_class.c_str(), cRNG, "random number generator");
1480
        assert(rngs.size()==pos);
1481
		rngs.push_back(rng);
1482
        rngs[pos]->initialize(opt_seedset*moduleId, i, num_rngs_per_module, getParsimProcId(), getParsimNumPartitions(), getConfig());
1483
	}
1484
}
1485

  
1486 1486
void EnvirBase::setEventlogRecording(bool enabled)
1487 1487
{
1488 1488
    // NOTE: eventlogmgr must be non-NULL when record_eventlog is true
......
1508 1508

  
1509 1509
//-------------------------------------------------------------
1510 1510

  
1511
int EnvirBase::getNumRNGs() const
1511
int EnvirBase::getNumRNGsPerModule() const
1512 1512
{
1513
    return num_rngs;
1513
    return num_rngs_per_module;
1514 1514
}
1515 1515

  
1516 1516
cRNG *EnvirBase::getRNG(int k)
1517 1517
{
1518
    if (k<0 || k>=num_rngs)
1519
        throw cRuntimeError("RNG index %d is out of range (num-rngs=%d, check the configuration)", k, num_rngs);
1518
    if (k<0 || k>=rngs.size())
1519
        throw cRuntimeError("RNG index %d is out of range (num-rngs=%d*<numberOfModules>=%d, check the configuration)", k, num_rngs_per_module, rngs.size());
1520 1520
    return rngs[k];
1521 1521
}
1522 1522

  
......
1544 1544
                                "numeric RNG indices expected",
1545 1545
                                suffix, value, component->getFullPath().c_str());
1546 1546

  
1547
        if (physRng>getNumRNGs())
1547
        if (physRng>rngs.size())
1548 1548
            throw cRuntimeError("Configuration error: rng-%d=%d of module/channel %s: "
1549 1549
                                "RNG index out of range (num-rngs=%d)",
1550
                                modRng, physRng, component->getFullPath().c_str(), getNumRNGs());
1550
                                modRng, physRng, component->getFullPath().c_str(), rngs.size());
1551 1551
        if (modRng>=mapsize)
1552 1552
        {
1553 1553
            if (modRng>=100)
src/envir/envirbase.h
108 108
// end
109 109

  
110 110
    // Random number generators. Module RNG's map to these RNG objects.
111
    int num_rngs;
112
    cRNG **rngs;
113

  
114
    cRNG *seedGenerator; // central (and private) random num gen for generating seeds for all public ones
111
    int num_rngs_per_module;
112
	std::vector<cRNG*> rngs;
115 113

  
116 114
    // Output file managers
117 115
    EventlogFileManager *eventlogmgr;  // NULL if no event log is being written, must be non NULL if record_eventlog is true
......
195 193
    // leave to subclasses: virtual cEnvir& flush();
196 194

  
197 195
    // RNGs
198
    virtual int getNumRNGs() const;
196
    virtual int getNumRNGsPerModule() const;
199 197
    virtual cRNG *getRNG(int k);
200 198
    virtual void getRNGMappingFor(cComponent *component);
201 199

  
......
222 220
    virtual bool idle();
223 221
    //@}
224 222

  
223
	virtual void createRNGs();
224

  
225 225
  protected:
226 226
    // functions added locally
227 227
    virtual bool simulationRequired();
......
272 272
    // Utility function: optionally appends host name to fname
273 273
    virtual void processFileName(opp_string& fname);
274 274

  
275

  
276
    cRNG *getSeedGenerator() const { return seedGenerator; }
277

  
278 275
  protected:
279 276
    // Utility function: checks simulation fingerprint and displays a message accordingly
280 277
    void checkFingerprint();
src/sim/ccomponent.cc
736 736
*/
737 737
}
738 738

  
739
cRNG* cComponent::getRNG(int k) const
740
{
741
	const cModule* const thisMod=dynamic_cast<const cModule* const>(this);
742
	int modId=0;
743
	if(thisMod) modId=thisMod->getId();
744
	k+=modId*ev.getNumRNGsPerModule();
745
	return ev.getRNG(k);
746
}
747

  
src/sim/csimplemodule.cc
603 603
    return coroutine ? coroutine->getStackUsage() : 0;
604 604
}
605 605

  
606
void cSimpleModule::initLocalRNGs()
607
{
608
    //TODO
609
    unsigned nrNumGens;
610
    unsigned long * seeds;
611

  
612
    //
613
    // how many local random number generators do we need?
614
    // default is 1
615
    //
616
    nrNumGens = ev.getConfig()->parseLong(
617
            ev.getConfig()->getPerObjectConfigValue(getFullPath().c_str(),
618
                    "number-local-rngs"), "1", 1);
619

  
620
    //
621
    // read the seeds from ini file
622
    //
623
    const char * seedString = ev.getConfig()->getPerObjectConfigValue(
624
            getFullPath().c_str(), "local-rng-seed");
625

  
626
    //
627
    // setup seeds for each RNG
628
    //
629
    seeds = new unsigned long[nrNumGens];
630
    cStringTokenizer tokenizer(seedString);
631
    const char * token = NULL;
632
    for (unsigned i = 0; i < nrNumGens; i++)
633
    {
634
        if (tokenizer.hasMoreTokens())
635
        {
636
            token = tokenizer.nextToken();
637
            if (strcmp(token, "auto") == 0)
638
            {
639
                token = NULL;
640
            }
641
        }
642

  
643
        EnvirBase* e = dynamic_cast<EnvirBase*> (&ev);
644
        if (e != NULL)
645
        {
646
            if (token)
647
            {
648
                //if the seed is set in the ini for this module, use ini-settings
649
                //with fallback to autogeneration if parsing failes
650
                seeds[i] = ev.getConfig()->parseLong(token, "",
651
                        e->getSeedGenerator()->intRand());
652
            }
653
            else
654
            {
655
                //else use SeedGenerator for automatic seed generation.
656
                seeds[i] = e->getSeedGenerator()->intRand();
657
            }
658
            token = NULL;
659
        }
660
        else
661
        {
662
            throw cRuntimeError(
663
                    "cSimpleModule: Failed to initialize Number Generator, dynamic cast to EnvirBase failed.");
664
        }
665
    }
666

  
667
    //
668
    // generate the required number of RNGs with the corresponding seeds
669
    //
670
    setupSeeds(nrNumGens,seeds);
671
    delete[] seeds;
672

  
673
}
674

  
675 606
void cSimpleModule::setMessageMetaData(cMessage* msg)
676 607
{
677 608
    msg->setEventDuration(SimTime::simTimeUninitialized);
src/sim/csimulation.cc
312 312
        vect = v;
313 313
        size += delta;
314 314
    }
315
	ev.createRNGs();
315 316
    vect[last_id] = mod;
316 317
    return last_id;
317 318
}
......
426 427
    // read config and setup thread pool
427 428
    setupThreadPool();
428 429

  
429
    // setup local RNGs for each module according to config
430
    setupLocalRNGs();
431

  
432 430
    // reset counters. Note msgQueue.clear() was already called from setupNetwork()
433 431
    cThreadPool::setSimTime(0.0);
434 432
    //sim_time = 0;
......
844 842
        return eventsPerSimTimeInstance + 1;
845 843
}
846 844

  
847
void cSimulation::setupLocalRNGs() {
848

  
849
    //
850
    // Walk through vect[] and setup RNGs for each cSimpleModule
851
    //
852
    // TODO: Better way to do this? What about dynamically created Modules?
853
    cSimpleModule* mod = NULL;
854
    for (int i = 1; i <= last_id; i++) {
855
        if (vect[i]) {
856
            mod = dynamic_cast<cSimpleModule*>(vect[i]);
857
            if (mod) {
858
                mod->initLocalRNGs();
859
            }
860
        }
861
    }
862
}
863

  
864 845
//----
865 846

  
866 847
/**
......
941 922
    virtual cEnvir& flush()  {::fflush(stdout); return *this;}
942 923

  
943 924
    // RNGs
944
    virtual int getNumRNGs() const {return 0;}
925
    virtual int getNumRNGsPerModule() const {return 0;}
945 926
    virtual cRNG *getRNG(int k)  {unsupported(); return NULL;}
946 927
    virtual void getRNGMappingFor(cComponent *component)  {component->setRNGMap(0,NULL);}
928
	virtual void createRNGs() {unsupported();}
947 929

  
948 930
    // output vectors
949 931
    virtual void *registerOutputVector(const char *modulename, const char *vectorname)  {return NULL;}
src/sim/cthreadpool.cc
49 49

  
50 50
Register_GlobalConfigOption(CFG_IN_THREADPOOL_CPU_ID_OFFSET, "cpu-id-offset", CFG_INT, "0", "Offset for Thread Affinity. (When running multiple instances of Horizon at once)");
51 51
Register_PerRunConfigOption(CFGID_THREADPOOL_SIZE, "thread-pool-size", CFG_INT, "5", "Number of Threads in Threadpool");
52
Register_GlobalConfigOption(CFGID_SIMTIME_SCALE, "simtime-scale", CFG_INT, "-12", "Sets the scale exponent, and thus the resolution of time for the 64-bit fixed-point simulation time representation. Accepted values are -18..0; for example, -6 selects microsecond resolution. -12 means picosecond resolution, with a maximum simtime of ~110 days.");
53 52

  
54 53

  
55 54
static __thread cThreadLocalData* localData = NULL;

Also available in: Unified diff