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.
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.")
def cpu_nonlinear(host: Host, capacity: float, n: int) -> float: """ Non-linear resource sharing for CPU """ # emulates a degradation in CPU according to the number of tasks # totally unrealistic but for learning purposes capacity = capacity / 2 if n > 1 else capacity this_actor.info("Host %s, %d concurrent tasks, new capacity %f" % (host.name, n, capacity)) return capacity
def __call__(self): computation_amount = this_actor.get_host().speed this_actor.info("Execute {:.0f} flops, should take 1 second.".format(computation_amount)) activity = this_actor.exec_init(computation_amount) activity.start() activity.wait() this_actor.info("Goodbye now!")
def __call__(self): # FIXME: It should be ok to initialize self.mbox from __init__, but it's currently failing on the OS X Jenkins slave. self.mbox = Mailbox.by_name("receiver-{:d}".format(self.id)) 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.
def __call__(self): for host in self.hosts: mbox = Mailbox.by_name(host.name) msg = "Hello. I'm " + str(this_actor.get_host().name) size = int(1e6) this_actor.info("Sending msg to " + host.name) mbox.put(msg, size) this_actor.info("Done dispatching all messages. Goodbye!")
def my_daemon(): """The daemon, displaying a message every 3 seconds until all other processes stop""" Actor.self().daemonize() while True: this_actor.info("Hello from the infinite loop") this_actor.sleep_for(3.0) this_actor.info( "I will never reach that point: daemons are killed when regular processes are done" )
def forwarder(*args): """Our second class of actors is also a function""" if len(args) < 2: raise AssertionError( "Actor forwarder requires 2 parameters, but got only {:d}".format(len(args))) mb_in = Mailbox.by_name(args[0]) mb_out = Mailbox.by_name(args[1]) msg = mb_in.get() this_actor.info("Forward '{:s}'.".format(msg)) mb_out.put(msg, len(msg))
def victim_a_fun(): this_actor.on_exit(lambda: this_actor.info("I have been killed!")) this_actor.info("Hello!") this_actor.info("Suspending myself") this_actor.suspend() # - Start by suspending itself # - Then is resumed and start to execute a task this_actor.info("OK, OK. Let's work") this_actor.execute(1e9) # - But will never reach the end of it this_actor.info("Bye!")
def __call__(self): # List in which we store all ongoing communications pending_comms = [] # Vector of the used mailboxes mboxes = [ Mailbox.by_name("receiver-{:d}".format(i)) for i in range(0, self.receivers_count) ] # Start dispatching all messages to receivers, in a round robin fashion for i in range(0, self.messages_count): content = "Message {:d}".format(i) mbox = mboxes[i % self.receivers_count] this_actor.info("Send '{:s}' to '{:s}'".format(content, str(mbox))) # Create a communication representing the ongoing communication, and store it in pending_comms comm = mbox.put_async(content, self.msg_size) pending_comms.append(comm) # Start sending messages to let the workers know that they should stop for i in range(0, self.receivers_count): mbox = mboxes[i] this_actor.info("Send 'finalize' to '{:s}'".format(str(mbox))) comm = mbox.put_async("finalize", 0) pending_comms.append(comm) this_actor.info("Done dispatching all messages") # Now that all message exchanges were initiated, wait for their completion in one single call Comm.wait_all(pending_comms) this_actor.info("Goodbye now!")
def link_nonlinear(link: Link, capacity: float, n: int) -> float: """ Non-linear resource sharing for links Note that the callback is called twice in this example: 1) link UP: with the number of active flows (from 9 to 1) 2) link DOWN: with 0 active flows. A crosstraffic communication is happing in the down link, but it's not considered as an active flow. """ # emulates a degradation in link according to the number of flows # you probably want something more complex than that and based on real # experiments capacity = min(capacity, capacity * (1.0 - (n - 1) / 10.0)) this_actor.info("Link %s, %d active communications, new capacity %f" % (link.name, n, capacity)) return capacity
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 monitor(): boivin = Host.by_name("Boivin") jacquelin = Host.by_name("Jacquelin") fafard = Host.by_name("Fafard") actor = Actor.create("worker", fafard, worker, boivin, jacquelin) this_actor.sleep_for(5) this_actor.info("After 5 seconds, move the process to {:s}".format( jacquelin.name)) actor.host = jacquelin this_actor.sleep_until(15) this_actor.info("At t=15, move the process to {:s} and resume it.".format( fafard.name)) actor.host = fafard actor.resume()
def __call__(self): mbox = Mailbox.by_name("receiver") pending_msgs = [] pending_comms = [] this_actor.info("Wait for %d messages asynchronously" % self.msg_count) for _ in range(self.msg_count): comm, data = mbox.get_async() pending_comms.append(comm) pending_msgs.append(data) while len(pending_comms) > 0: index = Comm.wait_any(pending_comms) msg = pending_msgs[index].get() this_actor.info("I got '%s'." % msg) del pending_comms[index] del pending_msgs[index]
def __call__(self): # List in which we store all ongoing communications pending_comms = [] # Vector of the used mailboxes mboxes = [ Mailbox.by_name("receiver-{:d}".format(i)) for i in range(0, self.receivers_count) ] # Start dispatching all messages to receivers, in a round robin fashion for i in range(0, self.messages_count): content = "Message {:d}".format(i) mbox = mboxes[i % self.receivers_count] this_actor.info("Send '{:s}' to '{:s}'".format(content, str(mbox))) # Create a communication representing the ongoing communication, and store it in pending_comms comm = mbox.put_async(content, self.msg_size) pending_comms.append(comm) # Start sending messages to let the workers know that they should stop for i in range(0, self.receivers_count): mbox = mboxes[i] this_actor.info("Send 'finalize' to '{:s}'".format(str(mbox))) comm = mbox.put_async("finalize", 0) pending_comms.append(comm) this_actor.info("Done dispatching all messages") # Now that all message exchanges were initiated, wait for their completion, in order of completion. # # This loop waits for first terminating message with wait_any() and remove it with del, until all comms are # terminated. # Even in this simple example, the pending comms do not terminate in the exact same order of creation. while pending_comms: changed_pos = Comm.wait_any(pending_comms) del pending_comms[changed_pos] if (changed_pos != 0): this_actor.info( "Remove the {:d}th pending comm: it terminated earlier than another comm that was initiated first." .format(changed_pos)) this_actor.info("Goodbye now!")
def do_sleep5(i, dur): if i > 0: this_actor.info("5-Iter {:d}".format(i)) do_sleep1(i - 1, dur) this_actor.sleep_for(dur) this_actor.info("5-Mid ({:d})".format(i)) do_sleep1(int(i / 2), dur) this_actor.info("5-Done ({:d})".format(i))
def worker(first_host, second_host): flop_amount = first_host.speed * 5 + second_host.speed * 5 this_actor.info("Let's move to {:s} to execute {:.2f} Mflops (5sec on {:s} and 5sec on {:s})".format( first_host.name, flop_amount / 1e6, first_host.name, second_host.name)) this_actor.set_host(first_host) this_actor.execute(flop_amount) this_actor.info("I wake up on {:s}. Let's suspend a bit".format( this_actor.get_host().name)) this_actor.suspend() this_actor.info("I wake up on {:s}".format(this_actor.get_host().name)) this_actor.info("Done")
def __call__(self): computation_amount = this_actor.get_host().speed this_actor.info("Execute {:.0f} flops, should take 1 second.".format(computation_amount)) activity = this_actor.exec_init(computation_amount).start() this_actor.sleep_for(0.5) this_actor.info("I changed my mind, cancel!") activity.cancel() this_actor.info("Goodbye now!")
def __call__(self): this_actor.execute(1e9) for disk in Host.current().get_disks(): this_actor.info("Using disk " + disk.name) disk.read(10000) disk.write(10000) mbox = Mailbox.by_name(this_actor.get_host().name) msg = mbox.get() this_actor.info("I got '%s'." % msg) this_actor.info("Finished executing. Goodbye!")
def __call__(self): computation_amount = this_actor.get_host().speed this_actor.info("Execute {:.0f} flops, should take 1 second.".format(computation_amount)) activity = this_actor.exec_init(computation_amount).start() while not activity.test(): this_actor.info("Remaining amount of flops: {:.0f} ({:.0f}%)".format( activity.remaining, 100 * activity.remaining_ratio)) this_actor.sleep_for(0.3) activity.wait() this_actor.info("Goodbye now!")
def receiver(mailbox_name): """ Our first class of actors is simply implemented with a function, that takes a single string as parameter. Later, this actor class is instantiated within the simulation. """ mailbox = Mailbox.by_name(mailbox_name) this_actor.info( "Hello s4u, I'm ready to get any message you'd want on {:s}".format(mailbox.name)) msg1 = mailbox.get() msg2 = mailbox.get() msg3 = mailbox.get() this_actor.info( "I received '{:s}', '{:s}' and '{:s}'".format(msg1, msg2, msg3)) this_actor.info("I'm done. See you.")
def runner(): computation_amount = this_actor.get_host().speed n_task = 10 this_actor.info( "Execute %d tasks of %g flops, should take %d second in a CPU without degradation. It will take the double here." % (n_task, computation_amount, n_task)) tasks = [ this_actor.exec_init(computation_amount).start() for _ in range(n_task) ] this_actor.info("Waiting for all tasks to be done!") for task in tasks: task.wait() this_actor.info("Finished executing. Goodbye now!")
def __call__(self): pending_comms = [] mbox = Mailbox.by_name("receiver") for i in range(self.msg_count): msg = "Message " + str(i) size = self.msg_size * (i + 1) this_actor.info("Send '%s' to '%s, msg size: %d'" % (msg, mbox.name, size)) comm = mbox.put_async(msg, size) pending_comms.append(comm) this_actor.info("Done dispatching all messages") # Now that all message exchanges were initiated, wait for their completion in one single call Comm.wait_all(pending_comms) this_actor.info("Goodbye now!")
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))
def __call__(self): fafard = Host.by_name("Fafard") ginette = Host.by_name("Ginette") boivin = Host.by_name("Boivin") this_actor.info("I'm a wizard! I can run a task on the Ginette host from the Fafard one! Look!") activity = this_actor.exec_init(48.492e6) activity.host = ginette activity.start() this_actor.info("It started. Running 48.492Mf takes exactly one second on Ginette (but not on Fafard).") this_actor.sleep_for(0.1) this_actor.info("Loads in flops/s: Boivin={:.0f}; Fafard={:.0f}; Ginette={:.0f}".format(boivin.load, fafard.load, ginette.load)) activity.wait() this_actor.info("Done!") this_actor.info("And now, harder. Start a remote task on Ginette and move it to Boivin after 0.5 sec") activity = this_actor.exec_init(73293500) activity.host = ginette activity.start() this_actor.sleep_for(0.5) this_actor.info( "Loads before the move: Boivin={:.0f}; Fafard={:.0f}; Ginette={:.0f}".format( boivin.load, fafard.load, ginette.load)) activity.host = boivin this_actor.sleep_for(0.1) this_actor.info( "Loads after the move: Boivin={:.0f}; Fafard={:.0f}; Ginette={:.0f}".format( boivin.load, fafard.load, ginette.load)) activity.wait() this_actor.info("Done!")
def sleeper(): this_actor.info("Sleeper started") this_actor.sleep_for(3) this_actor.info("I'm done. See you!")
def master(): this_actor.info("Start 1st sleeper") actor = Actor.create("1st sleeper from master", Host.current(), sleeper) this_actor.info("Join the 1st sleeper (timeout 2)") actor.join(2) this_actor.info("Start 2nd sleeper") actor = Actor.create("2nd sleeper from master", Host.current(), sleeper) this_actor.info("Join the 2nd sleeper (timeout 4)") actor.join(4) this_actor.info("Start 3rd sleeper") actor = Actor.create("3rd sleeper from master", Host.current(), sleeper) 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!")
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()))
def __call__(self): this_actor.info("Hello! I go to sleep.") this_actor.sleep_for(10) this_actor.info("Done sleeping.")
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))