Initial import: grid-bot — grid trading bot for BTC-USDT on Cifra Markets
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
# mypy: allow-untyped-defs
|
||||
r"""
|
||||
This package enables an interface for accessing MPS (Metal Performance Shaders) backend in Python.
|
||||
Metal is Apple's API for programming metal GPU (graphics processor unit). Using MPS means that increased
|
||||
performance can be achieved, by running work on the metal GPU(s).
|
||||
See https://developer.apple.com/documentation/metalperformanceshaders for more details.
|
||||
"""
|
||||
|
||||
import torch
|
||||
from torch import Tensor
|
||||
|
||||
|
||||
_is_in_bad_fork = getattr(torch._C, "_mps_is_in_bad_fork", lambda: False)
|
||||
_default_mps_generator: torch._C.Generator = None # type: ignore[assignment]
|
||||
|
||||
|
||||
# local helper function (not public or exported)
|
||||
def _get_default_mps_generator() -> torch._C.Generator:
|
||||
global _default_mps_generator
|
||||
if _default_mps_generator is None:
|
||||
_default_mps_generator = torch._C._mps_get_default_generator()
|
||||
return _default_mps_generator
|
||||
|
||||
|
||||
def device_count() -> int:
|
||||
r"""Returns the number of available MPS devices."""
|
||||
return int(torch._C._has_mps and torch._C._mps_is_available())
|
||||
|
||||
|
||||
def synchronize() -> None:
|
||||
r"""Waits for all kernels in all streams on a MPS device to complete."""
|
||||
return torch._C._mps_deviceSynchronize()
|
||||
|
||||
|
||||
def get_rng_state(device: int | str | torch.device = "mps") -> Tensor:
|
||||
r"""Returns the random number generator state as a ByteTensor.
|
||||
|
||||
Args:
|
||||
device (torch.device or int, optional): The device to return the RNG state of.
|
||||
Default: ``'mps'`` (i.e., ``torch.device('mps')``, the current MPS device).
|
||||
"""
|
||||
return _get_default_mps_generator().get_state()
|
||||
|
||||
|
||||
def set_rng_state(new_state: Tensor, device: int | str | torch.device = "mps") -> None:
|
||||
r"""Sets the random number generator state.
|
||||
|
||||
Args:
|
||||
new_state (torch.ByteTensor): The desired state
|
||||
device (torch.device or int, optional): The device to set the RNG state.
|
||||
Default: ``'mps'`` (i.e., ``torch.device('mps')``, the current MPS device).
|
||||
"""
|
||||
new_state_copy = new_state.clone(memory_format=torch.contiguous_format)
|
||||
_get_default_mps_generator().set_state(new_state_copy)
|
||||
|
||||
|
||||
def manual_seed(seed: int) -> None:
|
||||
r"""Sets the seed for generating random numbers.
|
||||
|
||||
Args:
|
||||
seed (int): The desired seed.
|
||||
"""
|
||||
# the torch.mps.manual_seed() can be called from the global
|
||||
# torch.manual_seed() in torch/random.py. So we need to make
|
||||
# sure mps is available (otherwise we just return without
|
||||
# erroring out)
|
||||
if not torch._C._has_mps:
|
||||
return
|
||||
seed = int(seed)
|
||||
_get_default_mps_generator().manual_seed(seed)
|
||||
|
||||
|
||||
def seed() -> None:
|
||||
r"""Sets the seed for generating random numbers to a random number."""
|
||||
_get_default_mps_generator().seed()
|
||||
|
||||
|
||||
def empty_cache() -> None:
|
||||
r"""Releases all unoccupied cached memory currently held by the caching
|
||||
allocator so that those can be used in other GPU applications.
|
||||
"""
|
||||
torch._C._mps_emptyCache()
|
||||
|
||||
|
||||
def set_per_process_memory_fraction(fraction) -> None:
|
||||
r"""Set memory fraction for limiting process's memory allocation on MPS device.
|
||||
The allowed value equals the fraction multiplied by recommended maximum device memory
|
||||
(obtained from Metal API device.recommendedMaxWorkingSetSize).
|
||||
If trying to allocate more than the allowed value in a process, it will raise an out of
|
||||
memory error in allocator.
|
||||
|
||||
Args:
|
||||
fraction(float): Range: 0~2. Allowed memory equals total_memory * fraction.
|
||||
|
||||
.. note::
|
||||
Passing 0 to fraction means unlimited allocations
|
||||
(may cause system failure if out of memory).
|
||||
Passing fraction greater than 1.0 allows limits beyond the value
|
||||
returned from device.recommendedMaxWorkingSetSize.
|
||||
"""
|
||||
|
||||
if not isinstance(fraction, float):
|
||||
raise TypeError("Invalid type for fraction argument, must be `float`")
|
||||
if fraction < 0 or fraction > 2:
|
||||
raise ValueError(f"Invalid fraction value: {fraction}. Allowed range: 0~2")
|
||||
|
||||
torch._C._mps_setMemoryFraction(fraction)
|
||||
|
||||
|
||||
def current_allocated_memory() -> int:
|
||||
r"""Returns the current GPU memory occupied by tensors in bytes.
|
||||
|
||||
.. note::
|
||||
The returned size does not include cached allocations in
|
||||
memory pools of MPSAllocator.
|
||||
"""
|
||||
return torch._C._mps_currentAllocatedMemory()
|
||||
|
||||
|
||||
def driver_allocated_memory() -> int:
|
||||
r"""Returns total GPU memory allocated by Metal driver for the process in bytes.
|
||||
|
||||
.. note::
|
||||
The returned size includes cached allocations in MPSAllocator pools
|
||||
as well as allocations from MPS/MPSGraph frameworks.
|
||||
"""
|
||||
return torch._C._mps_driverAllocatedMemory()
|
||||
|
||||
|
||||
def recommended_max_memory() -> int:
|
||||
r"""Returns recommended max Working set size for GPU memory in bytes.
|
||||
|
||||
.. note::
|
||||
Recommended max working set size for Metal.
|
||||
returned from device.recommendedMaxWorkingSetSize.
|
||||
"""
|
||||
return torch._C._mps_recommendedMaxMemory()
|
||||
|
||||
|
||||
def compile_shader(source: str):
|
||||
r"""Compiles compute shader from source and allows one to invoke kernels
|
||||
defined there from the comfort of Python runtime
|
||||
Example::
|
||||
|
||||
>>> # xdoctest: +REQUIRES(env:TORCH_DOCTEST_MPS)
|
||||
>>> lib = torch.mps.compile_shader(
|
||||
... "kernel void full(device float* out, constant float& val, uint idx [[thread_position_in_grid]]) { out[idx] = val; }"
|
||||
... )
|
||||
>>> x = torch.zeros(16, device="mps")
|
||||
>>> lib.full(x, 3.14)
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
from torch.utils._cpp_embed_headers import _embed_headers
|
||||
|
||||
if not hasattr(torch._C, "_mps_compileShader"):
|
||||
raise RuntimeError("MPS is not available")
|
||||
source = _embed_headers(
|
||||
[l + "\n" for l in source.split("\n")],
|
||||
[Path(__file__).parent.parent / "include"],
|
||||
set(),
|
||||
)
|
||||
return torch._C._mps_compileShader(source)
|
||||
|
||||
|
||||
def is_available() -> bool:
|
||||
return device_count() > 0
|
||||
|
||||
|
||||
from . import profiler
|
||||
from .event import Event
|
||||
|
||||
|
||||
__all__ = [
|
||||
"compile_shader",
|
||||
"device_count",
|
||||
"get_rng_state",
|
||||
"manual_seed",
|
||||
"seed",
|
||||
"set_rng_state",
|
||||
"synchronize",
|
||||
"empty_cache",
|
||||
"set_per_process_memory_fraction",
|
||||
"current_allocated_memory",
|
||||
"driver_allocated_memory",
|
||||
"Event",
|
||||
"profiler",
|
||||
"recommended_max_memory",
|
||||
"is_available",
|
||||
]
|
||||
@@ -0,0 +1,45 @@
|
||||
import torch
|
||||
|
||||
|
||||
class Event:
|
||||
r"""Wrapper around an MPS event.
|
||||
|
||||
MPS events are synchronization markers that can be used to monitor the
|
||||
device's progress, to accurately measure timing, and to synchronize MPS streams.
|
||||
|
||||
Args:
|
||||
enable_timing (bool, optional): indicates if the event should measure time
|
||||
(default: ``False``)
|
||||
"""
|
||||
|
||||
def __init__(self, enable_timing: bool = False) -> None:
|
||||
self.__eventId = torch._C._mps_acquireEvent(enable_timing)
|
||||
|
||||
def __del__(self) -> None:
|
||||
# checks if torch._C is already destroyed
|
||||
if hasattr(torch._C, "_mps_releaseEvent") and self.__eventId > 0:
|
||||
torch._C._mps_releaseEvent(self.__eventId)
|
||||
|
||||
def record(self) -> None:
|
||||
r"""Records the event in the default stream."""
|
||||
torch._C._mps_recordEvent(self.__eventId)
|
||||
|
||||
def wait(self) -> None:
|
||||
r"""Makes all future work submitted to the default stream wait for this event."""
|
||||
torch._C._mps_waitForEvent(self.__eventId)
|
||||
|
||||
def query(self) -> bool:
|
||||
r"""Returns True if all work currently captured by event has completed."""
|
||||
return torch._C._mps_queryEvent(self.__eventId)
|
||||
|
||||
def synchronize(self) -> None:
|
||||
r"""Waits until the completion of all work currently captured in this event.
|
||||
This prevents the CPU thread from proceeding until the event completes.
|
||||
"""
|
||||
torch._C._mps_synchronizeEvent(self.__eventId)
|
||||
|
||||
def elapsed_time(self, end_event: "Event") -> float:
|
||||
r"""Returns the time elapsed in milliseconds after the event was
|
||||
recorded and before the end_event was recorded.
|
||||
"""
|
||||
return torch._C._mps_elapsedTimeOfEvents(self.__eventId, end_event.__eventId)
|
||||
@@ -0,0 +1,100 @@
|
||||
import contextlib
|
||||
from collections.abc import Iterator
|
||||
from typing import Literal
|
||||
|
||||
import torch
|
||||
|
||||
|
||||
__all__ = [
|
||||
"start",
|
||||
"stop",
|
||||
"profile",
|
||||
"metal_capture",
|
||||
"is_metal_capture_enabled",
|
||||
"is_capturing_metal",
|
||||
]
|
||||
|
||||
|
||||
ProfilerMode = Literal["interval", "event", "interval,event"]
|
||||
|
||||
|
||||
def start(mode: ProfilerMode = "interval", wait_until_completed: bool = False) -> None:
|
||||
r"""Start OS Signpost tracing from MPS backend.
|
||||
|
||||
The generated OS Signposts could be recorded and viewed in
|
||||
XCode Instruments Logging tool.
|
||||
|
||||
Args:
|
||||
mode(str): OS Signpost tracing mode could be "interval", "event",
|
||||
or both "interval,event".
|
||||
The interval mode traces the duration of execution of the operations,
|
||||
whereas event mode marks the completion of executions.
|
||||
See document `Recording Performance Data`_ for more info.
|
||||
wait_until_completed(bool): Waits until the MPS Stream complete
|
||||
executing each encoded GPU operation. This helps generating single
|
||||
dispatches on the trace's timeline.
|
||||
Note that enabling this option would affect the performance negatively.
|
||||
|
||||
.. _Recording Performance Data:
|
||||
https://developer.apple.com/documentation/os/logging/recording_performance_data
|
||||
"""
|
||||
mode_normalized = mode.lower().replace(" ", "")
|
||||
torch._C._mps_profilerStartTrace( # type: ignore[attr-defined]
|
||||
mode_normalized, wait_until_completed
|
||||
)
|
||||
|
||||
|
||||
def stop() -> None:
|
||||
r"""Stops generating OS Signpost tracing from MPS backend."""
|
||||
torch._C._mps_profilerStopTrace() # type: ignore[attr-defined]
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def profile(
|
||||
mode: ProfilerMode = "interval", wait_until_completed: bool = False
|
||||
) -> Iterator[None]:
|
||||
r"""Context Manager to enabling generating OS Signpost tracing from MPS backend.
|
||||
|
||||
Args:
|
||||
mode(str): OS Signpost tracing mode could be "interval", "event",
|
||||
or both "interval,event".
|
||||
The interval mode traces the duration of execution of the operations,
|
||||
whereas event mode marks the completion of executions.
|
||||
See document `Recording Performance Data`_ for more info.
|
||||
wait_until_completed(bool): Waits until the MPS Stream complete
|
||||
executing each encoded GPU operation. This helps generating single
|
||||
dispatches on the trace's timeline.
|
||||
Note that enabling this option would affect the performance negatively.
|
||||
|
||||
.. _Recording Performance Data:
|
||||
https://developer.apple.com/documentation/os/logging/recording_performance_data
|
||||
"""
|
||||
try:
|
||||
start(mode, wait_until_completed)
|
||||
yield
|
||||
finally:
|
||||
stop()
|
||||
|
||||
|
||||
def is_metal_capture_enabled() -> bool:
|
||||
"""Checks if `metal_capture` context manager is usable
|
||||
To enable metal capture, set MTL_CAPTURE_ENABLED envvar
|
||||
"""
|
||||
return torch._C._mps_isCaptureEnabled() # type: ignore[attr-defined, no-any-return]
|
||||
|
||||
|
||||
def is_capturing_metal() -> bool:
|
||||
"""Checks if metal capture is in progress"""
|
||||
return torch._C._mps_isCapturing() # type: ignore[attr-defined, no-any-return]
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def metal_capture(fname: str) -> Iterator[None]:
|
||||
"""Context manager that enables capturing of Metal calls into gputrace"""
|
||||
try:
|
||||
torch._C._mps_startCapture(fname) # type: ignore[attr-defined]
|
||||
yield
|
||||
# Drain all the work that were enqueued during the context call
|
||||
torch.mps.synchronize()
|
||||
finally:
|
||||
torch._C._mps_stopCapture() # type: ignore[attr-defined]
|
||||
Reference in New Issue
Block a user