Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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}")
Ejemplo n.º 3
0
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}")
Ejemplo n.º 4
0
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}")
Ejemplo n.º 5
0
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")
Ejemplo n.º 6
0
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}")
Ejemplo n.º 7
0
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)
Ejemplo n.º 8
0
    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'])
Ejemplo n.º 9
0
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}.")
Ejemplo n.º 10
0
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'))
Ejemplo n.º 11
0
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}")
Ejemplo n.º 12
0
 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)
Ejemplo n.º 13
0
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)
Ejemplo n.º 14
0
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()
Ejemplo n.º 15
0
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()
Ejemplo n.º 16
0
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}")
Ejemplo n.º 17
0
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}")
Ejemplo n.º 18
0
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}")
Ejemplo n.º 19
0
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}")