def estimate_bw(disk: Disk, n_flows: int, read: bool): """ Calculates the bandwidth for disk doing async operations """ size = 100000 cur_time = Engine.get_clock() activities = [ disk.read_async(size) if read else disk.write_async(size) for _ in range(n_flows) ] for act in activities: act.wait() elapsed_time = Engine.get_clock() - cur_time estimated_bw = float(size * n_flows) / elapsed_time this_actor.info( "Disk: %s, concurrent %s: %d, estimated bandwidth: %f" % (disk.name, "read" if read else "write", n_flows, estimated_bw))
def __call__(self): workload = 100E6 host = this_actor.get_host() nb = host.get_pstate_count() this_actor.info("Count of Processor states={:d}".format(nb)) this_actor.info("Current power peak={:f}".format(host.speed)) # Run a task this_actor.execute(workload) task_time = Engine.get_clock() this_actor.info("Task1 duration: {:.2f}".format(task_time)) # Change power peak new_pstate = 2 this_actor.info( "Changing power peak value to {:f} (at index {:d})".format( host.get_pstate_speed(new_pstate), new_pstate)) host.pstate = new_pstate this_actor.info("Changed power peak={:f}".format(host.speed)) # Run a second task this_actor.execute(workload) task_time = Engine.get_clock() - task_time this_actor.info("Task2 duration: {:.2f}".format(task_time)) # Verify that the default pstate is set to 0 host2 = Host.by_name("MyHost2") this_actor.info("Count of Processor states={:d}".format( host2.get_pstate_count())) this_actor.info("Final power peak={:f}".format(host2.speed))
class Receiver: def __init__(self, *args): if len(args) != 1: # Receiver actor expects 1 argument: its ID raise AssertionError( "Actor receiver requires 1 parameter, but got {:d}".format(len(args))) self.mbox = Mailbox.by_name("receiver-{:s}".format(args[0])) def __call__(self): this_actor.info("Wait for my first message") while True: received = self.mbox.get() this_actor.info("I got a '{:s}'.".format(received)) if received == "finalize": break # If it's a finalize message, we're done. if __name__ == '__main__': e = Engine(sys.argv) # Load the platform description e.load_platform(sys.argv[1]) # Register the classes representing the actors e.register_actor("sender", Sender) e.register_actor("receiver", Receiver) e.load_deployment(sys.argv[2]) e.run()
host.pstate = new_pstate this_actor.info("Changed power peak={:f}".format(host.speed)) # Run a second task this_actor.execute(workload) task_time = Engine.get_clock() - task_time this_actor.info("Task2 duration: {:.2f}".format(task_time)) # Verify that the default pstate is set to 0 host2 = Host.by_name("MyHost2") this_actor.info("Count of Processor states={:d}".format( host2.get_pstate_count())) this_actor.info("Final power peak={:f}".format(host2.speed)) if __name__ == '__main__': e = Engine(sys.argv) if len(sys.argv) < 2: raise AssertionError( "Usage: exec-dvfs.py platform_file [other parameters] (got {:d} params)" .format(len(sys.argv))) e.load_platform(sys.argv[1]) Actor.create("dvfs_test", Host.by_name("MyHost1"), Dvfs()) Actor.create("dvfs_test", Host.by_name("MyHost2"), Dvfs()) e.run()
this_actor.info("Join the 3rd sleeper (timeout 2)") actor.join(2) this_actor.info("Start 4th sleeper") actor = Actor.create("4th sleeper from master", Host.current(), sleeper) this_actor.info("Waiting 4") this_actor.sleep_for(4) this_actor.info("Join the 4th sleeper after its end (timeout 1)") actor.join(1) this_actor.info("Goodbye now!") this_actor.sleep_for(1) this_actor.info("Goodbye now!") if __name__ == '__main__': e = Engine(sys.argv) if len(sys.argv) < 2: raise AssertionError( "Usage: actor-join.py platform_file [other parameters]") e.load_platform(sys.argv[1]) Actor.create("master", Host.by_name("Tremblay"), master) e.run() this_actor.info("Simulation time {}".format(Engine.get_clock()))
from simgrid import Engine, this_actor import sys class Sleeper: """This actor just sleeps until termination""" def __init__(self, *args): # sys.exit(1); simgrid.info("Exiting now (done sleeping or got killed).")) this_actor.on_exit(lambda: print("BAAA")) def __call__(self): this_actor.info("Hello! I go to sleep.") this_actor.sleep_for(10) this_actor.info("Done sleeping.") if __name__ == '__main__': e = Engine(sys.argv) if len(sys.argv) < 2: raise AssertionError( "Usage: actor-lifetime.py platform_file actor-lifetime_d.xml [other parameters]" ) e.load_platform(sys.argv[1]) # Load the platform description e.register_actor("sleeper", Sleeper) # Deploy the sleeper processes with explicit start/kill times e.load_deployment(sys.argv[2]) e.run()
def load_platform(): """ Create a simple 1-host platform """ zone = NetZone.create_empty_zone("Zone1") runner_host = zone.create_host("runner", 1e6) runner_host.set_sharing_policy( Host.SharingPolicy.NONLINEAR, functools.partial(cpu_nonlinear, runner_host)) runner_host.seal() zone.seal() # create actor runner Actor.create("runner", runner_host, runner) if __name__ == '__main__': e = Engine(sys.argv) # create platform load_platform() # runs the simulation e.run() # explicitly deleting Engine object to avoid segfault during cleanup phase. # During Engine destruction, the cleanup of std::function linked to non_linear callback is called. # If we let the cleanup by itself, it fails trying on its destruction because the python main program # has already freed its variables del (e)
# This serves as an example for the simgrid.yield() function, with which an actor can request # to be rescheduled after the other actor that are ready at the current timestamp. # # It can also be used to benchmark our context-switching mechanism. class Yielder: """Main function of the Yielder process""" number_of_yields = 0 def __init__(self, *args): self.number_of_yields = int(args[0]) def __call__(self): for _ in range(self.number_of_yields): this_actor.yield_() this_actor.info("I yielded {:d} times. Goodbye now!".format( self.number_of_yields)) if __name__ == '__main__': e = Engine(sys.argv) e.load_platform(sys.argv[1]) # Load the platform description # Register the class representing the actors e.register_actor("yielder", Yielder) e.load_deployment(sys.argv[2]) e.run() # - Run the simulation
this_actor.sleep_for(1) this_actor.info("Start a new actor, and kill it right away") victim_c = Actor.create("victim C", Host.by_name("Jupiter"), victim_a_fun) victim_c.kill() this_actor.sleep_for(1) this_actor.info("Killing everybody but myself") Actor.kill_all() this_actor.info("OK, goodbye now. I commit a suicide.") this_actor.exit() this_actor.info( "This line never gets displayed: I'm already dead since the previous line.") if __name__ == '__main__': e = Engine(sys.argv) if len(sys.argv) < 2: raise AssertionError( "Usage: actor-kill.py platform_file [other parameters]") e.load_platform(sys.argv[1]) # Load the platform description # Create and deploy killer process, that will create the victim actors Actor.create("killer", Host.by_name("Tremblay"), killer) e.run()
this_actor.sleep_for(5) this_actor.info("Suspend again the lazy guy while he's sleeping...") lazy.suspend() this_actor.info("This time, don't let him finish his siesta.") this_actor.sleep_for(2) this_actor.info("Wake up, lazy guy!") lazy.resume() this_actor.sleep_for(5) this_actor.info( "Give a 2 seconds break to the lazy guy while he's working...") lazy.suspend() this_actor.sleep_for(2) this_actor.info("Back to work, lazy guy!") lazy.resume() this_actor.info("OK, I'm done here.") if __name__ == '__main__': e = Engine(sys.argv) if len(sys.argv) < 2: raise AssertionError( "Usage: actor-suspend.py platform_file [other parameters]") e.load_platform(sys.argv[1]) # Load the platform description hosts = e.get_all_hosts() Actor.create("dream_master", hosts[0], dream_master) e.run() # Run the simulation
import sys from simgrid import Engine, this_actor def sender(): this_actor.sleep_for(3) this_actor.info("Goodbye now!") def receiver(): this_actor.sleep_for(5) this_actor.info("Five seconds elapsed") if __name__ == '__main__': e = Engine(sys.argv) e.load_platform(sys.argv[1]) # Load the platform description # Register the classes representing the actors e.register_actor("sender", sender) e.register_actor("receiver", receiver) e.load_deployment(sys.argv[2]) e.run() this_actor.info("Dummy import...") import gc gc.collect() this_actor.info("done.")
Disk.SharingPolicy.LINEAR) def create_sata_disk(host: Host, disk_name: str): """ Same for a SATA disk, only read operation follows a non-linear resource sharing """ disk = host.create_disk(disk_name, "68MBps", "50MBps") disk.set_sharing_policy(Disk.Operation.READ, Disk.SharingPolicy.NONLINEAR, functools.partial(sata_dynamic_sharing, disk)) # this is the default behavior, expliciting only to make it clearer disk.set_sharing_policy(Disk.Operation.WRITE, Disk.SharingPolicy.LINEAR) disk.set_sharing_policy(Disk.Operation.READWRITE, Disk.SharingPolicy.LINEAR) if __name__ == '__main__': e = Engine(sys.argv) # simple platform containing 1 host and 2 disk zone = NetZone.create_full_zone("bob_zone") bob = zone.create_host("bob", 1e6) create_ssd_disk(bob, "Edel (SSD)") create_sata_disk(bob, "Griffon (SATA II)") zone.seal() Actor.create("runner", bob, host) e.run() this_actor.info("Simulated time: %g" % Engine.get_clock()) # explicitly deleting Engine object to avoid segfault during cleanup phase. # During Engine destruction, the cleanup of std::function linked to non_linear callback is called. # If we let the cleanup by itself, it fails trying on its destruction because the python main program
# Actors that are created as object will execute their __call__ method. # So, the following constitutes the main function of the Sender actor. def __call__(self): this_actor.info("Hello s4u, I have something to send") mailbox = Mailbox.by_name(self.mbox) mailbox.put(self.msg, len(self.msg)) this_actor.info("I'm done. See you.") if __name__ == '__main__': # Here comes the main function of your program # When your program starts, you have to first start a new simulation engine, as follows e = Engine(sys.argv) # Then you should load a platform file, describing your simulated platform e.load_platform("../../platforms/small_platform.xml") # And now you have to ask SimGrid to actually start your actors. # # The easiest way to do so is to implement the behavior of your actor in a single function, # as we do here for the receiver actors. This function can take any kind of parameters, as # long as the last parameters of Actor::create() match what your function expects. Actor.create("receiver", Host.by_name("Fafard"), receiver, "mb42") # If your actor is getting more complex, you probably want to implement it as a class instead, # as we do here for the sender actors. The main behavior goes into operator()() of the class. # # You can then directly start your actor, as follows:
this_actor.execute(98095) this_actor.info("Done.") # This simple example does not do anything beyond that def privileged(): # You can also specify the priority of your execution as follows. # An execution of priority 2 computes twice as fast as a regular one. # # So instead of a half/half sharing between the two executions, # we get a 1/3 vs 2/3 sharing. this_actor.execute(98095, priority=2) this_actor.info("Done.") # Note that the timings printed when executing this example are a bit misleading, # because the uneven sharing only last until the privileged actor ends. # After this point, the unprivileged one gets 100% of the CPU and finishes # quite quickly. i = 0 if "--" in sys.argv: i = sys.argv.index("--") e = Engine(sys.argv[0:i]) e.load_platform(sys.argv[i + 1]) Actor.create("executor", Host.by_name("Tremblay"), executor) Actor.create("privileged", Host.by_name("Tremblay"), privileged) e.run()