async def main(): vm_package = await vm.repo( image_hash="9a3b5d67b0b27746283cb5f287c13eab1beaa12d92a9f536b747c7ae", min_mem_gib=0.5, min_storage_gib=2.0, ) async def worker(work_ctx, tasks): async for task in tasks: script = work_ctx.new_script() print("task data:", task.data, file=sys.stderr) script.run("/bin/sleep", "1") yield script task.accept_result(result=task.data) async with Golem( budget=10.0, subnet_tag="goth", event_consumer=log_event_repr, ) as golem: # We use an async task generator that yields tasks removed from # an async queue. Each computed task will potentially spawn # new tasks -- this is made possible thanks to using async task # generator as an input to `executor.submit()`. task_queue = asyncio.Queue() # Seed the queue with the first task: await task_queue.put(Task(data=3)) async def input_generator(): """Task generator yields tasks removed from `queue`.""" while True: task = await task_queue.get() if task.data == 0: break yield task async for task in golem.execute_tasks( worker, input_generator(), vm_package, max_workers=1, timeout=timedelta(minutes=6), ): print("task result:", task.result, file=sys.stderr) for n in range(task.result): await task_queue.put(Task(data=task.result - 1)) print("all done!", file=sys.stderr)
async def main(): vm_package = await vm.repo( image_hash="9a3b5d67b0b27746283cb5f287c13eab1beaa12d92a9f536b747c7ae", min_mem_gib=0.5, min_storage_gib=2.0, ) async def worker(work_ctx, tasks): """Compute just one task and exit.""" async for task in tasks: script = work_ctx.new_script() script.run("/bin/sleep", "1") yield script task.accept_result() return async with Golem( budget=10.0, subnet_tag="goth", event_consumer=log_event_repr, ) as golem: tasks = [Task(data=n) for n in range(3)] async for task in golem.execute_tasks( worker, tasks, vm_package, max_workers=1, timeout=timedelta(minutes=6), ): print(f"Task computed: {task}")
async def main( scan_size: int, max_workers: int, subnet_tag, payment_driver=None, payment_network=None ): payload = await vm.repo(image_hash=IMAGE_HASH) async def worker(ctx: WorkContext, tasks): assert ctx.provider_id not in scanned_nodes async for task in tasks: print( f"{TEXT_COLOR_CYAN}" f"Getting info for {ctx.provider_id} (aka {ctx.provider_name})" f"{TEXT_COLOR_DEFAULT}", ) script = ctx.new_script() future_result = script.run("/bin/cat", "/proc/cpuinfo") yield script result = (await future_result).stdout or "" cpu_model_match = re.search("^model name\\s+:\\s+(.*)$", result, flags=re.MULTILINE) if cpu_model_match: result = cpu_model_match.group(1) else: result = None # add the node to the set so we don't end up signing another agreement with it scanned_nodes.add(ctx.provider_id) # and accept the result (pass the result to the loop in `main`) task.accept_result((ctx.provider_id, ctx.provider_name, result)) # as we don't really want the engine to execute any more tasks on this node, # we signal the parent generator to exit and through that # also request termination of the worker and the agreement # # issuing a `break` here instead will usually not do what the user is expecting, # as the parent generator would just exit cleanly without notifying the # engine and there's nothing stopping the engine from re-launching the activity/worker # on the same agreement await tasks.aclose() async with Golem( budget=1, strategy=ScanStrategy(), subnet_tag=subnet_tag, payment_driver=payment_driver, payment_network=payment_network, ) as golem: print_env_info(golem) print( f"{TEXT_COLOR_YELLOW}Scanning {pluralize(scan_size, 'node')}, " f"using {pluralize(max_workers, 'concurrent worker')}.{TEXT_COLOR_DEFAULT}" ) tasks: List[Task] = [Task(i) for i in range(scan_size)] async for task in golem.execute_tasks(worker, tasks, payload, max_workers=max_workers): print(f"{TEXT_COLOR_MAGENTA}{task.result}{TEXT_COLOR_DEFAULT}")
async def main(subnet_tag: str): package = await vm.repo( image_hash="7c63ebd87868e27eb99a687d1175e77450d7b3ff73fc86e6bdcef37b", min_mem_gib=4.0, min_storage_gib=8.0, ) async def worker(ctx: WorkContext, tasks): async for task in tasks: ctx.run("/golem/entrypoints/runold.sh") output_file = "output.txt" ctx.download_file("/golem/output/output.txt", output_file) try: # Set timeout for executing the script on the provider. Two minutes is plenty # of time for computing a single frame, for other tasks it may be not enough. # If the timeout is exceeded, this worker instance will be shut down and all # remaining tasks, including the current one, will be computed by other providers. yield ctx.commit(timeout=timedelta(seconds=18000)) # TODO: Check if job results are valid # and reject by: task.reject_task(reason = 'invalid file') task.accept_result(result=output_file) except BatchTimeoutError: print(f"{utils.TEXT_COLOR_RED}" f"Task timed out: {task}, time: {task.running_time}" f"{utils.TEXT_COLOR_DEFAULT}") raise # Iterator over the frame indices that we want to render frames: range = range(0, 1) # Worst-case overhead, in minutes, for initialization (negotiation, file transfer etc.) # TODO: make this dynamic, e.g. depending on the size of files to transfer init_overhead = 3 # Providers will not accept work if the timeout is outside of the [5 min, 30min] range. # We increase the lower bound to 6 min to account for the time needed for our demand to # reach the providers. min_timeout, max_timeout = 30, 150 timeout = timedelta( minutes=max(min(init_overhead + len(frames) * 2, max_timeout), min_timeout)) # By passing `event_consumer=log_summary()` we enable summary logging. # See the documentation of the `yapapi.log` module on how to set # the level of detail and format of the logged information. async with Executor( package=package, max_workers=3, budget=10.0, timeout=timeout, subnet_tag=subnet_tag, event_consumer=log_summary(log_event_repr), ) as executor: async for task in executor.submit( worker, [Task(data=frame) for frame in frames]): print( f"{utils.TEXT_COLOR_CYAN}" f"Task computed: {task}, result: {task.result}, time: {task.running_time}" f"{utils.TEXT_COLOR_DEFAULT}")
async def main(): package = await vm.repo( image_hash="9a3b5d67b0b27746283cb5f287c13eab1beaa12d92a9f536b747c7ae", min_mem_gib=0.5, min_storage_gib=2.0, ) first_worker = True async def worker(ctx: WorkContext, tasks): """A worker function for `Golem.execute_tasks()`. The first call to this function will produce a worker that sends an invalid `run` command to the provider. This should cause `yield script` to fail with `CommandExecutionError`. The remaining calls will just send `sleep 5` to the provider to simulate some work. """ nonlocal first_worker should_fail = first_worker first_worker = False async for task in tasks: script = ctx.new_script() if should_fail: # Send a command that will fail on the provider script.run("xyz") yield script else: # Simulate some work script.run("/bin/sleep", "5") yield script task.accept_result() async with Golem( budget=10.0, subnet_tag="goth", ) as golem: tasks = [Task(data=n) for n in range(6)] async for task in golem.execute_tasks( worker, tasks, package, max_workers=1, timeout=timedelta(minutes=6), ): print(f"Task computed: {task}, time: {task.running_time}") print("All tasks computed")
async def main(subnet_tag: str, app: App, batches: List[Batch]): package = await vm.repo( # using existing image for 'blender' example image_hash="9a3b5d67b0b27746283cb5f287c13eab1beaa12d92a9f536b747c7ae", min_mem_gib=1.0, min_storage_gib=2.0, ) async def worker(ctx: WorkContext, tasks): cwd = pathlib.Path.cwd() async for task in tasks: batch = task.data try: os.remove(batch.local_out(cwd)) except: pass for exe in batch.all_executables(): ctx.send_file(batch.local_exe(cwd, exe), batch.remote_exe(exe)) batch.make_local_sh(cwd) ctx.send_file(batch.local_sh(cwd), batch.remote_sh()) ctx.run("/bin/bash", batch.remote_sh()) ctx.download_file(batch.remote_out(), batch.local_out(cwd)) try: yield ctx.commit(timeout=timedelta(seconds=batch.timeout())) task.accept_result(result=batch.local_out(cwd)) except BatchTimeoutError: print( f"{text_colors.RED}" f"Task timed out: {task.data.id}, time: {task.running_time}" f"{text_colors.DEFAULT}") raise # Worst-case overhead, in minutes, for initialization (negotiation, file transfer etc.) timeout = timedelta(minutes=app.args.time_out) # By passing `event_consumer=log_summary()` we enable summary logging. # See the documentation of the `yapapi.log` module on how to set # the level of detail and format of the logged information. async with Executor( package=package, max_workers=len(batches), budget=10.0, timeout=timeout, subnet_tag=subnet_tag, event_consumer=log_summary(log_event_repr), ) as executor: async for task in executor.submit( worker, [Task(data=batch) for batch in batches]): print( f"{text_colors.CYAN}" f"Task computed: {task.data.id}, result: {task.result}, time: {task.running_time}" f"{text_colors.DEFAULT}")
async def main(): package = await vm.repo( image_hash="d646d7b93083d817846c2ae5c62c72ca0507782385a2e29291a3d376", ) tasks = [Task(data=None)] async with Golem(budget=1.0, subnet_tag="devnet-beta") as golem: async for completed in golem.execute_tasks(worker, tasks, payload=package): print(completed.result.stdout)
async def run_step(self, step, timeout=timedelta(minutes=10), budget=10, subnet_tag="community.3" ): package = await vm.repo( image_hash=step["image"], min_mem_gib=1, min_storage_gib=5.0, ) async def worker(ctx: WorkContext, tasks): async for task in tasks: step_name = step['name'] commands = step['commands'] # prepair envs in string form of: "k1=v1 k2=v2 ... kn=vn " envs = step.get('environment') print(f"\033[36;1mSending the context zip file: {self.tar_fname}\033[0m") ctx.send_file(self.tar_fname , "/golem/resource/context.zip") # extracting tar file. print(f"\033[36;1mExtracting the zip file: {self.tar_fname}\033[0m") ctx.run("/bin/sh", "-c", "unzip /golem/resource/context.zip") # run all commands one by one for command in commands: print(f"\033[36;1mRunning {command}\033[0m") # set envs. ctx.run("/bin/sh", "-c", f"{command} >> /golem/output/cmd.log 2>&1", env=envs) log_fname = get_temp_log_file(step_name) ctx.download_file(f"/golem/output/cmd.log", log_fname) try: yield ctx.commit(timeout=timedelta(minutes=30)) task.accept_result(result=log_fname) except BatchTimeoutError: print(f"Task timed out: {task}, time: {task.running_time}") raise ctx.log("no more task to run") # By passing `event_emitter=log_summary()` we enable summary logging. # See the documentation of the `yapapi.log` module on how to set # the level of detail and format of the logged information. async with Executor( package=package, max_workers=1, budget=budget, timeout=timeout, subnet_tag=subnet_tag, event_consumer=log_summary(log_event_repr), ) as executer: async for task in executer.submit(worker, [Task(data=step)]): print(f"\033[36;1mStep completed: {task}\033[0m") # grab the logs self.state[step['name']]['log'] = task.result # notify about this task! self.state[step['name']]['state'] = StepState.SUCCESS self.post_progress(step['name'])
async def main(): package = await vm.repo( image_hash="d646d7b93083d817846c2ae5c62c72ca0507782385a2e29291a3d376") tasks = [Task(data=None)] timeout = timedelta(hours=24) async with Golem( budget=10.0, strategy=ShortDebitNoteIntervalAndPaymentTimeout(), subnet_tag="goth", event_consumer=log_event_repr, ) as golem: logger = logging.getLogger("yapapi") logger.handlers[0].setLevel(logging.DEBUG) async for completed in golem.execute_tasks(worker, tasks, payload=package, max_workers=1, timeout=timeout): print(f"Task finished: {completed}.")
async def main(): package = await vm.repo( image_hash="c0317d4db8930afde1862f27973ee2f5b766c4d50a87409406e2e23f", min_mem_gib=2, min_storage_gib=2.5, ) async def worker_train_model(ctx: WorkContext, tasks): async for task in tasks: global_round = task.data['global_round'] node_id = task.data['node_id'] model_path = os.path.join(ROUND_WEIGHTS_FOLDER, f'round_{global_round - 1}.h5') ctx.send_file(model_path, f"/golem/work/model_{global_round - 1}.h5") specs = { 'start': task.data['start'], 'end': task.data['end'], 'batch_size': BATCH_SIZE, 'model_path': f'model_{global_round - 1}.h5', 'epochs': PROVIDER_EPOCHS, 'global_round': task.data['global_round'], 'node_number': task.data['node_id'] } ctx.send_json( "/golem/work/specs.json", specs, ) ctx.send_file('client.py', "/golem/work/client.py") ctx.run("/bin/sh", "-c", "python3 client.py") node_model_output = f'/golem/output/model_round_{global_round}_{node_id}.h5' node_log_file = f'/golem/output/log_round_{global_round}_{node_id}.json' ctx.download_file( node_model_output, os.path.join(WORKER_MODEL_WEIGHTS_FOLDER, f'round_{global_round}_worker_{node_id}.h5')) ctx.download_file( node_log_file, os.path.join( WORKER_LOGS_FOLDER, f'log_round_{global_round}_worker_{node_id}.json')) yield ctx.commit(timeout=timedelta(minutes=7)) task.accept_result() print(f"{TEXT_COLOR_GREEN}" f"Initialising your model." f"{TEXT_COLOR_DEFAULT}") model = get_compiled_model() print(f"{TEXT_COLOR_GREEN}" f"Loading the data" f"{TEXT_COLOR_DEFAULT}") training_dataset, testing_dataset, train_length, test_length = load_dataset( BATCH_SIZE) print(f"{TEXT_COLOR_GREEN}" f"Initial model evaluation - " f"{TEXT_COLOR_DEFAULT}") eval_results = model.evaluate(testing_dataset) print(f"{TEXT_COLOR_BLUE}" f"ROUND 0 | Loss: {eval_results[0]} | Accuracy: {eval_results[1]}" f"{TEXT_COLOR_DEFAULT}") print(f"{TEXT_COLOR_MAGENTA}" f"Saving Model Weights for round 0" f"{TEXT_COLOR_DEFAULT}") model.save(os.path.join(ROUND_WEIGHTS_FOLDER, 'round_0.h5')) for global_round_number in range(1, GLOBAL_TRAINING_ROUNDS + 1): print(f"{TEXT_COLOR_GREEN}" f"Beginning Training Round {global_round_number}" f"{TEXT_COLOR_DEFAULT}") async with Executor( package=package, max_workers=NUM_PROVIDERS, budget=20.0, timeout=timedelta(minutes=29), subnet_tag=SUBNET_TAG, event_consumer=log_summary(log_event_repr), ) as executor: # No problem if we miss a few samples training_subset_steps = int(train_length / NUM_PROVIDERS) executor_tasks = [ Task( data={ 'start': x, 'end': x + training_subset_steps, 'global_round': global_round_number, 'node_id': index + 1 }) for index, x in enumerate( list(range(0, train_length, training_subset_steps))) ] async for task in executor.submit(worker_train_model, executor_tasks): print( f"{TEXT_COLOR_CYAN}" f"Training round {global_round_number} completed on provider node {task.data['node_id']}" f"{TEXT_COLOR_DEFAULT}") all_worker_weights = get_client_model_weights( WORKER_MODEL_WEIGHTS_FOLDER, global_round_number) averaged_weights = federated_avg_weights(all_worker_weights) model.set_weights(averaged_weights) print(f"{TEXT_COLOR_GREEN}" f"TRAINING ROUND {global_round_number} complete!" f"{TEXT_COLOR_DEFAULT}") eval_results = model.evaluate(testing_dataset) print( f"{TEXT_COLOR_BLUE}" f"ROUND {global_round_number} | Loss: {eval_results[0]} | Accuracy: {eval_results[1]}" f"{TEXT_COLOR_DEFAULT}") print(f"{TEXT_COLOR_MAGENTA}" f"Saving Model Weights for round {global_round_number}" f"{TEXT_COLOR_DEFAULT}") model.save( os.path.join(ROUND_WEIGHTS_FOLDER, f'round_{global_round_number}.h5'))
async def main(args): package = await vm.repo( image_hash="055911c811e56da4d75ffc928361a78ed13077933ffa8320fb1ec2db", min_mem_gib=0.5, min_storage_gib=2.0, ) async with Golem( budget=10.0, subnet_tag=args.subnet_tag, payment_driver=args.payment_driver, payment_network=args.payment_network, ) as golem: print_env_info(golem) start_time = datetime.now() completed = golem.execute_tasks( compute_keyspace, [Task(data="compute_keyspace")], payload=package, timeout=KEYSPACE_TIMEOUT_ALL_TASKS, ) keyspace = 0 async for task in completed: keyspace = task.result print( f"{TEXT_COLOR_CYAN}" f"Task computed: keyspace size count. The keyspace size is {keyspace}" f"{TEXT_COLOR_DEFAULT}" ) data = (Task(data=c) for c in range(0, keyspace, args.chunk_size)) max_workers = args.max_workers or math.ceil(keyspace / args.chunk_size) // 2 completed = golem.execute_tasks( perform_mask_attack, data, payload=package, max_workers=max_workers, timeout=MASK_ATTACK_TIMEOUT, ) password = None async for task in completed: print( f"{TEXT_COLOR_CYAN}Task computed: {task}, result: {task.result}{TEXT_COLOR_DEFAULT}" ) result = _parse_result(task.result) if result: password = result if password: print(f"{TEXT_COLOR_GREEN}Password found: {password}{TEXT_COLOR_DEFAULT}") else: print(f"{TEXT_COLOR_RED}No password found{TEXT_COLOR_DEFAULT}") print(f"{TEXT_COLOR_CYAN}Total time: {datetime.now() - start_time}{TEXT_COLOR_DEFAULT}")
async def intermediate_tasks(): async for task in computed_input_tasks: print(f"ALEF computed task: {task.data} -> {task.result}", file=sys.stderr) yield Task(data=task.result)
async def main(): vm_package = await vm.repo( image_hash="9a3b5d67b0b27746283cb5f287c13eab1beaa12d92a9f536b747c7ae", min_mem_gib=0.5, min_storage_gib=2.0, ) first_task = True async def duplicator(work_ctx, tasks): """A worker that executes `echo {task.data} {task.data}` command on provider. The command's output is the result of the whole task. The first ever task computed by an instance of this worker fails. It succeeds when re-tried. This may be used to test re-trying tasks, creating new agreements and displaying summary information on task/activity failures. """ async for task in tasks: nonlocal first_task script = work_ctx.new_script() if first_task: first_task = False script.run("/bin/sleep", "1") script.run("/command/not/found") script.run("/bin/sleep", "1") future_result = script.run("/bin/echo", task.data, task.data) yield script result = await future_result output = result.stdout.strip() task.accept_result(output) async with Golem(budget=1.0, subnet_tag="goth") as golem: # Construct a pipeline: # # input_tasks # | # V # [ Job ALEF ] # | # V # intermediate_tasks # | # V # [ Job BET ] # | # V # output_tasks input_tasks = [Task(s) for s in "01234567"] computed_input_tasks = golem.execute_tasks( duplicator, input_tasks, payload=vm_package, max_workers=1, job_id="ALEF", ) async def intermediate_tasks(): async for task in computed_input_tasks: print(f"ALEF computed task: {task.data} -> {task.result}", file=sys.stderr) yield Task(data=task.result) output_tasks = golem.execute_tasks( duplicator, intermediate_tasks(), payload=vm_package, max_workers=1, job_id="BET", ) async for task in output_tasks: print(f"BET computed task: {task.data} -> {task.result}", file=sys.stderr)
async def test_demand_resubscription(log_dir: Path, goth_config_path: Path, monkeypatch) -> None: """Test that checks that a demand is re-submitted after its previous submission expires.""" configure_logging(log_dir) # Override the default test configuration to create only one provider node nodes = [ { "name": "requestor", "type": "Requestor" }, { "name": "provider-1", "type": "VM-Wasm-Provider", "use-proxy": True }, ] goth_config = load_yaml(goth_config_path, [("nodes", nodes)]) vm_package = await vm.repo( image_hash="9a3b5d67b0b27746283cb5f287c13eab1beaa12d92a9f536b747c7ae", min_mem_gib=0.5, min_storage_gib=2.0, ) runner = Runner(base_log_dir=log_dir, compose_config=goth_config.compose_config) async with runner(goth_config.containers): requestor = runner.get_probes(probe_type=RequestorProbe)[0] env = dict(os.environ) env.update(requestor.get_agent_env_vars()) # Setup the environment for the requestor for key, val in env.items(): monkeypatch.setenv(key, val) monitor = EventMonitor() monitor.add_assertion(assert_demand_resubscribed) monitor.start() # The requestor enable_default_logger() async def worker(work_ctx, tasks): async for task in tasks: script = work_ctx.new_script() script.run("/bin/sleep", "5") yield script task.accept_result() async with Golem( budget=10.0, event_consumer=monitor.add_event_sync, ) as golem: task: Task # mypy needs this for some reason async for task in golem.execute_tasks( worker, [Task(data=n) for n in range(20)], vm_package, max_workers=1, timeout=timedelta(seconds=30), ): logger.info("Task %d computed", task.data) await monitor.stop() for a in monitor.failed: raise a.result()
async def main(golem, show_usage, min_cpu_threads): print_env_info(golem) package = await vm.repo( image_hash="9a3b5d67b0b27746283cb5f287c13eab1beaa12d92a9f536b747c7ae", # only run on provider nodes that have more than 0.5gb of RAM available min_mem_gib=0.5, # only run on provider nodes that have more than 2gb of storage space available min_storage_gib=2.0, # only run on provider nodes which a certain number of CPU threads available min_cpu_threads=min_cpu_threads, ) async def worker(ctx: WorkContext, tasks): script_dir = pathlib.Path(__file__).resolve().parent scene_path = str(script_dir / "cubes.blend") # Set timeout for the first script executed on the provider. Usually, 30 seconds # should be more than enough for computing a single frame of the provided scene, # however a provider may require more time for the first task if it needs to download # the VM image first. Once downloaded, the VM image will be cached and other tasks that use # that image will be computed faster. script = ctx.new_script(timeout=timedelta(minutes=10)) script.upload_file(scene_path, "/golem/resource/scene.blend") async for task in tasks: frame = task.data crops = [{"outfilebasename": "out", "borders_x": [0.0, 1.0], "borders_y": [0.0, 1.0]}] script.upload_json( { "scene_file": "/golem/resource/scene.blend", "resolution": (400, 300), "use_compositing": False, "crops": crops, "samples": 100, "frames": [frame], "output_format": "PNG", "RESOURCES_DIR": "/golem/resources", "WORK_DIR": "/golem/work", "OUTPUT_DIR": "/golem/output", }, "/golem/work/params.json", ) script.run("/golem/entrypoints/run-blender.sh") output_file = f"output_{frame}.png" script.download_file(f"/golem/output/out{frame:04d}.png", output_file) try: yield script # TODO: Check if job results are valid # and reject by: task.reject_task(reason = 'invalid file') task.accept_result(result=output_file) except BatchTimeoutError: print( f"{TEXT_COLOR_RED}" f"Task {task} timed out on {ctx.provider_name}, time: {task.running_time}" f"{TEXT_COLOR_DEFAULT}" ) raise # reinitialize the script which we send to the engine to compute subsequent frames script = ctx.new_script(timeout=timedelta(minutes=1)) if show_usage: raw_state = await ctx.get_raw_state() usage = format_usage(await ctx.get_usage()) cost = await ctx.get_cost() print( f"{TEXT_COLOR_MAGENTA}" f" --- {ctx.provider_name} STATE: {raw_state}\n" f" --- {ctx.provider_name} USAGE: {usage}\n" f" --- {ctx.provider_name} COST: {cost}" f"{TEXT_COLOR_DEFAULT}" ) # Iterator over the frame indices that we want to render frames: range = range(0, 60, 10) # Worst-case overhead, in minutes, for initialization (negotiation, file transfer etc.) # TODO: make this dynamic, e.g. depending on the size of files to transfer init_overhead = 3 # Providers will not accept work if the timeout is outside of the [5 min, 30min] range. # We increase the lower bound to 6 min to account for the time needed for our demand to # reach the providers. min_timeout, max_timeout = 6, 30 timeout = timedelta(minutes=max(min(init_overhead + len(frames) * 2, max_timeout), min_timeout)) num_tasks = 0 start_time = datetime.now() try: await golem.start() completed_tasks = golem.execute_tasks( worker, [Task(data=frame) for frame in frames], payload=package, max_workers=3, timeout=timeout, ) async for task in completed_tasks: num_tasks += 1 print( f"{TEXT_COLOR_CYAN}" f"Task computed: {task}, result: {task.result}, time: {task.running_time}" f"{TEXT_COLOR_DEFAULT}" ) print( f"{TEXT_COLOR_CYAN}" f"{num_tasks} tasks computed, total time: {datetime.now() - start_time}" f"{TEXT_COLOR_DEFAULT}" ) finally: await golem.stop()
async def main(args): package = await vm.repo( image_hash="2c17589f1651baff9b82aa431850e296455777be265c2c5446c902e9", min_mem_gib=0.5, min_storage_gib=2.0, ) async def worker_check_keyspace(ctx: WorkContext, tasks): async for task in tasks: keyspace_sh_filename = "keyspace.sh" ctx.send_file(keyspace_sh_filename, "/golem/work/keyspace.sh") ctx.run("/bin/sh", "/golem/work/keyspace.sh") output_file = "keyspace.txt" ctx.download_file("/golem/work/keyspace.txt", output_file) yield ctx.commit() task.accept_result() async def worker_find_password(ctx: WorkContext, tasks): ctx.send_file("in.hash", "/golem/work/in.hash") async for task in tasks: skip = task.data limit = skip + step # Commands to be run on the provider commands = ( "rm -f /golem/work/*.potfile ~/.hashcat/hashcat.potfile; " f"touch /golem/work/hashcat_{skip}.potfile; " f"hashcat -a 3 -m 400 /golem/work/in.hash {args.mask} --skip={skip} --limit={limit} --self-test-disable -o /golem/work/hashcat_{skip}.potfile || true" ) ctx.run(f"/bin/sh", "-c", commands) output_file = f"hashcat_{skip}.potfile" ctx.download_file(f"/golem/work/hashcat_{skip}.potfile", output_file) yield ctx.commit() task.accept_result(result=output_file) # beginning of the main flow write_hash(args.hash) write_keyspace_check_script(args.mask) # By passing `event_consumer=log_summary()` we enable summary logging. # See the documentation of the `yapapi.log` module on how to set # the level of detail and format of the logged information. async with Executor( package=package, max_workers=args.number_of_providers, budget=10.0, # timeout should be keyspace / number of providers dependent timeout=timedelta(minutes=25), subnet_tag=args.subnet_tag, event_consumer=log_summary(log_event_repr), ) as executor: keyspace_computed = False # This is not a typical use of executor.submit as there is only one task, with no data: async for _task in executor.submit(worker_check_keyspace, [Task(data=None)]): keyspace_computed = True if not keyspace_computed: # Assume the errors have been already reported and we may return quietly. return keyspace = read_keyspace() print( f"{utils.TEXT_COLOR_CYAN}" f"Task computed: keyspace size count. The keyspace size is {keyspace}" f"{utils.TEXT_COLOR_DEFAULT}") step = int(keyspace / args.number_of_providers) + 1 ranges = range(0, keyspace, step) async for task in executor.submit( worker_find_password, [Task(data=range) for range in ranges]): print(f"{utils.TEXT_COLOR_CYAN}" f"Task computed: {task}, result: {task.result}" f"{utils.TEXT_COLOR_DEFAULT}") password = read_password(ranges) if password is None: print( f"{utils.TEXT_COLOR_RED}No password found{utils.TEXT_COLOR_DEFAULT}" ) else: print(f"{utils.TEXT_COLOR_GREEN}" f"Password found: {password}" f"{utils.TEXT_COLOR_DEFAULT}")
async def main(subnet_tag: str): package = await vm.repo( image_hash="9a3b5d67b0b27746283cb5f287c13eab1beaa12d92a9f536b747c7ae", min_mem_gib=0.5, min_storage_gib=2.0, ) async def worker(ctx: WorkContext, tasks): scene_path = str(script_dir / "cubes.blend") ctx.send_file(scene_path, "/golem/resource/scene.blend") async for task in tasks: frame = task.data crops = [{ "outfilebasename": "out", "borders_x": [0.0, 1.0], "borders_y": [0.0, 1.0] }] ctx.send_json( "/golem/work/params.json", { "scene_file": "/golem/resource/scene.blend", "resolution": (400, 300), "use_compositing": False, "crops": crops, "samples": 100, "frames": [frame], "output_format": "PNG", "RESOURCES_DIR": "/golem/resources", "WORK_DIR": "/golem/work", "OUTPUT_DIR": "/golem/output", }, ) ctx.run("/golem/entrypoints/run-blender.sh") output_file = f"output_{frame}.png" ctx.download_file(f"/golem/output/out{frame:04d}.png", output_file) try: # Set timeout for executing the script on the provider. Two minutes is plenty # of time for computing a single frame, for other tasks it may be not enough. # If the timeout is exceeded, this worker instance will be shut down and all # remaining tasks, including the current one, will be computed by other providers. yield ctx.commit(timeout=timedelta(seconds=120)) # TODO: Check if job results are valid # and reject by: task.reject_task(reason = 'invalid file') task.accept_result(result=output_file) except BatchTimeoutError: print(f"{utils.TEXT_COLOR_RED}" f"Task timed out: {task}, time: {task.running_time}" f"{utils.TEXT_COLOR_DEFAULT}") raise # Iterator over the frame indices that we want to render frames: range = range(0, 60, 10) # Worst-case overhead, in minutes, for initialization (negotiation, file transfer etc.) # TODO: make this dynamic, e.g. depending on the size of files to transfer init_overhead = 3 # Providers will not accept work if the timeout is outside of the [5 min, 30min] range. # We increase the lower bound to 6 min to account for the time needed for our demand to # reach the providers. min_timeout, max_timeout = 6, 30 timeout = timedelta( minutes=max(min(init_overhead + len(frames) * 2, max_timeout), min_timeout)) # By passing `event_consumer=log_summary()` we enable summary logging. # See the documentation of the `yapapi.log` module on how to set # the level of detail and format of the logged information. async with Executor( package=package, max_workers=3, budget=10.0, timeout=timeout, subnet_tag=subnet_tag, event_consumer=log_summary(log_event_repr), ) as executor: async for task in executor.submit( worker, [Task(data=frame) for frame in frames]): print( f"{utils.TEXT_COLOR_CYAN}" f"Task computed: {task}, result: {task.result}, time: {task.running_time}" f"{utils.TEXT_COLOR_DEFAULT}")
async def main(subnet_tag, payment_driver=None, payment_network=None): package = await vm.repo( image_hash="a23ce2c0c29ea9711e4a293a2805700e2f0cb6450fddf9506812eb1b", min_mem_gib=0.5, min_storage_gib=2.0, ) tasks = [() for _ in range(10)] async def worker(ctx: WorkContext, tasks): async for task in tasks: output_file = f"output_{datetime.now()}_{random.random()}.txt" script = ctx.new_script(timeout=timedelta(minutes=10)) script.run("/usr/bin/stress-ng", "--cpu", "1", "--timeout", "1") script.run("/golem/task.sh", "-o", "1024", "-t", "5") script.run("/golem/task.sh", "-f", "/golem/output/output.txt,1048576") script.download_file(f"/golem/output/output.txt", output_file) script.run("/golem/task.sh", "-e", "1024", "-t", "5") try: yield script task.accept_result(result=output_file) except BatchTimeoutError: print( f"{TEXT_COLOR_RED}" f"Task {task} timed out on {ctx.provider_name}, time: {task.running_time}" f"{TEXT_COLOR_DEFAULT}") raise async with Golem( budget=10.0, subnet_tag=subnet_tag, payment_driver=payment_driver, payment_network=payment_network, ) as golem: print( f"yapapi version: {TEXT_COLOR_YELLOW}{yapapi_version}{TEXT_COLOR_DEFAULT}\n" f"Using subnet: {TEXT_COLOR_YELLOW}{subnet_tag}{TEXT_COLOR_DEFAULT}, " f"payment driver: {TEXT_COLOR_YELLOW}{golem.payment_driver}{TEXT_COLOR_DEFAULT}, " f"and network: {TEXT_COLOR_YELLOW}{golem.payment_network}{TEXT_COLOR_DEFAULT}\n" ) num_tasks = 0 start_time = datetime.now() completed_tasks = golem.execute_tasks( worker, [Task(data=data) for data in tasks], payload=package, max_workers=50, timeout=timedelta(minutes=30), ) async for task in completed_tasks: num_tasks += 1 print( f"{TEXT_COLOR_CYAN}" f"Task computed: {task}, result: {task.result}, time: {task.running_time}" f"{TEXT_COLOR_DEFAULT}") print( f"{TEXT_COLOR_CYAN}" f"{num_tasks} tasks computed, total time: {datetime.now() - start_time}" f"{TEXT_COLOR_DEFAULT}")
async def main(subnet_tag, driver=None, network=None): package = await vm.repo( image_hash="2c5d9a80847eb147261c4e33df6e6955666ddd932ec40fd8b005f799", min_mem_gib=1, min_storage_gib=10.0, ) async def worker(ctx: WorkContext, tasks): script_dir = pathlib.Path(__file__).resolve().parent async for task in tasks: frame = task.data ctx.run("/bin/sh", "-c", "./generate_data.sh") output_file = f"output/{frame}.zip" ctx.download_file(f"/golem/output/data.zip", output_file) try: # Set timeout for executing the script on the provider. Two minutes is plenty # of time for computing a single frame, for other tasks it may be not enough. # If the timeout is exceeded, this worker instance will be shut down and all # remaining tasks, including the current one, will be computed by other providers. yield ctx.commit(timeout=timedelta(seconds=1750)) # TODO: Check if job results are valid # and reject by: task.reject_task(reason = 'invalid file') task.accept_result(result=output_file) except BatchTimeoutError: print( f"{TEXT_COLOR_RED}" f"Task {task} timed out on {ctx.provider_name}, time: {task.running_time}" f"{TEXT_COLOR_DEFAULT}") raise # Iterator over the frame indices that we want to render frames: range = range( 0, 60, ) # Worst-case overhead, in minutes, for initialization (negotiation, file transfer etc.) # TODO: make this dynamic, e.g. depending on the size of files to transfer init_overhead = 3 # Providers will not accept work if the timeout is outside of the [5 min, 30min] range. # We increase the lower bound to 6 min to account for the time needed for our demand to # reach the providers. min_timeout, max_timeout = 6, 30 timeout = timedelta( minutes=max(min(init_overhead + len(frames) * 2, max_timeout), min_timeout)) # By passing `event_consumer=log_summary()` we enable summary logging. # See the documentation of the `yapapi.log` module on how to set # the level of detail and format of the logged information. async with Executor( package=package, max_workers=30, budget=10.0, timeout=timeout, subnet_tag=subnet_tag, driver=driver, network=network, event_consumer=log_summary(log_event_repr), ) as executor: sys.stderr.write( f"yapapi version: {TEXT_COLOR_YELLOW}{yapapi_version}{TEXT_COLOR_DEFAULT}\n" f"Using subnet: {TEXT_COLOR_YELLOW}{subnet_tag}{TEXT_COLOR_DEFAULT}, " f"payment driver: {TEXT_COLOR_YELLOW}{executor.driver}{TEXT_COLOR_DEFAULT}, " f"and network: {TEXT_COLOR_YELLOW}{executor.network}{TEXT_COLOR_DEFAULT}\n" ) num_tasks = 0 start_time = datetime.now() async for task in executor.submit( worker, [Task(data=frame) for frame in frames]): num_tasks += 1 print( f"{TEXT_COLOR_CYAN}" f"Task computed: {task}, result: {task.result}, time: {task.running_time}" f"{TEXT_COLOR_DEFAULT}") print( f"{TEXT_COLOR_CYAN}" f"{num_tasks} tasks computed, total time: {datetime.now() - start_time}" f"{TEXT_COLOR_DEFAULT}")