OPTaaS can facilitate parallel computation, where you generate a batch of configurations, pass them to a number of workers to calculate the results, and then store the results to get the next batch of configurations.
from mindfoundry.optaas.client.client import OPTaaSClient
client = OPTaaSClient('https://optaas.mindfoundry.ai', '<Your OPTaaS API key>')
from mindfoundry.optaas.client.parameter import FloatParameter
task = client.create_task(
title='Batching Example',
parameters=[
FloatParameter('x', minimum=0, maximum=1),
FloatParameter('y', minimum=0.1, maximum=2)
]
)
This is just a simple example of how you would pass a Configuration to a worker and get a Result back. Your process will of course likely be more complex!
The number of workers will depend on how much processing power you have available. In order to get the best quality configurations from OPTaaS, we recommend using no more than 10.
from multiprocessing import Pool
from time import sleep
from mindfoundry.optaas.client.result import Result
number_of_workers = 4
def spin_off_workers_and_get_results(configurations):
with Pool(number_of_workers) as pool:
return pool.map(get_result, configurations)
def get_result(configuration):
x = configuration.values['x']
y = configuration.values['y']
sleep(1) # Calculating score...
score = (x * y) - (x / y)
return Result(configuration=configuration, score=score)
configurations = task.generate_configurations(number_of_workers)
display(configurations)
[{'type': 'default', 'values': {'x': 0.5, 'y': 1.05}}, { 'type': 'exploration', 'values': {'x': 0.5515729001609302, 'y': 0.9539107654962646}}, { 'type': 'exploration', 'values': {'x': 0.4024718947116285, 'y': 0.6400426939913346}}, { 'type': 'exploration', 'values': {'x': 0.8954369174051902, 'y': 0.2679197390779888}}]
The next batch will be the same size as the number of results you record.
number_of_batches = 3
for _ in range(number_of_batches):
results = spin_off_workers_and_get_results(configurations)
print(f"Scores: {[result.score for result in results]}\n")
configurations = task.record_results(results)
print(f"Next configurations: {[c.values for c in configurations]}\n")
Scores: [0.04880952380952386, 0.32982698432350455, -3.5595532282188787, 0.19394652746118213] Next configurations: [{'x': 0.6177680922768689, 'y': 0.450418600138205}, {'x': 0.08624546027300994, 'y': 1.810425236962426}, {'x': 0.2448349778331208, 'y': 0.3929881953445803}, {'x': 0.11298400991785473, 'y': 0.44078687252193205}] Scores: [-1.0932879041023202, 0.10850272429629561, -0.5267912228698785, -0.20652157717292371] Next configurations: [{'x': 0.12110706920922909, 'y': 0.9073183154180738}, {'x': 0.5814744623833986, 'y': 1.9081733977000617}, {'x': 0.07067751248062448, 'y': 1.4424042554392127}, {'x': 0.1581821251140786, 'y': 1.4039505211339234}] Scores: [-0.023595376669542353, 0.8048257865186552, 0.05294575000372527, 0.10941057509098914] Next configurations: [{'x': 0.99999998, 'y': 1.99999998}, {'x': 0.99999998, 'y': 1.99999998}, {'x': 0.99999998, 'y': 1.99999998}, {'x': 0.99999998, 'y': 1.99999998}]