Unified representation
Run code and inspect results using the same abstraction. Check out the example below ⏬
From be905d801d83490d9f674f534607b7e95be5434c Mon Sep 17 00:00:00 2001
From: frthjf 404 Integration to launch MPI jobs. A way to assert that components have been cached. Integration to submit to the Slurm scheduler. If the execution is successful, the component is marked as finished. By design, component instances can only be executed once. They are automatically assigned a timestamp, random seed, as well as a nickname for easy identification. Invocations of Components can be executed in different ways. You may, for example, like to run components using multiprocessing or execute in a cloud environment. However, instead of adding the execution logic directly to your component code, machinable makes it easy to separate concerns. You can encapsulate the execution implementation in its own execution class that can then be used to execute the component. Invocations of Components can be executed in different ways. You may, for example, like to run components using multiprocessing or execute in a cloud environment. However, instead of adding the execution logic directly to your component code, machinable makes it easy to separate concerns. You can encapsulate the execution implementation in its own execution class that can then be used to execute the component. The benefit of this requirement is that you can refer to the classes via their module import path. For example, using this module convention, you can simplify the instantiation of classes that are located in different modules: The benefit of this requirement is that you can refer to the classes via their module import path. For example, using this module convention, you can simplify the instantiation of classes that are located in different modules: Overall, interfaces make it easy to associate data with code as instantiation, storage and retrieval are managed automatically behind the scenes. Overall, interfaces make it easy to associate data with code as instantiation, storage and retrieval are managed automatically behind the scenes. machinable is a Python API for research code. It provides an object-oriented skeleton that helps you develop and experiment in a unified interface while handling tedious housekeeping behind the scenes. The key idea is to unify the running of code and the retrieval of produced results in one abstraction. A detailed discussion of this approach can be found in the about section, but for now, here is a minimal example that illustrates the idea. machinable is a Python API for research code. It provides an object-oriented skeleton that helps you develop and experiment in a unified interface while handling tedious housekeeping behind the scenes. The key idea is to unify the running of code and the retrieval of produced results in one abstraction. A detailed discussion of this approach can be found in the about section, but for now, here is a minimal example that illustrates the idea.PAGE NOT FOUND
But if you don't change your direction, and if you keep looking, you may end up where you are heading.
Source
from typing import List, Optional
+# your code
Source
from typing import List, Optional
import os
diff --git a/assets/examples_aimstack-storage_index.md.880b0b35.lean.js b/assets/examples_aimstack-storage_index.md.e95360b0.lean.js
similarity index 100%
rename from assets/examples_aimstack-storage_index.md.880b0b35.lean.js
rename to assets/examples_aimstack-storage_index.md.e95360b0.lean.js
diff --git a/assets/examples_globus-storage_index.md.68197128.js b/assets/examples_globus-storage_index.md.620b6419.js
similarity index 99%
rename from assets/examples_globus-storage_index.md.68197128.js
rename to assets/examples_globus-storage_index.md.620b6419.js
index 97c423c1..771dd36a 100644
--- a/assets/examples_globus-storage_index.md.68197128.js
+++ b/assets/examples_globus-storage_index.md.620b6419.js
@@ -13,7 +13,7 @@ import{_ as s,o as n,c as a,O as l}from"./chunks/framework.62020867.js";const i=
print(matches)
# download from globus
-storage.download(matches[0].uuid)
Source
from typing import TYPE_CHECKING, List
+storage.download(matches[0].uuid)
Source
from typing import TYPE_CHECKING, List
import os
import time
diff --git a/assets/examples_globus-storage_index.md.68197128.lean.js b/assets/examples_globus-storage_index.md.620b6419.lean.js
similarity index 100%
rename from assets/examples_globus-storage_index.md.68197128.lean.js
rename to assets/examples_globus-storage_index.md.620b6419.lean.js
diff --git a/assets/examples_mpi-execution_index.md.e2d88fe1.js b/assets/examples_mpi-execution_index.md.5075bb2c.js
similarity index 99%
rename from assets/examples_mpi-execution_index.md.e2d88fe1.js
rename to assets/examples_mpi-execution_index.md.5075bb2c.js
index 4658efb5..4c95a632 100644
--- a/assets/examples_mpi-execution_index.md.e2d88fe1.js
+++ b/assets/examples_mpi-execution_index.md.5075bb2c.js
@@ -1,7 +1,7 @@
import{_ as s,o as n,c as a,O as l}from"./chunks/framework.62020867.js";const i=JSON.parse('{"title":"MPI execution","description":"","frontmatter":{},"headers":[],"relativePath":"examples/mpi-execution/index.md","filePath":"examples/mpi-execution/index.md"}'),p={name:"examples/mpi-execution/index.md"},o=l(`
MPI execution
Usage example
from machinable import get
with get("mpi", {"ranks": 8}):
- ... # your MPI ready component
Source
from typing import Literal, Optional, Union
+ ... # your MPI ready component
Source
from typing import Literal, Optional, Union
import sys
diff --git a/assets/examples_mpi-execution_index.md.e2d88fe1.lean.js b/assets/examples_mpi-execution_index.md.5075bb2c.lean.js
similarity index 100%
rename from assets/examples_mpi-execution_index.md.e2d88fe1.lean.js
rename to assets/examples_mpi-execution_index.md.5075bb2c.lean.js
diff --git a/assets/examples_require-execution_index.md.36bcc19a.js b/assets/examples_require-execution_index.md.9f45fc51.js
similarity index 98%
rename from assets/examples_require-execution_index.md.36bcc19a.js
rename to assets/examples_require-execution_index.md.9f45fc51.js
index 2ff7ef4e..4076e430 100644
--- a/assets/examples_require-execution_index.md.36bcc19a.js
+++ b/assets/examples_require-execution_index.md.9f45fc51.js
@@ -1,7 +1,7 @@
import{_ as s,o as a,c as n,O as l}from"./chunks/framework.62020867.js";const C=JSON.parse('{"title":"Require execution","description":"","frontmatter":{},"headers":[],"relativePath":"examples/require-execution/index.md","filePath":"examples/require-execution/index.md"}'),p={name:"examples/require-execution/index.md"},o=l(`
Require execution
Usage example
from machinable import get
with get("require"):
- ... # components to check
Source
from machinable import Execution
+ ... # components to check
Source
from machinable import Execution
class Require(Execution):
diff --git a/assets/examples_require-execution_index.md.36bcc19a.lean.js b/assets/examples_require-execution_index.md.9f45fc51.lean.js
similarity index 100%
rename from assets/examples_require-execution_index.md.36bcc19a.lean.js
rename to assets/examples_require-execution_index.md.9f45fc51.lean.js
diff --git a/assets/examples_slurm-execution_index.md.b1b1e5c2.js b/assets/examples_slurm-execution_index.md.292b100f.js
similarity index 97%
rename from assets/examples_slurm-execution_index.md.b1b1e5c2.js
rename to assets/examples_slurm-execution_index.md.292b100f.js
index ffd44a78..34b497b3 100644
--- a/assets/examples_slurm-execution_index.md.b1b1e5c2.js
+++ b/assets/examples_slurm-execution_index.md.292b100f.js
@@ -1,15 +1,17 @@
import{_ as s,o as n,c as a,O as l}from"./chunks/framework.62020867.js";const i=JSON.parse('{"title":"Slurm execution","description":"","frontmatter":{},"headers":[],"relativePath":"examples/slurm-execution/index.md","filePath":"examples/slurm-execution/index.md"}'),o={name:"examples/slurm-execution/index.md"},p=l(`
Slurm execution
Usage example
from machinable import get
with get("slurm", {"ranks": 8, 'preamble': 'mpirun'}):
- ... # your component
Source
from typing import Literal, Optional, Union
+ ... # your component
Source
from typing import Literal, Optional, Union
import os
import subprocess
import sys
import time
+import arrow
import yaml
from machinable import Execution, Project
+from machinable.config import to_dict
from machinable.errors import ExecutionFailed
from machinable.utils import chmodx, run_and_stream
from pydantic import BaseModel, ConfigDict
@@ -104,7 +106,7 @@ import{_ as s,o as n,c as a,O as l}from"./chunks/framework.62020867.js";const i=
dry: bool = False
def on_before_dispatch(self):
- if self.config.confirm:
+ if self.config.confirm and not self.config.dry:
return confirm(self)
def on_compute_default_resources(self, executable):
@@ -170,8 +172,6 @@ import{_ as s,o as n,c as a,O as l}from"./chunks/framework.62020867.js";const i=
if ranks is not None:
if mpi_args:
mpi_args = mpi_args.replace("{ranks}", str(ranks))
- else:
- mpi_args = "-n " + str(executable.config.get("ranks"))
python = self.config.python or sys.executable
# usage dependencies
@@ -211,12 +211,6 @@ import{_ as s,o as n,c as a,O as l}from"./chunks/framework.62020867.js";const i=
if self.config.preamble:
script += self.config.preamble
- # add debug information
- script += "\\n"
- script += f"# {executable.module} <{executable.id}>\\n"
- script += f"# {executable.local_directory()}>\\n"
- script += "\\n"
-
if mpi:
if mpi[-1] != " ":
mpi += " "
@@ -232,6 +226,16 @@ import{_ as s,o as n,c as a,O as l}from"./chunks/framework.62020867.js";const i=
print(f"Submitting job {executable} with resources: ")
print(yaml.dump(resources))
+ # add debug information
+ script += "\\n\\n"
+ script += f"# generated at: {arrow.now()}\\n"
+ script += f"# {executable.module} <{executable.id}>\\n"
+ script += f"# {executable.local_directory()}\\n\\n"
+ script += "# " + yaml.dump(executable.version()).replace(
+ "\\n", "\\n# "
+ )
+ script += "\\n"
+
# submit to slurm
script_file = chmodx(
self.save_file([executable.id, "slurm.sh"], script)
diff --git a/assets/examples_slurm-execution_index.md.b1b1e5c2.lean.js b/assets/examples_slurm-execution_index.md.292b100f.lean.js
similarity index 100%
rename from assets/examples_slurm-execution_index.md.b1b1e5c2.lean.js
rename to assets/examples_slurm-execution_index.md.292b100f.lean.js
diff --git a/assets/guide_component.md.771e9d5c.js b/assets/guide_component.md.8f272292.js
similarity index 99%
rename from assets/guide_component.md.771e9d5c.js
rename to assets/guide_component.md.8f272292.js
index 9e37020b..396a4329 100644
--- a/assets/guide_component.md.771e9d5c.js
+++ b/assets/guide_component.md.8f272292.js
@@ -17,7 +17,7 @@ import{_ as p,D as t,o as c,c as r,z as n,a as s,G as o,B as l,O as e}from"./chu
>>> mnist.launch()
Downloading 'mnist' ...
>>> mnist.execution.is_finished()
True
>>> mnist.seed
-1632827863
launch()
after successful execution, do not trigger another execution since the component is marked as cached. On the other hand, if the execution failed, calling launch()
will resume the execution with the same configuration.Implementing custom execution
from multiprocessing import Pool
+1632827863
launch()
after successful execution, do not trigger another execution since the component is marked as cached. On the other hand, if the execution failed, calling launch()
will resume the execution with the same configuration.Implementing custom execution
from multiprocessing import Pool
from machinable import Execution
diff --git a/assets/guide_component.md.771e9d5c.lean.js b/assets/guide_component.md.8f272292.lean.js
similarity index 100%
rename from assets/guide_component.md.771e9d5c.lean.js
rename to assets/guide_component.md.8f272292.lean.js
diff --git a/assets/guide_interface.md.0cb088fc.js b/assets/guide_interface.md.72ed9d18.js
similarity index 98%
rename from assets/guide_interface.md.0cb088fc.js
rename to assets/guide_interface.md.72ed9d18.js
index 7a05058b..b1510015 100644
--- a/assets/guide_interface.md.0cb088fc.js
+++ b/assets/guide_interface.md.72ed9d18.js
@@ -1,4 +1,4 @@
-import{_ as t,D as p,o as c,c as r,z as a,a as s,G as l,B as o,O as e}from"./chunks/framework.62020867.js";const I=JSON.parse('{"title":"Interface","description":"","frontmatter":{},"headers":[],"relativePath":"guide/interface.md","filePath":"guide/interface.md"}'),i={name:"guide/interface.md"},y=a("h1",{id:"interface",tabindex:"-1"},[s("Interface "),a("a",{class:"header-anchor",href:"#interface","aria-label":'Permalink to "Interface"'},"")],-1),D=a("p",null,[a("a",{href:"./element.html"},"Elements"),s(" by themselves are limited in that they are effectively stateless. You can construct and use them but any computed result or additional information will not be persisted.")],-1),F=e(`
from machinable import Interface
+import{_ as t,D as p,o as c,c as r,z as a,a as s,G as l,B as o,O as e}from"./chunks/framework.62020867.js";const k=JSON.parse('{"title":"Interface","description":"","frontmatter":{},"headers":[],"relativePath":"guide/interface.md","filePath":"guide/interface.md"}'),i={name:"guide/interface.md"},y=a("h1",{id:"interface",tabindex:"-1"},[s("Interface "),a("a",{class:"header-anchor",href:"#interface","aria-label":'Permalink to "Interface"'},"")],-1),D=a("p",null,[a("a",{href:"./element.html"},"Elements"),s(" by themselves are limited in that they are effectively stateless. You can construct and use them but any computed result or additional information will not be persisted.")],-1),F=e(`
from machinable import Interface
class MnistData(Interface):
"""A dataset of handwritten characters"""
@@ -21,7 +21,7 @@ import{_ as t,D as p,o as c,c as r,z as a,a as s,G as l,B as o,O as e}from"./chu
├─ estimate_gravity.py # contains a data analysis component
├─ evolution/
| └─ simulate_offspring.py # contains a evolutionary simulation
-└─ main.py # main script to execute
from machinable import get
+└─ main.py # main script to execute
from machinable import get
from estimate_gravity import EstimateGravity
from evolution.simulate_offspring import SimulateOffspring
@@ -40,4 +40,4 @@ import{_ as t,D as p,o as c,c as r,z as a,a as s,G as l,B as o,O as e}from"./chu
mnist = get("mnist_data")
with open(mnist.local_directory("download_script.sh"), "w") as f:
f.write(...)
- os.chmod(f.name, 0o755)
Introduction
What is machinable?
from random import random
+import{_ as s,o as a,c as n,O as l}from"./chunks/framework.62020867.js";const C=JSON.parse('{"title":"Introduction","description":"","frontmatter":{},"headers":[],"relativePath":"guide/introduction.md","filePath":"guide/introduction.md"}'),o={name:"guide/introduction.md"},p=l(`
Introduction
What is machinable?
from random import random
from pydantic import BaseModel, Field
@@ -26,7 +26,7 @@ import{_ as s,o as a,c as n,O as l}from"./chunks/framework.62020867.js";const C=
print(
f"After {self.config.samples} samples, "
f"PI is approximately {self.load_file('result.json')['pi']}."
- )
from machinable import get
+ )
from machinable import get
# Imports component in \`montecarlo.py\` with samples=150;
# if an component with this configuration exists, it
diff --git a/assets/guide_introduction.md.cf46eed6.lean.js b/assets/guide_introduction.md.c4095de6.lean.js
similarity index 100%
rename from assets/guide_introduction.md.cf46eed6.lean.js
rename to assets/guide_introduction.md.c4095de6.lean.js
diff --git a/examples/aimstack-storage/index.html b/examples/aimstack-storage/index.html
index dd0ca663..b751a2f2 100644
--- a/examples/aimstack-storage/index.html
+++ b/examples/aimstack-storage/index.html
@@ -11,7 +11,7 @@
-
+
@@ -28,7 +28,7 @@
get("aimstack", {"repo": "./path/to/aim-repo"}).__enter__()
-# your code
Source
from typing import List, Optional
+# your code
Source
from typing import List, Optional
import os
@@ -84,7 +84,7 @@
for k, v in interface.__model__.model_dump().items():
run[k] = v
research code
A modular system to manage research code so you can move quickly while enabling reuse and collaboration.
Run code and inspect results using the same abstraction. Check out the example below ⏬
Spend more time experimenting while relying on machinable to keep things organized.
Tweak, extend, override while leveraging first-class support for Jupyter as well as the CLI.
Some research code
Running code ...
python regression.py --rate=0.1 --logs=1 --name=run-01
... and loading the corresponding results ...
python plot_regression_result.py --component=run-01
... are distinct and often redundant.
This means you have to manually keep track by remembering what the component with rate=0.1
was called.
machinable research code
Running code ...
machinable regression rate=0.1 logs_=True --launch
... and loading the corresponding results ...
machinable regression rate=0.1 logs_=True --launch --plot
... are distinct but use the same abstraction.
This means no need to worry about names as machinable automatically keeps track if you ran rate=0.1
before.
This page contains detailed API reference documentation. It is intended to be an in-depth resource for understanding the implementation details of machinable's interfaces. You may prefer reviewing the more explanatory guide before consulting this reference.