Rename `run_program` to just `run` (#580)
* update contributing with new arm64 setup Signed-off-by: Paul S. Schweigert <paul@paulschweigert.com> * refactor run_program method to run Signed-off-by: Paul S. Schweigert <paul@paulschweigert.com> * s/run/run_program/g for docs and notebooks Signed-off-by: Paul S. Schweigert <paul@paulschweigert.com> --------- Signed-off-by: Paul S. Schweigert <paul@paulschweigert.com>
This commit is contained in:
parent
f2de405a6e
commit
0bada3fea3
|
@ -134,7 +134,7 @@ If you wish to rebuild only a specific component (for example, the `gateway`), y
|
||||||
|
|
||||||
```docker-compose -f docker-compose-dev.yml build gateway```
|
```docker-compose -f docker-compose-dev.yml build gateway```
|
||||||
|
|
||||||
For Apple Silicon system (arm64 / aarch64), use `docker-compose-dev-arm64.yml` instead of `docker-compose-dev.yml`
|
For Apple Silicon system (arm64 / aarch64), set `TARGETARCH=arm64` before running the `docker-compose` command.
|
||||||
|
|
||||||
### Assigning yourself
|
### Assigning yourself
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ Full docs can be found at https://qiskit-extensions.github.io/quantum-serverless
|
||||||
circuits.append(circuit)
|
circuits.append(circuit)
|
||||||
|
|
||||||
# run program
|
# run program
|
||||||
job = serverless.run_program(
|
job = serverless.run(
|
||||||
program=program,
|
program=program,
|
||||||
arguments={
|
arguments={
|
||||||
"circuits": circuits
|
"circuits": circuits
|
||||||
|
|
|
@ -33,6 +33,7 @@ import os
|
||||||
import tarfile
|
import tarfile
|
||||||
from typing import Dict, Any, Optional, List
|
from typing import Dict, Any, Optional, List
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
import warnings
|
||||||
|
|
||||||
import ray.runtime_env
|
import ray.runtime_env
|
||||||
import requests
|
import requests
|
||||||
|
@ -63,6 +64,12 @@ class BaseJobClient:
|
||||||
"""Runs program."""
|
"""Runs program."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def run(
|
||||||
|
self, program: Program, arguments: Optional[Dict[str, Any]] = None
|
||||||
|
) -> "Job":
|
||||||
|
"""Runs program."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def get(self, job_id) -> Optional["Job"]:
|
def get(self, job_id) -> Optional["Job"]:
|
||||||
"""Returns job by job id"""
|
"""Returns job by job id"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -121,6 +128,41 @@ class RayJobClient(BaseJobClient):
|
||||||
]
|
]
|
||||||
|
|
||||||
def run_program(self, program: Program, arguments: Optional[Dict[str, Any]] = None):
|
def run_program(self, program: Program, arguments: Optional[Dict[str, Any]] = None):
|
||||||
|
warnings.warn(
|
||||||
|
"`run_program` is deprecated. Please, consider using `run` instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
arguments = arguments or {}
|
||||||
|
arguments_string = ""
|
||||||
|
if program.arguments is not None:
|
||||||
|
arg_list = []
|
||||||
|
for key, value in arguments.items():
|
||||||
|
if isinstance(value, dict):
|
||||||
|
arg_list.append(f"--{key}='{json.dumps(value)}'")
|
||||||
|
else:
|
||||||
|
arg_list.append(f"--{key}={value}")
|
||||||
|
arguments_string = " ".join(arg_list)
|
||||||
|
entrypoint = f"python {program.entrypoint} {arguments_string}"
|
||||||
|
|
||||||
|
# set program name so OT can use it as parent span name
|
||||||
|
env_vars = {
|
||||||
|
**(program.env_vars or {}),
|
||||||
|
**{OT_PROGRAM_NAME: program.title},
|
||||||
|
}
|
||||||
|
|
||||||
|
job_id = self._job_client.submit_job(
|
||||||
|
entrypoint=entrypoint,
|
||||||
|
submission_id=f"qs_{uuid4()}",
|
||||||
|
runtime_env={
|
||||||
|
"working_dir": program.working_dir,
|
||||||
|
"pip": program.dependencies,
|
||||||
|
"env_vars": env_vars,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return Job(job_id=job_id, job_client=self)
|
||||||
|
|
||||||
|
def run(self, program: Program, arguments: Optional[Dict[str, Any]] = None):
|
||||||
arguments = arguments or {}
|
arguments = arguments or {}
|
||||||
arguments_string = ""
|
arguments_string = ""
|
||||||
if program.arguments is not None:
|
if program.arguments is not None:
|
||||||
|
@ -168,6 +210,46 @@ class GatewayJobClient(BaseJobClient):
|
||||||
|
|
||||||
def run_program( # pylint: disable=too-many-locals
|
def run_program( # pylint: disable=too-many-locals
|
||||||
self, program: Program, arguments: Optional[Dict[str, Any]] = None
|
self, program: Program, arguments: Optional[Dict[str, Any]] = None
|
||||||
|
) -> "Job":
|
||||||
|
warnings.warn(
|
||||||
|
"`run_program` is deprecated. Please, consider using `run` instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
url = f"{self.host}/api/{self.version}/programs/run/"
|
||||||
|
artifact_file_path = os.path.join(program.working_dir, "artifact.tar")
|
||||||
|
|
||||||
|
with tarfile.open(artifact_file_path, "w") as tar:
|
||||||
|
for filename in os.listdir(program.working_dir):
|
||||||
|
fpath = os.path.join(program.working_dir, filename)
|
||||||
|
tar.add(fpath, arcname=filename)
|
||||||
|
|
||||||
|
with open(artifact_file_path, "rb") as file:
|
||||||
|
response_data = safe_json_request(
|
||||||
|
request=lambda: requests.post(
|
||||||
|
url=url,
|
||||||
|
data={
|
||||||
|
"title": program.title,
|
||||||
|
"entrypoint": program.entrypoint,
|
||||||
|
"arguments": json.dumps(
|
||||||
|
arguments or {}, cls=QiskitObjectsEncoder
|
||||||
|
),
|
||||||
|
"dependencies": json.dumps(program.dependencies or []),
|
||||||
|
},
|
||||||
|
files={"artifact": file},
|
||||||
|
headers={"Authorization": f"Bearer {self._token}"},
|
||||||
|
timeout=REQUESTS_TIMEOUT,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
job_id = response_data.get("id")
|
||||||
|
|
||||||
|
if os.path.exists(artifact_file_path):
|
||||||
|
os.remove(artifact_file_path)
|
||||||
|
|
||||||
|
return Job(job_id, job_client=self)
|
||||||
|
|
||||||
|
def run( # pylint: disable=too-many-locals
|
||||||
|
self, program: Program, arguments: Optional[Dict[str, Any]] = None
|
||||||
) -> "Job":
|
) -> "Job":
|
||||||
url = f"{self.host}/api/{self.version}/programs/run/"
|
url = f"{self.host}/api/{self.version}/programs/run/"
|
||||||
artifact_file_path = os.path.join(program.working_dir, "artifact.tar")
|
artifact_file_path = os.path.join(program.working_dir, "artifact.tar")
|
||||||
|
|
|
@ -83,7 +83,7 @@ class Program: # pylint: disable=too-many-instance-attributes
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"Passing `arguments` as constructor argument to `Program` is deprecated "
|
"Passing `arguments` as constructor argument to `Program` is deprecated "
|
||||||
"and will be removed in v0.2. "
|
"and will be removed in v0.2. "
|
||||||
"Please, consider passing `arguments` to `run_program` "
|
"Please, consider passing `arguments` to `run` "
|
||||||
"method of `QuantumServerless` object.",
|
"method of `QuantumServerless` object.",
|
||||||
DeprecationWarning,
|
DeprecationWarning,
|
||||||
stacklevel=2,
|
stacklevel=2,
|
||||||
|
|
|
@ -30,6 +30,7 @@ import logging
|
||||||
import os.path
|
import os.path
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Optional, List, Dict, Any
|
from typing import Optional, List, Dict, Any
|
||||||
|
import warnings
|
||||||
|
|
||||||
import ray
|
import ray
|
||||||
import requests
|
import requests
|
||||||
|
@ -254,7 +255,7 @@ class Provider(JsonSerializable):
|
||||||
def run_program(
|
def run_program(
|
||||||
self, program: Program, arguments: Optional[Dict[str, Any]] = None
|
self, program: Program, arguments: Optional[Dict[str, Any]] = None
|
||||||
) -> Job:
|
) -> Job:
|
||||||
"""Execute a program as a async job.
|
"""(Deprecated) Execute a program as a async job.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> serverless = QuantumServerless()
|
>>> serverless = QuantumServerless()
|
||||||
|
@ -270,6 +271,43 @@ class Provider(JsonSerializable):
|
||||||
arguments: arguments to run program with
|
arguments: arguments to run program with
|
||||||
program: Program object
|
program: Program object
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Job
|
||||||
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
"`run_program` is deprecated. Please, consider using `run` instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
job_client = self.job_client()
|
||||||
|
|
||||||
|
if job_client is None:
|
||||||
|
logging.warning( # pylint: disable=logging-fstring-interpolation
|
||||||
|
f"Job has not been submitted as no provider "
|
||||||
|
f"with remote host has been configured. "
|
||||||
|
f"Selected provider: {self}"
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
return job_client.run_program(program, arguments)
|
||||||
|
|
||||||
|
def run(self, program: Program, arguments: Optional[Dict[str, Any]] = None) -> Job:
|
||||||
|
"""Execute a program as a async job.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> serverless = QuantumServerless()
|
||||||
|
>>> program = Program(
|
||||||
|
>>> "job.py",
|
||||||
|
>>> arguments={"arg1": "val1"},
|
||||||
|
>>> dependencies=["requests"]
|
||||||
|
>>> )
|
||||||
|
>>> job = serverless.run(program)
|
||||||
|
>>> # <Job | ...>
|
||||||
|
|
||||||
|
Args:
|
||||||
|
arguments: arguments to run program with
|
||||||
|
program: Program object
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Job
|
Job
|
||||||
"""
|
"""
|
||||||
|
@ -283,7 +321,7 @@ class Provider(JsonSerializable):
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return job_client.run_program(program, arguments)
|
return job_client.run(program, arguments)
|
||||||
|
|
||||||
|
|
||||||
class KuberayProvider(Provider):
|
class KuberayProvider(Provider):
|
||||||
|
@ -537,8 +575,16 @@ class GatewayProvider(Provider):
|
||||||
def run_program(
|
def run_program(
|
||||||
self, program: Program, arguments: Optional[Dict[str, Any]] = None
|
self, program: Program, arguments: Optional[Dict[str, Any]] = None
|
||||||
) -> Job:
|
) -> Job:
|
||||||
|
warnings.warn(
|
||||||
|
"`run_program` is deprecated. Please, consider using `run` instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
return self._job_client.run_program(program, arguments)
|
return self._job_client.run_program(program, arguments)
|
||||||
|
|
||||||
|
def run(self, program: Program, arguments: Optional[Dict[str, Any]] = None) -> Job:
|
||||||
|
return self._job_client.run(program, arguments)
|
||||||
|
|
||||||
def get_jobs(self, **kwargs) -> List[Job]:
|
def get_jobs(self, **kwargs) -> List[Job]:
|
||||||
return self._job_client.list(**kwargs)
|
return self._job_client.list(**kwargs)
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ class QuantumServerless:
|
||||||
def run_program(
|
def run_program(
|
||||||
self, program: Program, arguments: Optional[Dict[str, Any]] = None
|
self, program: Program, arguments: Optional[Dict[str, Any]] = None
|
||||||
) -> Optional[Job]:
|
) -> Optional[Job]:
|
||||||
"""Execute a program as a async job
|
"""(Deprecated) Execute a program as a async job
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> serverless = QuantumServerless()
|
>>> serverless = QuantumServerless()
|
||||||
|
@ -106,10 +106,40 @@ class QuantumServerless:
|
||||||
Returns:
|
Returns:
|
||||||
Job
|
Job
|
||||||
"""
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
"`run_program` is deprecated. Please, consider using `run` instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
if program.arguments is not None:
|
if program.arguments is not None:
|
||||||
arguments = program.arguments
|
arguments = program.arguments
|
||||||
return self._selected_provider.run_program(program, arguments)
|
return self._selected_provider.run_program(program, arguments)
|
||||||
|
|
||||||
|
def run(
|
||||||
|
self, program: Program, arguments: Optional[Dict[str, Any]] = None
|
||||||
|
) -> Optional[Job]:
|
||||||
|
"""Execute a program as a async job
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> serverless = QuantumServerless()
|
||||||
|
>>> program = Program(
|
||||||
|
>>> "job.py",
|
||||||
|
>>> dependencies=["requests"]
|
||||||
|
>>> )
|
||||||
|
>>> job = serverless.run(program, {"arg1": 1})
|
||||||
|
>>> # <Job | ...>
|
||||||
|
|
||||||
|
Args:
|
||||||
|
arguments: arguments to run program with
|
||||||
|
program: Program object
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Job
|
||||||
|
"""
|
||||||
|
if program.arguments is not None:
|
||||||
|
arguments = program.arguments
|
||||||
|
return self._selected_provider.run(program, arguments)
|
||||||
|
|
||||||
def get_job_by_id(self, job_id: str) -> Optional[Job]:
|
def get_job_by_id(self, job_id: str) -> Optional[Job]:
|
||||||
"""Returns job by job id.
|
"""Returns job by job id.
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ def test_program():
|
||||||
version="0.0.1",
|
version="0.0.1",
|
||||||
)
|
)
|
||||||
|
|
||||||
job = serverless.run_program(program)
|
job = serverless.run(program)
|
||||||
|
|
||||||
assert isinstance(job, Job)
|
assert isinstance(job, Job)
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ def test_state():
|
||||||
|
|
||||||
wait_for_job_client(serverless)
|
wait_for_job_client(serverless)
|
||||||
|
|
||||||
job = serverless.run_program(
|
job = serverless.run(
|
||||||
Program("test", entrypoint="job_with_state.py", working_dir=resources_path)
|
Program("test", entrypoint="job_with_state.py", working_dir=resources_path)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ program = Program(
|
||||||
working_dir="./"
|
working_dir="./"
|
||||||
)
|
)
|
||||||
|
|
||||||
job = serverless.run_program(program)
|
job = serverless.run(program)
|
||||||
|
|
||||||
job.status()
|
job.status()
|
||||||
# <JobStatus.SUCCEEDED: 'SUCCEEDED'>
|
# <JobStatus.SUCCEEDED: 'SUCCEEDED'>
|
||||||
|
|
|
@ -263,7 +263,7 @@
|
||||||
" working_dir=\"./source_files/vqe/\"\n",
|
" working_dir=\"./source_files/vqe/\"\n",
|
||||||
")\n",
|
")\n",
|
||||||
"\n",
|
"\n",
|
||||||
"job = serverless.run_program(program, arguments=input_arguments)\n",
|
"job = serverless.run(program, arguments=input_arguments)\n",
|
||||||
"job"
|
"job"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -213,7 +213,7 @@
|
||||||
" working_dir=\"./source_files/qaoa/\"\n",
|
" working_dir=\"./source_files/qaoa/\"\n",
|
||||||
")\n",
|
")\n",
|
||||||
"\n",
|
"\n",
|
||||||
"job = serverless.run_program(program, arguments=input_arguments)\n",
|
"job = serverless.run(program, arguments=input_arguments)\n",
|
||||||
"job"
|
"job"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -157,7 +157,7 @@
|
||||||
" dependencies=[\"pyscf\"]\n",
|
" dependencies=[\"pyscf\"]\n",
|
||||||
")\n",
|
")\n",
|
||||||
"\n",
|
"\n",
|
||||||
"job = serverless.run_program(program)\n",
|
"job = serverless.run(program)\n",
|
||||||
"job"
|
"job"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -94,7 +94,7 @@
|
||||||
" description=\"Benchmark program to test compute resources.\"\n",
|
" description=\"Benchmark program to test compute resources.\"\n",
|
||||||
")\n",
|
")\n",
|
||||||
"\n",
|
"\n",
|
||||||
"job = serverless.run_program(program, arguments={\n",
|
"job = serverless.run(program, arguments={\n",
|
||||||
" \"n_qubits\": 2,\n",
|
" \"n_qubits\": 2,\n",
|
||||||
" \"n_entries\": 2,\n",
|
" \"n_entries\": 2,\n",
|
||||||
" \"depth_of_recursion\": 4,\n",
|
" \"depth_of_recursion\": 4,\n",
|
||||||
|
|
|
@ -84,7 +84,7 @@ Step 3: run program
|
||||||
circuits.append(circuit)
|
circuits.append(circuit)
|
||||||
|
|
||||||
# run program
|
# run program
|
||||||
job = serverless.run_program(
|
job = serverless.run(
|
||||||
program=program,
|
program=program,
|
||||||
arguments={
|
arguments={
|
||||||
"circuits": circuits
|
"circuits": circuits
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
"id": "4dd85621-9ab0-4f34-9ab4-07ad773c5e00",
|
"id": "4dd85621-9ab0-4f34-9ab4-07ad773c5e00",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"source": [
|
"source": [
|
||||||
"After importing the necessary classes and configuring them, we can run the program by calling the `run_program()` method of the `QuantumServerless` object:\n",
|
"After importing the necessary classes and configuring them, we can run the program by calling the `run()` method of the `QuantumServerless` object:\n",
|
||||||
"\n",
|
"\n",
|
||||||
"`Program` accepts couple of required parameters:\n",
|
"`Program` accepts couple of required parameters:\n",
|
||||||
"- title - name of the program\n",
|
"- title - name of the program\n",
|
||||||
|
@ -120,7 +120,7 @@
|
||||||
" working_dir=\"./source_files/\"\n",
|
" working_dir=\"./source_files/\"\n",
|
||||||
")\n",
|
")\n",
|
||||||
"\n",
|
"\n",
|
||||||
"job = serverless.run_program(program)\n",
|
"job = serverless.run(program)\n",
|
||||||
"job"
|
"job"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -170,7 +170,7 @@
|
||||||
" working_dir=\"./source_files/\"\n",
|
" working_dir=\"./source_files/\"\n",
|
||||||
")\n",
|
")\n",
|
||||||
"\n",
|
"\n",
|
||||||
"job = serverless.run_program(program, arguments={\"circuits\": circuits})\n",
|
"job = serverless.run(program, arguments={\"circuits\": circuits})\n",
|
||||||
"job"
|
"job"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -140,7 +140,7 @@
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"source": [
|
"source": [
|
||||||
"And finally we are creating our program and running it using `run_program` method and passing `arguments` parameter in form of dictionary with `circuit` key and our circuit as value"
|
"And finally we are creating our program and running it using `run` method and passing `arguments` parameter in form of dictionary with `circuit` key and our circuit as value"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -168,7 +168,7 @@
|
||||||
" working_dir=\"./source_files/\"\n",
|
" working_dir=\"./source_files/\"\n",
|
||||||
")\n",
|
")\n",
|
||||||
"\n",
|
"\n",
|
||||||
"job = serverless.run_program(program, arguments={\"circuit\": circuit})\n",
|
"job = serverless.run(program, arguments={\"circuit\": circuit})\n",
|
||||||
"job"
|
"job"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -135,7 +135,7 @@
|
||||||
" dependencies=[\"qiskit-experiments\"]\n",
|
" dependencies=[\"qiskit-experiments\"]\n",
|
||||||
")\n",
|
")\n",
|
||||||
"\n",
|
"\n",
|
||||||
"job = serverless.run_program(program, arguments={\"circuit\": circuit})\n",
|
"job = serverless.run(program, arguments={\"circuit\": circuit})\n",
|
||||||
"job"
|
"job"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue