diff --git a/.gitattributes b/.gitattributes index daacfe9b3fb9cb81ff1c9f85ee021080f57a7f1b..604ffa217ded3a6b645774342eb32d3e53b12936 100644 --- a/.gitattributes +++ b/.gitattributes @@ -226,3 +226,9 @@ workspace/outputs/audit_venv/lib/python3.11/site-packages/pip/_vendor/distlib/t6 workspace/outputs/audit_venv/lib/python3.11/site-packages/pip/_vendor/distlib/w64-arm.exe filter=lfs diff=lfs merge=lfs -text workspace/outputs/audit_venv/lib/python3.11/site-packages/pip/_vendor/distlib/w64.exe filter=lfs diff=lfs merge=lfs -text workspace/outputs/audit_venv/lib/python3.11/site-packages/pydantic_core/_pydantic_core.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text +workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libc10.so filter=lfs diff=lfs merge=lfs -text +workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libc10_cuda.so filter=lfs diff=lfs merge=lfs -text +workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libtorch_cpu.so filter=lfs diff=lfs merge=lfs -text +workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libtorch_cuda.so filter=lfs diff=lfs merge=lfs -text +workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libtorch_cuda_linalg.so filter=lfs diff=lfs merge=lfs -text +workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libtorch_python.so filter=lfs diff=lfs merge=lfs -text diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/autograd/rpc_messages/rpc_with_profiling_resp.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/autograd/rpc_messages/rpc_with_profiling_resp.h new file mode 100644 index 0000000000000000000000000000000000000000..fb9db4ccb84e2f961a3829d2ec28dfec7fcb2136 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/autograd/rpc_messages/rpc_with_profiling_resp.h @@ -0,0 +1,63 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace torch::distributed::autograd { +class TORCH_API RpcWithProfilingResp : public rpc::RpcCommandBase { + public: + // For sending RPCs over the wire + RpcWithProfilingResp( + rpc::MessageType messageType, + c10::intrusive_ptr wrappedMessage, + std::vector profiledEvents, + rpc::ProfilingId profilingId); + + // For receiving RPCs. Used in from message when converting a message received + // over the wire. + RpcWithProfilingResp( + rpc::MessageType messageType, + std::unique_ptr wrappedRpc, + rpc::MessageType wrappedMessageType, + std::vector tensors, + std::vector profiledEvents, + rpc::ProfilingId profilingId); + c10::intrusive_ptr toMessageImpl() && override; + static std::unique_ptr fromMessage( + const rpc::Message& message); + // Retrieve remote Events + std::vector getProfiledEvents() const; + // Retrieve the globally unique profiling ID corresponding to this command. + const rpc::ProfilingId& getProfilingId() const; + // Retrieve the original RPC which this ProfilingRPC wraps. + RpcCommandBase& wrappedRpc(); + // Destructively move the wrapped RPC. + std::unique_ptr moveWrappedRpc() &&; + // Message type of the wrapped RPC + rpc::MessageType wrappedMessageType() const; + // Set the wrapped RPC for this RPC. + void setWrappedRpc(std::unique_ptr wrappedRpc); + + private: + // message type + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const rpc::MessageType messageType_; + // wrapped message + c10::intrusive_ptr wrappedMessage_; + std::unique_ptr wrappedRpc_; + rpc::MessageType wrappedMessageType_; + std::vector tensors_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const std::vector profiledEvents_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const rpc::ProfilingId profilingId_; +}; +} // namespace torch::distributed::autograd + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/autograd/rpc_messages/rref_backward_req.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/autograd/rpc_messages/rref_backward_req.h new file mode 100644 index 0000000000000000000000000000000000000000..1cb78980aa6deeef29a2e918eaf87ed970b7a127 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/autograd/rpc_messages/rref_backward_req.h @@ -0,0 +1,43 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace torch::distributed::autograd { + +// Internal system RPC to invoke distributed backward pass on remote nodes when +// 'rref.backward()' is invoked. +class TORCH_API RRefBackwardReq : public rpc::RpcCommandBase { + public: + RRefBackwardReq( + const rpc::RRefId& rrefId, + int64_t autogradContextId, + bool retainGraph = false); + + const rpc::RRefId& getRRefId() const; + + int64_t getAutogradContextId() const; + + bool retainGraph() const; + + // Serialization and deserialization methods. + c10::intrusive_ptr toMessageImpl() && override; + static std::unique_ptr fromMessage( + const rpc::Message& message); + + private: + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const rpc::RRefId rrefId_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const int64_t autogradContextId_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const bool retainGraph_; +}; + +} // namespace torch::distributed::autograd + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/autograd/rpc_messages/rref_backward_resp.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/autograd/rpc_messages/rref_backward_resp.h new file mode 100644 index 0000000000000000000000000000000000000000..c4bf412302ced62d07a5ca8a24675376f1ed2b68 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/autograd/rpc_messages/rref_backward_resp.h @@ -0,0 +1,22 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::distributed::autograd { + +// Response for the RRefBackwardReq. +class TORCH_API RRefBackwardResp : public rpc::RpcCommandBase { + public: + RRefBackwardResp() = default; + c10::intrusive_ptr toMessageImpl() && override; + static std::unique_ptr fromMessage( + const rpc::Message& message); +}; + +} // namespace torch::distributed::autograd + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/autograd/utils.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/autograd/utils.h new file mode 100644 index 0000000000000000000000000000000000000000..47903ceb5e9bf2491e8896cdc2fed920b03e9448 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/autograd/utils.h @@ -0,0 +1,61 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +namespace torch::distributed::autograd { + +// This method is used to attach the 'send' autograd function to the autograd +// graph when we use RPC. This method creates a new 'send' autograd function +// and attaches the provided tensors as next_edges to the 'send' function. In +// addition to this, it also registers the send function in the provided +// autograd context. Finally, the RPC message is updated with appropriate +// autograd information for the recipient. +TORCH_API void addSendRpcBackward( + const ContextPtr& autogradContext, + const AutogradMetadata& autogradMetadata, + std::vector& tensors); + +// This method is used to attach the 'recv' autograd function to the autograd +// graph when we use RPC. This method creates a new 'recv' autograd function +// and attaches the provided tensors as inputs to the 'recv' function. It +// creates a new autograd context if needed and registers the 'recv' function +// with this context. +// +// Returns a pointer to the autograd context created. +TORCH_API ContextPtr addRecvRpcBackward( + const AutogradMetadata& autogradMetadata, + std::vector& tensors, + rpc::worker_id_t fromWorkerId, + const rpc::DeviceMap& deviceMap); + +// This method is a wrapper utility used internally to wrap autograd info +// and attach autograd function for each type of rpc call if it has valid +// context and tensors require grads or forceGradRecording is true, in this +// case, return RpcWithAutograd message; otherwise return original rpc message. +// NB: forceGradRecording is useful when the request does not contain any tensor +// but the corresponding response does. +TORCH_API c10::intrusive_ptr getMessageWithAutograd( + const rpc::worker_id_t dstId, + c10::intrusive_ptr wrappedRpcMsg, + rpc::MessageType msgType, + bool forceGradRecording = false, + const rpc::DeviceMap& deviceMap = {}); + +// Send message after autograd checking +TORCH_API c10::intrusive_ptr sendMessageWithAutograd( + rpc::RpcAgent& agent, + const rpc::WorkerInfo& dst, + c10::intrusive_ptr wrappedRpcMsg, + bool forceGradRecording = false, + const float rpcTimeoutSeconds = torch::distributed::rpc::kUnsetRpcTimeout, + bool forceDisableProfiling = false); + +} // namespace torch::distributed::autograd + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Backend.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Backend.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bb018312224b7b5a008373a25e1e822ef3084061 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Backend.hpp @@ -0,0 +1,559 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +constexpr auto kBackendDefaultTimeout = + std::chrono::milliseconds(30 * 60 * 1000); + +namespace c10d { + +enum class ErrorType { + SUCCESS = 0, + TIMEOUT = 1, + // e.g., NCCL error, etc + COMM_ERROR = 2, + // TODO, do we need to distinguish between remote timeout or remote COMM + // errors? + REMOTE_ERROR = 3 +}; + +class TORCH_API Backend : public torch::CustomClassHolder { + public: + // Backend Options is a base struct that defines the basic options + // when constructing a Backend. Each Backend subclass should + // extend this struct and define its options if it wants to provide more + // config options (beyond basic ones defined here) to end user. + struct TORCH_API Options : torch::CustomClassHolder { + explicit Options( + std::string backend, + std::chrono::milliseconds timeout = kBackendDefaultTimeout) + : timeout(timeout), backend(std::move(backend)) {} + ~Options() override = default; + Options(const Options&) = default; + + std::chrono::milliseconds timeout; + + // backend name + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const std::string backend; + std::string group_name; + std::string group_desc; + std::vector global_ranks_in_group; + }; + + explicit Backend(int rank, int size); + ~Backend() override = 0; + + int getRank() const { + return rank_; + } + + int getSize() const { + return size_; + } + + // Returns an unique opaque ID of this backend that can be used to correlate + // with its collectives. + int64_t getID() const { + return reinterpret_cast(this); + } + + virtual bool supportsSplitting() const { + return false; + } + + virtual bool supportsCoalescing() const { + return false; + } + + virtual bool supportsTimeEstimation() const { + return false; + } + + virtual bool supportsShrinking() const { + return false; + } + + // Shrink the backend by excluding specified ranks. Backends that support + // communicator shrinking should override this and return a new backend + // instance representing the shrunken group. Backends may use opts_override + // to supply backend-specific options for the new group. + virtual c10::intrusive_ptr shrink( + const std::vector& /*ranks_to_exclude*/, + int /*shrink_flags*/ = 0, + const c10::intrusive_ptr& /*opts_override*/ = nullptr) { + TORCH_CHECK( + false, + c10::str("Backend ", getBackendName(), " does not support shrink")); + } + + virtual void setTimeout(std::chrono::milliseconds timeout) { + TORCH_CHECK( + false, + c10::str( + "Backend ", getBackendName(), " does not support setting timeout")); + } + + virtual void startCoalescing() { + TORCH_CHECK( + false, + c10::str( + "Backend ", + getBackendName(), + " does not implement startCoalescing")); + } + + virtual c10::intrusive_ptr endCoalescing() { + TORCH_CHECK( + false, + c10::str( + "Backend ", getBackendName(), " does not implement endCoalescing")); + } + + // Subclasses must override this method to return the backend name + virtual const std::string getBackendName() const { + TORCH_INTERNAL_ASSERT(false, "getBackendName is not implemented."); + } + + // Subclasses must override this method to return the backend name + virtual c10::intrusive_ptr getBackendOptions() { + TORCH_CHECK( + false, + c10::str( + "Backend ", + getBackendName(), + " does not implement getBackendOptions.")); + } + + virtual c10::intrusive_ptr broadcast( + std::vector& /* tensors */, + const BroadcastOptions& /* opts */ = BroadcastOptions()) { + TORCH_CHECK( + false, + c10::str("Backend ", getBackendName(), " does not support broadcast")); + } + + virtual c10::intrusive_ptr allreduce( + std::vector& /* tensors */, + const AllreduceOptions& /* opts */ = AllreduceOptions()) { + TORCH_CHECK( + false, + c10::str("Backend ", getBackendName(), " does not support allreduce")); + } + + virtual c10::intrusive_ptr allreduce_sparse( + std::vector& /* tensors */, + const AllreduceOptions& /* opts */ = AllreduceOptions()) { + TORCH_CHECK( + false, + c10::str( + "Backend ", + getBackendName(), + " does not support allreduce sparse")); + } + + virtual c10::intrusive_ptr allreduce_coalesced( + std::vector& /* tensors */, + const AllreduceCoalescedOptions& /* opts */ = + AllreduceCoalescedOptions()) { + TORCH_CHECK( + false, + c10::str( + "Backend ", + getBackendName(), + " does not support allreduce_coalesced")); + } + + virtual c10::intrusive_ptr reduce( + std::vector& /* tensors */, + const ReduceOptions& /* opts */ = ReduceOptions()) { + TORCH_CHECK( + false, + c10::str("Backend ", getBackendName(), " does not support reduce")); + } + + virtual c10::intrusive_ptr allgather( + std::vector>& /* outputTensors */, + std::vector& /* inputTensors */, + const AllgatherOptions& /* opts */ = AllgatherOptions()) { + TORCH_CHECK( + false, + c10::str("Backend ", getBackendName(), " does not support allgather")); + } + + // Gathers a single tensor inputBuffer into a single buffer outputBuffer that + // is interpreted as a contiguous collection of size inputBuffer * WORLD_SIZE. + // For implementers of ProcessGroup API and advanced users only. + // Note: this function will be deprecated in near future. + virtual c10::intrusive_ptr _allgather_base( + at::Tensor& /* outputBuffer */, + at::Tensor& /* inputBuffer */, + const AllgatherOptions& /* opts */ = AllgatherOptions()) { + TORCH_CHECK( + false, + c10::str( + "Backend ", getBackendName(), " does not support _allgather_base")); + } + + // This function is deprecated and will be moved out of Backend to comms: + // * do not add dependencies on this function, + // * do not implement it in your Backend, implement _allgather_base + // instead. + virtual c10::intrusive_ptr allgather_coalesced( + std::vector>& /* outputTensorLists */, + std::vector& /* inputTensors */, + const AllgatherOptions& /* opts */ = AllgatherOptions()) { + TORCH_CHECK( + false, + c10::str( + "Backend ", + getBackendName(), + " does not support allgather_coalesced")); + } + + // This function is a coalesced version of `allgather_into_tensor` (currently + // still named as `_allgather_base`). Each tensor in the vector corresponds to + // an input/output of one `allgather_into_tensor` operation. + virtual c10::intrusive_ptr allgather_into_tensor_coalesced( + std::vector& /* outputs */, + std::vector& /* inputs */, + const AllgatherOptions& /* opts */ = AllgatherOptions()) { + TORCH_CHECK( + false, + c10::str( + "Backend ", + getBackendName(), + " does not support allgather_into_tensor_coalesced")); + } + + virtual c10::intrusive_ptr gather( + std::vector>& /* outputTensors */, + std::vector& /* inputTensors */, + const GatherOptions& /* opts */ = GatherOptions()) { + TORCH_CHECK( + false, + c10::str("Backend ", getBackendName(), " does not support gather")); + } + + virtual c10::intrusive_ptr scatter( + std::vector& /* outputTensors */, + std::vector>& /* inputTensors */, + const ScatterOptions& /* opts */ = ScatterOptions()) { + TORCH_CHECK( + false, + c10::str("Backend ", getBackendName(), " does not support scatter")); + } + + virtual c10::intrusive_ptr reduce_scatter( + std::vector& /* outputTensors */, + std::vector>& /* inputTensors */, + const ReduceScatterOptions& /* opts */ = ReduceScatterOptions()) { + TORCH_CHECK( + false, + c10::str( + "Backend ", getBackendName(), " does not support reduce_scatter")); + } + + virtual c10::intrusive_ptr _reduce_scatter_base( + at::Tensor& /* outputBuffer */, + at::Tensor& /* inputBuffer */, + const ReduceScatterOptions& /* opts */ = ReduceScatterOptions()) { + TORCH_CHECK( + false, + c10::str( + "Backend ", + getBackendName(), + " does not support _reduce_scatter_base")); + } + + // This function is a coalesced version of `reduce_scatter_tensor` (currently + // still named as `_reduce_scatter_base`). Each tensor in the vector + // corresponds to an input/output of one `reduce_scatter_tensor` operation. + virtual c10::intrusive_ptr reduce_scatter_tensor_coalesced( + std::vector& /* outputs */, + std::vector& /* inputs */, + const ReduceScatterOptions& /* opts */ = ReduceScatterOptions()) { + TORCH_CHECK( + false, + c10::str( + "Backend ", + getBackendName(), + " does not support reduce_scatter_tensor_coalesced")); + } + + virtual c10::intrusive_ptr alltoall_base( + at::Tensor& /* outputBuffer */, + at::Tensor& /* inputBuffer */, + std::vector& /* outputSplitSizes */, + std::vector& /* inputSplitSizes */, + const AllToAllOptions& /* opts */ = AllToAllOptions()) { + TORCH_CHECK( + false, + c10::str( + "Backend ", getBackendName(), " does not support alltoall_base")); + } + + virtual c10::intrusive_ptr alltoall( + std::vector& /* outputTensors */, + std::vector& /* inputTensors */, + const AllToAllOptions& opts = AllToAllOptions()) { + TORCH_CHECK( + false, + c10::str("Backend ", getBackendName(), " does not support alltoall")); + } + + virtual void monitoredBarrier( + const BarrierOptions& /* unused */, + bool /* unused */ = false) { + auto backendName = getBackendName(); + TORCH_CHECK( + false, + c10::str( + "Backend ", + backendName, + " does not support monitoredBarrier, only GLOO supports monitored barrier.")); + } + + // Agrees on an initial sequence number for the whole group by having rank 0 + // create it and broadcast it to other ranks using the store. Only implemented + // for GLOO and NCCL backends currently. + virtual void setSequenceNumberForGroup() { + auto backendName = getBackendName(); + TORCH_CHECK( + false, + c10::str( + "Backend ", + backendName, + " does not yet support sequence numbers.")); + } + + // Retrieves the current sequence number for the whole group, which should be + // in sync. If the returned number is not consistent across the group, it + // may indicate that there is some sort of collective desynchronization. + virtual uint64_t getSequenceNumberForGroup() { + auto backendName = getBackendName(); + TORCH_CHECK( + false, + c10::str( + "Backend ", + backendName, + " does not yet support sequence numbers.")); + } + + virtual c10::intrusive_ptr send( + std::vector& /* tensors */, + int /* dstRank */, + int /* tag */) { + TORCH_CHECK( + false, + c10::str("Backend ", getBackendName(), " does not support send")); + } + + virtual c10::intrusive_ptr recv( + std::vector& /* tensors */, + int /* srcRank */, + int /* tag */) { + TORCH_CHECK( + false, + c10::str("Backend ", getBackendName(), " does not support recv")); + } + + virtual c10::intrusive_ptr recvAnysource( + std::vector& /* tensors */, + int /* tag */) { + TORCH_CHECK( + false, + c10::str( + "Backend ", getBackendName(), " does not support recvAnysource")); + } + + virtual c10::intrusive_ptr barrier( + const BarrierOptions& /* opts */ = BarrierOptions()) { + TORCH_CHECK( + false, + c10::str("Backend ", getBackendName(), " does not support barrier")); + } + + virtual void registerOnCompletionHook( + std::function)>&& hook) { + TORCH_CHECK( + false, + "Only ProcessGrouppNCCL supports onCompletion hook, but got ", + getBackendName(), + " backend."); + } + + virtual void waitForPendingWorks() { + TORCH_CHECK( + false, + "Only ProcessGrouppNCCL supports waitForPendingWorks, but got ", + getBackendName(), + " backend."); + } + + virtual void enableCollectivesTiming() { + TORCH_CHECK( + false, + "Backend ", + getBackendName(), + " is missing implementation of enableCollectivesTiming."); + } + + virtual c10::intrusive_ptr split( + const c10::intrusive_ptr& store, + const std::vector& ranks, + const c10::intrusive_ptr& opts) { + TORCH_CHECK( + false, + "Backend ", + getBackendName(), + " is missing implementation of split."); + } + + virtual c10::intrusive_ptr merge( + const c10::intrusive_ptr& store, + const c10::intrusive_ptr& opts, + const int& rank, + const int& size) { + TORCH_CHECK( + false, + "Backend ", + getBackendName(), + " is missing implementation of merge."); + } + + bool hasHooks() const { + return onCompletionHook_ != nullptr; + } + + // Do not call this directly, use ProcessGroup::setGroupName instead. + virtual void setGroupUid(const std::string& pg_uid) { + pg_uid_ = pg_uid; + } + + const std::string& getGroupUid() const { + return pg_uid_; + } + + void setGroupDesc(const std::string& desc) { + pg_desc_ = desc; + } + + const std::string& getGroupDesc() const { + return pg_desc_; + } + + // See similar functions in ProcessGroup.hpp for context. + std::optional getBoundDeviceId() const { + return bound_device_id_; + } + + // Perform an eager connect to the specified device if the backend supports + // it. + virtual void eagerConnectSingleDevice(at::Device device) { + // no-op in the default case; this is an optimization some + // backends may perform + } + + void setBoundDeviceId(std::optional device) { + if (device) { + TORCH_CHECK(device->has_index(), "setBoundDeviceId must have an index"); + } + bound_device_id_ = device; + } + + virtual ErrorType getError() { + TORCH_CHECK( + false, + c10::str("Backend ", getBackendName(), " does not support getError")); + } + + virtual std::shared_ptr getMemAllocator() { + TORCH_CHECK( + false, + c10::str( + "Backend ", getBackendName(), " does not support getMemAllocator")); + } + + // Allocate tensor (aten::empty) from backend's communication-optimized memory + // pool + virtual at::Tensor allocateTensor(long size, at::TensorOptions options = {}) { + TORCH_CHECK( + false, + c10::str( + "Backend ", getBackendName(), " does not support allocateTensor")); + } + + // Returns true if backend supports tensor allocation + virtual bool supportsTensorAlloc(c10::DeviceIndex deviceIdx) { + // Change to true in concrete backend if supported + return false; + } + + // Aborts all pending operations and connections in the backend if the backend + // supports it. + virtual void abort() {} + + // Shutdown the backend if the backend supports it. This should be used for + // normal shutdown. + virtual void shutdown() {} + + // APIs related to memory offload + virtual void suspend() { + TORCH_CHECK( + false, + c10::str("Backend ", getBackendName(), " does not support suspend")); + } + + virtual void resume() { + TORCH_CHECK( + false, + c10::str("Backend ", getBackendName(), " does not support resume")); + } + + virtual std::unordered_map getMemoryStats() { + TORCH_CHECK( + false, + c10::str( + "Backend ", getBackendName(), " does not support getMemoryStats")); + } + + protected: + // Implementations of this interface need to call this to setup + // appropriate logging etc. + void init(); + + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const int rank_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const int size_; + // Debug level setting. It is parsed once when ProcessGroup is constructed and + // remains the same across use of this process group. + DebugLevel dist_debug_level_; + std::string pg_uid_; + std::string pg_desc_; + + std::function)> onCompletionHook_; + + std::optional bound_device_id_; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Backoff.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Backoff.hpp new file mode 100644 index 0000000000000000000000000000000000000000..329dc1f97857e93886096a508bcde1b20c75146d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Backoff.hpp @@ -0,0 +1,57 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include + +namespace c10d { + +class TORCH_API Backoff { + public: + virtual ~Backoff() = default; + + virtual std::chrono::milliseconds nextBackoff() = 0; + virtual void reset() = 0; + + void sleepBackoff() { + std::this_thread::sleep_for(nextBackoff()); + } +}; + +class TORCH_API ExponentialBackoffWithJitter : public Backoff { + public: + ExponentialBackoffWithJitter(); + + std::chrono::milliseconds nextBackoff() override; + void reset() override; + + public: + std::chrono::milliseconds initialInterval{500}; + double randomizationFactor{0.5}; + double multiplier{1.5}; + std::chrono::milliseconds maxInterval{60000}; + + private: + std::mt19937 gen_; + std::chrono::milliseconds currentInterval_{0}; +}; + +class TORCH_API FixedBackoff : public Backoff { + public: + FixedBackoff(std::chrono::milliseconds interval); + + std::chrono::milliseconds nextBackoff() override; + void reset() override; + + private: + std::chrono::milliseconds interval_; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/FakeProcessGroup.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/FakeProcessGroup.hpp new file mode 100644 index 0000000000000000000000000000000000000000..453d2f4e64f83cf9466ce951e8be8a4f666a1393 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/FakeProcessGroup.hpp @@ -0,0 +1,258 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace c10d { + +class FakeWork : public Work { + public: + int seq_id = -1; + bool wait(std::chrono::milliseconds timeout = kNoTimeout) override { + return true; + } + + c10::intrusive_ptr getFuture() override { + auto fut = c10::make_intrusive(c10::NoneType::get()); + fut->markCompleted(); + return fut; + } +}; + +class FakeProcessGroup : public Backend { + public: + struct Options : Backend::Options { + explicit Options() : Backend::Options("fake") {} + + int fake_option = 0; + bool error_on_collective = false; + }; + + // Static factory method for official APIs + static c10::intrusive_ptr _create_internal( + int rank, + int size, + c10::intrusive_ptr options = c10::make_intrusive()) { + return c10::make_intrusive( + rank, size, std::move(options)); + } + + const std::string getBackendName() const override { + return "fake"; + } + + c10::intrusive_ptr getBackendOptions() override { + return c10::static_intrusive_pointer_cast(options_); + } + + c10::intrusive_ptr broadcast( + std::vector& /* tensors */, + const BroadcastOptions& /* opts */ = BroadcastOptions()) override { + checkCollectiveError(); + return c10::make_intrusive(); + } + + c10::intrusive_ptr allreduce( + std::vector& /* tensors */, + const AllreduceOptions& /* opts */ = AllreduceOptions()) override { + checkCollectiveError(); + return c10::make_intrusive(); + } + + c10::intrusive_ptr allreduce_sparse( + std::vector& /* tensors */, + const AllreduceOptions& /* opts */ = AllreduceOptions()) override { + checkCollectiveError(); + return c10::make_intrusive(); + } + + c10::intrusive_ptr allreduce_coalesced( + std::vector& /* tensors */, + const AllreduceCoalescedOptions& /* opts */ = + AllreduceCoalescedOptions()) override { + checkCollectiveError(); + return c10::make_intrusive(); + } + + c10::intrusive_ptr reduce( + std::vector& /* tensors */, + const ReduceOptions& /* opts */ = ReduceOptions()) override { + checkCollectiveError(); + return c10::make_intrusive(); + } + + // NOTE [allgather on FakeProcessGroup] + // Assume each rank have the same input tensor so we just copy to the results + // since it's not a real allgather, we simply make this copying logic to let + // some simple validation works (i.e. calling allgather to see if each rank + // have the same tensor or not). + // + // NOTE: in general it's not good form to try to make FakeProcessGroup work + // with real data, but the reasoning here is that we want FakeProcessGroup to + // work with DeviceMesh's init code that have the data validation, which + // makes it worth the tradeoff. + c10::intrusive_ptr allgather( + std::vector>& outputTensors, + std::vector& inputTensors, + const AllgatherOptions& /* opts */ = AllgatherOptions()) override { + checkCollectiveError(); + for (auto& tensor : outputTensors[0]) { + tensor.copy_(inputTensors[0]); + } + return c10::make_intrusive(); + } + + c10::intrusive_ptr _allgather_base( + at::Tensor& outputBuffer, + at::Tensor& inputBuffer, + const AllgatherOptions& /* opts */ = AllgatherOptions()) override { + checkCollectiveError(); + auto chunks = outputBuffer.chunk(size_); + for (auto& tensor : chunks) { + tensor.copy_(inputBuffer); + } + return c10::make_intrusive(); + } + + c10::intrusive_ptr allgather_coalesced( + std::vector>& /* outputTensorLists */, + std::vector& /* inputTensors */, + const AllgatherOptions& /* opts */ = AllgatherOptions()) override { + checkCollectiveError(); + return c10::make_intrusive(); + } + + c10::intrusive_ptr allgather_into_tensor_coalesced( + std::vector& outputs, + std::vector& inputs, + const AllgatherOptions& /* opts */ = AllgatherOptions()) override { + checkCollectiveError(); + for (size_t i = 0; i < outputs.size(); ++i) { + auto chunks = outputs[i].chunk(size_); + for (auto& chunk : chunks) { + chunk.copy_(inputs[i]); + } + } + return c10::make_intrusive(); + } + + c10::intrusive_ptr gather( + std::vector>& /* outputTensors */, + std::vector& /* inputTensors */, + const GatherOptions& /* opts */ = GatherOptions()) override { + checkCollectiveError(); + return c10::make_intrusive(); + } + + c10::intrusive_ptr scatter( + std::vector& /* outputTensors */, + std::vector>& /* inputTensors */, + const ScatterOptions& /* opts */ = ScatterOptions()) override { + checkCollectiveError(); + return c10::make_intrusive(); + } + + c10::intrusive_ptr reduce_scatter( + std::vector& /* outputTensors */, + std::vector>& /* inputTensors */, + const ReduceScatterOptions& /* opts */ = + ReduceScatterOptions()) override { + checkCollectiveError(); + return c10::make_intrusive(); + } + + c10::intrusive_ptr _reduce_scatter_base( + at::Tensor& /* outputBuffer */, + at::Tensor& /* inputBuffer */, + const ReduceScatterOptions& /* opts */ = + ReduceScatterOptions()) override { + checkCollectiveError(); + return c10::make_intrusive(); + } + + c10::intrusive_ptr reduce_scatter_tensor_coalesced( + std::vector& /* outputs */, + std::vector& /* inputs */, + const ReduceScatterOptions& /* opts */ = + ReduceScatterOptions()) override { + checkCollectiveError(); + return c10::make_intrusive(); + } + + c10::intrusive_ptr alltoall_base( + at::Tensor& /* outputBuffer */, + at::Tensor& /* inputBuffer */, + std::vector& /* outputSplitSizes */, + std::vector& /* inputSplitSizes */, + const AllToAllOptions& /* opts */ = AllToAllOptions()) override { + checkCollectiveError(); + return c10::make_intrusive(); + } + + c10::intrusive_ptr alltoall( + std::vector& /* outputTensors */, + std::vector& /* inputTensors */, + const AllToAllOptions& opts = AllToAllOptions()) override { + checkCollectiveError(); + return c10::make_intrusive(); + } + + c10::intrusive_ptr send( + std::vector& /* tensors */, + int /* dstRank */, + int /* tag */) override { + return c10::make_intrusive(); + } + + c10::intrusive_ptr recv( + std::vector& /* tensors */, + int /* srcRank */, + int /* tag */) override { + return c10::make_intrusive(); + } + + c10::intrusive_ptr recvAnysource( + std::vector& /* tensors */, + int /* tag */) override { + return c10::make_intrusive(); + } + + void startCoalescing() override { + // No-op + } + + c10::intrusive_ptr endCoalescing(OpType /* optype */) { + checkCollectiveError(); + return c10::make_intrusive(); + } + + c10::intrusive_ptr endCoalescing() override { + checkCollectiveError(); + return c10::make_intrusive(); + } + + c10::intrusive_ptr barrier( + const BarrierOptions& /* opts */ = BarrierOptions()) override { + checkCollectiveError(); + return c10::make_intrusive(); + } + + // Private constructor used by official APIs + FakeProcessGroup(int rank, int size, c10::intrusive_ptr options) + : Backend(rank, size), options_(std::move(options)) {} + c10::intrusive_ptr options_; + + private: + void checkCollectiveError() { + TORCH_CHECK( + !options_ || !options_->error_on_collective, + "FakeProcessGroup collective operation error (error_on_collective=true)"); + } +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/FileStore.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/FileStore.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7725d9856572a906d688992dd6eaa284d019887d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/FileStore.hpp @@ -0,0 +1,72 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include +#include + +#include + +namespace c10d { + +class TORCH_API FileStore : public Store { + public: + explicit FileStore(std::string path, int numWorkers); + + c10::intrusive_ptr clone() override; + + ~FileStore() override; + + void set(const std::string& key, const std::vector& value) override; + + std::vector compareSet( + const std::string& key, + const std::vector& expectedValue, + const std::vector& desiredValue) override; + + std::vector get(const std::string& key) override; + + int64_t add(const std::string& key, int64_t value) override; + + int64_t getNumKeys() override; + + bool deleteKey(const std::string& key) override; + + bool check(const std::vector& keys) override; + + void wait(const std::vector& keys) override; + + void wait( + const std::vector& keys, + const std::chrono::milliseconds& timeout) override; + + // Returns the path used by the FileStore. + const std::string& getPath() const noexcept { + return path_; + } + + std::vector listKeys() override; + + protected: + int64_t addHelper(const std::string& key, int64_t i); + + std::string path_; + off_t pos_{0}; + + int numWorkers_; + const std::string cleanupKey_; + const std::string refCountKey_; + const std::string regularPrefix_; + const std::string deletePrefix_; + + std::unordered_map> cache_; + + std::mutex activeFileOpLock_; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/FlightRecorder.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/FlightRecorder.hpp new file mode 100644 index 0000000000000000000000000000000000000000..60985a09d1e7153c4949737ee82ffb1cf66c104a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/FlightRecorder.hpp @@ -0,0 +1,336 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace c10d { + +#define DEFINE_CONSTANT(name, value) \ + static c10::IValue name = value; \ + static std::string name##_str = value; +// Update whenever changing contents or formatting of the dump +// (minor when adding fields, major when changing existing fields) +// Also update both JSON and Pickle dumps to make use of the newly defined +// field(s). +DEFINE_CONSTANT(version_val, "2.10") +DEFINE_CONSTANT(entries_key, "entries") +DEFINE_CONSTANT(nccl_comm_key, "nccl_comm_state") +DEFINE_CONSTANT(comm_lib_version_key, "comm_lib_version") +DEFINE_CONSTANT(version_key, "version") +DEFINE_CONSTANT(pg_config_key, "pg_config") +DEFINE_CONSTANT(pg_status_key, "pg_status") +DEFINE_CONSTANT(record_id_key, "record_id") +DEFINE_CONSTANT(pg_id_key, "pg_id") +DEFINE_CONSTANT(pg_name_key, "process_group") +DEFINE_CONSTANT(collective_seq_id_key, "collective_seq_id") +DEFINE_CONSTANT(p2p_seq_id_key, "p2p_seq_id") +DEFINE_CONSTANT(is_p2p_key, "is_p2p") +DEFINE_CONSTANT(op_id_key, "op_id") +DEFINE_CONSTANT(profiling_name_key, "profiling_name") +DEFINE_CONSTANT(input_sizes_key, "input_sizes") +DEFINE_CONSTANT(input_dtypes_key, "input_dtypes") +DEFINE_CONSTANT(output_sizes_key, "output_sizes") +DEFINE_CONSTANT(output_dtypes_key, "output_dtypes") +DEFINE_CONSTANT(time_created_key, "time_created_ns") +DEFINE_CONSTANT(duration_key, "duration_ms") +DEFINE_CONSTANT(timeout_key, "timeout_ms") +DEFINE_CONSTANT(frames_key, "frames") +DEFINE_CONSTANT(state_key, "state") +DEFINE_CONSTANT(line_key, "line") +DEFINE_CONSTANT(name_key, "name") +DEFINE_CONSTANT(filename_key, "filename") +DEFINE_CONSTANT(retired_key, "retired") +DEFINE_CONSTANT(time_discovered_started_key, "time_discovered_started_ns") +DEFINE_CONSTANT(time_discovered_completed_key, "time_discovered_completed_ns") +DEFINE_CONSTANT(completed_state, "completed") +DEFINE_CONSTANT(scheduled_state, "scheduled") +DEFINE_CONSTANT(started_state, "started") +DEFINE_CONSTANT(thread_id_key, "thread_id") +DEFINE_CONSTANT(thread_name_key, "thread_name") +#undef DEFINE_CONSTANT + +// Write NCCL debug info to local disk or any storage users define. +// There are some constrains we set for the debug info writer: +// 1. The writer should only be registered once. +// 2. Once registered, users cannot change it including un-register. +// 3. It is recommended to register the customized writer in the trainer setup, +// If users don't register before calling launchAsyncDebugDump, then users +// lose the chance to register (and the default writer will be +// auto-registered). +class TORCH_API DebugInfoWriter { + public: + virtual ~DebugInfoWriter() = default; + virtual void write(const std::string& trace); + static DebugInfoWriter& getWriter(int rank); + static void registerWriter(std::unique_ptr writer); + virtual std::string getWriterTarget() { + return filename_; + } + + protected: + DebugInfoWriter( + const std::string& namePrefix, + int rank, + bool enableDynamicFilename = false) { + filename_ = c10::str(namePrefix, rank); + enable_dynamic_filename_ = enableDynamicFilename; + rank_ = rank; + } + std::string filename_; + int rank_; + bool enable_dynamic_filename_; + + private: + static std::unique_ptr writer_; + static std::atomic hasWriterRegistered_; +}; + +template +struct FlightRecorder { + static FlightRecorder* get() { + // intentionally leak on exit + // because this will hold python state that may get destructed + static FlightRecorder* instance = + new FlightRecorder(); + return instance; + } + FlightRecorder() { + // NOTE: This default value (2000) is duplicated in ProcessGroupNCCL.cpp + // and ProcessGroupNCCL.hpp because they cannot directly query max_entries_ + // (no public accessor). Keep these values in sync. + max_entries_ = getCvarInt( + {"TORCH_FR_BUFFER_SIZE", "TORCH_NCCL_TRACE_BUFFER_SIZE"}, 2000); + capture_cpp_stack_ = getCvarBool( + {"TORCH_FR_CPP_STACK", "TORCH_NCCL_TRACE_CPP_STACK"}, false); + enabled_ = max_entries_ > 0; + reset_epoch_start_idx_[0] = 0; + } + struct Entry { + size_t id_; // incremented id in the trace buffer + // used to figure out where in the circular entries + // buffer this entry will be located to + // update state information + size_t reset_epoch_; // epoch when this entry was created + size_t pg_id_; + std::tuple pg_name_; // + + // collective_seq_id and p2p_seq_id refer to actual kernel launches (e.g. 1 + // per coalesced group). + // collective_seq_id only increments for true collective operations (over + // all ranks in the group). p2p_seq_id only increments over non-collective + // operations in the group. op_id refers to logical operations (e.g. one per + // op inside coalesced group) + size_t collective_seq_id_; + size_t p2p_seq_id_; + size_t op_id_; + std::string profiling_name_; + + std::shared_ptr traceback_; + // we borrow pointers to start_ and end_ so we can query the state + // on reporting. However, once the event is completed, the call + // to `complete` will clear these. + EventType *start_, *end_; + + // timestamp when the entry was created, likely close to the time the work + // was 'enqueued'- not necessarily started + c10::time_t time_created_; + + // configured timeout for this entry + c10::time_t timeout_ms_; + + // Is this a P2P event? + bool isP2P_; + + std::optional duration_; + + // timestamp when our CPU threads discovered that the kernel started. + // will always be _after_ it actually started, and can be very late + // if the watchdog thread got stuck on CUDA APIs. + std::optional time_discovered_started_; + + // timestamp when our CPU threads discovered that the kernel completed. + // will always be _after_ it actually completed, and can be the same time + // as the discovery of the start if the watchdog thread is stuck on CUDA + // APIs + std::optional time_discovered_completed_; + + // size information for input/output tensors + c10::SmallVector input_dims_; + std::vector input_dtypes_; + c10::SmallVector output_dims_; + std::vector output_dtypes_; + c10::SmallVector sizes_; // flattened from inputs, outputs + std::thread::id thread_id_; + std::string thread_name_; + bool retired_ = false; // is this work entry no longer in the workMetaList_? + // a retired but not completed event has timed out + + // Returns the traceback of current entry, in string form. + // Note: `getTraceback` invokes `torch::symbolize`, which may need to + // acquire the GIL. If you don't want to block the current thread or take + // the risk of a GIL deadlock, you can use an asynchronous calling mechanism + // like std::async. + TORCH_API std::string getTraceback(); + }; + + bool enabled_ = false; + bool capture_cpp_stack_ = false; + std::mutex mutex_; + std::vector entries_; + size_t max_entries_ = 0; + size_t next_ = 0; + size_t id_ = 0; + size_t reset_epoch_ = 0; + std::unordered_map + reset_epoch_start_idx_; // maps reset_epoch to the idx where it starts + std::map> all_pg_status_; + std::map, std::vector> + pg_name_to_ranks_; + std::string comm_lib_version_; + + struct TraceIdentifier { + std::optional id; + std::optional reset_epoch; + }; + + TraceIdentifier recordWithResetEnabled( + size_t pg_id, + const std::tuple& pg_name, + size_t collective_seq_id, + size_t p2p_seq_id, + size_t op_id, + std::string profiling_name, + const std::vector& inputs, + const std::vector& outputs, + EventType* start, + EventType* end, + std::chrono::milliseconds timeout_ms, + std::shared_ptr pg_status, + bool isP2P); + + std::optional record( + size_t pg_id, + const std::tuple& pg_name, + size_t collective_seq_id, + size_t p2p_seq_id, + size_t op_id, + std::string profiling_name, + const std::vector& inputs, + const std::vector& outputs, + EventType* start, + EventType* end, + std::chrono::milliseconds timeout_ms, + std::shared_ptr pg_status, + bool isP2P); + + TORCH_API void record_pg_ranks( + const std::tuple& pg_name, + std::vector ranks); + + void record_accelerator_version(const std::string comm_lib_version); + + void update_state(Entry& r); + + std::vector dump_entries(); + + // Returns the index in entries_ for the given id and reset_epoch. + // Caller must hold mutex_lock before calling this method. + size_t getIdxFromId(size_t id, size_t reset_epoch) const; + + // Returns the entry with the given id and reset_epoch, if it exists. + // Otherwise, returns std::nullopt. + TORCH_API std::optional getEntry( + std::optional id, + std::optional reset_epoch); + + TORCH_API std::optional getEntry(std::optional id); + + /* + Mark an Event as completed and free its events. + This is called by the watchdog thread, and is asynchronous from the + perspective of the main thread. + compute_duration defaults to true since retire_id is only called in the + watchdog thread, which is currently a place we call cuda APIs which may hang, + but care should be taken to avoid computing duration in any function that must + never hang. (timing must also be enabled for compute_duration - see + TORCH_NCCL_ENABLE_TIMING). + */ + TORCH_API void retire_id( + std::optional id, + std::optional reset_epoch, + bool compute_duration = true); + + TORCH_API void retire_id( + std::optional id, + bool compute_duration = true); + + TORCH_API void reset_all(); + + const c10::List getCollectiveTrace( + bool includeStacktraces, + bool onlyActive); + + // dump pg_entries + const c10::Dict getPgConfig(); + + const std::map> + getPgConfigJson(); + + // dump pg_status + const c10::Dict getPgStatus(); + + const std::map> + getPgStatusJson(); + + std::string dump_json( + const std::optional>>& extraDumpMap, + bool includeCollectives, + bool onlyActive); + + std::string dump( + const std::optional>>& extraDumpMap, + bool includeCollectives, + bool includeStackTraces, + bool onlyActive); +}; + +// Whether to include stack trace in the Flight Recorder trace (default true) +static std::vector TORCH_INCLUDE_STACK_TRACE = { + "TORCH_INCLUDE_STACK_TRACE"}; + +// Whether to include only active collectives in the Flight Recorder trace +// (default false) +static std::vector TORCH_INCLUDE_ONLY_ACTIVE = { + "TORCH_INCLUDE_ONLY_ACTIVE"}; + +// Dumps the fr traces and additional information about the Process +// Group. +TORCH_API std::string dump_fr_trace( + bool includeCollectives, + bool includeStackTraces, + bool onlyActive); + +// Dumps the fr traces and additional information about the Process +// Group in JSON formatted string. +// We don't include stack traces in JSON format as it is far too much data. +TORCH_API std::string dump_fr_trace_json( + bool includeCollectives, + bool onlyActive); +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/FlightRecorderDetail.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/FlightRecorderDetail.hpp new file mode 100644 index 0000000000000000000000000000000000000000..89b9987f011d005e95dd208dbd53a4c6b6954b81 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/FlightRecorderDetail.hpp @@ -0,0 +1,641 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include + +#include +#include + +#include + +namespace c10d { + +template +float getDurationFromEvent(EventType& start, EventType& end); + +// Returns the traceback of current entry, in string form. +// Note: `getTraceback` invokes `torch::symbolize`, which may need to acquire +// the GIL. If you don't want to block the current thread or take the risk of a +// GIL deadlock, you can use an asynchronous calling mechanism like std::async. +template +std::string FlightRecorder::Entry::getTraceback() { + torch::CapturedTraceback* traceback = traceback_.get(); + torch::SymbolizedTracebacks s_tbs = torch::symbolize({traceback}); + // We use 0 because we only have one traceback here. + const auto& s_tb = s_tbs.tracebacks.at(0); + std::stringstream oss; + for (auto idx : c10::irange(s_tb.size())) { + auto frame_id = s_tb[idx]; + const auto& frame = s_tbs.all_frames.at(frame_id); + oss << '#' << idx << ' ' << frame.funcname << " from " << frame.filename + << ':' << frame.lineno << '\n'; + } + /* Resulted format is like: + #0 all_reduce from pytorch/torch/distributed/distributed_c10d.py:2696 + #1 wrapper from pytorch/torch/distributed/c10d_logger.py:83 + #2 bar from /home/user/repro.py:15 + #3 foo from /home/user/repro.py:24 + #4 main from /home/user/repro.py:34 + #5 from /home/user/repro.py:40 + */ + return oss.str(); +} + +template +std::optional FlightRecorder::record( + size_t pg_id, + const std::tuple& pg_name, + size_t collective_seq_id, + size_t p2p_seq_id, + size_t op_id, + std::string profiling_name, + const std::vector& inputs, + const std::vector& outputs, + EventType* start, + EventType* end, + std::chrono::milliseconds timeout_ms, + std::shared_ptr pg_status, + bool isP2P) { + auto result = recordWithResetEnabled( + pg_id, + pg_name, + collective_seq_id, + p2p_seq_id, + op_id, + std::move(profiling_name), + inputs, + outputs, + start, + end, + timeout_ms, + std::move(pg_status), + isP2P); + return result.id; +} + +template +typename FlightRecorder::TraceIdentifier FlightRecorder:: + recordWithResetEnabled( + size_t pg_id, + const std::tuple& pg_name, + size_t collective_seq_id, + size_t p2p_seq_id, + size_t op_id, + std::string profiling_name, + const std::vector& inputs, + const std::vector& outputs, + EventType* start, + EventType* end, + std::chrono::milliseconds timeout_ms, + std::shared_ptr pg_status, + bool isP2P) { + if (!enabled_) { + return TraceIdentifier{std::nullopt, std::nullopt}; + } + auto traceback = + torch::CapturedTraceback::gather(true, true, capture_cpp_stack_); + std::lock_guard guard(mutex_); + if (all_pg_status_.find(pg_id) == all_pg_status_.end()) { + // Current pg_status is not in FR. + all_pg_status_[pg_id] = std::move(pg_status); + } + + TORCH_CHECK( + reset_epoch_start_idx_.find(reset_epoch_) != + reset_epoch_start_idx_.end()); + + auto te = Entry{ + id_, + reset_epoch_, + pg_id, + pg_name, + collective_seq_id, + p2p_seq_id, + op_id, + std::move(profiling_name), + std::move(traceback), + start, + end, + c10::getTime(), + timeout_ms.count(), + isP2P, + std::nullopt, + std::nullopt, + std::nullopt, + {}, + {}, + {}, + {}, + {}, + std::this_thread::get_id(), + c10::getThreadName(), + false}; + + for (const auto& input : inputs) { + c10::IntArrayRef sizes = input.sizes(); + te.input_dtypes_.push_back(input.dtype().toScalarType()); + te.input_dims_.push_back(static_cast(sizes.size())); + te.sizes_.insert(te.sizes_.end(), sizes.begin(), sizes.end()); + } + + for (const auto& output : outputs) { + c10::IntArrayRef sizes = output.sizes(); + te.output_dtypes_.push_back(output.dtype().toScalarType()); + te.output_dims_.push_back(static_cast(sizes.size())); + te.sizes_.insert(te.sizes_.end(), sizes.begin(), sizes.end()); + } + + const auto next = next_++; + + if (entries_.size() < max_entries_) { + entries_.emplace_back(std::move(te)); + } else { + entries_[next] = std::move(te); + } + + if (next_ == max_entries_) { + next_ = 0; + } + + const auto id = id_++; + return TraceIdentifier{id, reset_epoch_}; +} + +template +void FlightRecorder::record_pg_ranks( + const std::tuple& pg_name, + std::vector ranks) { + if (!enabled_) { + return; + } + std::lock_guard guard(mutex_); + pg_name_to_ranks_[pg_name] = std::move(ranks); +} + +template +void FlightRecorder::record_accelerator_version( + const std::string comm_lib_version) { + if (!enabled_) { + return; + } + std::lock_guard guard(mutex_); + comm_lib_version_ = std::move(comm_lib_version); +} + +template +void FlightRecorder::update_state(Entry& r) { + try { + if (r.start_ != nullptr) { + bool started = r.start_->query(); + if (started && !r.time_discovered_started_) { + r.time_discovered_started_ = c10::getTime(); + } + } + if (r.end_ != nullptr) { + bool completed = r.end_->query(); + if (completed && !r.time_discovered_completed_) { + r.time_discovered_completed_ = c10::getTime(); + } + } + } catch (std::exception& e) { + LOG(ERROR) << "Failed to update state for entry " << r.id_ << ": " + << r.profiling_name_ << " with error: " << e.what(); + } +} + +template +std::vector::Entry> FlightRecorder< + EventType>::dump_entries() { + std::vector result; + { + std::lock_guard guard(mutex_); + // Filter entries during insertion - only keep entries from current epoch + auto filter = [this](const Entry& e) { + return e.reset_epoch_ == reset_epoch_; + }; + std::copy_if( + entries_.begin() + static_cast(next_), + entries_.end(), + std::back_inserter(result), + filter); + std::copy_if( + entries_.begin(), + entries_.begin() + static_cast(next_), + std::back_inserter(result), + filter); + } + // query any remaining events + for (auto& r : result) { + update_state(r); + r.start_ = r.end_ = nullptr; + } + return result; +} + +template +// Returns the index in entries_ for the given id and reset_epoch. +// Caller must hold mutex_lock before calling this method. +size_t FlightRecorder::getIdxFromId(size_t id, size_t reset_epoch) + const { + // Look up the starting idx for the given reset epoch + auto it = reset_epoch_start_idx_.find(reset_epoch); + TORCH_CHECK(it != reset_epoch_start_idx_.end()); + // Calculate idx based on where the epoch started + return (it->second + id) % max_entries_; +} + +template +// Returns the entry with the given id and reset_epoch, if it exists. Otherwise, +// returns std::nullopt. +std::optional::Entry> FlightRecorder< + EventType>:: + getEntry(std::optional id, std::optional reset_epoch) { + if (!enabled_ || !id || !reset_epoch) { + return std::nullopt; + } + + std::unique_lock guard(mutex_); + Entry entry = entries_.at(getIdxFromId(*id, *reset_epoch)); + if (entry.id_ == *id && entry.reset_epoch_ == *reset_epoch) { + return entry; + } + return std::nullopt; +} + +template +std::optional::Entry> FlightRecorder< + EventType>::getEntry(std::optional id) { + return getEntry(id, 0); +} + +template +void FlightRecorder::retire_id( + std::optional id, + std::optional reset_epoch, + bool compute_duration) { + if (!enabled_ || !id || !reset_epoch) { + return; + } + + bool can_compute_duration = false; + EventType* startEvent = nullptr; + EventType* endEvent = nullptr; + std::optional duration = std::nullopt; + + std::unique_lock guard(mutex_); + + Entry* entry = &entries_.at(getIdxFromId(*id, *reset_epoch)); + if (entry->id_ == *id && entry->reset_epoch_ == *reset_epoch) { + update_state(*entry); + + if (compute_duration) { + can_compute_duration = entry->time_discovered_completed_.has_value() && + entry->start_ && entry->end_; + startEvent = entry->start_; + endEvent = entry->end_; + } + entry->retired_ = true; + entry->start_ = entry->end_ = nullptr; + } + + if (can_compute_duration) { + // Compute duration without without holding the lock, because + // cudaEventDuration() can hang, and we need to acquire the lock before we + // can dump(), which we never want to block. + guard.unlock(); + duration = getDurationFromEvent(*startEvent, *endEvent); + guard.lock(); + + // Refresh the entry pointer, see if the entry has been overwritten + entry = &entries_.at(getIdxFromId(*id, *reset_epoch)); + if (!(entry->id_ == *id && entry->reset_epoch_ == *reset_epoch)) { + LOG(INFO) << "retire_id abandoned for id " << *id + << ", event was overwritten while waiting to compute duration."; + return; + } + if (duration.has_value()) { + entry->duration_ = duration; + } + } +} + +template +void FlightRecorder::retire_id( + std::optional id, + bool compute_duration) { + retire_id(id, 0, compute_duration); +} + +template +void FlightRecorder::reset_all() { + std::lock_guard guard(mutex_); + if (!entries_.empty()) { + // Soft delete: increment epoch to mark all existing entries as old + // Store where the new epoch starts in the circular buffer + reset_epoch_++; + reset_epoch_start_idx_[reset_epoch_] = next_; + id_ = 0; + } +} + +template +const c10::List FlightRecorder::getCollectiveTrace( + bool includeStacktraces, + bool onlyActive) { + auto entries = new_list(); + // Entries are returned in the order they were recorded + auto result = dump_entries(); + std::vector tracebacks; + torch::SymbolizedTracebacks stracebacks; + std::vector all_frames; + if (includeStacktraces) { + for (auto& e : result) { + tracebacks.push_back(e.traceback_.get()); + } + stracebacks = torch::symbolize(tracebacks); + for (const auto& f : stracebacks.all_frames) { + auto d = new_dict(); + d.insert(name_key, f.funcname); + d.insert(filename_key, f.filename); + d.insert(line_key, int64_t(f.lineno)); + all_frames.emplace_back(std::move(d)); + } + } + for (auto i : c10::irange(result.size())) { + auto dict = new_dict(); + auto& e = result.at(i); + // Skip completed events + if (onlyActive && e.time_discovered_completed_.has_value()) { + continue; + } + if (includeStacktraces) { + auto& tb = stracebacks.tracebacks.at(i); + auto frames = new_list(); + for (auto frame : tb) { + frames.push_back(all_frames.at(frame)); + } + dict.insert(frames_key, frames); + } + + dict.insert(record_id_key, int64_t(e.id_)); + dict.insert(pg_id_key, int64_t(e.pg_id_)); + dict.insert(pg_name_key, e.pg_name_); + dict.insert(thread_name_key, e.thread_name_); + dict.insert(thread_id_key, c10::str(e.thread_id_)); + dict.insert(collective_seq_id_key, int64_t(e.collective_seq_id_)); + dict.insert(p2p_seq_id_key, int64_t(e.p2p_seq_id_)); + dict.insert(op_id_key, int64_t(e.op_id_)); + dict.insert(profiling_name_key, e.profiling_name_); + dict.insert(time_created_key, int64_t(e.time_created_)); + if (e.duration_) { + dict.insert(duration_key, *e.duration_); + } + + auto it = e.sizes_.begin(); + auto read_sizes = [&](const c10::SmallVector& dims) { + auto sizes = new_list(); + for (auto dim : dims) { + auto arg_sizes = new_list(); + for ([[maybe_unused]] auto i : c10::irange(dim)) { + arg_sizes.push_back(*it++); + } + sizes.push_back(arg_sizes); + } + return sizes; + }; + + dict.insert(input_sizes_key, read_sizes(e.input_dims_)); + std::vector input_dtypes_strs; + input_dtypes_strs.reserve(e.input_dtypes_.size()); + for (const auto& input_dtype : e.input_dtypes_) { + input_dtypes_strs.emplace_back(c10::toString(input_dtype)); + } + dict.insert(input_dtypes_key, input_dtypes_strs); + dict.insert(output_sizes_key, read_sizes(e.output_dims_)); + std::vector output_dtypes_strs; + output_dtypes_strs.reserve(e.output_dtypes_.size()); + for (const auto& output_dtype : e.output_dtypes_) { + output_dtypes_strs.emplace_back(c10::toString(output_dtype)); + } + dict.insert(output_dtypes_key, output_dtypes_strs); + if (e.time_discovered_completed_.has_value()) { + dict.insert(state_key, completed_state); + } else if (e.time_discovered_started_.has_value()) { + dict.insert(state_key, started_state); + } else { + dict.insert(state_key, scheduled_state); + } + + dict.insert( + time_discovered_started_key, + e.time_discovered_started_.has_value() + ? int64_t(*e.time_discovered_started_) + : c10::IValue()); + dict.insert( + time_discovered_completed_key, + e.time_discovered_completed_.has_value() + ? int64_t(*e.time_discovered_completed_) + : c10::IValue()); + dict.insert(retired_key, e.retired_); + dict.insert(timeout_key, e.timeout_ms_); + dict.insert(is_p2p_key, e.isP2P_); + + entries.push_back(dict); + } + return entries; +} + +template +const c10::Dict FlightRecorder< + EventType>::getPgConfig() { + auto pg_config = new_dict(); + for (const auto& [pg_name, ranks] : pg_name_to_ranks_) { + auto pg_info = new_dict(); + pg_info.insert("name", std::get<0>(pg_name)); + pg_info.insert("desc", std::get<1>(pg_name)); + pg_info.insert("ranks", ranks_str(ranks)); + pg_config.insert(std::get<0>(pg_name), pg_info); + } + return pg_config; +} + +template +const std::map> FlightRecorder< + EventType>::getPgConfigJson() { + std::map> result; + for (const auto& [pg_name, ranks] : pg_name_to_ranks_) { + auto pg_info = std::map(); + pg_info["name"] = std::get<0>(pg_name); + pg_info["desc"] = std::get<1>(pg_name); + pg_info["ranks"] = ranks_str(ranks); + result.emplace(std::get<0>(pg_name), pg_info); + } + return result; +} + +template +const c10::Dict FlightRecorder< + EventType>::getPgStatus() { + auto all_pg_status = new_dict(); + for (const auto& [pg_id, status] : all_pg_status_) { + auto pg_status = new_dict(); + pg_status.insert("last_enqueued_collective", status->lastEnqueuedSeq); + pg_status.insert("last_started_collective", status->lastStartedSeq); + pg_status.insert("last_completed_collective", status->lastCompletedSeq); + all_pg_status.insert(std::to_string(pg_id), pg_status); + } + return all_pg_status; +} + +template +const std::map> FlightRecorder< + EventType>::getPgStatusJson() { + std::map> result; + for (const auto& [pg_id, status] : all_pg_status_) { + auto pg_status = std::map(); + pg_status["last_enqueued_collective"] = + std::to_string(status->lastEnqueuedSeq); + pg_status["last_started_collective"] = + std::to_string(status->lastStartedSeq); + pg_status["last_completed_collective"] = + std::to_string(status->lastCompletedSeq); + result[std::to_string(pg_id)] = pg_status; + } + return result; +} + +using json = nlohmann::json; +template +std::string FlightRecorder::dump_json( + const std::optional>>& extraDumpMap, + bool includeCollectives, + bool onlyActive) { + json result; + result[version_key_str] = version_val_str; + result[comm_lib_version_key_str] = comm_lib_version_; + result[pg_config_key_str] = getPgConfigJson(); + result[pg_status_key_str] = getPgStatusJson(); + + // collective trace + if (includeCollectives) { + std::list entries; + for (auto& e : dump_entries()) { + json j; + if (onlyActive && e.time_discovered_completed_.has_value()) { + continue; + } + j[record_id_key_str] = int64_t(e.id_); + j[pg_id_key_str] = int64_t(e.pg_id_); + j[pg_name_key_str] = e.pg_name_; + j[thread_name_key_str] = e.thread_name_; + j[thread_id_key_str] = c10::str(e.thread_id_); + j[collective_seq_id_key_str] = int64_t(e.collective_seq_id_); + j[p2p_seq_id_key_str] = int64_t(e.p2p_seq_id_); + j[op_id_key_str] = int64_t(e.op_id_); + j[profiling_name_key_str] = e.profiling_name_; + j[time_created_key_str] = int64_t(e.time_created_); + if (e.duration_) { + j[duration_key_str] = *e.duration_; + } + auto it = e.sizes_.begin(); + auto read_sizes = [&](const c10::SmallVector& dims) { + auto sizes = std::list>(); + for (auto dim : dims) { + auto arg_sizes = std::list(); + for (auto i : c10::irange(dim)) { + (void)i; + arg_sizes.push_back(*it++); + } + sizes.push_back(arg_sizes); + } + return sizes; + }; + j[input_sizes_key_str] = read_sizes(e.input_dims_); + std::vector input_dtypes_strs; + input_dtypes_strs.reserve(e.input_dtypes_.size()); + for (const auto& input_dtype : e.input_dtypes_) { + input_dtypes_strs.emplace_back(c10::toString(input_dtype)); + } + j[input_dtypes_key_str] = input_dtypes_strs; + j[output_sizes_key_str] = read_sizes(e.output_dims_); + std::vector output_dtypes_strs; + output_dtypes_strs.reserve(e.output_dtypes_.size()); + for (const auto& output_dtype : e.output_dtypes_) { + output_dtypes_strs.emplace_back(c10::toString(output_dtype)); + } + j[output_dtypes_key_str] = output_dtypes_strs; + if (e.time_discovered_completed_.has_value()) { + j[state_key_str] = completed_state_str; + } else if (e.time_discovered_started_.has_value()) { + j[state_key_str] = started_state_str; + } else { + j[state_key_str] = scheduled_state_str; + } + j[time_discovered_started_key_str] = + e.time_discovered_started_.has_value() + ? int64_t(*e.time_discovered_started_) + : 0; + j[time_discovered_completed_key_str] = + e.time_discovered_completed_.has_value() + ? int64_t(*e.time_discovered_completed_) + : 0; + j[retired_key_str] = e.retired_; + j[timeout_key_str] = e.timeout_ms_; + j[is_p2p_key_str] = e.isP2P_; + entries.emplace_back(j); + } + + if (!entries.empty()) { + result[entries_key_str] = entries; + } + } + + if (extraDumpMap.has_value()) { + result[nccl_comm_key_str] = extraDumpMap.value(); + } + return result.dump(); +} + +template +std::string FlightRecorder::dump( + const std::optional>>& extraDumpMap, + bool includeCollectives, + bool includeStackTraces, + bool onlyActive) { + STATIC_SCOPED_WAIT_COUNTER(pytorch.wait_counter.FlightRecorder__dump); + auto result = new_dict(); + // common values + result.insert(version_key, version_val); + result.insert(pg_config_key, getPgConfig()); + result.insert(comm_lib_version_key_str, comm_lib_version_); + result.insert(pg_status_key, getPgStatus()); + + // collective trace + if (includeCollectives) { + result.insert( + entries_key, getCollectiveTrace(includeStackTraces, onlyActive)); + } + + // convert extraDumpMap into a dictionary + auto per_comm_dict = new_dict(); + if (extraDumpMap.has_value()) { + for (const auto& [ncclId, ncclDump] : extraDumpMap.value()) { + auto inner_dict = new_dict(); + for (const auto& [key, value] : ncclDump) { + inner_dict.insert(key, value); + } + per_comm_dict.insert(ncclId, inner_dict); + } + } + if (!per_comm_dict.empty()) { + result.insert(nccl_comm_key, per_comm_dict); + } + return pickle_str(result); +} +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Functional.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Functional.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1970c4abb9fa4ef0192a7814e2eebc8637c11410 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Functional.hpp @@ -0,0 +1,182 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace c10d { + +C10_EXPORT at::Tensor& all_reduce_( + at::Tensor& input, + std::string reduce_op, + std::string group_name); + +C10_EXPORT at::Tensor& all_reduce_( + at::Tensor& input, + std::string reduce_op, + c10::intrusive_ptr group); + +C10_EXPORT at::Tensor all_reduce( + const at::Tensor& input, + std::string reduce_op, + std::string group_name); + +C10_EXPORT at::Tensor all_reduce( + const at::Tensor& input, + std::string reduce_op, + c10::intrusive_ptr group); + +C10_EXPORT std::vector all_reduce_coalesced_( + std::vector inputs, + // NOLINTNEXTLINE(performance-unnecessary-value-param) + std::string reduce_op, + c10::intrusive_ptr group); + +C10_EXPORT std::vector all_reduce_coalesced_( + std::vector inputs, + // NOLINTNEXTLINE(performance-unnecessary-value-param) + std::string reduce_op, + // NOLINTNEXTLINE(performance-unnecessary-value-param) + std::string group_name); + +C10_EXPORT std::vector all_reduce_coalesced( + std::vector inputs, + std::string reduce_op, + c10::intrusive_ptr group); + +C10_EXPORT std::vector all_reduce_coalesced( + // NOLINTNEXTLINE(performance-unnecessary-value-param) + std::vector inputs, + std::string reduce_op, + std::string group_name); + +C10_EXPORT std::vector all_gather_into_tensor_coalesced( + std::vector inputs, + int64_t group_size, + // NOLINTNEXTLINE(performance-unnecessary-value-param) + std::string group_name); + +C10_EXPORT std::vector all_gather_into_tensor_coalesced( + std::vector inputs, + int64_t group_size, + c10::intrusive_ptr group); + +C10_EXPORT at::Tensor all_gather_into_tensor( + const at::Tensor& input, + int64_t group_size, + std::string group_name); + +C10_EXPORT at::Tensor all_gather_into_tensor( + const at::Tensor& input, + int64_t group_size, + c10::intrusive_ptr group); + +C10_EXPORT at::Tensor& all_gather_into_tensor_out( + at::Tensor& input, + int64_t group_size, + const std::string& group_name, + at::Tensor& output); + +C10_EXPORT at::Tensor& all_gather_into_tensor_out( + at::Tensor& input, + int64_t group_size, + c10::intrusive_ptr group, + at::Tensor& output); + +C10_EXPORT std::vector reduce_scatter_tensor_coalesced( + std::vector inputs, + // NOLINTNEXTLINE(performance-unnecessary-value-param) + std::string reduce_op, + int64_t group_size, + c10::intrusive_ptr group); + +C10_EXPORT std::vector reduce_scatter_tensor_coalesced( + std::vector inputs, + // NOLINTNEXTLINE(performance-unnecessary-value-param) + std::string reduce_op, + int64_t group_size, + // NOLINTNEXTLINE(performance-unnecessary-value-param) + std::string group_name); + +C10_EXPORT at::Tensor reduce_scatter_tensor( + const at::Tensor& input, + std::string reduce_op, + int64_t group_size, + c10::intrusive_ptr group); + +C10_EXPORT at::Tensor reduce_scatter_tensor( + const at::Tensor& input, + std::string reduce_op, + int64_t group_size, + std::string group_name); + +C10_EXPORT at::Tensor reduce_scatter_tensor_out( + const at::Tensor& input, + std::string reduce_op, + int64_t group_size, + c10::intrusive_ptr group, + at::Tensor& output); + +C10_EXPORT at::Tensor reduce_scatter_tensor_out( + const at::Tensor& input, + std::string reduce_op, + int64_t group_size, + std::string group_name, + at::Tensor& output); + +C10_EXPORT at::Tensor all_to_all_single( + const at::Tensor& input, + at::SymIntArrayRef output_split_sizes, + at::SymIntArrayRef input_split_sizes, + // NOLINTNEXTLINE(performance-unnecessary-value-param) + std::string group_name); + +C10_EXPORT at::Tensor all_to_all_single( + const at::Tensor& input, + at::SymIntArrayRef output_split_sizes, + at::SymIntArrayRef input_split_sizes, + c10::intrusive_ptr group); + +C10_EXPORT at::Tensor& broadcast_( + at::Tensor& input, + int64_t src, + c10::intrusive_ptr group); + +C10_EXPORT at::Tensor& broadcast_( + at::Tensor& input, + int64_t src, + std::string group_name); + +C10_EXPORT at::Tensor broadcast( + const at::Tensor& input, + int64_t src, + c10::intrusive_ptr group); + +C10_EXPORT at::Tensor broadcast( + const at::Tensor& input, + int64_t src, + std::string group_name); + +C10_EXPORT at::Tensor isend( + at::Tensor& send_buf, + int64_t dst, + int64_t tag, + std::string group_name); + +C10_EXPORT at::Tensor irecv( + at::Tensor& recv_buf, + int64_t src, + int64_t tag, + std::string group_name); + +C10_EXPORT std::vector batch_p2p_ops( + std::vector op_list, + std::vector peer_list, + std::vector tag_list, + std::vector tensors_for_op, + std::string group_name); + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/GlooDeviceFactory.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/GlooDeviceFactory.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9770bbe9f3822bc68fa8c3344e92c17b95004dff --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/GlooDeviceFactory.hpp @@ -0,0 +1,40 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef USE_C10D_GLOO + +#include + +#include +#include +#include + +namespace c10d { + +class TORCH_API GlooDeviceFactory { + public: + // Create new device instance for specific interface. + static std::shared_ptr<::gloo::transport::Device> makeDeviceForInterface( + const std::string& interface, + bool lazyInit); + + // Create new device instance for specific hostname or address. + static std::shared_ptr<::gloo::transport::Device> makeDeviceForHostname( + const std::string& hostname, + bool lazyInit); +}; + +TORCH_DECLARE_SHARED_REGISTRY( + GlooDeviceRegistry, + ::gloo::transport::Device, + const std::string&, /* interface */ + const std::string&, /* hostname */ + bool /* lazyInit */); + +} // namespace c10d + +#endif // USE_C10D_GLOO + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/GroupRegistry.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/GroupRegistry.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4df50c8b39e5fbfc27e74477651d865a5d3dc06d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/GroupRegistry.hpp @@ -0,0 +1,27 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace c10d { + +C10_EXPORT void set_thread_isolation_mode(bool enable); + +bool get_thread_isolation_mode(); + +C10_EXPORT void register_process_group( + const std::string& group_name, + const c10::intrusive_ptr& group); + +C10_EXPORT c10::intrusive_ptr resolve_process_group( + const std::string& group_name); + +C10_EXPORT void unregister_process_group(const std::string& group_name); + +C10_EXPORT void unregister_all_process_groups(); + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/HashStore.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/HashStore.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e9b6186ef3bbf413ade67ddc83b764c43e655fa6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/HashStore.hpp @@ -0,0 +1,86 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include + +namespace c10d { + +class TORCH_API HashStore : public Store { + public: + c10::intrusive_ptr clone() override; + + ~HashStore() override = default; + + void set(const std::string& key, const std::vector& data) override; + + std::vector compareSet( + const std::string& key, + const std::vector& expectedValue, + const std::vector& desiredValue) override; + + std::vector get(const std::string& key) override; + + void wait(const std::vector& keys) override { + wait(keys, timeout_); + } + + void wait( + const std::vector& keys, + const std::chrono::milliseconds& timeout) override; + + int64_t add(const std::string& key, int64_t value) override; + + int64_t getNumKeys() override; + + bool check(const std::vector& keys) override; + + bool deleteKey(const std::string& key) override; + + void append(const std::string& key, const std::vector& value) + override; + + std::vector> multiGet( + const std::vector& keys) override; + + void multiSet( + const std::vector& keys, + const std::vector>& values) override; + + // Returns true if this store support append, multiGet and multiSet + bool hasExtendedApi() const override; + + void queuePush(const std::string& key, const std::vector& value) + override; + + std::vector queuePop(const std::string& key, bool block) override; + + int64_t queueLen(const std::string& key) override; + + std::vector listKeys() override; + + protected: + bool checkLocked( + const std::unique_lock& lock, + const std::vector& keys); + + void waitLocked( + std::unique_lock& lock, + const std::vector& keys, + const std::chrono::milliseconds& timeout); + + protected: + std::unordered_map> map_; + std::unordered_map>> queues_; + std::mutex m_; + std::condition_variable cv_; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/NCCLUtils.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/NCCLUtils.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c8dd7f59bb97fbd0b1a9ccbce42bf0cf50ade5d1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/NCCLUtils.hpp @@ -0,0 +1,458 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef USE_C10D_NCCL + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +constexpr int64_t kCommInitBusyWaitMillis = 2; + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 14, 0) +#define NCCL_HAS_COMM_NONBLOCKING +#endif + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 18, 0) +#define NCCL_HAS_COMM_SPLIT +#endif + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 23, 0) +#define NCCL_HAS_INIT_RANK_SCALABLE +#endif + +// ncclGetLastError() is enabled only for NCCL versions 2.13+ +// ncclRemoteError only exists in NCCL versions 2.13+ +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 13, 0) +#define ENABLE_NCCL_GET_LAST_ERROR +#define NCCL_REMOTE_ERROR +#endif + +static_assert( + NCCL_VERSION_CODE >= NCCL_VERSION(2, 7, 0), + "NCCL version must be 2.7 or later"); +// The following macros represent features supported prior to NCCL 2.7, +// therefore we can define them unconditionally, given the static_assert above. +// TODO: remove these macros from code. +#define ENABLE_NCCL_ERROR_CHECKING +#define ENABLE_NCCL_P2P_SUPPORT +// End of macros for NCCL 2.7 and below. + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 11, 0) +#define ENABLE_NCCL_PREMUL_SUM_SUPPORT +#endif + +// Note: the first version that supports ncclConfig_t is 2.14. Here we +// fast-forward the version requirement to 2.17 where ncclConfig_t has CTA and +// CGA fields because they have already been pybinded out. +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 17, 0) +#define NCCL_HAS_CONFIG +#endif + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 19, 0) +#define NCCL_HAS_COMM_REGISTER +#endif + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 27, 0) +#define NCCL_HAS_COMM_WINDOW_REGISTER +#endif + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 19, 0) +#define NCCL_HAS_MEM_ALLOC +#endif + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 26, 0) +#define NCCL_HAS_QOS +#endif + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 24, 0) +#define NCCL_SUPPORTS_FP8 +#endif + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 27, 0) +#define NCCL_HAS_COLLNET +#endif + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 27, 0) +#define NCCL_HAS_CTA_POLICY +#endif + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 27, 0) +#define NCCL_HAS_NVLS_CTAS +#endif + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 27, 0) +#define NCCL_HAS_COMM_SHRINK +#endif + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 29, 7) +#define NCCL_HAS_COMM_OFFLOAD +#endif + +// Macro to throw on a non-successful NCCL return value. +#define C10D_NCCL_CHECK(cmd, failureReason) \ + do { \ + ncclResult_t result = cmd; \ + if (result != ncclSuccess) { \ + std::string err = "NCCL error in: " + std::string(__FILE__) + ":" + \ + std::to_string(__LINE__) + ", " + ncclGetErrorWithVersion(result) + \ + "\n" + getNcclErrorDetailStr(result, failureReason); \ + TORCH_CHECK_WITH(DistBackendError, false, err); \ + } \ + } while (0) + +// Macro to throw on a non-successful NCCL return value for NONBLOCKING calls. +#define C10D_NCCL_CHECK_NONBLOCKING(cmd, failureReason) \ + do { \ + ncclResult_t result = cmd; \ + if (result != ncclSuccess && result != ncclInProgress) { \ + std::string err = "NCCL error in: " + std::string(__FILE__) + ":" + \ + std::to_string(__LINE__) + ", " + ncclGetErrorWithVersion(result) + \ + "\n" + getNcclErrorDetailStr(result, failureReason); \ + TORCH_CHECK_WITH(DistBackendError, false, err); \ + } \ + } while (0) + +// Error out if (current time - startTime) is greater than timeout (sec). +#define C10D_CHECK_TIMEOUT(startTime, timeout) \ + do { \ + auto currentTime = std::chrono::steady_clock::now(); \ + auto timeElapsed = std::chrono::duration_cast( \ + currentTime - startTime) \ + .count(); \ + if (timeElapsed > timeout) { \ + std::string err = "NCCL timeout in: " + std::string(__FILE__) + ":" + \ + std::to_string(__LINE__); \ + TORCH_CHECK_WITH(DistBackendError, false, err); \ + } \ + } while (0) + +// Macro to throw on a non-successful NCCL return value, non-blocking. +// Thread-safe: uses NCCLComm wrapper's getAsyncError() which acquires mutex +// before calling ncclCommGetAsyncError to prevent race conditions between +// watchdog and main threads. +#define C10D_NCCL_CHECK_TIMEOUT_BASE( \ + cmd, commWrapper, failureReason, yield_fn) \ + do { \ + ncclResult_t result = cmd; \ + auto startTimepoint = std::chrono::steady_clock::now(); \ + auto timeout = nccl_nonblocking_timeout(); \ + while (result == ncclInProgress) { \ + C10D_CHECK_TIMEOUT(startTimepoint, timeout); \ + yield_fn; \ + commWrapper->getAsyncError(&result); \ + } \ + if (result != ncclSuccess) { \ + std::string err = "NCCL error in: " + std::string(__FILE__) + ":" + \ + std::to_string(__LINE__) + ", " + ncclGetErrorWithVersion(result) + \ + "\n" + getNcclErrorDetailStr(result, failureReason); \ + TORCH_CHECK_WITH(DistBackendError, false, err); \ + } \ + } while (0) + +// Sleep for kCommInitBusyWaitMillis milliseconds. +#define C10D_SCHED_SLEEP() \ + std::this_thread::sleep_for( \ + std::chrono::milliseconds(kCommInitBusyWaitMillis)) + +// Macro to throw exception on a non-successful NCCL return value or timeout. +// This macro uses sched_yield() to yield the CPU. +// Thus suitable for NCCL calls that would quickly turn ncclSuccess, e.g. +// collectives. +#define C10D_NCCL_CHECK_TIMEOUT(cmd, commWrapper, failureReason) \ + C10D_NCCL_CHECK_TIMEOUT_BASE(cmd, commWrapper, failureReason, sched_yield()) + +// Macro to throw exception on a non-successful NCCL return value or timeout. +// This macro uses sleep to yield the CPU. +// Thus suitable for NCCL calls that would take longer to turn ncclSuccess, e.g. +// ncclCommInitRankConfig, ncclCommFinalize, etc. +#define C10D_NCCL_CHECK_TIMEOUT_SLEEP(cmd, commWrapper, failureReason) \ + C10D_NCCL_CHECK_TIMEOUT_BASE( \ + cmd, commWrapper, failureReason, C10D_SCHED_SLEEP()) + +#define C10D_NCCL_CHECK_TIMEOUT_GROUPEND(cmd, comm, failureReason) \ + do { \ + ncclResult_t state = cmd; \ + auto startTimepoint = std::chrono::steady_clock::now(); \ + auto timeout = nccl_nonblocking_timeout(); \ + if (state == ncclInProgress) { \ + do { \ + C10D_CHECK_TIMEOUT(startTimepoint, timeout); \ + sched_yield(); \ + comm->getAsyncError(&state); \ + } while (state == ncclInProgress); \ + } \ + if (state != ncclSuccess) { \ + std::string err = "NCCL error in: " + std::string(__FILE__) + ":" + \ + std::to_string(__LINE__) + ", " + ncclGetErrorWithVersion(state) + \ + "\n" + getNcclErrorDetailStr(state, failureReason); \ + TORCH_CHECK_WITH(DistBackendError, false, err); \ + } \ + } while (0) + +// Macro to print and abort on a non-successful NCCL return value. +#define C10D_NCCL_ASSERT(cmd) \ + do { \ + ncclResult_t result = cmd; \ + if (result != ncclSuccess) { \ + std::string err = ncclGetErrorWithVersion(result); \ + fprintf( \ + stderr, \ + "NCCL error in: %s:%d, %s\n", \ + __FILE__, \ + __LINE__, \ + err.c_str()); \ + abort(); \ + } \ + } while (0) + +namespace c10d { + +// NCCL type typing +static std::map ncclDataType = { + {at::kChar, ncclInt8}, + {at::kByte, ncclUint8}, + {at::kFloat, ncclFloat}, + {at::kDouble, ncclDouble}, + {at::kInt, ncclInt32}, + {at::kLong, ncclInt64}, + {at::kHalf, ncclHalf}, + {at::kBool, ncclUint8}, +#ifdef NCCL_SUPPORTS_FP8 + {at::kFloat8_e5m2, ncclFloat8e5m2}, + {at::kFloat8_e4m3fn, ncclFloat8e4m3}, +#else + {at::kFloat8_e5m2, ncclUint8}, + {at::kFloat8_e4m3fn, ncclUint8}, +#endif + // NVIDIA GPUs does not support the UZ version standing for "no negative + // zero". See https://onnx.ai/onnx/technical/float8.html + {at::kFloat8_e4m3fnuz, ncclUint8}, + {at::kFloat8_e5m2fnuz, ncclUint8}, +#if HAS_NCCL_BF16_DATATYPE + {at::kBFloat16, ncclBfloat16}, +#endif // HAS_NCCL_BF16_DATATYPE +}; + +TORCH_API size_t hashTensors(const std::vector& tensors); +TORCH_API std::string getNcclVersion(); +TORCH_API std::tuple getNcclVersionTuple(); +TORCH_API int getNcclVersionNumber(); +TORCH_API std::string ncclGetErrorWithVersion(ncclResult_t error); +int nccl_nonblocking_timeout(); + +// Provides additional detail into NCCL error codes based on when these are +// thrown in the NCCL codebase. +TORCH_API std::string getNcclErrorDetailStr( + ncclResult_t error, + std::optional processGroupFailureReason = std::nullopt); + +// Helper function that gets the data type and issues error if not supported +ncclDataType_t getNcclDataType(at::ScalarType type); + +// RAII wrapper for NCCL communicator +class NCCLComm { + using MutexType = std::recursive_mutex; + using LockType = std::unique_lock; + + public: + explicit NCCLComm(ncclComm_t ncclComm); + + NCCLComm() = default; + + ~NCCLComm() noexcept; + + void setUniqueHash(ncclUniqueId ncclId); + void setUniqueHash(std::string hash); + std::string getUniqueHash(); + + static std::shared_ptr create( + int numRanks, + int rank, + ncclUniqueId commId, + at::DeviceIndex deviceIndex); + +#ifdef NCCL_HAS_CONFIG + static std::shared_ptr create( + int numRanks, + int rank, + ncclUniqueId commId, + at::DeviceIndex deviceIndex, + ncclConfig_t& config); +#ifdef NCCL_HAS_INIT_RANK_SCALABLE + static std::shared_ptr create_scalable( + int numRanks, + int rank, + std::vector& commIds, + at::DeviceIndex deviceIndex, + ncclConfig_t& config); +#endif // NCCL_HAS_INIT_RANK_SCALABLE +#endif // NCCL_HAS_CONFIG + +#ifdef NCCL_HAS_COMM_SPLIT + static std::shared_ptr split( + NCCLComm* source, + int color_id, + int rank, + ncclConfig_t& config); +#endif // NCCL_HAS_COMM_SPLIT + +#ifdef NCCL_HAS_COMM_SHRINK + static std::shared_ptr shrink( + NCCLComm* source, + std::vector& ranks_to_exclude, + ncclConfig_t* config, + int shrinkFlags = 0); +#endif // NCCL_HAS_COMM_SHRINK + +#if (defined(IS_NCCLX) || defined(USE_ROCM)) && defined(NCCL_COMM_DUMP) + std::unordered_map ncclCommDump(); +#endif + + at::DeviceIndex getDeviceIndex(); + + // Must not be copyable + NCCLComm(const NCCLComm&) = delete; + NCCLComm& operator=(const NCCLComm&) = delete; + + // Do not support move assignment as there is no valid use case + NCCLComm& operator=(NCCLComm&& other) = delete; + + // Move constructable + // NOLINTNEXTLINE(*-noexcept-move-*) + NCCLComm(NCCLComm&& other); + + ncclComm_t getNcclComm(); + + // Wait for the communicator to be ready. This is a blocking function. + // Useful in nonblocking mode: NCCL requires the communicator to be ready + // before issuing a second command. + // Arguments: + // longInterval: if true, wait with sleep of an interval; otherwise, wait + // with `sched_yield` which is faster (but acquires CPU more frequently). + // Use `longInterval=true` when waiting for initialization or finalize to + // complete. Use `longInterval=false` when waiting collective call to return + // ncclSuccess. + void waitReady(bool longInterval); + + std::optional getNcclCommFailureReason() const; + + void abort(std::optional commFailureReason = std::nullopt); + + // Finalize a communicator -- asking it to flush its operations. When the + // communicator is marked as nonblocking, this is a nonblocking function; + // otherwise, it will block till all operations complete. + void finalize(); + + // Destroy a communicator. This is a blocking function. + void destroy(); + + bool isInitialized() const; + + bool isAborted() const; + + uint64_t getCommSplitCounter() const; + + ncclResult_t checkForNcclError(); + + // Thread-safe wrapper for ncclCommGetAsyncError that acquires the mutex + // before calling the NCCL API. This is needed because NCCL does not provide + // thread-safety guarantees for ncclCommGetAsyncError, and both the main + // thread and watchdog thread may call it concurrently. + ncclResult_t getAsyncError(ncclResult_t* asyncError); + + ncclResult_t registerSegment( + void* ptr, + size_t size, + bool errorOnRereg = true, + bool window = false); + + ncclResult_t deregisterSegment(void* ptr, bool window = false); + + std::string repr() const; + + // APIs related to memory offload (require NCCL 2.29.7+ at runtime) + void suspend(); + + void resume(); + + std::unordered_map getMemoryStats(); + + friend class ProcessGroupNCCL; + + protected: + // Unique hash for this communicator. + std::string uniqueHash_; + bool aborted_{false}; + uint64_t ncclCommSplitCounter_{0}; + ncclResult_t ncclAsyncErr_{ncclSuccess}; + mutable MutexType mutex_; + // Rank that this communicator corresponds to. + int rank_{}; + // Optional reason for communicator failure, provided by ProcessGroupNCCL for + // better error messaging. + std::optional commFailureReason_; + bool initialized_{false}; + // Whether this communicator is using nonblocking mode. Recorded during comm + // creation or split. For safety, we give a default value of true (more + // protection). + bool nonBlocking_{true}; + // Device index for which the NCCL comm is created + at::DeviceIndex deviceIndex_{-1}; +#ifdef NCCL_HAS_COMM_REGISTER + // Stores handlers for tensors registered by NCCL + std::unordered_map registeredSegmentHandles_; +#endif // NCCL_HAS_COMM_REGISTER + + private: + ncclComm_t ncclComm_{nullptr}; +}; + +// Helper that automatically cleans up premul sums. +struct ncclRedOpRAII { + ncclRedOpRAII() = default; + ncclRedOpRAII(ncclRedOp_t op) : op_(op) {} + ncclRedOpRAII(ncclRedOp_t op, ncclComm_t comm) + : op_(op), comm_(comm), premul_sum_(true) {} + ncclRedOpRAII(const ncclRedOpRAII&) = delete; + ncclRedOpRAII& operator=(const ncclRedOpRAII&) = delete; + ncclRedOpRAII(ncclRedOpRAII&& tmp) noexcept : ncclRedOpRAII() { + std::swap(tmp.op_, this->op_); + std::swap(tmp.comm_, this->comm_); + std::swap(tmp.premul_sum_, this->premul_sum_); + } +#if defined(ENABLE_NCCL_PREMUL_SUM_SUPPORT) + ~ncclRedOpRAII() { + if (premul_sum_) { + ncclRedOpDestroy(op_, comm_); + } + } +#endif // ENABLE_NCCL_PREMUL_SUM_SUPPORT + operator ncclRedOp_t() const { + return op_; + } + ncclRedOp_t op_{}; + ncclComm_t comm_{}; + bool premul_sum_ = false; +}; + +void printNcclCommProxyTrace( + const std::string& dumpReason, + const std::unordered_map& dumpMap); +} // namespace c10d + +#endif // USE_C10D_NCCL + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/NanCheck.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/NanCheck.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a912bfeed4ee795f41b1e26cd540caea5d40e36a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/NanCheck.hpp @@ -0,0 +1,17 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace c10d { + +// Check for NaNs in a tensor. If any are found, throw an error. +// Dispatches to device-specific implementations via the c10d::check_for_nan op. +TORCH_API void checkForNan(const at::Tensor& tensor); + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ParamCommsUtils.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ParamCommsUtils.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9cec8cbdb9ad81a4ccf6b35e5879e13acef4722b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ParamCommsUtils.hpp @@ -0,0 +1,260 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace torch { + +class TORCH_API ParamCommsDebugInfo : public c10::DebugInfoBase { + public: + ParamCommsDebugInfo() = default; + ParamCommsDebugInfo( + std::tuple pgName, + int rank, + std::string&& collName, + int64_t inNelems, + int64_t outNelems, + at::ScalarType dType, + std::vector inSplitSizes, + std::vector outSplitSizes, + int globalRankStart, + int globalRankStride, + int worldSize, + bool isAsynchronizedOp = true); + + ~ParamCommsDebugInfo() override = default; + + const std::string getProcessGroupName() const { + return std::get<0>(pgName_); + } + + const std::string getProcessGroupDesc() const { + return std::get<1>(pgName_); + } + + int getRank() const { + return rank_; + } + + int getWorldSize() const { + return worldSize_; + } + + int getGlobalRankStart() const { + return globalRankStart_; + } + + int getGlobalRankStride() const { + return globalRankStride_; + } + + const std::string getCollectiveName() const { + return collectiveName_; + } + + int64_t getInMessageNelems() const { + return inMessageNelems_; + } + + int64_t getOutMessageNelems() const { + return outMessageNelems_; + } + + at::ScalarType getDType() const { + return dType_; + } + + const std::vector& getInputSplitSizes() const { + return inputSplitSizes_; + } + + const std::vector& getOutputSplitSizes() const { + return outputSplitSizes_; + } + + const std::vector& getGroupRanks() const { + return groupRanks_; + } + + bool isAsynchronizedOp() const { + return isAsynchronizedOp_; + } + + int64_t getSequenceNumber() const { + return sequenceNumber_; + } + + bool getIsP2P() const { + return isP2P_; + } + + void setSequenceInfo(int64_t seqNum, bool isP2P) { + sequenceNumber_ = seqNum; + isP2P_ = isP2P; + } + + private: + std::tuple pgName_; // + int rank_{}; + int worldSize_{}; + std::string collectiveName_; + int64_t inMessageNelems_{}; + int64_t outMessageNelems_{}; + at::ScalarType dType_ = at::kByte; + std::vector inputSplitSizes_; + std::vector outputSplitSizes_; + int globalRankStart_{}; + int globalRankStride_{}; + std::vector groupRanks_; + bool isAsynchronizedOp_{}; + int64_t sequenceNumber_{-1}; + bool isP2P_{false}; +}; + +// Helper to set sequence info from tuple-typed seq arguments (NCCL backend). +// No-op fallback for backends that pass non-tuple seq types (e.g., XPU/XCCL). +template +inline void maybeSetSequenceInfo( + const std::shared_ptr& info, + const std::tuple& seq) { + info->setSequenceInfo(std::get<0>(seq), std::get<1>(seq)); +} + +template +inline void maybeSetSequenceInfo( + const std::shared_ptr&, + const T&) {} + +#define RECORD_PARAM_COMMS( \ + seq, \ + pgName, \ + rank, \ + collName, \ + inNelems, \ + outNelems, \ + dType, \ + inSplitSizes, \ + outSplitSizes, \ + globalRankStart, \ + globalRankStride, \ + worldSize) \ + auto paramCommsInfo = std::make_shared( \ + pgName, \ + rank, \ + collName, \ + inNelems, \ + outNelems, \ + dType, \ + inSplitSizes, \ + outSplitSizes, \ + globalRankStart, \ + globalRankStride, \ + worldSize, \ + false); \ + torch::maybeSetSequenceInfo(paramCommsInfo, seq); \ + c10::DebugInfoGuard g(c10::DebugInfoKind::PARAM_COMMS_INFO, paramCommsInfo); \ + std::initializer_list paramList = { \ + seq, \ + pgName, \ + rank, \ + collName, \ + inSplitSizes, \ + outSplitSizes, \ + globalRankStart, \ + globalRankStride, \ + worldSize, \ + false}; \ + c10::ArrayRef paramInputs(paramList); \ + RECORD_FUNCTION(at::kParamCommsCallName, paramInputs); + +#define RECORD_PARAM_COMMS_DATA( \ + seq, \ + pgName, \ + InputTensors, \ + OutputTensors, \ + rank, \ + collName, \ + inNelems, \ + outNelems, \ + dType, \ + inSplitSizes, \ + outSplitSizes, \ + globalRankStart, \ + globalRankStride, \ + worldSize) \ + RECORD_PARAM_COMMS_DATA_WITH_ASYNC_OP( \ + seq, \ + pgName, \ + InputTensors, \ + OutputTensors, \ + rank, \ + collName, \ + inNelems, \ + outNelems, \ + dType, \ + inSplitSizes, \ + outSplitSizes, \ + globalRankStart, \ + globalRankStride, \ + worldSize, \ + true); + +#define RECORD_PARAM_COMMS_DATA_WITH_ASYNC_OP( \ + seq, \ + pgName, \ + InputTensors, \ + OutputTensors, \ + rank, \ + collName, \ + inNelems, \ + outNelems, \ + dType, \ + inSplitSizes, \ + outSplitSizes, \ + globalRankStart, \ + globalRankStride, \ + worldSize, \ + isAsyncOp) \ + auto paramCommsInfo = std::make_shared( \ + pgName, \ + rank, \ + collName, \ + inNelems, \ + outNelems, \ + dType, \ + inSplitSizes, \ + outSplitSizes, \ + globalRankStart, \ + globalRankStride, \ + worldSize, \ + isAsyncOp); \ + torch::maybeSetSequenceInfo(paramCommsInfo, seq); \ + c10::DebugInfoGuard g(c10::DebugInfoKind::PARAM_COMMS_INFO, paramCommsInfo); \ + std::initializer_list paramList = { \ + c10::IValue(InputTensors), \ + seq, \ + pgName, \ + rank, \ + collName, \ + inSplitSizes, \ + outSplitSizes, \ + globalRankStart, \ + globalRankStride, \ + worldSize, \ + isAsyncOp}; \ + c10::ArrayRef paramInputs(paramList); \ + RECORD_FUNCTION_WITH_INPUTS_OUTPUTS( \ + at::kParamCommsCallName, \ + paramInputs, \ + std::vector(1, c10::IValue(OutputTensors))); +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/PrefixStore.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/PrefixStore.hpp new file mode 100644 index 0000000000000000000000000000000000000000..48411dd8182e462c0e2592f30e0714a70769cc63 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/PrefixStore.hpp @@ -0,0 +1,82 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace c10d { + +class TORCH_API PrefixStore : public Store { + public: + explicit PrefixStore(std::string prefix, c10::intrusive_ptr store); + + c10::intrusive_ptr clone() override; + + using Store::set; + void set(const std::string& key, const std::vector& value) override; + + using Store::compareSet; + std::vector compareSet( + const std::string& key, + const std::vector& expectedValue, + const std::vector& desiredValue) override; + + std::vector get(const std::string& key) override; + + int64_t add(const std::string& key, int64_t value) override; + + bool deleteKey(const std::string& key) override; + + int64_t getNumKeys() override; + + bool check(const std::vector& keys) override; + + void wait(const std::vector& keys) override; + + void wait( + const std::vector& keys, + const std::chrono::milliseconds& timeout) override; + + const std::chrono::milliseconds& getTimeout() const noexcept override; + + void setTimeout(const std::chrono::milliseconds& timeout) override; + + void append(const std::string& key, const std::vector& value) + override; + + std::vector> multiGet( + const std::vector& keys) override; + + void multiSet( + const std::vector& keys, + const std::vector>& values) override; + + // Returns true if this store support append, multiGet and multiSet + bool hasExtendedApi() const override; + + void queuePush(const std::string& key, const std::vector& value) + override; + + std::vector queuePop(const std::string& key, bool block) override; + + int64_t queueLen(const std::string& key) override; + + c10::intrusive_ptr getUnderlyingStore(); + + // Recursively to fetch the store before layers of wrapping with PrefixStore. + c10::intrusive_ptr getUnderlyingNonPrefixStore(); + + std::vector listKeys() override; + + protected: + std::string prefix_; + c10::intrusive_ptr store_; + + std::string joinKey(const std::string& key); + std::vector joinKeys(const std::vector& keys); +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroup.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroup.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ee183245b7d345bf1d26ce85b49c839608583d27 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroup.hpp @@ -0,0 +1,1037 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// ************************************************************************* +// PROCESS GROUP collective communication API IS BEING CHANGED BETWEEN +// versions 1.7 and 1.8. +// PLEASE DO NOT ADD ANY DEPENDENCIES. +// SEE RFC: https://github.com/pytorch/pytorch/issues/39662 +// ************************************************************************* + +constexpr auto kProcessGroupDefaultTimeout = + std::chrono::milliseconds(30 * 60 * 1000); + +namespace c10d { + +// We only call `register_work()` in two cases: +// 1. If the work object is created from a functional collective call. +// 2. If the work object is created from a non-functional collective call within +// the `with allow_inflight_collective_as_graph_input_ctx()` context manager. +C10_EXPORT void register_work( + const at::Tensor& tensor, + const c10::intrusive_ptr& work); + +C10_EXPORT at::Tensor wait_tensor(const at::Tensor& tensor); + +// We only call `unregister_work()` in one case: +// 1. If the work object is created from a non-functional collective call within +// the `with allow_inflight_collective_as_graph_input_ctx()` context manager. +// +// Q: What about the functional collective case? +// A: The unregistration of work object for functional collective is done in +// the required user-side explicit call to `wait_tensor()`. +C10_EXPORT void unregister_work(const c10::intrusive_ptr& work); + +C10_EXPORT size_t get_work_registry_size(); + +C10_EXPORT void set_allow_inflight_collective_as_graph_input(bool value); + +C10_EXPORT bool allow_inflight_collective_as_graph_input(); + +// ProcessGroup is a base class that captures collective and point to +// point communication in a fixed set of processes. +// +// The functions specified in the class below describe the API alone; +// implementations are provided in subclasses. +// +// Every function that performs I/O is executed asynchronously by a +// thread pool owned by the ProcessGroup (by default). They return an +// object that can be used to wait for completion or error. +// +// The ProcessGroup can instantiate subgroups with fewer or an equal +// number of members. Implementations must take care that multiple +// process groups can be used in parallel and synchronize accordingly. +// +// The ProcessGroup assumes a fixed set of processes. If the set +// changes, existing instances must be destructed and instantiation +// and initialization must start from scratch. For members of the +// process group to find each other (referred to as rendezvous from +// hereon) +// +class TORCH_API ProcessGroup : public torch::CustomClassHolder { + public: + struct TORCH_API MergeOptions : torch::CustomClassHolder { + explicit MergeOptions( + const std::chrono::milliseconds timeout = kProcessGroupDefaultTimeout, + const std::optional group_name = std::nullopt, + const std::optional group_desc = std::nullopt) + : timeout(timeout), group_name(group_name), group_desc(group_desc) {} + ~MergeOptions() override = default; + MergeOptions(const MergeOptions&) = delete; + MergeOptions& operator=(const MergeOptions&) = delete; + + std::chrono::milliseconds timeout; + std::optional group_name; + std::optional group_desc; + }; + + enum BackendType : uint8_t { + UNDEFINED = 0, + GLOO = 1, + NCCL = 2, + UCC = 3, + MPI = 4, + XCCL = 5, + CUSTOM = 6, + }; + + static std::string backendTypeToString(const BackendType& type) { + switch (type) { + case BackendType::GLOO: + return "gloo"; + case BackendType::NCCL: + return "nccl"; + case BackendType::XCCL: + return "xccl"; + case BackendType::UCC: + return "ucc"; + case BackendType::MPI: + return "mpi"; + case BackendType::UNDEFINED: + return "undefined"; + case BackendType::CUSTOM: + return "custom"; + default: + TORCH_CHECK(false, "THis should never happen!"); + } + } + + static BackendType strToBackendType(const std::string& backend) { + if (backend == "undefined") { + return BackendType::UNDEFINED; + } else if (backend == "gloo") { + return BackendType::GLOO; + } else if (backend == "nccl") { + return BackendType::NCCL; + } else if (backend == "xccl") { + return BackendType::XCCL; + } else if (backend == "ucc") { + return BackendType::UCC; + } else if (backend == "mpi") { + return BackendType::MPI; + } else { + return BackendType::CUSTOM; + } + } + + // Not used, set for backwards compatibility and only used for TypeDef in + // Ops.cpp + explicit ProcessGroup(int rank, int size); + + explicit ProcessGroup( + c10::intrusive_ptr<::c10d::Store> store, + int rank, + int size); + ~ProcessGroup() override; + + virtual int getRank() const { + return rank_; + } + + virtual int getSize() const { + return size_; + } + + // Returns an unique opaque ID of this process group object. + int64_t getID() const { + return reinterpret_cast(this); + } + + // Returns an unique opaque ID of a backend for the specific backend type + // that can correlate with this process group's collectives. + int64_t getBackendID(BackendType backend_type) const { + return reinterpret_cast(getBackend(backend_type).get()); + } + + virtual const std::string getBackendName() const { + return backendTypeToString(backendType_); + } + + BackendType getBackendType() const { + return backendType_; + } + + inline bool backendSupportsSequenceNumbers(BackendType backendType) { + if (backendType == BackendType::GLOO || backendType == BackendType::NCCL || + backendType == BackendType::XCCL || backendType == BackendType::UCC) + return true; + return false; + } + + virtual void setTimeout(std::chrono::milliseconds timeout) { + for (auto& backend : backendTypeToBackend_) { + backend.second->setTimeout(timeout); + } + } + + int64_t incrementSplitCount() { + return splitCounter_++; + } + + virtual void startCoalescing(c10::DeviceType deviceType) { + // only nccl has implemented startCoalescing so only execute for nccl + // backends + auto backend = getBackend(deviceType); + backend->startCoalescing(); + } + + virtual c10::intrusive_ptr endCoalescing(c10::DeviceType deviceType) { + // only nccl has implemented endCoalescing so only execute for nccl + // backends + auto backend = getBackend(deviceType); + auto work = backend->endCoalescing(); + return work; + } + + virtual c10::intrusive_ptr broadcast( + std::vector& tensors, + const BroadcastOptions& opts = BroadcastOptions()) { + static auto op = + c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::broadcast_", "") + .typed< + std::tuple, c10::intrusive_ptr>( + at::TensorList, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + int64_t, + int64_t, + bool, + int64_t)>(); + // It's awakward to unbox the opts here and box them again in the custom C++ + // op. But it's also complicated to make opts as a CustomClassHolder. Leave + // it as it is now. + auto work = std::get<1>(op.call( + tensors, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + opts.rootRank, + opts.rootTensor, + opts.asyncOp, + opts.timeout.count())); + + if (c10d::allow_inflight_collective_as_graph_input()) { + for (const auto& tensor : tensors) { + c10d::register_work(tensor, work); + } + } + return work; + } + + virtual c10::intrusive_ptr allreduce( + std::vector& tensors, + const AllreduceOptions& opts = AllreduceOptions()) { + static auto op = + c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::allreduce_", "") + .typed< + std::tuple, c10::intrusive_ptr>( + at::TensorList, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + const c10::intrusive_ptr<::c10d::ReduceOp>&, + const std::optional& sparse_indices, + bool, + int64_t)>(); + + auto work = std::get<1>(op.call( + tensors, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + c10::make_intrusive(opts.reduceOp), + opts.sparseIndices, + opts.asyncOp, + opts.timeout.count())); + + if (c10d::allow_inflight_collective_as_graph_input()) { + for (const auto& tensor : tensors) { + c10d::register_work(tensor, work); + } + } + return work; + } + + virtual c10::intrusive_ptr allreduce_coalesced( + std::vector& tensors, + const AllreduceCoalescedOptions& opts = AllreduceCoalescedOptions()) { + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::allreduce_coalesced_", "") + .typed( + at::TensorList, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + const c10::intrusive_ptr<::c10d::ReduceOp>&, + bool, + int64_t)>(); + + auto work = op.call( + tensors, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + c10::make_intrusive(opts.reduceOp), + opts.asyncOp, + opts.timeout.count()); + + if (c10d::allow_inflight_collective_as_graph_input()) { + for (const auto& tensor : tensors) { + c10d::register_work(tensor, work); + } + } + return work; + } + + virtual c10::intrusive_ptr reduce( + std::vector& tensors, + const ReduceOptions& opts = ReduceOptions()) { + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::reduce_", "") + .typed( + at::TensorList, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + const c10::intrusive_ptr<::c10d::ReduceOp>&, + int64_t, + int64_t, + bool, + int64_t)>(); + auto work = op.call( + tensors, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + c10::make_intrusive(opts.reduceOp), + opts.rootRank, + opts.rootTensor, + opts.asyncOp, + opts.timeout.count()); + + if (c10d::allow_inflight_collective_as_graph_input()) { + for (const auto& tensor : tensors) { + c10d::register_work(tensor, work); + } + } + return work; + } + + virtual c10::intrusive_ptr allgather( + std::vector>& outputTensors, + std::vector& inputTensors, + const AllgatherOptions& opts = AllgatherOptions()) { + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::allgather_", "") + .typed>, + c10::intrusive_ptr>( + const std::vector>&, + at::TensorList, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + bool, + int64_t)>(); + + auto work = std::get<1>(op.call( + outputTensors, + inputTensors, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + opts.asyncOp, + opts.timeout.count())); + + if (c10d::allow_inflight_collective_as_graph_input()) { + for (const auto& tensor_list : outputTensors) { + for (const auto& tensor : tensor_list) { + c10d::register_work(tensor, work); + } + } + } + return work; + } + + // Gathers a single tensor inputBuffer into a single buffer outputBuffer that + // is interpreted as a contiguous collection of size inputBuffer * WORLD_SIZE. + // For implementers of ProcessGroup API and advanced users only. + // Note: this function will be deprecated in near future. + virtual c10::intrusive_ptr _allgather_base( + at::Tensor& outputBuffer, + at::Tensor& inputBuffer, + const AllgatherOptions& opts = AllgatherOptions()) { + static auto op = + c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::_allgather_base_", "") + .typed>( + at::Tensor&, + at::Tensor&, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + bool, + int64_t)>(); + + auto work = std::get<1>(op.call( + outputBuffer, + inputBuffer, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + opts.asyncOp, + opts.timeout.count())); + + if (c10d::allow_inflight_collective_as_graph_input()) { + c10d::register_work(outputBuffer, work); + } + return work; + } + + // This function is deprecated and will be moved out of ProcessGroup to comms: + // * do not add dependencies on this function, + // * do not implement it in your ProcessGroup, implement _allgather_base + // instead. + virtual c10::intrusive_ptr allgather_coalesced( + std::vector>& outputTensorLists, + std::vector& inputTensors, + const AllgatherOptions& opts = AllgatherOptions()) { + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::allgather_coalesced_", "") + .typed( + const std::vector>&, + const at::TensorList&, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + bool)>(); + + auto work = op.call( + outputTensorLists, + inputTensors, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + opts.asyncOp); + + if (c10d::allow_inflight_collective_as_graph_input()) { + for (const auto& tensor_list : outputTensorLists) { + for (const auto& tensor : tensor_list) { + c10d::register_work(tensor, work); + } + } + } + return work; + } + + // This function is a coalesced version of `allgather_into_tensor` (currently + // still named as `_allgather_base`). Each tensor in the vector corresponds to + // an input/output of one `allgather_into_tensor` operation. + virtual c10::intrusive_ptr allgather_into_tensor_coalesced( + std::vector& outputTensors, + std::vector& inputTensors, + const AllgatherOptions& opts = AllgatherOptions()) { + static auto op = + c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::allgather_into_tensor_coalesced_", "") + .typed( + const at::TensorList, + const at::TensorList, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + bool)>(); + + auto work = op.call( + outputTensors, + inputTensors, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + opts.asyncOp); + + if (c10d::allow_inflight_collective_as_graph_input()) { + for (const auto& tensor : outputTensors) { + c10d::register_work(tensor, work); + } + } + return work; + } + + virtual c10::intrusive_ptr gather( + std::vector>& outputTensors, + std::vector& inputTensors, + const GatherOptions& opts = GatherOptions()) { + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::gather_", "") + .typed( + const std::vector>&, + const at::TensorList&, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + int64_t, + bool, + int64_t)>(); + auto work = op.call( + outputTensors, + inputTensors, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + opts.rootRank, + opts.asyncOp, + opts.timeout.count()); + + if (c10d::allow_inflight_collective_as_graph_input()) { + for (const auto& tensor_list : outputTensors) { + for (const auto& tensor : tensor_list) { + c10d::register_work(tensor, work); + } + } + } + return work; + } + + virtual c10::intrusive_ptr scatter( + std::vector& outputTensors, + std::vector>& inputTensors, + const ScatterOptions& opts = ScatterOptions()) { + static auto op = + c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::scatter_", "") + .typed< + std::tuple, c10::intrusive_ptr>( + const at::TensorList&, + const std::vector>&, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + int64_t, + bool, + int64_t)>(); + auto work = std::get<1>(op.call( + outputTensors, + inputTensors, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + opts.rootRank, + opts.asyncOp, + opts.timeout.count())); + + if (c10d::allow_inflight_collective_as_graph_input()) { + for (const auto& tensor : outputTensors) { + c10d::register_work(tensor, work); + } + } + return work; + } + + virtual c10::intrusive_ptr reduce_scatter( + std::vector& outputTensors, + std::vector>& inputTensors, + const ReduceScatterOptions& opts = ReduceScatterOptions()) { + static auto op = + c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::reduce_scatter_", "") + .typed< + std::tuple, c10::intrusive_ptr>( + const at::TensorList&, + const std::vector>&, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + const c10::intrusive_ptr<::c10d::ReduceOp>&, + bool, + int64_t)>(); + auto work = std::get<1>(op.call( + outputTensors, + inputTensors, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + c10::make_intrusive<::c10d::ReduceOp>(opts.reduceOp), + opts.asyncOp, + opts.timeout.count())); + + if (c10d::allow_inflight_collective_as_graph_input()) { + for (const auto& tensor : outputTensors) { + c10d::register_work(tensor, work); + } + } + return work; + } + + virtual c10::intrusive_ptr _reduce_scatter_base( + at::Tensor& outputBuffer, + at::Tensor& inputBuffer, + const ReduceScatterOptions& opts = ReduceScatterOptions()) { + static auto op = + c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::_reduce_scatter_base_", "") + .typed>( + at::Tensor&, + at::Tensor&, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + const c10::intrusive_ptr<::c10d::ReduceOp>&, + bool, + int64_t)>(); + auto work = std::get<1>(op.call( + outputBuffer, + inputBuffer, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + c10::make_intrusive<::c10d::ReduceOp>(opts.reduceOp), + opts.asyncOp, + opts.timeout.count())); + + if (c10d::allow_inflight_collective_as_graph_input()) { + c10d::register_work(outputBuffer, work); + } + return work; + } + + // This function is a coalesced version of `reduce_scatter_tensor` (currently + // still named as `_reduce_scatter_base`). Each tensor in the vector + // corresponds to an input/output of one `reduce_scatter_tensor` operation. + virtual c10::intrusive_ptr reduce_scatter_tensor_coalesced( + std::vector& outputTensors, + std::vector& inputTensors, + const ReduceScatterOptions& opts = ReduceScatterOptions()) { + static auto op = + c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::reduce_scatter_tensor_coalesced_", "") + .typed( + const at::TensorList, + const at::TensorList, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + const c10::intrusive_ptr<::c10d::ReduceOp>&, + bool, + int64_t)>(); + + auto work = op.call( + outputTensors, + inputTensors, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + c10::make_intrusive<::c10d::ReduceOp>(opts.reduceOp), + opts.asyncOp, + opts.timeout.count()); + + if (c10d::allow_inflight_collective_as_graph_input()) { + for (const auto& tensor : outputTensors) { + c10d::register_work(tensor, work); + } + } + return work; + } + + virtual c10::intrusive_ptr alltoall_base( + at::Tensor& outputBuffer, + at::Tensor& inputBuffer, + std::vector& outputSplitSizes, + std::vector& inputSplitSizes, + const AllToAllOptions& opts = AllToAllOptions()) { + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::alltoall_base_", "") + .typed( + at::Tensor&, + at::Tensor&, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + std::vector, + std::vector, + bool, + int64_t)>(); + auto work = op.call( + outputBuffer, + inputBuffer, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + outputSplitSizes, + inputSplitSizes, + opts.asyncOp, + opts.timeout.count()); + + if (c10d::allow_inflight_collective_as_graph_input()) { + c10d::register_work(outputBuffer, work); + } + return work; + } + + virtual c10::intrusive_ptr alltoall( + std::vector& outputTensors, + std::vector& inputTensors, + const AllToAllOptions& opts = AllToAllOptions()) { + static auto op = + c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::alltoall_", "") + .typed< + std::tuple, c10::intrusive_ptr>( + const at::TensorList&, + const at::TensorList&, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + bool, + int64_t)>(); + auto work = std::get<1>(op.call( + outputTensors, + inputTensors, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + opts.asyncOp, + opts.timeout.count())); + + if (c10d::allow_inflight_collective_as_graph_input()) { + for (const auto& tensor : outputTensors) { + c10d::register_work(tensor, work); + } + } + return work; + } + + virtual void monitoredBarrier( + const BarrierOptions& opts, + bool wait_all_ranks = false) { + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::monitored_barrier_", "") + .typed&, + const std::vector&, + int64_t, + bool)>(); + // Default to using cpu implementation, monitored barrier is only for GLOO + at::Tensor tensor = at::empty({0}, at::TensorOptions().device(at::kCPU)); + op.call( + tensor, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + opts.device_ids, + opts.timeout.count(), + wait_all_ranks); + } + + // Agrees on an initial sequence number for the whole group by having rank 0 + // create it and broadcast it to other ranks using the store. Only implemented + // for GLOO and NCCL backends currently. + virtual void setSequenceNumberForGroup() { + auto backendType = getBackendType(); + // TODO: HACK for backend name to get sequence number for that backend. + if (backendSupportsSequenceNumbers(backendType)) { + getDefaultBackend()->setSequenceNumberForGroup(); + } else { + TORCH_CHECK( + false, + c10::str( + "ProcessGroup ", + getBackendName(), + " does not yet support sequence numbers.")); + } + } + + // Retrieves the current sequence number for the whole group, which should be + // in sync. If the returned number is not consistent across the group, it + // may indicate that there is some sort of collective desynchronization. + virtual uint64_t getSequenceNumberForGroup() { + auto backendType = getBackendType(); + + // TODO: HACK for backend name to get sequence number for that backend. + if (backendSupportsSequenceNumbers(backendType)) { + return getDefaultBackend()->getSequenceNumberForGroup(); + } else { + TORCH_CHECK( + false, + c10::str( + "ProcessGroup ", + getBackendName(), + " does not yet support sequence numbers.")); + } + } + + virtual c10::intrusive_ptr send( + std::vector& tensors, + int dstRank, + int tag) { + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::send", "") + .typed( + at::TensorList, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + int64_t, + int64_t)>(); + auto work = op.call( + tensors, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + dstRank, + tag); + if (c10d::allow_inflight_collective_as_graph_input()) { + for (const auto& tensor : tensors) { + c10d::register_work(tensor, work); + } + } + return work; + } + + virtual c10::intrusive_ptr recv( + std::vector& tensors, + int srcRank, + int tag) { + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::recv_", "") + .typed( + at::TensorList, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + int64_t, + int64_t)>(); + auto work = op.call( + tensors, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + srcRank, + tag); + if (c10d::allow_inflight_collective_as_graph_input()) { + for (const auto& tensor : tensors) { + c10d::register_work(tensor, work); + } + } + return work; + } + + virtual c10::intrusive_ptr recvAnysource( + std::vector& tensors, + int tag) { + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::recv_any_source_", "") + .typed( + at::TensorList, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + int64_t)>(); + auto work = op.call( + tensors, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + tag); + if (c10d::allow_inflight_collective_as_graph_input()) { + for (const auto& tensor : tensors) { + c10d::register_work(tensor, work); + } + } + return work; + } + + virtual c10::intrusive_ptr barrier( + const BarrierOptions& opts = BarrierOptions()) { + at::Tensor tensor; + // TODO: if nccl was specified then use it + auto device = opts.device; + if (device.has_value()) { + // set device tensor from argument + tensor = at::empty( + {1}, at::TensorOptions().device(device.value()).dtype(at::kByte)); + } else if (backendType_ == c10d::ProcessGroup::BackendType::NCCL) { + // set cuda tensor + tensor = at::empty( + {1}, + at::TensorOptions().device(at::DeviceType::CUDA).dtype(at::kByte)); + } else if (backendType_ == c10d::ProcessGroup::BackendType::XCCL) { + // set xpu tensor for override cpu dispatch + tensor = at::empty( + {1}, + at::TensorOptions().device(at::DeviceType::XPU).dtype(at::kByte)); + } else { + // Default to using cpu implementation + tensor = at::empty( + {1}, + at::TensorOptions().device(at::DeviceType::CPU).dtype(at::kByte)); + } + + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("c10d::barrier", "") + .typed( + at::Tensor, + const c10::intrusive_ptr<::c10d::ProcessGroup>&, + const std::vector&, + bool, + int64_t)>(); + + auto work = op.call( + tensor, + c10::intrusive_ptr::unsafe_reclaim_from_nonowning(this), + opts.device_ids, + opts.asyncOp, + opts.timeout.count()); + if (c10d::allow_inflight_collective_as_graph_input()) { + c10d::register_work(tensor, work); + } + return work; + } + + bool hasBackends() { + return !deviceTypeToBackendType_.empty(); + } + + void setBackend( + c10::DeviceType deviceType, + BackendType backendType, + const std::optional>& backend) { + // TODO: should we add these entries after the backend setting succeeds? + deviceTypeToBackendType_[deviceType] = backendType; + deviceTypes_.insert(deviceType); + // if the backendType is already set then reuse it for this device + if (backendTypeToBackend_.find(backendType) != + backendTypeToBackend_.end()) { + auto existingBackend = backendTypeToBackend_.at(backendType); + deviceTypeToBackend_[deviceType] = existingBackend; + TORCH_CHECK( + existingBackend->getBoundDeviceId() == + (*backend)->getBoundDeviceId()); + } else { + // check if backend has value + if (backend.has_value()) { + deviceTypeToBackend_[deviceType] = backend.value(); + backendTypeToBackend_[backendType] = backend.value(); + (*backend)->setBoundDeviceId(bound_device_id_); + } + } + } + + c10::intrusive_ptr getDefaultBackend() const { + auto backend_iter = backendTypeToBackend_.find(backendType_); + TORCH_CHECK( + backend_iter != backendTypeToBackend_.end(), + "Could not find the default backend type ", + uint16_t(backendType_), + " for Process Group with name ", + getBackendName(), + "."); + return backend_iter->second; + } + + void setDefaultBackend(const BackendType& backendType) { + backendType_ = backendType; + } + + void setDefaultBackend(const std::string& backend) { + backendType_ = strToBackendType(backend); + } + + c10::intrusive_ptr getBackend(c10::DeviceType deviceType); + + c10::intrusive_ptr getBackend(BackendType backendType) const { + TORCH_CHECK( + backendTypeToBackend_.find(backendType) != backendTypeToBackend_.end(), + "Could not find backend type ", + uint16_t(backendType), + " for Process Group with name ", + backendTypeToString(backendType), + "."); + return backendTypeToBackend_.at(backendType); + } + + // Return device types supported by this ProcessGroup. + // Note: the return type is `Device` rather than `DeviceType` for the purpose + // of easy comparison at Python level. The `Device` will have default index + // (-1). + std::vector getDeviceTypes() const { + std::vector devices; + devices.reserve(deviceTypes_.size()); + for (auto& dt : deviceTypes_) { + devices.emplace_back(dt); + } + return devices; + } + + void registerOnCompletionHook( + std::function)>&& hook) { + getDefaultBackend()->registerOnCompletionHook(std::move(hook)); + } + + void waitForPendingWorks() { + getDefaultBackend()->waitForPendingWorks(); + } + + virtual void shutdown() { + for (auto& backend : backendTypeToBackend_) { + backend.second->shutdown(); + } + } + + virtual void abort() { + for (auto& backend : backendTypeToBackend_) { + backend.second->abort(); + } + } + + bool hasHooks() const { + auto backend_iter = backendTypeToBackend_.find(backendType_); + if (backend_iter == backendTypeToBackend_.end()) { + TORCH_WARN( + "No backend of type ", + uint16_t(backendType_), + " found for Process Group with name ", + getBackendName(), + ". Assuming no hooks are registered."); + return false; + } + + return backend_iter->second->hasHooks(); + } + + virtual const std::string& getGroupName() const; + virtual void setGroupName(const std::string& name); + virtual const std::string& getGroupDesc() const; + virtual void setGroupDesc(const std::string& name); + void enableCollectivesTiming(); + + void release_resources() override; + + // ProcessGroups optionally can be "bound" to a specific device. + // Currently this is only for nccl and allows for some opt-in + // optimizations such as automatic use of ncclCommSplit. The device + // is specified in `init_process_group` and eventually makes it + // here and then down into the actual backend instances. + std::optional getBoundDeviceId() const { + return bound_device_id_; + } + + c10::intrusive_ptr getStore() const { + return store_; + } + + void setBoundDeviceId(std::optional device) { + if (device) { + TORCH_CHECK(device->has_index(), "setBoundDeviceId must have an index"); + } + bound_device_id_ = device; + } + + // This creates a new subgroup using the specified ranks. + // The current rank must be included in the list of new_ranks. + virtual c10::intrusive_ptr splitGroup( + const std::vector& ranks, + const std::optional& timeout, + const std::optional>& opts, + const std::optional& name, + const std::optional& groupDesc); + + // This creates a new subgroup using the specified ranks. + // The current rank must be included in the list of new_ranks. + virtual c10::intrusive_ptr mergeRemoteGroup( + const c10::intrusive_ptr& store, + const MergeOptions& opts, + const int& size); + + protected: + // Implementations of this interface need to call this to setup + // appropriate logging etc. + void init(); + + c10::intrusive_ptr store_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const int rank_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const int size_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + BackendType backendType_; + std::string pg_desc_; + int64_t splitCounter_; + + // Debug level setting. It is parsed once when ProcessGroup is constructed and + // remains the same across use of this process group. + DebugLevel dist_debug_level_{DebugLevel::Off}; + + // Backend classes for this ProcessGroup + std::unordered_set deviceTypes_; + // This mapping is ordered, as splitGroup must call split on the underlying + // backends in a consistent order. + std::map deviceTypeToBackendType_; + std::unordered_map> + deviceTypeToBackend_; + std::unordered_map> + backendTypeToBackend_; + + std::optional bound_device_id_; +}; + +// Thread local functions for managing the currently active process group. +TORCH_API c10::intrusive_ptr& currentProcessGroup(); +TORCH_API void setProcessGroup(c10::intrusive_ptr processGroup); + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupGloo.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupGloo.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b90e183651105c4dd2518056dbd16c6bb4c82923 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupGloo.hpp @@ -0,0 +1,508 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef USE_C10D_GLOO + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +namespace c10d { + +constexpr const char* GLOO_BACKEND_NAME = "gloo"; + +// Control whether or not connections are established in a full mesh or lazily +// as needed. +static std::vector TORCH_GLOO_LAZY_INIT = {"TORCH_GLOO_LAZY_INIT"}; + +// Returns default value for lazyInit. +bool TORCH_API getDefaultGlooLazyInit(); + +// ProcessGroupGloo implements Gloo bindings for c10d. +// +// All functions on this class are expected to be called in the same +// order across processes in the group. This is the only way that we +// can guarantee to match up the same calls across processes. For +// multi-threaded usage of process groups, you can consider using +// multiple process group instances. +// +class TORCH_API ProcessGroupGloo : public Backend { + public: + // AsyncWork is the Gloo specific superclass for asynchronous work items. + // We can split asynchronous work into 3 phases: + // 1) Sanity checks and prepare input (e.g. memcpy) + // 2) Run operation on background thread + // 3) Synchronize with completion on foreground thread + // + // There is state to be shared between these 3 phases and all of this state + // is captured in the AsyncWork class and its derivatives. + // + // Note: while we are porting operations to use new style collectives, there + // is a split between operations using the existing caching approach and + // operations using the new AsyncWork base class. Over time we will port + // all operations and perform needed cleanup. + // + // FIXME: This probably should be called WorkGloo since the work is executed + // in sync mode by a background thread. + class TORCH_API AsyncWork : public Work { + public: + explicit AsyncWork( + std::shared_ptr context, + std::vector> outputTensors, + OpType opType, + uint64_t seq, + std::chrono::milliseconds timeout, + const char* profilingTitle = nullptr, + const std::optional>& inputTensors = + std::nullopt); + + ~AsyncWork() override = default; + + static void execute(const c10::intrusive_ptr& work); + + virtual void run() = 0; + + std::vector result() override; + + c10::intrusive_ptr getFuture() override; + uint64_t getSequencenumber() const override; + std::chrono::milliseconds getTimeout() const; + virtual const std::vector getInputTensors() = 0; + virtual const std::vector getOutputTensors() = 0; + inline std::string getProfilerTitle() const { + return profilingTitle_; + } + inline at::ThreadLocalState getTLS() const { + return tls_; + } + + protected: + friend class ProcessGroupGloo; + // unique id used to tell the trace buffer that this + // work has completed + std::optional trace_id_; + std::optional trace_reset_epoch_; + std::shared_ptr context_; + const std::chrono::milliseconds timeout_; + + private: + void finishWorkGloo(); + void finishWorkGlooError(const std::exception_ptr& eptr); + inline void recordAsyncWorkProfilingInfo( + const char* profilingTitle, + const std::optional>& inputTensors); + + const std::vector> outputTensors_; + c10::intrusive_ptr future_; + std::function recordFunctionBeforeCallback_; + const uint64_t seq_; + std::string profilingTitle_; + at::ThreadLocalState tls_; + }; + + // Wrap c10d store as Gloo store + class TORCH_API GlooStore : public ::gloo::rendezvous::Store { + public: + GlooStore(c10::intrusive_ptr<::c10d::Store> store) + : store_(std::move(store)) {} + + void setUint(const std::string& key, const std::vector& value) { + store_->set(key, value); + } + + void set(const std::string& key, const std::vector& value) override { + std::vector tmp(value.begin(), value.end()); + store_->set(key, tmp); + } + + std::vector getUint(const std::string& key) { + auto value = store_->get(key); + return value; + } + + std::vector get(const std::string& key) override { + auto value = store_->get(key); + return std::vector(value.begin(), value.end()); + } + + void wait(const std::vector& keys) override { + store_->wait(keys, ::c10d::Store::kDefaultTimeout); + } + + void wait( + const std::vector& keys, + const std::chrono::milliseconds& timeout) override { + store_->wait(keys, timeout); + } + +#ifdef GLOO_STORE_HAS_STORE_V2 + bool has_v2_support() override { + return store_->hasExtendedApi(); + } + + std::vector> multi_get( + const std::vector& keys) override { + std::vector> res; + for (auto& value : store_->multiGet(keys)) { + res.emplace_back(value.begin(), value.end()); + } + return res; + } + + void multi_set( + const std::vector& keys, + const std::vector>& values) override { + std::vector> u_values; + u_values.reserve(values.size()); + for (auto& value : values) { + u_values.emplace_back(value.begin(), value.end()); + } + store_->multiSet(keys, u_values); + } + + void append(const std::string& key, const std::vector& value) + override { + std::vector tmp(value.begin(), value.end()); + return store_->append(key, tmp); + } + + int64_t add(const std::string& key, int64_t value) override { + return store_->add(key, value); + } +#endif + + const c10::intrusive_ptr<::c10d::Store>& _getStore() const { + return store_; + } + + protected: + c10::intrusive_ptr<::c10d::Store> store_; + }; + + // For send and recv operations there is no need to pass them to the + // thread pool as they are entirely completed by the device thread. + // This work object is used to synchronize completion of the send or + // recv operation. It keeps a reference to the tensor it is + // operating on to prevent it from being deallocated while the + // operation is still in flight. + class TORCH_API SendWork : public Work { + public: + explicit SendWork( + at::Tensor& tensor, + std::unique_ptr<::gloo::transport::UnboundBuffer> buffer, + uint64_t seq); + + bool wait(std::chrono::milliseconds timeout = kNoTimeout) override; + + void abort() override; + + uint64_t getSequencenumber() const override; + + protected: + at::Tensor tensor_; + std::unique_ptr<::gloo::transport::UnboundBuffer> buffer_; + const uint64_t seq_; + }; + + class TORCH_API RecvWork : public Work { + public: + explicit RecvWork( + at::Tensor& tensor, + std::unique_ptr<::gloo::transport::UnboundBuffer> buffer, + OpType opType, + uint64_t seq, + const char* profilingTitle = nullptr); + + int sourceRank() const override; + + bool wait(std::chrono::milliseconds timeout = kNoTimeout) override; + + void abort() override; + + uint64_t getSequencenumber() const override; + + protected: + at::Tensor tensor_; + std::unique_ptr<::gloo::transport::UnboundBuffer> buffer_; + int srcRank_{-1}; + const uint64_t seq_; + }; + + struct TORCH_API Options : public Backend::Options { + explicit Options( + std::chrono::milliseconds timeout = kBackendDefaultTimeout); + + // return intrusive_ptr of the object + static c10::intrusive_ptr create( + std::chrono::milliseconds timeout = kBackendDefaultTimeout) { + return c10::make_intrusive(timeout); + } + + static c10::intrusive_ptr create_default( + std::chrono::milliseconds timeout = kBackendDefaultTimeout); + + std::vector> devices; + int threads{2}; + }; + + const std::string getBackendName() const override { + return std::string(GLOO_BACKEND_NAME); + } + + bool supportsSplitting() const override { + return true; + } + + // Helper functions to create a new device object. + // They are static functions on this class to keep them logically + // separate from the rest of the code base (e.g. torch/csrc/distributed). + + // Create new device instance for specific interface. + static std::shared_ptr<::gloo::transport::Device> createDeviceForInterface( + const std::string& interface, + bool lazyInit = false); + + // Create new device instance for specific hostname or address. + static std::shared_ptr<::gloo::transport::Device> createDeviceForHostname( + const std::string& hostname, + bool lazyInit = false); + + // Create new device instance. + // It tries to resolve this machine's hostname and bind to that address. + // If that fails (i.e. the hostname doesn't resolve to an address), it + // falls back to binding to the loopback address. + static std::shared_ptr<::gloo::transport::Device> createDefaultDevice( + bool lazyInit = false); + + explicit ProcessGroupGloo( + const c10::intrusive_ptr& store, + int rank, + int size, + c10::intrusive_ptr options = Options::create()); + + ~ProcessGroupGloo() override; + + c10::intrusive_ptr getOptions() { + return options_; + } + + void setTimeout(std::chrono::milliseconds timeout) override { + options_->timeout = timeout; + for (auto& context : contexts_) { + context->setTimeout(timeout); + } + } + + c10::intrusive_ptr getBackendOptions() override { + return c10::static_intrusive_pointer_cast(options_); + } + + c10::intrusive_ptr split( + const c10::intrusive_ptr& store, + const std::vector& ranks, + const c10::intrusive_ptr& opts) override; + + c10::intrusive_ptr merge( + const c10::intrusive_ptr& store, + const c10::intrusive_ptr& opts, + const int& rank, + const int& size) override; + + const std::vector& groupRanks() const; + + c10::intrusive_ptr broadcast( + std::vector& tensors, + const BroadcastOptions& opts = BroadcastOptions()) override; + + c10::intrusive_ptr allreduce( + std::vector& tensors, + const AllreduceOptions& opts = AllreduceOptions()) override; + + c10::intrusive_ptr allreduce_sparse( + std::vector& tensors, + const AllreduceOptions& opts = AllreduceOptions()) override; + + c10::intrusive_ptr allreduce_coalesced( + std::vector& tensors, + const AllreduceCoalescedOptions& opts = + AllreduceCoalescedOptions()) override; + + c10::intrusive_ptr reduce( + std::vector& tensors, + const ReduceOptions& opts = ReduceOptions()) override; + + c10::intrusive_ptr _reduce_scatter_base( + at::Tensor& outputTensor, + at::Tensor& inputTensor, + const ReduceScatterOptions& opts = ReduceScatterOptions()) override; + + c10::intrusive_ptr _allgather_base( + at::Tensor& output_tensor, + at::Tensor& input_tensor, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr allgather( + std::vector>& outputs, + std::vector& inputs, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr allgather_coalesced( + std::vector>& output_lists, + std::vector& input_list, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr allgather_into_tensor_coalesced( + std::vector& outputs, + std::vector& inputs, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr gather( + std::vector>& outputs, + std::vector& inputs, + const GatherOptions& opts = GatherOptions()) override; + + c10::intrusive_ptr scatter( + std::vector& outputs, + std::vector>& inputs, + const ScatterOptions& opts = ScatterOptions()) override; + + c10::intrusive_ptr reduce_scatter( + std::vector& outputs, + std::vector>& inputs, + const ReduceScatterOptions& opts = ReduceScatterOptions()) override; + + c10::intrusive_ptr reduce_scatter_tensor_coalesced( + std::vector& outputTensors, + std::vector& inputTensors, + const ReduceScatterOptions& opts = ReduceScatterOptions()) override; + + c10::intrusive_ptr alltoall_base( + at::Tensor& outputTensor, + at::Tensor& inputTensor, + std::vector& outputCounts, + std::vector& inputCounts, + const AllToAllOptions& opts = AllToAllOptions()) override; + + c10::intrusive_ptr alltoall( + std::vector& outputTensors, + std::vector& inputTensors, + const AllToAllOptions& opts = AllToAllOptions()) override; + + c10::intrusive_ptr send( + std::vector& tensors, + int dstRank, + int tag) override; + + c10::intrusive_ptr recv( + std::vector& tensors, + int srcRank, + int tag) override; + + c10::intrusive_ptr recvAnysource( + std::vector& tensors, + int tag) override; + + c10::intrusive_ptr barrier( + const BarrierOptions& opts = BarrierOptions()) override; + + void enableCollectivesTiming() override; + + const std::shared_ptr<::gloo::rendezvous::Store>& _getStore() const { + return store_; + } + + // Similar to barrier(), but blocks rank 0 until all other ranks have + // acknowledged that they are alive (through send/recv from rank 0). Rank 0 + // is able to report all failed ranks if waitAllRanks = true, otherwise + // reports the first rank it detected as failed. + void monitoredBarrier( + const BarrierOptions& opts = BarrierOptions(), + bool waitAllRanks = false) override; + + // Agrees on an initial sequence number for the whole group by having rank 0 + // create it and broadcast it to other ranks using the store. + void setSequenceNumberForGroup() override; + + // Retrieves the current sequence number for the whole group, which should be + // in sync. If the returned number is not consistent across the group, it + // may indicate that there is some sort of collective desynchronization. + uint64_t getSequenceNumberForGroup() override; + + int getNumThreads() { + return options_->threads; + } + + protected: + std::shared_ptr<::gloo::rendezvous::Store> store_; + const c10::intrusive_ptr options_; + + // Every Gloo context represents a set of connections to its peers. + // In order to use more than one device (or allow for parallelism on + // a single device), you need multiple contexts. + std::vector> contexts_; + std::vector threads_; + bool stop_{false}; + + // Incremented for every collective we kick off. + // The value is used as tag for collective operations. Collectives are kicked + // off in identical order across processes. Therefore the tag can be used + // to match up operations during concurrent execution. + uint32_t collectiveCounter_{0}; + + // Returns next collective tag to use (uses collectiveCounter_). + uint32_t nextTag(); + + // Returns the context to use for the specified tag. + // With `nextTag` returning an increasing number, this should lead + // to contexts being used in a round-robin fashion. + std::shared_ptr<::gloo::Context> getContext(uint32_t tag); + + // Entrypoint for worker threads. + void runLoop(int workerIndex); + + // Queue work to run on worker thread. + void enqueue(c10::intrusive_ptr work); + + // Keep both a queue of pending work, and a vector with in progress work. + // Both of these can only be mutated when holding the queue lock. + // We keep both around instead of just the queue, so we can grab a weak_ptr + // to all in progress and pending work when executing a barrier. + // When executing a barrier, we need to ensure that all prior work + // has completed before completing itself. + std::deque> workQueue_; + std::vector> workInProgress_; + std::mutex workMutex_; + std::condition_variable workProduceCV_; + std::condition_variable workConsumeCV_; + uint64_t seq_{0}; + size_t local_id_; + std::shared_ptr pgStatus_ = + std::make_shared(); +}; + +} // namespace c10d + +#endif // USE_C10D_GLOO + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupGlooDetail.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupGlooDetail.hpp new file mode 100644 index 0000000000000000000000000000000000000000..98edd8124f9e6735f5025b16e00b20481b41373e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupGlooDetail.hpp @@ -0,0 +1,679 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef USE_C10D_GLOO + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#define GENERATE_ALL_TYPES(type, func, ...) \ + switch (type) { \ + case ::at::ScalarType::Float: \ + func(__VA_ARGS__); \ + break; \ + case ::at::ScalarType::Double: \ + func(__VA_ARGS__); \ + break; \ + case ::at::ScalarType::Half: \ + func(__VA_ARGS__); \ + break; \ + case ::at::ScalarType::BFloat16: \ + func(__VA_ARGS__); \ + break; \ + case ::at::ScalarType::Char: \ + func(__VA_ARGS__); \ + break; \ + case ::at::ScalarType::Byte: \ + case ::at::ScalarType::Bool: \ + func(__VA_ARGS__); \ + break; \ + case ::at::ScalarType::Int: \ + func(__VA_ARGS__); \ + break; \ + case ::at::ScalarType::Long: \ + func(__VA_ARGS__); \ + break; \ + default: \ + TORCH_CHECK(false, "Invalid scalar type"); \ + } + +#define HOST_NAME_MAX 256 +#else +#define GENERATE_ALL_TYPES(type, func, args...) \ + switch (type) { \ + case ::at::ScalarType::Float: \ + func(args); \ + break; \ + case ::at::ScalarType::Double: \ + func(args); \ + break; \ + case ::at::ScalarType::Half: \ + func(args); \ + break; \ + case ::at::ScalarType::BFloat16: \ + func(args); \ + break; \ + case ::at::ScalarType::Char: \ + func(args); \ + break; \ + case ::at::ScalarType::Byte: \ + case ::at::ScalarType::Bool: \ + func(args); \ + break; \ + case ::at::ScalarType::Int: \ + func(args); \ + break; \ + case ::at::ScalarType::Long: \ + func(args); \ + break; \ + default: \ + TORCH_CHECK(false, "Invalid scalar type"); \ + } +#endif + +namespace c10d { + +TORCH_DECLARE_TYPED_REGISTRY( + GlooAllreduceRegistry, + c10::DeviceType, + ProcessGroupGloo::AsyncWork, + c10::intrusive_ptr, + std::shared_ptr, + std::vector&, + ReduceOp, + uint32_t, + uint64_t, + std::chrono::milliseconds); + +// This function initializes a vector of CUDA streams, one for every +// tensor in the input tensor vector, and ensures that these streams are +// synchronized with the current default streams. This is needed so +// that new work on the new streams is serialized w.r.t. all operations +// on the tensors. +TORCH_API void initializeStreamsEvents( + const std::vector& tensors, + std::vector& streams, + std::vector& events); + +// This function initializes a vector of CUDA streams, one per device, +// and ensures that these streams are synchronized with the current default +// streams. It is assumed that the tensors in the nested tensor vectors are +// on the same device. +TORCH_API void initializeStreamsEvents( + std::vector>& tensors, + std::vector& streams, + std::vector& events); + +typedef void (*ReduceFunc)(void*, const void*, const void*, size_t); + +template , int> = 0> +ReduceFunc toFunction(const ReduceOp& r) { + switch (r) { + case ReduceOp::SUM: + case ReduceOp::AVG: + return ReduceFunc(&::gloo::sum); + case ReduceOp::PRODUCT: + return ReduceFunc(&::gloo::product); + case ReduceOp::MIN: + return ReduceFunc(&::gloo::min); + case ReduceOp::MAX: + return ReduceFunc(&::gloo::max); + case ReduceOp::BAND: + TORCH_CHECK(false, "Cannot use ReduceOp.BAND with non-integral dtype"); + break; + case ReduceOp::BOR: + TORCH_CHECK(false, "Cannot use ReduceOp.BOR with non-integral dtype"); + break; + case ReduceOp::BXOR: + TORCH_CHECK(false, "Cannot use ReduceOp.BXOR with non-integral dtype"); + break; + case ReduceOp::PREMUL_SUM: + TORCH_CHECK(false, "Cannot use ReduceOp.PREMUL_SUM with Gloo"); + break; + case ReduceOp::UNUSED: + default: + break; + } + + TORCH_CHECK(false, "Unhandled ReduceOp"); +} + +// Bitwise AND with SFINAE guard for integral types. +template , int> = 0> +void band(void* c, const void* a, const void* b, size_t n) { + auto tc = static_cast(c); + auto ta = static_cast(a); + auto tb = static_cast(b); + for (const auto i : c10::irange(n)) { + tc[i] = ta[i] & tb[i]; + } +} + +// Bitwise OR with SFINAE guard for integral types. +template , int> = 0> +void bor(void* c, const void* a, const void* b, size_t n) { + auto tc = static_cast(c); + auto ta = static_cast(a); + auto tb = static_cast(b); + for (const auto i : c10::irange(n)) { + tc[i] = ta[i] | tb[i]; + } +} + +// Bitwise XOR with SFINAE guard for integral types. +template , int> = 0> +void bxor(void* c, const void* a, const void* b, size_t n) { + auto tc = static_cast(c); + auto ta = static_cast(a); + auto tb = static_cast(b); + for (const auto i : c10::irange(n)) { + tc[i] = ta[i] ^ tb[i]; + } +} + +template , int> = 0> +ReduceFunc toFunction(const ReduceOp& r) { + switch (r) { + case ReduceOp::SUM: + case ReduceOp::AVG: + return ReduceFunc(&::gloo::sum); + case ReduceOp::PRODUCT: + return ReduceFunc(&::gloo::product); + case ReduceOp::MIN: + return ReduceFunc(&::gloo::min); + case ReduceOp::MAX: + return ReduceFunc(&::gloo::max); + case ReduceOp::BAND: + return ReduceFunc(&band); + case ReduceOp::BOR: + return ReduceFunc(&bor); + case ReduceOp::BXOR: + return ReduceFunc(&bxor); + case ReduceOp::PREMUL_SUM: + TORCH_CHECK(false, "Cannot use ReduceOp.PREMUL_SUM with Gloo"); + break; + case ReduceOp::UNUSED: + default: + break; + } + + TORCH_CHECK(false, "Unhandled ReduceOp"); +} + +template +void setInputs(O& opts, std::vector& tensors) { + opts.setInputs(getDataPointers(tensors), tensors[0].numel()); +} + +template +void setInput(O& opts, at::Tensor& tensor) { + opts.setInput(getDataPointer(tensor), tensor.numel()); +} + +template +void setInput(O& opts, at::Tensor& tensor, std::vector& counts) { + opts.setInput(getDataPointer(tensor), counts); +} + +template +void setInput(O& opts, at::Tensor& tensor, std::vector& counts) { + opts.setInput(getDataPointer(tensor), counts); +} + +template +void setOutputs(O& opts, std::vector& tensors, int64_t count) { + opts.setOutputs(getDataPointers(tensors), count); +} + +template +void setOutput(O& opts, at::Tensor& tensor) { + opts.setOutput(getDataPointer(tensor), tensor.numel()); +} + +template +void setOutput(O& opts, at::Tensor& tensor, std::vector& counts) { + opts.setOutput(getDataPointer(tensor), counts); +} + +template +void setOutput(O& opts, at::Tensor& tensor, std::vector& counts) { + opts.setOutput(getDataPointer(tensor), counts); +} + +static at::Tensor pinnedLike(at::Tensor& tensor) { + auto* allocator = at::detail::getCUDAHooks().getPinnedMemoryAllocator(); + auto storage = c10::Storage( + c10::Storage::use_byte_size_t(), + static_cast(at::detail::computeStorageNbytes( + tensor.sizes(), tensor.strides(), tensor.dtype().itemsize())), + allocator, + /*resizable=*/false); + return at::empty({0}, tensor.options().device(at::kCPU)) + .set_(storage, 0, tensor.sizes(), tensor.strides()); +} + +class AsyncAllreduceWork : public ProcessGroupGloo::AsyncWork { + public: + AsyncAllreduceWork( + std::shared_ptr context, + std::vector& inputs, + ReduceOp reduceOp, + uint32_t tag, + uint64_t seq, + std::chrono::milliseconds timeout) + : ProcessGroupGloo::AsyncWork( + std::move(context), + {inputs}, + OpType::ALLREDUCE, + seq, + timeout, + "gloo:all_reduce", + inputs), + inputs(inputs), + reduceOp(std::move(reduceOp)), + tag(tag) {} + + std::vector inputs; + const ReduceOp reduceOp; + const uint32_t tag; + + void allreduce(std::vector& tensors) { + auto tensor = tensors[0]; + if (tensor.is_complex()) { + TORCH_CHECK( + c10d::isComplexViewAsRealAllowed(reduceOp), + "all_reduce does not support", + reduceOp, + "on complex tensors"); + tensor = at::view_as_real(tensor); + } + gloo::AllreduceOptions opts(context_); + const auto& scalarType = tensor.scalar_type(); + opts.setReduceFunction(getFunction(scalarType, reduceOp)); + opts.setTag(tag); + opts.setTimeout(getTimeout()); + // Use tensor.numel() instead of tensors[0].numel() to + // get the right number of elements when tensors[0] is complex + GENERATE_ALL_TYPES(scalarType, setOutputs, opts, tensors, tensor.numel()); + gloo::allreduce(opts); + + // Gloo doesn't support AVG so we use SUM + division. + if (reduceOp == ReduceOp::AVG) { + tensors[0] /= context_->size; + } + } + + const std::vector getInputTensors() override { + return inputs; + } + + const std::vector getOutputTensors() override { + return inputs; + } + + void run() override { + allreduce(inputs); + } + + template + void getFunction(gloo::AllreduceOptions::Func& fn, const ReduceOp op) { + fn = toFunction(op); + } + + gloo::AllreduceOptions::Func getFunction( + const at::ScalarType& dtype, + const ReduceOp& op) { + gloo::AllreduceOptions::Func fn; + GENERATE_ALL_TYPES(dtype, getFunction, fn, op); + return fn; + } +}; + +class AsyncAllreduceCoalescedWork : public AsyncAllreduceWork { + public: + AsyncAllreduceCoalescedWork( + const std::shared_ptr& context, + std::vector& inputs, + ReduceOp reduceOp, + uint32_t tag, + uint64_t seq, + std::chrono::milliseconds timeout) + : AsyncAllreduceWork( + context, + inputs, + std::move(reduceOp), + tag, + seq, + timeout) {} + + void run() override { + allreduceCoalesced(inputs); + } + + private: + void allreduceCoalesced(std::vector& tensors) { + // reduce coalesced, flattened tensors. + at::Tensor coalescedTensor = flattenDenseTensors(tensors); + std::vector allreduceInput = {coalescedTensor}; + allreduce(allreduceInput); + + // separate and reshape tensors. + size_t offset = 0; + for (at::Tensor& tensor : tensors) { + const int64_t tensorNumel = tensor.numel(); + const c10::IntArrayRef tensorShape = tensor.sizes(); + tensor.copy_(coalescedTensor.slice(0, offset, offset + tensorNumel) + .view(tensorShape)); + offset += tensorNumel; + } + } +}; + +class AsyncSparseAllreduceWork : public ProcessGroupGloo::AsyncWork { + public: + AsyncSparseAllreduceWork( + std::shared_ptr context, + std::vector& inputs, + uint32_t tag, + uint64_t seq, + std::chrono::milliseconds timeout) + : ProcessGroupGloo::AsyncWork( + std::move(context), + {inputs}, + OpType::_ALLREDUCE_SPARSE, + seq, + timeout, + "gloo:sparse_all_reduce", + inputs), + inputs(inputs), + tag(tag) {} + + std::vector inputs; + const uint32_t tag; + + // We share dimensionality about the sparse tensors before collecting + // their contents. We assume here that the maximum number of sparse + // and dense dimensions is 4. This is stored in a contiguous piece of + // memory so that we can easily run allgather on it. + // + // The layout of this memory is as follows: + // + // - [0:4]: sparse dims + // - [4:8]: dense dims + // - [8]: nnz + // + class SparseTensorMetadata { + public: + static constexpr auto dim = 9; + + // Construct from an existing metadata tensor to facilitate structured + // access to metadata from peers, after gathering it. + explicit SparseTensorMetadata(at::Tensor metadata) + : metadata_(std::move(metadata)), + data_(metadata_.mutable_data_ptr()) { + AT_ASSERT(metadata_.scalar_type() == at::kLong); + AT_ASSERT(metadata_.dim() == 1); + AT_ASSERT(metadata_.size(0) == dim); + } + + // Populate the metadata. + void populate_from_sparse_tensor(const at::Tensor& tensor) { + const auto sparse_dim = tensor.sparse_dim(); + AT_ASSERT(sparse_dim <= 4); + for (const auto i : c10::irange(4)) { + if (i < sparse_dim) { + data_[i] = tensor.size(i); + } + } + const auto dense_dim = tensor.dense_dim(); + AT_ASSERT(dense_dim <= 4); + for (const auto i : c10::irange(4)) { + if (i < dense_dim) { + data_[i + 4] = tensor.size(sparse_dim + i); + } + } + data_[8] = tensor._nnz(); + } + + std::vector sizes() const { + std::vector sizes; + // Sparse sizes + for (const auto i : c10::irange(4)) { + if (data_[i] <= 0) { + break; + } + sizes.push_back(data_[i]); + } + // Dense sizes + for (const auto i : c10::irange(4, 8)) { + if (data_[i] <= 0) { + break; + } + sizes.push_back(data_[i]); + } + return sizes; + } + + int64_t nnz() const { + return data_[8]; + } + + protected: + at::Tensor metadata_; + int64_t* data_; + }; + + // Sparse allreduce is implemented with allgather on indices and values. + // Every process then sums the resulting sparse tensors locally. + // The nnz for sparse tensors may be different across processes, so first + // we run allgather on the nnz, and then allgather with max(nnz). + at::Tensor allreduce(std::vector& tensors) { + // TODO: This is a massive hack! There is some confusion about + // Variable/Tensor inside the body of this function. Turning off + // grad smooths over the confusion for now. This fixes + // test/test_c10d_gloo.py ProcessGroupGlooTest.test_sparse_allreduce_basics + // + // The correct fix is to stop allocating tensors that are not variables, + // but to conveniently do this c10d must depend on torch not ATen + at::AutoDispatchBelowAutograd guard; + auto input = tensors[0]; + + // Perform local reduction if we have multiple inputs. + for (const auto i : c10::irange(1, tensors.size())) { + input += tensors[i]; + } + + // Need to coalesce before we can access indices and values. + input = input.coalesce(); + + // Gather metadata information from all ranks. + auto metadata = allgather_metadata(input); + + // Sanity check dimensionality across ranks. + { + const auto expected = metadata[context_->rank].sizes(); + for (const auto i : c10::irange(context_->size)) { + if (i == context_->rank) { + continue; + } + const auto actual = metadata[i].sizes(); + TORCH_CHECK(actual == expected, "Sparse dimensions do not match"); + } + } + + // Gather all indices and all values. + auto indices = allgather_indices(input, metadata); + auto values = allgather_values(input, metadata); + + // Perform global reduction. + AT_ASSERT(static_cast(indices.size()) == context_->size); + AT_ASSERT(static_cast(values.size()) == context_->size); + auto output = at::sparse_coo_tensor( + indices[0], values[0], input.sizes(), input.options()); + for (const auto i : c10::irange(1, context_->size)) { + output += at::sparse_coo_tensor( + indices[i], values[i], input.sizes(), input.options()); + } + + // Coalesce for good measure. + return output.coalesce(); + } + + void run() override { + auto output = allreduce(inputs); + + // This copy is needed when we run a multi-gpu version of reduce (multiple + // inputs per rank). + for (const auto i : c10::irange(inputs.size())) { + inputs[i].copy_(output); + } + } + + const std::vector getInputTensors() override { + return inputs; + } + + const std::vector getOutputTensors() override { + return inputs; + } + + private: + std::vector allgather_metadata( + const at::Tensor& tensor) { + auto buffer = + at::zeros({context_->size, SparseTensorMetadata::dim}, at::kLong); + + // Prepare metadata vector (1 entry per rank) + std::vector metadata; + metadata.reserve(context_->size); + for (const auto i : c10::irange(context_->size)) { + metadata.emplace_back(buffer.select(0, i)); + } + + // Populate data for this rank + metadata[context_->rank].populate_from_sparse_tensor(tensor); + + // Allgather metadata + gloo::AllgatherOptions opts(context_); + opts.setOutput(buffer.mutable_data_ptr(), buffer.numel()); + opts.setTag(tag); + opts.setTimeout(getTimeout()); + gloo::allgather(opts); + + return metadata; + } + + std::vector allgather_indices( + const at::Tensor& tensor, + const std::vector& metadata) { + const auto sparseDim = tensor.sparse_dim(); + + std::vector counts(context_->size); + size_t totalSize = 0; + for (const auto i : c10::irange(metadata.size())) { + counts[i] = metadata[i].nnz() * sparseDim; + totalSize += counts[i]; + } + + auto output = at::empty({static_cast(totalSize)}, at::kLong); + + // tensors copied from cuda may not be contiguous, get a contiguous + // tensor before use its data_ptr + auto input = tensor.indices().contiguous(); + + // Allgatherv indices. + gloo::AllgathervOptions opts(context_); + opts.setInput( + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast) + const_cast(input.const_data_ptr()), + input.numel()); + opts.setOutput(output.mutable_data_ptr(), counts); + opts.setTag(tag); + opts.setTimeout(getTimeout()); + gloo::allgatherv(opts); + + // Compile indices tensor per rank. + std::vector indices; + indices.reserve(metadata.size()); + int64_t offset = 0; + for (const auto& i : metadata) { + const auto nnz = i.nnz(); + const auto numel = sparseDim * nnz; + indices.push_back( + output.narrow(0, offset, numel).reshape({sparseDim, nnz})); + offset += numel; + } + + return indices; + } + + std::vector allgather_values( + const at::Tensor& tensor, + const std::vector& metadata) { + // There are nnz #dense_dim()-dimensional tensors per rank. + const auto valueShape = tensor.sizes().slice(tensor.sparse_dim()); + int64_t denseNumel = 1; + for (auto dim : valueShape) { + denseNumel *= dim; + } + + std::vector counts(context_->size); + int64_t totalSize = 0; + for (const auto i : c10::irange(metadata.size())) { + counts[i] = metadata[i].nnz() * denseNumel; + totalSize += static_cast(counts[i]); + } + + auto output = at::empty({totalSize}, tensor.scalar_type()); + + // Allgatherv indices. + gloo::AllgathervOptions opts(context_); + // tensors copied from cuda may not be contiguous, get a contiguous + // tensor before use its data_ptr + at::Tensor valueTensor = tensor.values().contiguous(); + GENERATE_ALL_TYPES(valueTensor.scalar_type(), setInput, opts, valueTensor); + GENERATE_ALL_TYPES( + valueTensor.scalar_type(), setOutput, opts, output, counts); + opts.setTag(tag); + opts.setTimeout(getTimeout()); + gloo::allgatherv(opts); + + // Compile values tensor per rank. + std::vector values; + values.reserve(metadata.size()); + int64_t offset = 0; + for (const auto& i : metadata) { + const auto nnz = i.nnz(); + const auto numel = denseNumel * nnz; + auto tensorShape = std::vector({(int64_t)nnz}); + std::copy( + valueShape.begin(), + valueShape.end(), + std::back_inserter(tensorShape)); + values.push_back(output.narrow(0, offset, numel).reshape(tensorShape)); + offset += numel; + } + + return values; + } +}; + +} // namespace c10d + +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupMPI.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupMPI.hpp new file mode 100644 index 0000000000000000000000000000000000000000..467ec0c08c5339947f514e6d1ae243fe2520ce29 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupMPI.hpp @@ -0,0 +1,278 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef USE_C10D_MPI + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +namespace c10d { + +constexpr const char* MPI_BACKEND_NAME = "mpi"; + +// WorkEntry is the state associated with a single MPI run instance. +// It include the source Tensor list and destination Tensor list, as well as +// The actual run function that will operate either on src or dst or both. +struct WorkEntry { + explicit WorkEntry( + std::vector* srcPtr, + std::vector* dstPtr, + std::function&)> run) + : dst(dstPtr ? *dstPtr : std::vector()), run(std::move(run)) { + if (srcPtr) { + src = *srcPtr; + } + } + + // Not copyable + WorkEntry(const WorkEntry&) = delete; + // Not copy assignable + WorkEntry& operator=(const WorkEntry&) = delete; + + // For input and output tensors (in-place), we will always use src + std::vector src; + + // Copy of user provided outputs. + const std::vector dst; + + // src rank returned, for recv only + int* srcRank = nullptr; + std::function&)> run; +}; + +// ProcessGroupMPI implements MPI bindings for c10d. +// +// All functions on this class are expected to be called in the same +// order across processes in the group. This is the only way that we +// can guarantee to match up the same calls across processes. +// +// All MPI functions provided by this class is asynchronously scheduled on a +// Worker thread. Therefore, ProcessGroupMPI requires the MPI implementation +// that is used to have a minimum thread support value of MPI_THREAD_SERIALIZED. +// That is, The process may be multi-threaded, and multiple threads may make +// MPI calls, but only one at a time: MPI calls are not made concurrently from +// two distinct threads (all MPI calls are serialized). However, with +// MPI_THREAD_SERIALIZED, ProcessGroupMPI will only support a single process +// group. In other words, no more than 1 process group can be created globally. +// +// If you would like to use multiple ProcessGroupMPI, it requires your MPI +// implementation to have a thread support value of MPI_THREAD_MULTIPLE, that +// is, multiple threads may call MPI, with no restriction. +// +// Also note that ProcessGroupMPI only supports a single Tensor operation. In +// other words, the size of the input Tensor vector should always be 1. +// +// CUDA tensor can be supported if the MPI used is CUDA-aware MPI, and +// ProcessGroupMPI will automatically detect this support. +class TORCH_API ProcessGroupMPI : public Backend { + public: + class WorkMPI : public Work { + public: + explicit WorkMPI( + std::vector outputTensors, + const char* profilingTitle = nullptr, + const std::optional>& inputTensors = + std::nullopt) + : Work(-1, OpType::UNKNOWN, profilingTitle, inputTensors), + outputTensors_(std::move(outputTensors)), + future_(c10::make_intrusive( + c10::ListType::create(c10::TensorType::get()))) {} + + std::vector result() override; + + c10::intrusive_ptr getFuture() override; + + protected: + friend class ProcessGroupMPI; + + private: + void finishWorkMPI(); + void finishWorkMPIError(const std::exception_ptr& eptr); + + std::vector outputTensors_; + c10::intrusive_ptr future_; + }; + + class AsyncWork : public Work { + public: + AsyncWork( + MPI_Request request, + std::vector outputTensors, + const char* profilingTitle = nullptr, + const std::optional>& inputTensors = + std::nullopt); + + ~AsyncWork() override; + + bool isCompleted() override; + + bool isSuccess() const override; + + int sourceRank() const override; + + bool wait(std::chrono::milliseconds timeout = kUnsetTimeout) override; + + void abort() override; + + std::vector result() override; + + protected: + void populateException(); + + private: + const std::vector outputTensors_; + MPI_Request request_; + MPI_Status status_{}; + }; + + // Constructor will spawn up the worker thread loop + explicit ProcessGroupMPI(int rank, int size, MPI_Comm pgComm); + + ~ProcessGroupMPI() override; + + // Abort the MPI program, needs to be called when exception is detected + void abort() override; + + const std::string getBackendName() const override { + return std::string(MPI_BACKEND_NAME); + } + + c10::intrusive_ptr broadcast( + std::vector& data, + const BroadcastOptions& opts = BroadcastOptions()) override; + + c10::intrusive_ptr allreduce( + std::vector& tensors, + const AllreduceOptions& opts = AllreduceOptions()) override; + + c10::intrusive_ptr allreduce_coalesced( + std::vector& tensors, + const AllreduceCoalescedOptions& opts = + AllreduceCoalescedOptions()) override; + + c10::intrusive_ptr reduce( + std::vector& tensors, + const ReduceOptions& opts = ReduceOptions()) override; + + c10::intrusive_ptr allgather( + std::vector>& outputTensors, + std::vector& inputTensors, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr _allgather_base( + at::Tensor& outputbuffer, + at::Tensor& inputbuffer, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr allgather_coalesced( + std::vector>& outputTensorLists, + std::vector& inputTensors, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr gather( + std::vector>& outputTensors, + std::vector& inputTensors, + const GatherOptions& opts = GatherOptions()) override; + + c10::intrusive_ptr scatter( + std::vector& outputTensors, + std::vector>& inputTensors, + const ScatterOptions& opts = ScatterOptions()) override; + + c10::intrusive_ptr reduce_scatter( + std::vector& outputTensors, + std::vector>& inputTensors, + const ReduceScatterOptions& opts = ReduceScatterOptions()) override; + + c10::intrusive_ptr _reduce_scatter_base( + at::Tensor& outputTensor, + at::Tensor& inputTensor, + const ReduceScatterOptions& opts = ReduceScatterOptions()) override; + + c10::intrusive_ptr alltoall_base( + at::Tensor& outputTensor, + at::Tensor& inputTensor, + std::vector& outputSplitSizes, + std::vector& inputSplitSizes, + const AllToAllOptions& opts = AllToAllOptions()) override; + + c10::intrusive_ptr alltoall( + std::vector& outputTensors, + std::vector& inputTensors, + const AllToAllOptions& opts = AllToAllOptions()) override; + + c10::intrusive_ptr send( + std::vector& tensors, + int dstRank, + int tag) override; + + c10::intrusive_ptr recv( + std::vector& tensors, + int srcRank, + int tag) override; + + c10::intrusive_ptr recvAnysource( + std::vector& tensor, + int tag) override; + + c10::intrusive_ptr barrier( + const BarrierOptions& opts = BarrierOptions()) override; + + // Creating a new ProcessGroupMPI, will initialize MPI if not initialized + static c10::intrusive_ptr createProcessGroupMPI( + std::vector ranks = {}); + + protected: + using WorkType = + std::tuple, c10::intrusive_ptr>; + // Worker thread loop + void runLoop(); + // Helper function that is called by the destructor + void destroy(); + + c10::intrusive_ptr enqueue( + std::unique_ptr entry, + const char* profilingTitle = nullptr, + const std::optional>& inputTensors = + std::nullopt); + + bool stop_{false}; + + std::mutex pgMutex_; + std::thread workerThread_; + + std::deque queue_; + std::condition_variable queueProduceCV_; + std::condition_variable queueConsumeCV_; + + // Global states + static void initMPIOnce(); + static void mpiExit(); + + static std::mutex pgGlobalMutex_; + static int mpiThreadSupport_; + + MPI_Comm pgComm_; +}; + +} // namespace c10d + +#endif // USE_C10D_MPI + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupNCCL.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupNCCL.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ba4265b0613193c88987a766416ca749b54182fa --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupNCCL.hpp @@ -0,0 +1,1547 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef USE_C10D_NCCL + +#if defined(__linux__) +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace c10d { + +// Control broadcasting of NCCL uniqueId +static std::vector TORCH_NCCL_BCAST_UNIQUEID = { + "TORCH_NCCL_BCAST_UNIQUEID"}; + +// Control EagerInit P2P serialization warning +static std::vector + TORCH_NCCL_SHOW_EAGER_INIT_P2P_SERIALIZATION_WARNING = { + "TORCH_NCCL_SHOW_EAGER_INIT_P2P_SERIALIZATION_WARNING"}; + +// Control whether to always use high priority streams +static std::vector TORCH_NCCL_HIGH_PRIORITY = { + "TORCH_NCCL_HIGH_PRIORITY"}; + +// Control whether or not wait() is blocking or non-blocking. +static std::vector TORCH_NCCL_BLOCKING_WAIT = { + "TORCH_NCCL_BLOCKING_WAIT", + "NCCL_BLOCKING_WAIT"}; + +// TODO: We want to eventually remove this variable and make users to use +// the default value (3 - SkipCleanUp). +// Control whether or not we perform Async Error Handling with NCCL. +static std::vector TORCH_NCCL_ASYNC_ERROR_HANDLING = { + "TORCH_NCCL_ASYNC_ERROR_HANDLING", + "NCCL_ASYNC_ERROR_HANDLING"}; + +// Control whether dumping debug info on watchdog +// timeout is enabled. This variable must be set together with +// TORCH_NCCL_ENABLE_MONITORING=1 and TORCH_NCCL_TRACE_BUFFER_SIZE > 0. +static std::vector TORCH_NCCL_DUMP_ON_TIMEOUT = { + "TORCH_NCCL_DUMP_ON_TIMEOUT"}; + +// Control whether to propagate NCCL errors to all ranks through TCPStore. +static std::vector TORCH_NCCL_PROPAGATE_ERROR = { + "TORCH_NCCL_PROPAGATE_ERROR"}; + +// Control whether Desync Debug is enabled. This variable must be set +// together with TORCH_NCCL_ASYNC_ERROR_HANDLING. +static std::vector TORCH_NCCL_DESYNC_DEBUG = { + "TORCH_NCCL_DESYNC_DEBUG", + "NCCL_DESYNC_DEBUG"}; + +// Enable recording start-events for all ProcessGroupNCCL collectives, and +// compute accurate collective timing per-collective. (Note: end-events are +// recorded by default. Turn on this flag can increase chances of a watchdog +// hang due to performing a CUDA event query which eventually calls +// cudaEventElapsedTime() API. +static std::vector TORCH_NCCL_ENABLE_TIMING = { + "TORCH_NCCL_ENABLE_TIMING", + "NCCL_ENABLE_TIMING"}; + +// Enable monitoring thread which aborts the process when the ProcessGroupNCCL +// Watchdog thread gets stuck and no heartbeat is detected after +// TORCH_NCCL_HEARTBEAT_TIMEOUT_SEC. This can happen due to calling CUDA/NCCL +// APIs that may hang. It is Useful to prevent jobs being stuck for a prolonged +// time than necessary tying up cluster resources. +static std::vector TORCH_NCCL_ENABLE_MONITORING = { + "TORCH_NCCL_ENABLE_MONITORING"}; + +// Control the watchdog heartbeat timeout period after which the monitoring +// thread will abort the process. +static std::vector TORCH_NCCL_HEARTBEAT_TIMEOUT_SEC = { + "TORCH_NCCL_HEARTBEAT_TIMEOUT_SEC"}; + +// Whether to rethrow CUDA Errors in the watchdog (default true) +static std::vector TORCH_NCCL_RETHROW_CUDA_ERRORS = { + "TORCH_NCCL_RETHROW_CUDA_ERRORS"}; + +// The maximum number of events we store in the flight recorder's ring buffer. +// (One event could be the start or end of a collective, for example). +static std::vector TORCH_NCCL_TRACE_BUFFER_SIZE = { + "TORCH_NCCL_TRACE_BUFFER_SIZE"}; + +// Control how much extra time we will wait for dumping the debugging info +// before we exit and throws timeout exception. +static std::vector TORCH_NCCL_WAIT_TIMEOUT_DUMP_MILSEC = { + "TORCH_NCCL_WAIT_TIMEOUT_DUMP_MILSEC"}; + +// Control the interval inside the monitoring thread to check the coordinated +// signal from other ranks, e.g. to dump the debugging information. +static std::vector TORCH_NCCL_COORD_CHECK_MILSEC = { + "TORCH_NCCL_COORD_CHECK_MILSEC"}; + +// Whether to log C++ stack traces on unclean shutdown (default true) +static std::vector TORCH_NCCL_LOG_CPP_STACK_ON_UNCLEAN_SHUTDOWN = { + "TORCH_NCCL_LOG_CPP_STACK_ON_UNCLEAN_SHUTDOWN"}; + +// Whether to include only active collectives in the Flight Recorder trace +// (default false) +static std::vector TORCH_NCCL_EXTRA_DUMP_ON_EXEC = { + "TORCH_NCCL_EXTRA_DUMP_ON_EXEC"}; + +// Control whether to use CudaEventCache for the collective in watchdog thread. +// We noticed in the past when cuda global lock is held, destroying CudaEvent +// can cause a hang. +static std::vector TORCH_NCCL_CUDA_EVENT_CACHE = { + "TORCH_NCCL_CUDA_EVENT_CACHE"}; + +// Control the number of ranks each root can cover during NCCL comm init. +static std::vector TORCH_NCCL_RANKS_PER_ROOT = { + "TORCH_NCCL_RANKS_PER_ROOT"}; + +static std::vector TORCH_NCCL_NAN_CHECK = {"TORCH_NCCL_NAN_CHECK"}; + +constexpr const char* NCCL_BACKEND_NAME = "nccl"; + +constexpr const char* kStoreDumpKey = "exception_dump"; + +constexpr const char* kStoreErrorSignalKey = "remote_error"; + +constexpr const int kWorkStatusUpdatePeriodMs = 30 * 1000; // 30 seconds + +constexpr auto kProcessGroupNCCLDefaultTimeout = + std::chrono::milliseconds(10 * 60 * 1000); + +// NoHandling: do not handle asynchronous NCCL errors +// TearDown: tear down process upon error, see `WorkNCCL::handleException` +// CleanUpOnly: just clean up collectives and abort communicators without +// tearing down process SkipCleanUp: (this is a temporary option and can be +// removed in future) tear down process without cleaning up NCCL communicators. +// This should be used as a last resort in case `ncclCommAbort` itself is +// hanging +enum ErrorHandlingMode { + NoHandling = 0, + TearDown = 1, + CleanUpOnly = 2, + SkipCleanUp = 3 +}; + +#define SHOULD_CLEAN_UP(a) (a != NoHandling && a != SkipCleanUp) + +#define SHOULD_TEAR_DOWN(a) (a != NoHandling && a != CleanUpOnly) + +#define PRINT_COLLECTIVE_HASH_SIGNATURE(phase, opType, numel, hashValue) \ + LOG(WARNING) << logPrefix() << "Hash of " << phase << " to NCCL " << opType \ + << " with size " << numel << " is " << hashValue; + +// If set, ProcessGroupNCCL doesn't use recordStream calls to ensure +// caching allocator safety for tensors used on both user-facing and +// internal comm streams. +// Instead, it stashes live references to those tensors until after +// user-facing streams are synced with comm streams. +// See stashed_for_allocator_safety_ below. +static std::vector TORCH_NCCL_AVOID_RECORD_STREAMS = { + "TORCH_NCCL_AVOID_RECORD_STREAMS"}; + +// If set, ProcessGroupNCCL registers postAlloc and preFree hooks to cuda cache +// allocator so that whenever a tensor is allocated or freed, ProcessGroupNCCL +// can register/deregister the tensor on all available NCCL communicators. +static std::vector TORCH_NCCL_USE_TENSOR_REGISTER_ALLOCATOR_HOOK = + {"TORCH_NCCL_USE_TENSOR_REGISTER_ALLOCATOR_HOOK", + "NCCL_USE_TENSOR_REGISTER_ALLOCATOR_HOOK"}; + +#if defined(__linux__) +struct DumpPipe { + DumpPipe(int rank, const std::string& fileStem, int traceBufferSize) { + if (fileStem.empty() || traceBufferSize <= 0) { + return; + } + std::string filename = c10::str(fileStem, rank, ".pipe"); + TORCH_CHECK( + unlink(filename.c_str()) != -1 || errno == ENOENT, + "Error removing existing named pipe ", + filename, + ", Error: ", + std::strerror(errno)); + TORCH_CHECK( + mkfifo(filename.c_str(), 0666) != -1, + "Error creating named pipe ", + filename, + ", Error: ", + std::strerror(errno)); + fd_ = open(filename.c_str(), O_RDONLY | O_NONBLOCK); + LOG(INFO) << "Pipe file " << filename + << " has been opened, write to it to trigger NCCL Debug Dump."; + TORCH_CHECK(fd_ != -1, "Error opening named pipe ", filename); + } + bool shouldDump() { + if (fd_ == -1) { + return false; + } + // NOLINTNEXTLINE(*array*) + char buf[128]{}; + // non-blocking from O_NONBLOCK above. + // Ignore EINTR because we already will poll this + // again later. + ssize_t bytesRead = read(fd_, &buf, 128); + return bytesRead > 0; + } + ~DumpPipe() { + if (fd_ != -1) { + close(fd_); + } + } + + private: + int fd_ = -1; +}; +#else +struct DumpPipe { + DumpPipe(int rank) {} + bool shouldDump() { + return false; + } +}; +#endif + +// A shelf for stashing tensors between op call and `work.wait()`. +// Used in case of async ops. +class TensorShelf { + public: + // Stash tensors so that CachingAllocator cannot recycle them prematurely. + void stash(std::vector& tensors); + // Stash tensors from another shelf. + void stash(TensorShelf& other); + // Unstage the stashed tensors so that CachingAllocator can recycle them. + // Same as `clear()`. + void unstash(); + // Whether shelf is empty. + bool empty(); + // Clear the shelf. + void clear(); + + protected: + // Get the inner tensor vector. Use with caution as it is not protected by + // mutex. + std::vector& get(); + + private: + std::vector tVector_; + // Need a mutex to protect `tVector_` because it can be potentially accessed + // from both main thread and watchdog thread. + std::mutex mutex_; +}; + +// ProcessGroupNCCL implements NCCL bindings for c10d. +// +// All functions of the class are expected to be called in the same order +// across all processes in the process group. This is the only way that we +// can guarantee to match up the same calls among all processes. +// +// All NCCL functions provided by this class are asynchronous functions. More +// specifically, each NCCL call is scheduled on a separate CUDA stream that is +// different from the current CUDA stream. This is for the purpose of +// achieving potentially concurrency and better performance. As a result, +// it is the callers' responsibility to make sure that the CUDA stream their +// code works on needs to wait for the NCCL operation from +// this class. +// +// This can be done by calling: +// +// either WorkNCCL::wait() or WorkNCCL::synchronize(), both achieves the same +// functionality and are synonyms. +// +// Also note that WorkNCCL::finishedGPUExecution() is a helper function only +// provided by ProcessGroupNCCL to check if the NCCL operation of WorkNCCL has +// finished execution on the GPU (not just scheduled). +// +// Example on using the NCCL process group +// +// ProcessGroupNCCL pg(store, rank, size); +// std::shared_ptr work = pg.allreduce(tensors); +// +// // At this point, NCCL kernel has already by queued successfully +// // Now, let current stream wait for the NCCL to finish, this function is +// // async operation as well +// +// work->wait() +// +// // Now continue on other work in the current stream. +class TORCH_API ProcessGroupNCCL : public Backend { + public: + class WorkNCCL : public Work, public std::enable_shared_from_this { + public: + friend struct WorkInfo; + + // Constructor takes a list of CUDA devices + WorkNCCL( + std::string pgUID, + std::string pgDesc, + at::Device& device, + int rank, + OpType opType, + uint64_t seq, + bool isP2P = false, + const char* profilingTitle = nullptr, + const std::optional>& inputs = std::nullopt, + bool enableTiming = false, + bool cudaEventCacheEnabled = false, + DebugLevel distDebugLevel = DebugLevel::Off); + // Copy constructor doing partial copy without outputs_. Cleanup thread + // monitors and removes finished works. However it will deadlock when + // destructs outputs_ tensors who are view tensors in autograd graph. + WorkNCCL(const WorkNCCL& w); + + ~WorkNCCL() override = default; + + // Checks if the NCCL kernel has started to execute. + bool isStarted(); + + // Checks if request has completed. In this specific case of NCCL, it checks + // if the NCCL operation has completed on the GPU in its own NCCL stream. + // Non-blocking operation. + bool isCompleted() override; + + bool isSuccess() const override; + + // Same as calling synchronize() for NCCL work if timeout is not set. + // Otherwise, it will block the CPU thread until the NCCL work is completed + // or timed out. If timeout, exception will be thrown. + bool wait(std::chrono::milliseconds timeout = kNoTimeout) override; + + void blockCurrentStream() override { + synchronize(); + } + + void abort() override; + + // Let current stream wait on the completion of the NCCL work + // Throws on exceptions. + void synchronize() override; + + // Synchronize streams by blocking each on the NCCL stream + void synchronizeStream(); + + // Helper function to handle exception (throw if needed). + void handleException(ErrorHandlingMode asyncErrorHandling); + + // Helper function that checks if the NCCL kernels have finished + // execution on the GPUs + bool finishedGPUExecution(); + + // Get a Future object that will be marked as completed internally. + c10::intrusive_ptr getFuture() override; + + // Get a Future result of each work (e.g. success, different error types). + // instead of the tensor output. + c10::intrusive_ptr getFutureResult() override; + + float getDuration() const override; + + uint64_t getSequencenumber() const override; + + const std::string& logPrefix() const; + + // Helper function that sets an exception_ptr on the WorkNCCL object. + void setException(std::exception_ptr exception_ptr); + + // Helper function that returns True if the WorkNCCL object has timed out + // and False otherwise. + // In case of timeout, set exception on the WorkNCCL object. + bool checkTimeout( + std::optional timeout = std::nullopt); + + // Print the traceback of the collective at call time + void printTraceback() const; + + std::string getTraceback() const; + + std::vector result() override; + + protected: + // The process group unique id + std::string pgUID_; + + // The process group description + std::string pgDesc_; + + // The cached list of CUDA devices to operate on + at::Device device_; + + // The start CUDA event of NCCL operator tracking this work item. These + // start CUDA events are needed by desync debugging if enabled. + std::shared_ptr ncclStartEvent_; + + // The end CUDA event of NCCL operator tracking this work item. + std::shared_ptr ncclEndEvent_; + + // The NCCL communicator used for this work item. + std::shared_ptr ncclComm_; + + // whether this work is a barrier op + bool isBarrierOp_{false}; + + // Clone of blockingWait_ from ProcessGroupNCCL. + bool blockingWait_{false}; + + // Clone of opTimeout_ from ProcessGroupNCCL. + std::chrono::milliseconds opTimeout_{}; + + // Ephemeral timeouts are owned by exactly one work, + // and reset after that work completes. + // There may be more than one ephemeral timeout active at the same time, + // and this variable is used to track the ownership of ephemeral timeout. + std::chrono::milliseconds ownedEphermeralTimeout_ = + std::chrono::milliseconds(0); + + // Time point representing when the work started. + std::chrono::time_point workStartTime_; + + // Record the sequential number of collective or p2p. + uint64_t seq_; + bool isP2P_; + + // Indicates if the nccl start event has been updated to the store trace. + // This will be used by desync debug. + bool startTraceUpdated_{false}; + + // Record collective sizes for debug. We only record the size on the first + // device as multi-device per process is deprecated + size_t numelIn_ = 0; + size_t numelOut_ = 0; + + // Wrapper method for the static checkForNCCLErrors which can be overridden + // for tests. + virtual std::exception_ptr checkForNCCLErrors(); + + friend std::ostream& operator<<( + std::ostream& output, + const WorkNCCL& workNCCL); + + // Checks for NCCL errors and sets an appropriate exception_ptr. + void checkAndSetException(); + + // Just checks whether GPU execution has started, without modifying + // exception_ptr. + bool startedGPUExecutionInternal() const; + + // Just checks whether GPU execution has completed, without modifying + // exception_ptr. + bool finishedGPUExecutionInternal() const; + + // Reference to the store so that we can write aborted communicators + // to the store. + c10::intrusive_ptr store_; + + // Store a reference to NCCL collective's outputs, used by result and to + // give a more descriptive message when representing the Work as a string. + std::shared_ptr> outputs_; + + // TORCH_NCCL_AVOID_RECORD_STREAMS implementation helper. + // Stores references to participating non-output tensors (ie inputs, + // flattened intermediates). + // We'll clear this list in synchronizeStream, just after user-facing + // stream(s) are synced with the nccl work stream(s). + // By keeping these refs (as well as outputs_) alive until after the + // collective's work rejoins the user-facing streams, we achieve + // caching allocator safety without any recordStream calls. + // For in-place collectives, some refs stashed here may alias outputs_, + // but that doesn't do any harm. + std::shared_ptr stashed_for_allocator_safety_; + + // The future returned by getFuture. + c10::intrusive_ptr future_; + + // the future result (e.g., success or failure) of the work + c10::intrusive_ptr futureWorkResult_; + + bool timingEnabled_; + // unique id used to tell the trace buffer that this + // work has completed + std::optional trace_id_; + std::optional trace_reset_epoch_; + DebugLevel distDebugLevel_; + friend class ProcessGroupNCCL; + }; + + struct Options : Backend::Options { + // NOTE: timeout in ProcessGroupNCCL::Options denote the timeout for + // operations. This is only used when blockingWait_ is enabled. + explicit Options(bool is_high_priority_stream = false); + Options(const Options&) = default; + Options(Options&&) noexcept = default; + Options& operator=(const Options&) = delete; + Options& operator=(Options&&) noexcept = delete; + ~Options() override = default; + + // return intrusive_ptr of the object + static c10::intrusive_ptr create( + bool is_high_priority_stream = false) { + return c10::make_intrusive(is_high_priority_stream); + } + + // Schedule NCCL operations on high priority CUDA streams + bool is_high_priority_stream; + +#ifdef NCCL_HAS_CONFIG + // Configure ranks + ncclConfig_t config = NCCL_CONFIG_INITIALIZER; +#endif + + // Optional "parent" backend and color to create communicators from + // via `ncclCommSplit` + c10::intrusive_ptr split_from; + // Color to use for `ncclCommSplit`, values: + // * Non-negative value: in group; + // * NCCL_SPLIT_NOCOLOR (-1): not in group; + // * NCCL_SPLIT_NOCOLOR - 1: uninitialized. + // [Note 1]: the type must be `int` instead of `int64_t` because NCCL API + // accepts int. Otherwise, an implicit conversion may happen at the API call + // and the value may become negative. + // [Note 2]: this member is pybinded to Python, the value passed from Python + // must be within the numerical range of C++ int. Otherwise, Python will + // raise a RuntimeError saying type is incompatible. See also + // `_process_group_color` in `distributed_c10d.py`. +#ifdef NCCL_HAS_COMM_SPLIT + int split_color{NCCL_SPLIT_NOCOLOR - 1}; +#else + // [Note 3]: for older NCCL versions, NCCL_SPLIT_NOCOLOR is not defined. But + // `split_color` is pybinded to Python, so we need to define it. So we use + // the int value of `NCCL_SPLIT_NOCOLOR` (-1) instead. + int split_color{-2}; +#endif + }; + + // Helper class related to TORCH_NCCL_DESYNC_DEBUG + class DesyncDebugger { + public: + // Initialize and enable DesyncDebugger + void init( + int rank, + int size, + int globalRank, + int pgId, + c10::intrusive_ptr store); + + // Run desync debug. This function is called by watchdog at time of timeout. + void run(); + + // Log work start to store. + void logWorkStart(WorkNCCL& work); + + // Log work end to store. + void logWorkEnd(WorkNCCL& work); + + private: + // Whether desync debug is enabled. + // If false, all functions are no-op. + bool enabled_{false}; + + // From ProcessGroupNCCL + int rank_; + int size_; + int globalRank_; + int pgId_; + + // Reference to the store so that we can log start/end event. + c10::intrusive_ptr store_; + + // The store keys to trace the last NCCL collective kernel CUDA events - + // start event and end event respectively. These are used to do desync root + // cause analysis. + std::string traceKeyStart_; + std::string traceKeyEnd_; + }; + + // Class that runs as a separate thread aside from watchdog + // thread because we need to check the heartbeat from watchdog thread + // so that when we get stuck in some NCCL/CUDA calls, + // we can dump the debugging information and abort the process. + class HeartbeatMonitor { + public: + HeartbeatMonitor(ProcessGroupNCCL* pg); + virtual ~HeartbeatMonitor() = default; + + // Start the heartbeat monitor thread. + void start(); + + // Join the heartbeat monitor thread. + void join(); + + // Run the actual loop to check watchdog heartbeat. + virtual void runLoop(); + + // Set the terminal flag and notify the heartbeat monitor thread to stop. + void stop(); + + // Set the last update time of watchdog thread. + void setLastWorkListUpdateTime( + std::chrono::time_point time); + + int getDumpTimeout() const; + + // Util function to get the timeout error message + std::string getNCCLWatchdogTimeoutErrorMsg(const std::string& extraMsg); + + // Util function to get the timeout exit message + std::string getNCCLWatchdogTimeoutExitMsg(const std::string& exitReason); + + protected: + // We need to keep a reference to the PG instance so that we can access + // the member functions of the PG instance. We store a raw pointer on + // purpose because the heartbeat monitor thread now still lives within the + // lifetime of the PG instance. + ProcessGroupNCCL* pg_; + + private: + // Whether or not to print C++ stack traces to logs on unclean shutdown. + bool logCppStackOnUncleanShutdown_; + + // The time interval used for deciding whether there is no watchdog + // heartbeat. + int heartbeatTimeoutInSec_; + + // timeout for the dump to finish. + int waitTimeoutDumpInMilSec_; + + // Interval of check coordinated signals in ProcessGroupNCCL from other + // ranks e.g., trigger the dump of the debugging info for timeout when + // notified. + int coordCheckIntervalMilSec_; + + // We gate the heartbeat monitor thread so that we can roll it out + // gradually. + bool watchdogHeartbeatMonitorEnabled_; + + // Monitor thread which checks the heartbeat of Watchdog thread. + // If the monitor thread finds there is no heartbeat, it will dump debug + // info and then kill the watchdog thread to avoid hang. + std::thread ncclHeartbeatMonitorThread_; + + // Whether or not we should terminate the heartbeat monitoring threads. + std::atomic terminateHeartbeatMonitorThread_{false}; + + // Condition Variable for monitor thread to wake up early + std::condition_variable monitorWakeUpCV_; + + // Whether or not to dump debug info on exception including both watchdog + // timeout and nccl errors. + bool dumpOnTimeoutOrEx_; + + // Mutex to Guard monitorWakeUpCV_ + std::mutex monitorMutex_; + + // The last update time of WorkList inside watchdog thread. + std::chrono::time_point lastWorkListUpdateTime_; + }; + + // Class that runs as a side thread to check whether the NCCL collective + // is timed out or errors on the cached NCCL communicators. + class Watchdog { + public: + Watchdog(ProcessGroupNCCL* pg); + virtual ~Watchdog() = default; + + // Start the watchdog thread. + void start(); + + // Join the watchdog thread. + void join(); + + // Function that runs as part of a separate thread and checks for errors on + // NCCL communicators. We need a separate thread to check for NCCL errors + // since we can't rely on the user calling certain methods like wait(), + // isCompleted() etc. to detect and remediate errors. In addition to this, + // we need a mechanism to safely abort and remove NCCL communicators from + // our cache. This can be done cleanly by having a thread for the + // ProcessGroupNCCL class. Attempting to modify the communicator cache from + // the WorkNCCL class might run into issues with object lifetime since the + // ProcessGroupNCCL object might get destroyed before the WorkNCCL object. + void run(); + + // Watchdog's inside loop. + // Takes care of cleaning up completed work, and aborting upon failure or + // timeout. + void runLoop(); + + // Notify the loop inside watchdog. + void notify(); + + void checkAndSetRemoteError(); + + // A helper function to get the src rank of a signal from the Store. This is + // nonblocking function returning -1 if the signal is not available yet. + int getSignalSrcRank( + c10::intrusive_ptr& store, + const std::string& signal); + + uint64_t getHeartbt() const; + + void setDesyncDebug(bool desyncDebug); + + private: + std::thread ncclCommWatchdogThread_; + + // We need to keep a reference to the PG instance so that we can access + // the member functions of the PG instance. We store a raw pointer on + // purpose because the watchdog thread now still lives within the + // lifetime of the PG instance. + ProcessGroupNCCL* pg_; + + // Whether the NCCL watchdog should rethrow CUDA errors. + bool rethrowCUDAErrors_ = false; + + std::exception_ptr watchDogException_ = nullptr; + + // Condition Variable for watchdog thread sleep + std::condition_variable workMetaListCV_; + + // Heartbeat of watchdog thread. + std::atomic_uint64_t heartbeat_; + + // Whether or not to propagate detected errors to all ranks in the same PG + // through TCPStore. + bool propagatePgError_; + + // Whether or not to enable timeout root cause analysis. + bool desyncDebug_; + + DesyncDebugger desyncDebugger_; + }; + + // If you wish to create multiple process groups, each with a potentially + // different rank and size, you can do so by passing a new store instance + // to each one. If you have only a single store object, you can + // use the `c10d::PrefixStore` to derive scoped instances. + // This is also what the Python API in torch.distributed does. + // + // The process group instance keeps a reference to the store because + // it may be used long after the constructor runs. In fact, the constructor + // doesn't create any NCCL communicators. A single NCCL communicator can + // only be used on a specific set of devices, and are therefore created + // on-demand when a collective runs. If another collective is executed later, + // against a different set of devices, the process group creates another NCCL + // communicator. These NCCL communicators are cached and reused if possible. + // + ProcessGroupNCCL( + c10::intrusive_ptr store, + int rank, + int size, + c10::intrusive_ptr options = Options::create()); + + // This constructor includes the deprecated `groupName` argument. + // If you have existing code that uses the `groupName`, you can replace + // it by specifying a `c10d::PrefixStore(groupName, store)` for store. + C10_DEPRECATED ProcessGroupNCCL( + const c10::intrusive_ptr& store, + int rank, + int size, + const std::string& groupName, + c10::intrusive_ptr options = Options::create()) + : ProcessGroupNCCL(store, rank, size, std::move(options)) {} + + ~ProcessGroupNCCL() override; + + // This function returns a local uid for ProcessGroupNCCL. + uint64_t getUid() { + return static_cast(local_id_); + } + + c10::intrusive_ptr getOptions() { + return options_; + } + + c10::intrusive_ptr getBackendOptions() override { + return c10::static_intrusive_pointer_cast(options_); + } + + const std::string getBackendName() const override { + return std::string(NCCL_BACKEND_NAME); + } + + bool supportsSplitting() const override { + return true; + } + + bool supportsCoalescing() const override { + return true; + } + + bool supportsTimeEstimation() const override { +#ifdef NCCL_SIM_INFO_INITIALIZER + return true; +#else + return false; +#endif + } + + void setTimeout(std::chrono::milliseconds timeout) override { + options_->timeout = timeout; + } + + void startCoalescing() override; + + c10::intrusive_ptr endCoalescing() override; + + void startTimeEstimate(); + + float endTimeEstimate(); + + // For specifying a composite optype, such as ALLGATHER and REDUCE_SCATTER + c10::intrusive_ptr endCoalescing(OpType optype); + + c10::intrusive_ptr broadcast( + std::vector& tensors, + const BroadcastOptions& opts = BroadcastOptions()) override; + + c10::intrusive_ptr _broadcast_oop( + at::Tensor& outputTensors, + at::Tensor& inputTensors, + const BroadcastOptions& opts = BroadcastOptions()); + + c10::intrusive_ptr allreduce_sparse( + std::vector& tensors, + const AllreduceOptions& opts = AllreduceOptions()) override; + + c10::intrusive_ptr allreduce( + std::vector& tensors, + const AllreduceOptions& opts = AllreduceOptions()) override; + + c10::intrusive_ptr allreduce_coalesced( + std::vector& tensors, + const AllreduceCoalescedOptions& opts = + AllreduceCoalescedOptions()) override; + + c10::intrusive_ptr reduce( + std::vector& tensors, + const ReduceOptions& opts = ReduceOptions()) override; + + c10::intrusive_ptr _reduce_oop( + at::Tensor& outputTensors, + at::Tensor& inputTensors, + const ReduceOptions& opts = ReduceOptions()); + + c10::intrusive_ptr allgather( + std::vector>& outputTensors, + std::vector& inputTensors, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr _allgather_base( + at::Tensor& outputbuffer, + at::Tensor& inputbuffer, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr allgather_coalesced( + std::vector>& outputTensorLists, + std::vector& inputTensors, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr allgather_into_tensor_coalesced( + std::vector& outputs, + std::vector& inputs, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr reduce_scatter( + std::vector& outputTensors, + std::vector>& inputTensors, + const ReduceScatterOptions& opts = ReduceScatterOptions()) override; + + c10::intrusive_ptr _reduce_scatter_base( + at::Tensor& outputTensor, + at::Tensor& inputTensor, + const ReduceScatterOptions& opts = ReduceScatterOptions()) override; + + c10::intrusive_ptr reduce_scatter_tensor_coalesced( + std::vector& outputs, + std::vector& inputs, + const ReduceScatterOptions& opts = ReduceScatterOptions()) override; + + c10::intrusive_ptr barrier( + const BarrierOptions& opts = BarrierOptions()) override; + + c10::intrusive_ptr alltoall_base( + at::Tensor& outputTensor, + at::Tensor& inputTensor, + std::vector& outputSplitSizes, + std::vector& inputSplitSizes, + const AllToAllOptions& opts = AllToAllOptions()) override; + + c10::intrusive_ptr alltoall( + std::vector& outputTensors, + std::vector& inputTensors, + const AllToAllOptions& opts = AllToAllOptions()) override; + + c10::intrusive_ptr send( + std::vector& tensors, + int dstRank, + int tag) override; + + c10::intrusive_ptr recv( + std::vector& tensors, + int srcRank, + int tag) override; + + int64_t getCommPtr(); + + void groupStart(); + + void groupEnd(); + + void groupEndNonblocking(const std::shared_ptr& comm); + + c10::intrusive_ptr gather( + std::vector>& outputTensors, + std::vector& inputTensors, + const GatherOptions& opts = GatherOptions()) override; + + c10::intrusive_ptr scatter( + std::vector& outputTensors, + std::vector>& inputTensors, + const ScatterOptions& opts = ScatterOptions()) override; + + // Unsupported Ops + c10::intrusive_ptr recvAnysource( + std::vector& tensors, + int tag) override; + + // Agrees on an initial sequence number for the whole group by having rank 0 + // create it and broadcast it to other ranks using the store. + void setSequenceNumberForGroup() override; + + // Retrieves the current sequence number for the whole group, which should be + // in sync. If the returned number is not consistent across the group, it + // may indicate that there is some sort of collective desynchronization. + uint64_t getSequenceNumberForGroup() override; + + // Return the total number of splits the communicators held by this process + // group have performed. Counts ncclCommCreateFromRanks() for ncclx v2.21.5+ + uint64_t getCommSplitCounter() const; + + void registerOnCompletionHook( + std::function)>&& hook) override; + void waitForPendingWorks() override; + + void enableCollectivesTiming() override; + + c10::intrusive_ptr split( + const c10::intrusive_ptr& store, + const std::vector& ranks, + const c10::intrusive_ptr& opts) override; + + c10::intrusive_ptr merge( + const c10::intrusive_ptr& store, + const c10::intrusive_ptr& opts, + const int& rank, + const int& size) override; + + // Helper function for iteratively aborting communicators in the provided map + void abortCommsFromMap( + std::unordered_map>& ncclCommsMap, + const std::optional& abortReason); + + c10::intrusive_ptr initIntraNodeComm(); + + // Destroy (shutdown) this backend -- normal exit. + void shutdown() override; + + // Provides an API to abort the ProcessGroup (similar to ncclCommAbort) + // instead of relying on ProcessGroupNCCL destructor. + void abort() override; + + void eagerConnectSingleDevice(at::Device device) override; + + void performNocolorSplit(at::Device device); + + // If all comms on this PG are fully initialized, return true. + bool isInitialized(); + + ErrorType getError() override; + + bool supportsShrinking() const override { +#ifdef NCCL_HAS_COMM_SHRINK + return true; +#else + return false; +#endif + } + + // Backend-style shrink override that returns a Backend instance. + c10::intrusive_ptr shrink( + const std::vector& ranks_to_exclude, + int shrink_flags = 0, + const c10::intrusive_ptr& opts_override = + nullptr) override; + + std::shared_ptr getMemAllocator() override; + + // Allocate tensor from communication-optimized memory pool + at::Tensor allocateTensor(long size, at::TensorOptions options = {}) override; + + // Whether tensor allocation from NCCL memory pool is supported + bool supportsTensorAlloc(c10::DeviceIndex deviceIdx) override; + + // Performs NCCL user buffer registration for all buffers in + // the given MemPool + void registerMemPool(at::cuda::MemPool* pool, bool symm = false); + + // Performs NCCL user buffer de-registration for all buffers in + // the given MemPool + void deregisterMemPool(at::cuda::MemPool* pool); + + // This method adds a temporary extension for the timeout period, + // applying to all collectives between the calling of this API and + // the completion of the first collective on the GPU. While this feature + // provides flexibility in specific scenarios, it introduces statefulness + // to timeout setting. Therefore, it is advisable to use this API sparingly + // and consider alternative approaches, such as directly setting the timeout + // or utilizing a barrier collective (one can set any timeout to the barrier), + // whenever feasible. + void addEphemeralTimeout(const std::chrono::milliseconds& timeout); + + // This function is only intended for testing purposes because we don't + // want to expose the `WorkNCCL` via pybind. It verifies whether the + // `opTimeout_` of the provided WorkNCCL instance is the same as the specified + // timeout. + bool verifyWorkTimeoutForTest( + const c10::intrusive_ptr& work, + const std::chrono::milliseconds& timeout); + + void setEnableNanCheck(bool enableNanCheck); + + // APIs related to memory offload (require NCCL 2.29.7+ at runtime) + void suspend() override; + + void resume() override; + + std::unordered_map getMemoryStats() override; + + protected: + uint64_t getWatchdogHeartbt() const; + + // Instance of the heartbeat monitor thread. + std::unique_ptr heartbeatMonitor_; + + // Instance of the watchdog thread. + std::unique_ptr watchdog_; + + // Helper that broadcasts nccl unique ID to all ranks through the store + void broadcastUniqueNCCLID( + ncclUniqueId* ncclID, + bool isSingleP2POp, + const std::string& devicesKey, + int p2pRank); + + // Helper that allgathers nccl unique IDs to all ranks through the store + void allgatherUniqueNCCLIDs( + int rootIdx, + ncclUniqueId* ncclID, + std::vector& ncclIDs); + + // Helper that looks up the cached NCCL communicators only + std::shared_ptr getNCCLComm(const std::string& deviceKey); + + std::shared_ptr initNCCLComm( + const std::string& deviceKey, + at::Device& device, + OpType opType, + int p2pRank = 0, + bool isSendRecvSelf = false); + + // Initialize device-specific state (comm, stream, event, bookkeeping) for a + // given communicator on this process group instance. + void initializeDeviceStateForComm( + const at::Device& device, + std::shared_ptr comm); + + // Wrapper method which can be overridden for tests. + virtual std::exception_ptr checkForNCCLErrors( + std::shared_ptr& ncclComm); + + // Ensure thaht if record is True, the work obj will be enqueued via + // workEnqueue + virtual c10::intrusive_ptr initWork( + at::Device& device, + int rank, + OpType opType, + bool isP2P, + const char* profilingTitle = nullptr, + const std::vector& inputs = {}, + const std::vector& outputs = {}, + bool record = false); + + // In the timeout case and we will dump debug info such as the NCCL flight + // recorder to storage. Down the road, if we have more complicated or blocking + // operations, we might need to use a side thread to do it. + bool dumpDebuggingInfo( + bool includeStackTrace = true, + bool onlyActive = false); + + void dumpExtraDebuggingInfo(); + + // Abort all communicators on this rank. + bool abortComms(const std::optional& abortReason = std::nullopt); + + // A helper function to check if nonblocking API mode should be used. + // Use this helper instead of directly checking `useNonblocking_` variable. + bool useNonblocking(); + + protected: + int globalRankStart_{}; + int globalRankStride_{}; + + private: + bool eagerInit_{false}; + bool showSerializationWarning_{true}; + + // Helper that encapsulates work shared across all collective communication + // primitives. The callbacks have the following signatures: + // + // ncclResult_t fn(at::Tensor& input, at::Tensor& output, + // ncclComm_t, at::cuda::CUDAStream&); + // void {pre,post}(std::vector); + template + c10::intrusive_ptr collective( + at::Tensor& input, + at::Tensor& output, + Fn fn, + OpType opType, + bool asyncOp, + const char* profilingTitle = nullptr, + bool nanCheck = true); + + template + c10::intrusive_ptr collective( + at::Tensor& input, + at::Tensor& output, + Fn fn, + PreProcess pre, + PostProcess post, + OpType opType, + bool asyncOp, + const char* profilingTitle = nullptr, + bool nanCheck = true); + + template + c10::intrusive_ptr collective( + std::vector& inputs, + std::vector& outputs, + Fn fn, + PreProcess pre, + PostProcess post, + OpType opType, + bool asyncOp, + const char* profilingTitle = nullptr, + bool nanCheck = true); + + template + c10::intrusive_ptr collectiveCoalesced( + std::vector& input, + std::vector& output, + Fn fn, + OpType opType, + bool asyncOp, + const char* profilingTitle = nullptr); + + // Helper that encapsulates work shared across point-to-point communication + // primitives. It is the same structure as the helper used for collective + // communication primitives. + template + c10::intrusive_ptr pointToPoint( + at::Tensor& tensor, + Fn fn, + int peer, + OpType opType, + const char* profilingTitle = nullptr); + + template + c10::intrusive_ptr pointToPoint( + at::Tensor& tensor, + Fn fn, + int peer, + OpType opType, + PreProcess pre, + PostProcess post, + const char* profilingTitle); + + c10::intrusive_ptr allreduce_impl( + at::Tensor& tensor, + const char* profilingTitle = "nccl:all_reduce", + const AllreduceOptions& opts = AllreduceOptions()); + + // Checks for NCCL errors on each of the communicators and returns an + // appropriate exception_ptr (nullptr if no errors). + static std::exception_ptr checkForNCCLErrorsInternal( + std::shared_ptr& ncclComm); + + // Return the CUDA device most likely associated with this backend. + // If we aren't bound to a specific device, there is no strict + // guarantee that this heuristic is the correct assignment of ranks + // to GPUs that Python layers use, but in practice it tends to be. + // Fortunately we don't rely on this for correctness of any tensor + // operations, just for ancillary uses like barriers. + at::Device guessDeviceForRank() const; + + // Destroys initialized NCCL communicators in devNCCLComMap_ given by input + // key. Throws if there are no communicators to destroy. Also removes + // communicators from the cache and clears used device indices. + void destroyNCCLComms(const std::string& devNCCLCommMapKey); + + void runHookLoop(); + + // Generates a prefix that is unique to this process group and rank, for + // disambiguating logs + std::string createLogPrefix() const; + + // Returns the unique prefix created in createLogPrefix + const std::string& logPrefix() const; + + // Returns the global rank of the device. This function assumes that users + // always create a default global process group(PG) which includes all + // devices. It is called in the constructor of ProcessGroupNCCL, so it always + // return the rank_ of the very first PG created, aka, default global PG. + const int& globalRank() const; + + const c10::intrusive_ptr& globalStore() const; + + // Returns the global ranks of a PG. + const std::vector& groupRanks() const; + + // Util function to assign timeout to each work. + void assignTimeoutToWork( + const c10::intrusive_ptr& work, + const c10::intrusive_ptr& option); + + // Broadcast flight-recorder dump signal + void broadcastDumpSignal(); + + // A helper function to broadcast a signal (key) from a src rank to all other + // ranks using the specified store. + void broadcastSignal( + c10::intrusive_ptr& store, + const std::string& signal, + int srcRank); + + protected: + // Function that directly trigger std::abort so that the whole process + // gets terminated. + virtual void terminateProcess(const std::string& errMsg); + + // A helper function to wait for a future to complete or timeout. + // Returns true if the future completes before timeout, false otherwise. + bool waitForFutureOrTimeout( + std::future& fut, + const std::chrono::milliseconds& timeOutMilSec, + const std::string& futDescription, + ::c10d::C10dLoggingData& debugLog, + bool throwException = false); + + // A helper function to guess the device id of the current rank, based on + // bounded device or used device. Do not use this function if you already know + // the device id to operate on. + c10::DeviceIndex guessDeviceId() const; + + static const int64_t kWatchdogThreadSleepMillis; + + // The store is used to broadcast the NCCL unique ID of rank 0. This store + // comes with prefix and it is different across ProcessGroup NCCL instances + // (aka, different ProcessGroups). + c10::intrusive_ptr store_; + + // Reference to the store without prefix so that keys are same across all + // ProcessGroup NCCL instances and (key, value) pairs written to the store are + // global. + c10::intrusive_ptr globalStore_; + + // The lock which protects the write/read of + // ephemeralTimeoutActive_/ephemeralTimeoutInflight_. + // TODO(fduwjj): We need to have an audit on all mutexes we are adding here. + // And consolidate them if possible. + std::mutex mtxTimeoutExtension_; + + // The ephemeral timeout added on top of existing timeout for works issued + // before first work finishes. + std::chrono::milliseconds ephemeralTimeoutActive_ = + std::chrono::milliseconds(0); + + // The ephemeral timeout addition which has been already applied to work. + std::chrono::milliseconds ephemeralTimeoutInflight_ = + std::chrono::milliseconds(0); + + const c10::intrusive_ptr options_; + + // The number of NCCL communicators that have been created during + // the lifetime of this process group. This sequence number is + // used to scope keys used in the store. + uint64_t ncclCommCounter_{0}; + + // The NCCL communicator that the process group has cached. + // + // For collective operations: + // The key is a list of GPU devices that an operation is operating on + // The GPU devices are stored in a device sequence and the cache NCCL + // communicator is associated with this GPU device sequence + // + // e.g. If the process group op only uses device 0, then the value of + // the used device string stored (value of the hashmap) would be "0". + // + // If the process group op uses device 0 - 7 and the each tensor of the + // input tensor list is on device, 0, 1, 2, 3, 4, 5, 6, 7 separately, + // then the value of the used device string (key) stored would be + // "0,1,2,3,4,5,6,7" + // + // If the process group op uses device 0 - 7 and the each tensor of the + // input tensor list is on device, 0, 4, 5, 6, 7, 1, 2, 3 separately, + // then the value of the used device string stored would be + // "0,4,5,6,7,1,2,3" + // + // Note that the order of the device for the tensor list matters. + // + // For point-to-point operations: + // The key is a string of my current rank and the peer process rank. + // e.g. If process 1 and process 2 are involved in a point-to-point + // communication, the key will be "1:2" on both processes. Note: this is for + // the scenario where there is only 1 GPU per process. When it comes to + // multiple GPUs per process, this part may need to redesigned. + // TODO: we probably need a separate map for P2P comms + std::unordered_map> devNCCLCommMap_; + + // The NCCL communicators currently in process of being initialized. + std::unordered_map> + inInitializationCommMap_; + + // Mutex to guard maps like devNCCLCommMap_. + std::mutex mutex_; + + // Size of ring buffer where we store NCCL Traces for debugging. + int traceBufferSize_; + + // Stores TORCH_NCCL_DEBUG_INFO_PIPE_FILE + std::string debugInfoPipeFile_; + + // We gate the cudaEventCache so that we can roll it out gradually. + std::atomic cudaEventCacheEnabled_; + + std::thread onCompletionHookThread_; + + // Whether or not we should terminate the watchdog and workCleanup threads. + std::atomic terminateProcessGroup_; + + // Whether there are hooks pending to be fired + std::atomic hasPendingHooks_; + + // This is the signal from watchdog threads to indicate whether the monitor + // thread should dump. Making it static so that it is accessible from all the + // PGs. With this flag, monitor thread would dump debug info under any one of + // the three conditions: + // + // 1: watchdog thread of any PG detects a collective timeout. + // 2: timeout signal is received from other ranks through tcpstore. + // 3: current PG's watchdog heartbeat timeout occurs. + // + // Note that only the monitor thread from PG0 will dump the debug info for + // case one and two so that the debug info is only dumped once. + static std::atomic shouldDump_; + + // Mutex to Guard workMetaList_ + std::mutex workMetaListMutex_; + + bool writeDebugInfo_ = false; + + // Vector to store WorkNCCL pointers + std::list workMetaList_; + + // Mutex to Guard workMetaList_ + std::mutex completedWorkListMutex_; + + // Condition Variable for watchdog thread sleep + std::condition_variable completedWorkListCV_; + + std::list completedWorkList_; + + // Add Work Pointer to workVector + void workEnqueue( + const c10::intrusive_ptr& /*work*/); + + // The CUDA streams used by NCCL kernels + std::unordered_map ncclStreams_; + + // The CUDA events used to sync NCCL streams + std::unordered_map ncclEvents_; + + // Device Indexes used for all collectives in this group + std::set usedDeviceIdxs_; + + // Flag to denote if a coalescing groupStart/groupEnd block is active + int coalescing_state_ = 0; + + // Stores device indexes for all collectives run inside a coalescing block + at::Device coalescedDevice_ = at::Device("cuda"); + + // Stores communicators for all collectives run inside a coalescing block + std::shared_ptr coalescedComm_ = nullptr; + + // Whether the coalesced calls are sync or async. + bool coalescedAsync_{}; + + // keeps track of input and output tensors when coalescing is in flight. Will + // hand over these tensors to WorkNCCL's stash when coalescing is ended. + TensorShelf coalescedTensors_; + + // Some ops may have completed, but user still hasn't called `work.wait()`. + // When watchdog detects this, it transfers the TensorShelf from `work` to + // this `shelves` structure. Next time we execute ProcessGroupNCCL's methods + // on main thread, we clear the `shelves` in one shot. This is mainly because + // watchdog (a side thread) unstashing the shelf directly seems to cause some + // problem. + std::vector> shelvesToUnstash_; + std::mutex shelvesMutex_; + + // Whether or not wait() and synchronize() are blocking operations that wait + // for the operation to complete. + bool blockingWait_ = false; + + // Whether or not the workCleanupThread is used to perform async error + // handling. + ErrorHandlingMode asyncErrorHandling_ = NoHandling; + + ErrorType error_ = ErrorType::SUCCESS; + + std::mutex errorMutex_; + + // Whether or not to sleep after an exception is thrown in the watchdog. + bool sleepAfterException_{}; + + // Whether or not to enable nan check for input tensors to collectives. + bool enableNanCheck_; + + // Whether or not to create start CUDAEvent and enable timing for start + // and end events. Note that enableTiming_ is always true if desyncDebug_ + // is set to true. + std::atomic enableTiming_; + + // Flag to enable the print of hash value of input/output of collectives for + // verification. + std::atomic enableCollectiveHashDebug_; + + // Whether or not TORCH_NCCL_AVOID_RECORD_STREAMS was set + bool avoidRecordStreams_ = false; + + // The number of active ncclGroupStart() calls. This counter will be increased + // by 1 when ncclGroupStart() is called and decreased by 1 when ncclGroupEnd() + // is called. + static thread_local uint64_t ncclActiveGroupCounter_; + + // Counting for the sequential number of NCCL collective call. + // (specifically, how many actual kernels we launched, which differs from + // op_id_ when coalescing is enabled) + uint64_t seqCollective_{0}; + + // Counting for the sequential number of NCCL P2P calls. + uint64_t seqP2P_{0}; + + // Incrementing counter for logical operations (collective or p2p) issued on + // the ProcessGroup + uint64_t op_id_{0}; + + // The number of ProcessGroupNCCL created on the current rank. + size_t local_id_; + + std::string logPrefix_; + + c10::intrusive_ptr intraNodeComm_; + + // Number of devices on this node. + int localDeviceCount_{0}; + + std::shared_ptr pgStatus_ = + std::make_shared(); + + // Internal cached value: use NCCL non-blocking API mode or not. + // Use `useNonblocking()` method instead of accessing this variable directly. + std::optional useNonblocking_{std::nullopt}; + + // Communication-optimized memory pool associated with this PG + std::unique_ptr memPool_ = nullptr; +}; + +// Reset the flighrecorder recordings for the current rank. +TORCH_API void reset_nccl_trace(); + +// Dumps the NCCL comm traces and additional information about the Process +// Group. +TORCH_API std::string dump_nccl_trace( + bool includeCollectives, + bool includeStackTraces, + bool onlyActive); + +// Dumps the NCCL comm traces and additional information about the Process +// Group in JSON formatted string. +// We don't include stack traces in JSON format as it is far too much data. +TORCH_API std::string dump_nccl_trace_json( + bool includeCollectives, + bool onlyActive); + +// Gets a mutable reference to a global optional function.Heartbeat Monitor +// will use this function to dump traces, if available. Inside fbcode, we +// store a function here that uses an internal tool for process tracing +TORCH_API std::optional< + std::function)>>& +get_cpp_trace_dumper(); + +// Similar to get_cpp_trace_dumper, this stores a function defined in +// torch-python layer that lets us check whether the GIL can be acquired, +// helpful for instrumenting in cases where a hang was observed. +typedef bool (*gil_checker_t)(); + +TORCH_API gil_checker_t& get_gil_checker(); +} // namespace c10d + +#endif // USE_C10D_NCCL + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupUCC.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupUCC.hpp new file mode 100644 index 0000000000000000000000000000000000000000..12e737b61df23a0fc5503b60fc7a6136d311aaeb --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupUCC.hpp @@ -0,0 +1,363 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef USE_C10D_UCC + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#ifdef USE_CUDA +#include +#include +#endif + +namespace c10d { + +#define TORCH_UCC_DEVICE_NOT_SET -2 + +#ifdef USE_CUDA +#define SAVE_TENSORS(_TENSORS, _DATA) \ + do { \ + if ((_TENSORS)[0].device().is_cuda()) { \ + for (const auto i : c10::irange((_TENSORS).size())) { \ + c10::cuda::CUDACachingAllocator::recordStream( \ + (_TENSORS)[i].storage().data_ptr(), (*stream)); \ + } \ + } else { \ + (_DATA) = (_TENSORS); \ + } \ + } while (0) + +#else +#define SAVE_TENSORS(_TENSORS, _DATA) (_DATA) = (_TENSORS); +#endif + +constexpr const char* UCC_BACKEND_NAME = "ucc"; + +struct event_pool_t { +#ifdef USE_CUDA + std::queue> event_pool; +#endif + std::mutex event_pool_mutex; +}; + +class Comm; + +// UCC does not support multiple CUDA devices per process. +class TORCH_API ProcessGroupUCC : public Backend { + private: + void set_timeout(ucc_coll_args_t& args); + + public: + class WorkData { + public: + std::vector src; + std::vector dst; + std::vector flat; + WorkData() {} + virtual ~WorkData() = default; + }; + class AlltoallWorkData : public WorkData { + public: + AlltoallWorkData(int size) + : send_lengths(size), + send_offsets(size), + recv_lengths(size), + recv_offsets(size) {} + std::vector send_lengths; + std::vector send_offsets; + std::vector recv_lengths; + std::vector recv_offsets; + }; + + class AllgathervWorkData : public WorkData { + public: + AllgathervWorkData(int size) : recv_lengths(size), recv_offsets(size) {} + std::vector recv_lengths; + std::vector recv_offsets; + }; + + class ScattervWorkData : public WorkData { + public: + ScattervWorkData(int size) : send_lengths(size), send_offsets(size) {} + std::vector send_lengths; + std::vector send_offsets; + }; + + class ProgressEntry { + friend class ProcessGroupUCC; + friend class Comm; + + public: + ProgressEntry(CommBase* comm, ucc_coll_req_h request) + : status_(UCC_INPROGRESS), comm_(comm), request_(request) {} + // Finalizes UCC status or exception of collective request. + void finalize(std::exception_ptr eptr = nullptr); + ucc_status_t status_; + CommBase* comm_; + ucc_coll_req_h request_; + std::unique_ptr data; + c10::intrusive_ptr future_; + std::exception_ptr eptr_; + }; + + class WorkUCC : public Work { + friend class ProcessGroupUCC; + friend class Comm; + + public: + WorkUCC( + OpType opType, + uint64_t seq, + const char* prof_title, + const std::optional>& inputs, + const c10::intrusive_ptr& logger) + : Work(-1, opType, prof_title, inputs), logger_(logger), seq_(seq) {} + ~WorkUCC(); + void setException(); + void setAndThrowException(); + bool isCompleted() override; + bool isSuccess() const override; + bool wait(std::chrono::milliseconds timeout = kUnsetTimeout) override; + c10::intrusive_ptr getFuture() override; + std::vector result() override; + int sourceRank() const override; +#ifdef USE_CUDA + std::unique_ptr fence = nullptr; + event_pool_t* ep = nullptr; +#endif + int sourceRank_; + + protected: + std::shared_ptr entry_; + c10::intrusive_ptr logger_; + uint64_t seq_; + + private: + // The future returned by getFuture. + c10::intrusive_ptr future_; + // Store a reference to collective's outputs, used by result + std::shared_ptr> outputs_; + }; + + explicit ProcessGroupUCC( + const c10::intrusive_ptr& store, + int rank = -1, + int size = -1, + std::chrono::duration timeout = kBackendDefaultTimeout); + + void initComm(c10::Device dev); + + ~ProcessGroupUCC() override; + + const std::string getBackendName() const override { + return std::string(UCC_BACKEND_NAME); + } + +#ifdef USE_CUDA + std::unique_ptr getPooledEvent(); +#endif + + // Performs a health check by initializing dummy UCC & UCX communicators and + // then destroying them. This will help indicate and signal any + // UCC/UCX-related issues prior to the first collective. The actual + // initialization and subsequent destruction is ran on a separate thread and + // the main thread is signalled about timeouts/errors to report to the + // application. + void runHealthCheck(); + + template + c10::intrusive_ptr collective_post( + OpType opType, + PreProcess preproc, + PostProcess postproc, + ucc_coll_args_t& coll, + std::unique_ptr data, + c10::Device dev, + std::vector& inputTensors, + std::vector& outputTensors, + const char* prof_title); + + c10::intrusive_ptr broadcast( + std::vector& data, + const BroadcastOptions& opts = BroadcastOptions()) override; + + c10::intrusive_ptr allreduce( + std::vector& tensors, + const AllreduceOptions& opts = AllreduceOptions()) override; + + c10::intrusive_ptr allreduce_coalesced( + std::vector& tensors, + const AllreduceCoalescedOptions& opts = + AllreduceCoalescedOptions()) override; + + c10::intrusive_ptr reduce( + std::vector& tensors, + const ReduceOptions& opts = ReduceOptions()) override; + + c10::intrusive_ptr allgather( + std::vector>& outputTensors, + std::vector& inputTensors, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr _allgather_base( + at::Tensor& outputBuffer, + at::Tensor& inputBuffer, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr barrier( + const BarrierOptions& opts = BarrierOptions()) override; + + c10::intrusive_ptr gather( + std::vector>& outputTensors, + std::vector& inputTensors, + const GatherOptions& opts = GatherOptions()) override; + + c10::intrusive_ptr scatter( + std::vector& outputTensors, + std::vector>& inputTensors, + const ScatterOptions& opts = ScatterOptions()) override; + + c10::intrusive_ptr reduce_scatter( + std::vector& outputTensors, + std::vector>& inputTensors, + const ReduceScatterOptions& opts = ReduceScatterOptions()) override; + + c10::intrusive_ptr _reduce_scatter_base( + at::Tensor& outputTensor, + at::Tensor& inputTensor, + const ReduceScatterOptions& opts = ReduceScatterOptions()) override; + + c10::intrusive_ptr alltoall_base( + at::Tensor& outputTensor, + at::Tensor& inputTensor, + std::vector& outputSplitSizes, + std::vector& inputSplitSizes, + const AllToAllOptions& opts = AllToAllOptions()) override; + + c10::intrusive_ptr alltoall( + std::vector& outputTensors, + std::vector& inputTensors, + const AllToAllOptions& opts = AllToAllOptions()) override; + + c10::intrusive_ptr send( + std::vector& tensors, + int dstRank, + int tag) override; + + c10::intrusive_ptr recv( + std::vector& tensors, + int srcRank, + int tag) override; + + // Counting for the sequential number of UCC collective_post call. + uint64_t seq_{0}; + + // Agrees on an initial sequence number for the whole group by having rank 0 + // create it and broadcast it to other ranks using the store. + void setSequenceNumberForGroup() override; + + // Retrieves the current sequence number for the whole group, which should be + // in sync. If the returned number is not consistent across the group, it + // may indicate that there is some sort of collective desynchronization. + uint64_t getSequenceNumberForGroup() override; + + static c10::intrusive_ptr createProcessGroupUCC( + const c10::intrusive_ptr<::c10d::Store>& store, + int rank, + int size, + const std::chrono::duration& timeout); + + protected: + const std::chrono::duration timeout_; + std::shared_ptr oob; + std::shared_ptr comm = {nullptr}; + uint32_t comm_id; + ucc_team_h team{nullptr}; + ucc_ee_h cuda_ee{nullptr}; + ucc_ee_h cuda_ee_p2p[2]{nullptr, nullptr}; + +#ifdef USE_CUDA + std::unique_ptr stream = nullptr; + std::unique_ptr stream_p2p[2] = {nullptr, nullptr}; + event_pool_t ep; +#endif + c10::intrusive_ptr logger; +}; + +class Comm { + c10::intrusive_ptr logger; + std::shared_ptr oob; + CommUCC ucc_comm; + std::mutex mutex; + std::thread progress_thread; + std::condition_variable queue_produce_cv; + std::condition_variable queue_consume_cv; + std::deque> progress_queue; + bool stop_progress_loop; + bool collective_inprogress; + torch_ucc_phase_t finalize_phase; + + public: + c10::DeviceIndex cuda_device_index; + Comm( + const c10::intrusive_ptr& logger, + std::shared_ptr oob, + c10::Device dev, + bool is_health_check); + + ~Comm(); + + void ucc_create_team( + ucc_team_h& team, + std::shared_ptr oob); + + void ucc_destroy_team(ucc_team_h& team); + + c10::intrusive_ptr enqueue_p2p( + OpType opType, + ucc_coll_req_h request, + const char* prof_title); + +#ifdef USE_CUDA + void enqueue_cuda_collective( + std::unique_ptr data, + c10::intrusive_ptr work, + ucc_coll_args_t& coll, + ucc_team_h team, + ucc_ee_h ee); +#endif + + void enqueue_collective( + std::unique_ptr data, + c10::intrusive_ptr work, + ucc_coll_args_t& coll, + ucc_team_h team); + + static std::shared_ptr get_comm( + uint32_t& id, + c10::Device dev, + std::shared_ptr oob, + const c10::intrusive_ptr& logger, + bool is_health_check = false); + + void progress_loop(); +}; + +} // namespace c10d + +#endif // USE_C10D_UCC + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupWrapper.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupWrapper.hpp new file mode 100644 index 0000000000000000000000000000000000000000..71f2ffed254a8441143bd0ecf3f921984f9dedf6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/ProcessGroupWrapper.hpp @@ -0,0 +1,204 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef USE_C10D_GLOO + +#include +#include +#include + +namespace c10d { + +// ProcessGroupWrapper wraps a Backend for debugging purposes. It intercepts +// collective operations to verify consistency across ranks before dispatching +// to the wrapped backend. +// +// IMPORTANT: This wrapper must forward all Backend virtual methods to backend_. +// When adding new virtual methods to Backend that are overridden by backends +// like ProcessGroupNCCL, you must also add forwarding methods here. Otherwise, +// those methods will fail when TORCH_DISTRIBUTED_DEBUG=DETAIL is set. +// See https://github.com/pytorch/pytorch/issues/173538 for an example. +class TORCH_API ProcessGroupWrapper : public Backend { + public: + explicit ProcessGroupWrapper( + const c10::intrusive_ptr& backend, + c10::intrusive_ptr glooBackend); + + c10::intrusive_ptr broadcast( + std::vector& data, + const BroadcastOptions& opts = BroadcastOptions()) override; + + c10::intrusive_ptr allreduce( + std::vector& data, + const AllreduceOptions& opts = AllreduceOptions()) override; + + c10::intrusive_ptr allreduce_sparse( + std::vector& tensors, + const AllreduceOptions& opts = AllreduceOptions()) override; + + c10::intrusive_ptr allreduce_coalesced( + std::vector& tensors, + const AllreduceCoalescedOptions& opts = + AllreduceCoalescedOptions()) override; + + c10::intrusive_ptr reduce( + std::vector& tensors, + const ReduceOptions& opts = ReduceOptions()) override; + + c10::intrusive_ptr allgather( + std::vector>& outputTensors, + std::vector& inputTensors, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr _allgather_base( + at::Tensor& outputBuffer, + at::Tensor& inputBuffer, + const AllgatherOptions& opts = AllgatherOptions()) override; + + // This function is deprecated and will be moved out of ProcessGroup to comms: + // * do not add dependencies on this function, + // * do not implement it in your ProcessGroup, implement _allgather_base + // instead. + c10::intrusive_ptr allgather_coalesced( + std::vector>& outputTensorLists, + std::vector& inputTensors, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr allgather_into_tensor_coalesced( + std::vector& outputs, + std::vector& inputs, + const AllgatherOptions& opts = AllgatherOptions()) override; + + c10::intrusive_ptr gather( + std::vector>& outputTensors, + std::vector& inputTensors, + const GatherOptions& opts = GatherOptions()) override; + + c10::intrusive_ptr scatter( + std::vector& outputTensors, + std::vector>& inputTensors, + const ScatterOptions& opts = ScatterOptions()) override; + + c10::intrusive_ptr reduce_scatter( + std::vector& outputTensors, + std::vector>& inputTensors, + const ReduceScatterOptions& opts = ReduceScatterOptions()) override; + + c10::intrusive_ptr _reduce_scatter_base( + at::Tensor& inputBuffer, + at::Tensor& outputBuffer, + const ReduceScatterOptions& opts = ReduceScatterOptions()) override; + + c10::intrusive_ptr reduce_scatter_tensor_coalesced( + std::vector& outputs, + std::vector& inputs, + const ReduceScatterOptions& opts = ReduceScatterOptions()) override; + + c10::intrusive_ptr alltoall_base( + at::Tensor& outputTensor, + at::Tensor& inputTensor, + std::vector& outputSplitSizes, + std::vector& inputSplitSizes, + const AllToAllOptions& opts = AllToAllOptions()) override; + + c10::intrusive_ptr alltoall( + std::vector& outputTensors, + std::vector& inputTensors, + const AllToAllOptions& opts = AllToAllOptions()) override; + + void monitoredBarrier(const BarrierOptions& opts, bool waitAllRanks = false) + override; + + // Agrees on an initial sequence number for the whole group by having rank 0 + // create it and broadcast it to other ranks using the store. Only implemented + // for GLOO and NCCL backends currently. + // dont implement this + void setSequenceNumberForGroup() override; + + // Retrieves the current sequence number for the whole group, which should be + // in sync. If the returned number is not consistent across the group, it + // may indicate that there is some sort of collective desynchronization. + uint64_t getSequenceNumberForGroup() override; // just call underlying + + c10::intrusive_ptr send( + std::vector& tensors, + int dstRank, + int tag) override; + + c10::intrusive_ptr recv( + std::vector& tensors, + int srcRank, + int tag) override; + + c10::intrusive_ptr recvAnysource( + std::vector& tensors, + int tag) override; + + c10::intrusive_ptr barrier( + const BarrierOptions& opts = BarrierOptions()) override; + void registerOnCompletionHook( + std::function)>&& hook) override; + + void waitForPendingWorks() override; + void enableCollectivesTiming() override; + + c10::intrusive_ptr split( + const c10::intrusive_ptr& store, + const std::vector& ranks, + const c10::intrusive_ptr& opts) override; + + c10::intrusive_ptr merge( + const c10::intrusive_ptr& store, + const c10::intrusive_ptr& opts, + const int& rank, + const int& size) override; + + // Forward methods to wrapped backend + bool supportsSplitting() const override; + bool supportsCoalescing() const override; + bool supportsTimeEstimation() const override; + bool supportsShrinking() const override; + c10::intrusive_ptr shrink( + const std::vector& ranks_to_exclude, + int shrink_flags = 0, + const c10::intrusive_ptr& opts_override = nullptr) override; + void setTimeout(std::chrono::milliseconds timeout) override; + void startCoalescing() override; + c10::intrusive_ptr endCoalescing() override; + const std::string getBackendName() const override; + c10::intrusive_ptr getBackendOptions() override; + std::shared_ptr getMemAllocator() override; + at::Tensor allocateTensor(long size, at::TensorOptions options = {}) override; + bool supportsTensorAlloc(c10::DeviceIndex deviceIdx) override; + void abort() override; + void shutdown() override; + void suspend() override; + void resume() override; + std::unordered_map getMemoryStats() override; + + ErrorType getError() override; + void eagerConnectSingleDevice(at::Device device) override; + + c10::intrusive_ptr getWrappedPg() const; + + private: + // Underlying process group that actual application collectives will be + // dispatched to + c10::intrusive_ptr backend_; + // Gloo process group responsible for internal coordination such as monitored + // barrier, sequence number checking, collective fingerprint collecting. + c10::intrusive_ptr glooBackend_; + // Conducts several checks to ensure that the underlying collective is well + // formed with the goal of notifying the user about incorrect collective use + // in the application. + void runCollectiveChecks( + OpType op_type, + const std::vector& tensors); +}; +} // namespace c10d + +#endif // USE_C10D_GLOO + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/PyProcessGroup.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/PyProcessGroup.hpp new file mode 100644 index 0000000000000000000000000000000000000000..dd974d19037a5e7ae362dd5c4218c4bfcf4ea34f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/PyProcessGroup.hpp @@ -0,0 +1,361 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace c10d { + +// PyProcessGroup is a pybind11 trampoline class to allow a Python +// class to inherit from torch.distributed.ProcessGroup +class PyProcessGroup : public ProcessGroup { + public: + // PyWork is a pybind11 trampoline class to allow a Python + // class to inherit from torch.distributed.Work + class TORCH_PYTHON_API PyWork : public Work { + public: + PyWork() = default; + + bool wait(std::chrono::milliseconds timeout = kNoTimeout) override { + PYBIND11_OVERRIDE( + bool, /* Return type */ + Work, /* Parent class */ + wait, /* Name of function in C++ */ + timeout); + } + + c10::intrusive_ptr getFuture() override { + // We cannot use PYBIND11_OVERRIDE because: + // 1. We have to >MANUALLY< unwrap the PyFutureWrapper and + // 2. The python name is get_future + pybind11::gil_scoped_acquire gil; + auto override = + pybind11::get_override(static_cast(this), "get_future"); + + if (override) { + py::object o = override(); + auto futWrapper = + o.cast>(); + return futWrapper->fut; + } + + return Work::getFuture(); + } + }; + +#define WORK_OVERRIDE(cname, name, ...) \ + do { \ + pybind11::gil_scoped_acquire gil; \ + pybind11::function override = \ + pybind11::get_override(static_cast(this), #name); \ + if (override) { \ + auto o = override(__VA_ARGS__); \ + return c10::make_intrusive(o); \ + } \ + return cname::name(__VA_ARGS__); \ + } while (false) + + // This class is used to wrap a PyWork trampoline with it's corresponding + // Python object to prevent the Python object from being garbage collected. + class PyWorkHolder : public Work { + public: + PyWorkHolder(const c10::intrusive_ptr& work, py::object pyWork) + : work_(work), pyWork_(std::move(pyWork)) {} + + PyWorkHolder(py::object pyWork) + : work_(pyWork.cast>()), + pyWork_(std::move(pyWork)) {} + + ~PyWorkHolder() override { + // GIL must be held when freeing python objects. + py::gil_scoped_acquire gil; + pyWork_ = py::object(); + } + + bool wait(std::chrono::milliseconds timeout = kNoTimeout) override { + return work_->wait(timeout); + } + + c10::intrusive_ptr getFuture() override { + return work_->getFuture(); + } + + private: + c10::intrusive_ptr work_; + py::object pyWork_; + }; + + using ProcessGroup::ProcessGroup; + + const std::string getBackendName() const override { + PYBIND11_OVERRIDE( + std::string, /* Return type */ + ProcessGroup, /* Parent class */ + getBackendName, /* Name of function in C++ */ + ); + } + + int getRank() const override { + PYBIND11_OVERRIDE( + int, /* Return type */ + ProcessGroup, /* Parent class */ + getRank, /* Name of function in C++ */ + ); + } + + int getSize() const override { + PYBIND11_OVERRIDE( + int, /* Return type */ + ProcessGroup, /* Parent class */ + getSize, /* Name of function in C++ */ + ); + } + + void abort() override { + PYBIND11_OVERRIDE( + void, /* Return type */ + ProcessGroup, /* Parent class */ + abort, /* Name of function in C++ */ + ); + } + + const std::string& getGroupName() const override { + PYBIND11_OVERRIDE( + const std::string&, /* Return type */ + ProcessGroup, /* Parent class */ + getGroupName, /* Name of function in C++ */ + ); + } + + void setGroupName(const std::string& group_name) override { + PYBIND11_OVERRIDE( + void, /* Return type */ + ProcessGroup, /* Parent class */ + setGroupName, /* Name of function in C++ */ + group_name); + } + + const std::string& getGroupDesc() const override { + PYBIND11_OVERRIDE( + const std::string&, /* Return type */ + ProcessGroup, /* Parent class */ + getGroupDesc, /* Name of function in C++ */ + ); + } + + void setGroupDesc(const std::string& group_desc) override { + PYBIND11_OVERRIDE( + void, /* Return type */ + ProcessGroup, /* Parent class */ + setGroupDesc, /* Name of function in C++ */ + group_desc); + } + + c10::intrusive_ptr splitGroup( + const std::vector& ranks, + const std::optional& timeout, + const std::optional>& opts, + const std::optional& group_name, + const std::optional& group_desc) override { + PYBIND11_OVERRIDE( + c10::intrusive_ptr, /* Return type */ + ProcessGroup, /* Parent class */ + splitGroup, /* Name of function in C++ */ + ranks, + timeout, + opts, + group_name, + group_desc); + } + + c10::intrusive_ptr mergeRemoteGroup( + const c10::intrusive_ptr& store, + const MergeOptions& opts, + const int& size) override { + PYBIND11_OVERRIDE( + c10::intrusive_ptr, /* Return type */ + ProcessGroup, /* Parent class */ + mergeRemoteGroup, /* Name of function in C++ */ + store, + opts, + size); + } + + c10::intrusive_ptr allgather( + std::vector>& outputTensors, + std::vector& inputTensors, + const AllgatherOptions& opts = AllgatherOptions()) override { + WORK_OVERRIDE( + ProcessGroup, /* Parent class */ + allgather, /* Name of function in C++ */ + outputTensors, + inputTensors, + opts); + } + + c10::intrusive_ptr allgather_into_tensor_coalesced( + std::vector& outputTensors, + std::vector& inputTensors, + const AllgatherOptions& opts = AllgatherOptions()) override { + WORK_OVERRIDE( + ProcessGroup, /* Parent class */ + allgather_into_tensor_coalesced, /* Name of function in C++ */ + outputTensors, + inputTensors, + opts); + } + + c10::intrusive_ptr allreduce( + std::vector& tensors, + const AllreduceOptions& opts = AllreduceOptions()) override { + WORK_OVERRIDE( + // py::object, /* Return type */ + ProcessGroup, /* Parent class */ + allreduce, /* Name of function in C++ */ + tensors, + opts); + } + + c10::intrusive_ptr allreduce_coalesced( + std::vector& tensors, + const AllreduceCoalescedOptions& opts = + AllreduceCoalescedOptions()) override { + WORK_OVERRIDE( + ProcessGroup, /* Parent class */ + allreduce_coalesced, /* Name of function in C++ */ + tensors, + opts); + } + + c10::intrusive_ptr alltoall_base( + at::Tensor& outputBuffer, + at::Tensor& inputBuffer, + std::vector& outputSplitSizes, + std::vector& inputSplitSizes, + const AllToAllOptions& opts = AllToAllOptions()) override { + WORK_OVERRIDE( + ProcessGroup, /* Parent class */ + alltoall_base, /* Name of function in C++ */ + outputBuffer, + inputBuffer, + outputSplitSizes, + inputSplitSizes, + opts); + } + + c10::intrusive_ptr barrier( + const BarrierOptions& opts = BarrierOptions()) override { + WORK_OVERRIDE( + ProcessGroup, /* Parent class */ + barrier, /* Name of function in C++ */ + opts); + } + + c10::intrusive_ptr broadcast( + std::vector& tensors, + const BroadcastOptions& opts = BroadcastOptions()) override { + WORK_OVERRIDE( + ProcessGroup, /* Parent class */ + broadcast, /* Name of function in C++ */ + tensors, + opts); + } + + c10::intrusive_ptr reduce_scatter( + std::vector& outputTensors, + std::vector>& inputTensors, + const ReduceScatterOptions& opts = ReduceScatterOptions()) override { + WORK_OVERRIDE( + ProcessGroup, /* Parent class */ + reduce_scatter, /* Name of function in C++ */ + outputTensors, + inputTensors, + opts); + } + + c10::intrusive_ptr reduce_scatter_tensor_coalesced( + std::vector& outputTensors, + std::vector& inputTensors, + const ReduceScatterOptions& opts = ReduceScatterOptions()) override { + WORK_OVERRIDE( + ProcessGroup, /* Parent class */ + reduce_scatter_tensor_coalesced, /* Name of function in C++ */ + outputTensors, + inputTensors, + opts); + } + + c10::intrusive_ptr send( + std::vector& tensors, + int dstRank, + int tag) override { + WORK_OVERRIDE( + ProcessGroup, /* Parent class */ + send, /* Name of function in C++ */ + tensors, + dstRank, + tag); + } + + c10::intrusive_ptr recv( + std::vector& tensors, + int srcRank, + int tag) override { + WORK_OVERRIDE( + ProcessGroup, /* Parent class */ + recv, /* Name of function in C++ */ + tensors, + srcRank, + tag); + } +}; + +class TORCH_PYTHON_API PythonOnCompletionHook { + public: + // Wraps a py::object hook and acquires Python GIL in dtor before + // destructing the hook object. + PythonOnCompletionHook(py::object hook) : hook_(std::move(hook)) {} + PythonOnCompletionHook(const PythonOnCompletionHook&) = default; + + // NOLINTNEXTLINE(bugprone-exception-escape) + ~PythonOnCompletionHook() { + py::gil_scoped_acquire ag; + hook_.dec_ref(); + // Explicitly set hook_ to nullptr to prevent py::object's dtor + // to decref on the PyObject again. + // See Note [Destructing py::object] in python_ivalue.h + hook_.ptr() = nullptr; + } + + void operator()(const std::shared_ptr& workInfo) const { + std::exception_ptr eptr; + { + py::gil_scoped_acquire acquire; + try { + hook_(workInfo); + } catch (py::error_already_set& e) { + // py::error_already_set requires GIL to destruct, take + // special care. + eptr = std::make_exception_ptr(std::runtime_error(e.what())); + e.restore(); + PyErr_Clear(); + } catch (std::exception&) { + eptr = std::current_exception(); + } + } + // No more Python-related stuff at this point, i.e., this + // exception can be captured and handled by PG backend. + if (eptr) + std::rethrow_exception(eptr); + } + + private: + py::object hook_; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/RankLocal.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/RankLocal.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fbbde7e8ee787a1287dfe173f14128cf53e9c622 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/RankLocal.hpp @@ -0,0 +1,94 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) + +#pragma once + +#include + +#include + +namespace c10d { + +// `RankLocal` maintains a unique instance of T for each non-autograd thread. +// For non-autograd threads, `RankLocal::get()` functions similar to +// thread_local. For autograd threads, `RankLocal::get()` returns the +// instance of T corresponding to the enqueuing non-autograd thread. The +// mechanism allows for rank-specific context shared between forward and +// backward. It works for both the one-rank-per-process and one-rank-per-thread +// scenarios. +// +// NOTE: RankLocal doesn't make the underlying objects thread-safe. +template +class RankLocal { + public: + RankLocal(const RankLocal&) = delete; + RankLocal& operator=(const RankLocal&) = delete; + + static T& get() { + // Fast path: non-autograd threads can simply return + // the object reference cached in TLS. + if (cached_ != nullptr) { + return *cached_; + } + const auto node = torch::autograd::get_current_node(); + auto fwd_thread_id = node == nullptr ? at::RecordFunction::currentThreadId() + : node->thread_id(); + // Optimistically acquire the read lock first, since most likely we are in + // an autograd thread and the object has already been constructed. + { + std::shared_lock read_lock(lock_); + auto it = thread_id_to_rank_local_.find(fwd_thread_id); + if (it != thread_id_to_rank_local_.end()) { + // Cache for non-autograd threads + if (node == nullptr) { + cached_ = &it->second; + } + return it->second; + } + } + + std::unique_lock write_lock(lock_); + auto [it, _] = thread_id_to_rank_local_.try_emplace(fwd_thread_id); + // Cache for non-autograd threads + if (node == nullptr) { + cached_ = &it->second; + } + return it->second; + } + + // Apply a function to all thread-local instances and return the first + // non-empty result. This is useful for cross-thread lookups when we need + // to find data that may have been registered on a different thread. + // The function should have signature: std::optional(T&) + template + static auto find_across_all(F&& func) -> decltype(func(std::declval())) { + std::shared_lock read_lock(lock_); + for (auto& [thread_id, instance] : thread_id_to_rank_local_) { + auto result = func(instance); + if (result) { + return result; + } + } + return decltype(func(std::declval()))(); + } + + private: + RankLocal() = default; + thread_local static T* cached_; + static std::unordered_map thread_id_to_rank_local_; + static std::shared_mutex lock_; +}; + +template +thread_local T* RankLocal::cached_ = nullptr; + +template +std::unordered_map RankLocal::thread_id_to_rank_local_; + +template +std::shared_mutex RankLocal::lock_; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Store.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Store.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d3a30355e12486bb302a9172caaf8d5f7cf8f283 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Store.hpp @@ -0,0 +1,172 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace c10d { + +// callback function will be given arguments (std::optional oldValue, +// std::optional newValue) +using WatchKeyCallback = + std::function, std::optional)>; + +class TORCH_API Store : public torch::CustomClassHolder { + public: + static constexpr std::chrono::milliseconds kDefaultTimeout = + std::chrono::seconds(300); + static constexpr std::chrono::milliseconds kNoTimeout = + std::chrono::milliseconds::zero(); + + Store() : timeout_(kDefaultTimeout) {} + + explicit Store(const std::chrono::milliseconds& timeout) + : timeout_(timeout) {} + + Store(const Store&) = default; + Store(Store&&) noexcept = default; + + ~Store() override = default; + + // Clone a thread safe copy of this store object that points to the same + // underlying store. + virtual c10::intrusive_ptr clone() = 0; + + void set(const std::string& key, const std::string& value); + + virtual void set( + const std::string& key, + const std::vector& value) = 0; + + std::string compareSet( + const std::string& key, + const std::string& currentValue, + const std::string& newValue); + + virtual std::vector compareSet( + const std::string& key, + const std::vector& currentValue, + const std::vector& newValue) { + C10_THROW_ERROR(NotImplementedError, "Not implemented."); + } + + std::string get_to_str(const std::string& key); + + virtual std::vector get(const std::string& key) = 0; + + virtual int64_t add(const std::string& key, int64_t value) = 0; + + virtual bool deleteKey(const std::string& key) = 0; + + virtual bool check(const std::vector& keys) = 0; + + virtual int64_t getNumKeys() = 0; + + virtual void wait(const std::vector& keys) = 0; + + virtual void wait( + const std::vector& keys, + const std::chrono::milliseconds& timeout) = 0; + + virtual const std::chrono::milliseconds& getTimeout() const noexcept; + + virtual void setTimeout(const std::chrono::milliseconds& timeout); + + // watchKey() is deprecated and no longer supported. + virtual void watchKey( + const std::string& /* unused */, + // NOLINTNEXTLINE(performance-unnecessary-value-param) + WatchKeyCallback /* unused */) { + C10_THROW_ERROR( + NotImplementedError, + "watchKey is deprecated, no implementation support it."); + } + + virtual void append( + const std::string& key, + const std::vector& value); + + virtual std::vector> multiGet( + const std::vector& keys); + + virtual void multiSet( + const std::vector& keys, + const std::vector>& values); + + // Returns true if this store support append, multiGet and multiSet + virtual bool hasExtendedApi() const; + + virtual void queuePush( + const std::string& key, + const std::vector& value) { + C10_THROW_ERROR(NotImplementedError, "queue support is not implemented."); + } + + virtual std::vector queuePop(const std::string& key, bool block) { + C10_THROW_ERROR(NotImplementedError, "queue support is not implemented."); + } + + virtual int64_t queueLen(const std::string& key) { + C10_THROW_ERROR(NotImplementedError, "queue support is not implemented."); + } + + virtual std::vector listKeys() { + C10_THROW_ERROR( + NotImplementedError, "listKeys support is not implemented."); + } + + // Barrier operation that blocks until world_size workers have reached it. + // This is an optimized operation that combines increment and wait into a + // single operation, reducing network round trips compared to using + // separate add() and wait() calls. + virtual void barrier( + const std::string& key, + int64_t world_size, + const std::chrono::milliseconds& timeout); + + void barrier(const std::string& key, int64_t world_size) { + barrier(key, world_size, timeout_); + } + + protected: + std::chrono::milliseconds timeout_; +}; + +/* +StoreTimeoutGuard is a RAII guard that will set the store timeout and restore it +when it returns. +*/ +class StoreTimeoutGuard { + public: + explicit StoreTimeoutGuard( + Store& store, + const std::chrono::milliseconds& timeout) + : store_(store), oldTimeout_(store.getTimeout()) { + store.setTimeout(timeout); + } + + ~StoreTimeoutGuard() { + store_.setTimeout(oldTimeout_); + } + + /* Disabling copy and move semantics */ + StoreTimeoutGuard(const StoreTimeoutGuard&) = delete; + StoreTimeoutGuard& operator=(const StoreTimeoutGuard&) = delete; + StoreTimeoutGuard(StoreTimeoutGuard&&) = delete; + StoreTimeoutGuard& operator=(StoreTimeoutGuard&&) = delete; + + private: + Store& store_; + std::chrono::milliseconds oldTimeout_{}; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/TCPStore.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/TCPStore.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2b3bec0f2fbb045cd227911a919e74d81ea5e67a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/TCPStore.hpp @@ -0,0 +1,181 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include + +namespace c10d { +namespace detail { + +// TCPStore is a key-value store used by PyTorch mainly for distributed +// rendezvous, but for other purposes as well. (e.g., a centralized storage for +// synchronization among different processes.) +// +// It is run via a classic client-server architecture, where the server runs +// a separate background thread (alternatively we call it daemon thread). The +// client and server communicate via TCP sockets. +// +// Currently we have two types of server backends: +// 1. TCPStoreBackend: a single thread to handle all incoming request +// synchronously. +// 2. LibUVTCPStoreBackend: an event-driven asynchronous stream processing that +// leverages libuv library (https://github.com/libuv/libuv) for better +// performance. And this backend now is recommended to users. (We set the +// default value of `useLibUV` inside `TCPStoreOptions` to true now, so users +// should get it by default). +// +// Code structure: +// ├── TCPStore client side API and server setup code: +// │ TCPStore.hpp/TCPStore.cpp +// ├── TCPStoreBackend server side API implementation code: +// │ TCPStoreBackend.hpp/TCPStoreBackend.cpp +// | (actual class:`TCPStoreMasterDaemon`) +// ├── LibUVTCPStoreBackend +// │ TCPStoreLibUvBackend.cpp +// | (actual class: `LibUVStoreDaemon`) + +class TCPServer; + +class TCPClient; + +struct SocketAddress { + std::string host; + std::uint16_t port{}; +}; + +} // namespace detail + +struct TCPStoreOptions { + static constexpr std::uint16_t kDefaultPort = 29500; + + std::uint16_t port = kDefaultPort; + bool isServer = false; + std::optional numWorkers = std::nullopt; + bool waitWorkers = true; + std::chrono::milliseconds timeout = Store::kDefaultTimeout; + + // A boolean value indicating whether multiple store instances can be + // initialized with the same host:port pair. + bool multiTenant = false; + + // If specified, and if isServer is true, the underlying TCPServer will take + // over the bound socket associated to this fd. This option is useful to avoid + // port assignment races in certain scenarios. + std::optional masterListenFd = std::nullopt; + + // A boolean value indicating whether to use the experimental libUV backend. + bool useLibUV = true; +}; + +class TORCH_API TCPStore : public Store { + public: + static constexpr std::chrono::milliseconds kConnectRetryDelay{1000}; + + explicit TCPStore(std::string host, const TCPStoreOptions& opts = {}); + + ~TCPStore() override; + + c10::intrusive_ptr clone() override; + + void set(const std::string& key, const std::vector& value) override; + + std::vector compareSet( + const std::string& key, + const std::vector& expectedValue, + const std::vector& desiredValue) override; + + std::vector get(const std::string& key) override; + + int64_t add(const std::string& key, int64_t value) override; + + bool deleteKey(const std::string& key) override; + + bool check(const std::vector& keys) override; + + int64_t getNumKeys() override; + + void wait(const std::vector& keys) override; + + void wait( + const std::vector& keys, + const std::chrono::milliseconds& timeout) override; + + void append(const std::string& key, const std::vector& value) + override; + + std::vector> multiGet( + const std::vector& keys) override; + + void multiSet( + const std::vector& keys, + const std::vector>& values) override; + + bool hasExtendedApi() const override; + + void queuePush(const std::string& key, const std::vector& value) + override; + + std::vector queuePop(const std::string& key, bool block) override; + + int64_t queueLen(const std::string& key) override; + + std::vector listKeys() override; + + void barrier( + const std::string& key, + int64_t world_size, + const std::chrono::milliseconds& timeout) override; + + // Waits for all workers to join. + void waitForWorkers(); + + // Returns the hostname used by the TCPStore. + const std::string& getHost() const noexcept { + return addr_.host; + } + + // Returns the port used by the TCPStore. + std::uint16_t getPort() const noexcept { + return addr_.port; + } + + bool isLibUvBackend() const noexcept { + return usingLibUv_; + } + + // note(xilunwu): this function is only for internal testing + void _splitSet(const std::string& key, const std::vector& data); + + std::string repr() const; + + private: + int64_t incrementValueBy(const std::string& key, int64_t delta); + + void ping(); + void validate(); + + std::vector doGet(const std::string& key); + + void doWait( + c10::ArrayRef keys, + std::chrono::milliseconds timeout); + + detail::SocketAddress addr_; + std::shared_ptr server_; + std::unique_ptr client_; + std::optional numWorkers_; + + const std::string initKey_ = "init/"; + const std::string keyPrefix_ = "/"; + std::mutex activeOpLock_; + bool usingLibUv_ = true; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/TCPStoreBackend.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/TCPStoreBackend.hpp new file mode 100644 index 0000000000000000000000000000000000000000..531f4bdd2e3dd93751a835148225453bbe218ee1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/TCPStoreBackend.hpp @@ -0,0 +1,84 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include +#include + +#ifdef _WIN32 +#include +#include +#else +#include +#include +#endif + +namespace c10d::detail { + +// Magic number for client validation. +static const uint32_t validationMagicNumber = 0x3C85F7CE; + +enum class QueryType : uint8_t { + VALIDATE, + SET, + COMPARE_SET, + GET, + ADD, + CHECK, + WAIT, + GETNUMKEYS, + DELETE_KEY, + APPEND, + MULTI_GET, + MULTI_SET, + CANCEL_WAIT, + PING, + QUEUE_PUSH, + QUEUE_POP, + QUEUE_LEN, + LIST_KEYS, + BARRIER, +}; + +enum class CheckResponseType : uint8_t { READY, NOT_READY }; + +enum class WaitResponseType : uint8_t { STOP_WAITING, WAIT_CANCELED }; + +// Abstract base class to handle thread state for TCPStoreMasterDaemon. +// Contains the windows/unix implementations to signal a +// shutdown sequence for the thread +class BackgroundThread { + public: + explicit BackgroundThread(); + + virtual ~BackgroundThread() = 0; + virtual std::uint16_t port() const = 0; + + void start(); + bool stop_requested(); + + protected: + void dispose(); + virtual void run() = 0; + virtual void stop() = 0; + bool is_running() { + return is_running_.load(); + } + + private: + std::atomic is_running_{false}; + std::thread daemonThread_; +}; + +std::unique_ptr create_tcpstore_backend( + const TCPStoreOptions& opts); +std::unique_ptr create_libuv_tcpstore_backend( + const TCPStoreOptions& opts); +bool is_libuv_tcpstore_backend_available(); + +} // namespace c10d::detail + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/TraceUtils.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/TraceUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..8e584ac92c5c2a8aaf092cd25fc273f1fe1740f2 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/TraceUtils.h @@ -0,0 +1,324 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include // optional, for ostream fallback +#include // for fmt::join + +#include +#include +#include +#include +#include +#include + +namespace c10d { + +inline std::string getTraceStartKey(const std::string& pgName, int rank) { + return fmt::format(FMT_COMPILE("{}_{}_trace_start"), pgName, rank); +} + +inline std::string getTraceEndKey(const std::string& pgName, int rank) { + return fmt::format(FMT_COMPILE("{}_{}_trace_end"), pgName, rank); +} + +inline bool traceUpdate( + c10::intrusive_ptr& store, + const std::string& key, + uint64_t seq, + const std::string& col) { + std::vector value(col.size() + sizeof(seq) + 1); + std::memcpy(value.data(), &seq, sizeof(seq)); + std::memcpy(value.data() + sizeof(seq), col.data(), col.size()); + try { + store->set(key, value); + return true; + } catch (...) { + LOG(ERROR) << "Store is down while updating #" << seq << " with key " + << key; + return false; + } + return true; +} + +enum TraceDebugEvent { + kEventStart, + kEventEnd, +}; +// >> +using TraceMap = + std::map>>; + +inline std::string ranksToString(const std::vector& ranks) { + return fmt::to_string(fmt::join(ranks, ", ")); +} + +inline std::string ranksFromTrace( + const std::vector>& items) { + fmt::memory_buffer buf; + bool first = true; + for (const auto& [rank, _] : items) { + if (!first) { + fmt::format_to(std::back_inserter(buf), ", "); + } + fmt::format_to(std::back_inserter(buf), "{}", rank); + first = false; + } + return fmt::to_string(buf); +} + +inline std::string analyzeMissingRanks(const std::vector& missingRanks) { + return c10::str( + "\n\t - To our best knowledge, ranks [", + ranksToString(missingRanks), + "] are the lagging ranks that caused this timeout. " + "They never joined any collectives"); +} + +inline std::string analyzeLaggingRanks(const TraceMap& traceMap) { + uint64_t lagSeq = traceMap.begin()->first; + std::vector startRanks; + std::vector endRanks; + for (auto& p : traceMap.begin()->second) { + if (p.second.second == kEventStart) { + startRanks.push_back(p.first); + } else { + endRanks.push_back(p.first); + } + } + std::string report = + "\n\t - To our best knowledge, the lagging/dead/mismatched ranks " + "that caused the desync are:"; + if (!startRanks.empty()) { + report += c10::str( + "\n\t - [", + ranksToString(startRanks), + "] joined but didn't finish collective #", + lagSeq, + " (count from 1)"); + } + if (!endRanks.empty()) { + report += c10::str( + "\n\t [", + ranksToString(endRanks), + "] finished collective #", + lagSeq, + ", but didn't join collective #", + lagSeq + 1, + " (count from 1)"); + } + return report; +} + +inline std::string dumpSnapshot(TraceMap& traceMap) { + std::string report = "\n\t - Snapshot of ranks' latest states:"; + for (auto& tracePair : traceMap) { + uint64_t seq = tracePair.first; + std::map>& subMap = + tracePair.second; + + std::unordered_map> collectivesStart; + std::unordered_map> collectivesEnd; + for (const auto& p : subMap) { + int rank = p.first; + const std::string& col = p.second.first; + if (p.second.second == kEventStart) { + collectivesStart[col].push_back(rank); + } else { + collectivesEnd[col].push_back(rank); + } + } + + if (!collectivesStart.empty()) { + report += c10::str("\n\t #", seq, " started ranks:"); + for (auto& mapPair : collectivesStart) { + report += c10::str( + "\n\t [", + ranksToString(mapPair.second), + "] started ", + mapPair.first); + } + } + if (!collectivesEnd.empty()) { + report += c10::str("\n\t #", seq, " finished ranks:"); + for (auto& mapPair : collectivesEnd) { + report += c10::str( + "\n\t [", + ranksToString(mapPair.second), + "] finished ", + mapPair.first); + } + } + } + return report; +} + +inline bool parseTraceValue( + c10::intrusive_ptr& store, + const std::string& key, + uint64_t& seq, + std::string& col) { + try { + std::vector traceValue = store->get(key); + std::memcpy(&seq, traceValue.data(), sizeof(seq)); + std::string colName((char*)traceValue.data() + sizeof(seq)); + col = colName; + return true; + } catch (...) { + LOG(ERROR) << "Store is down while getting key " << key; + return false; + } + return true; +} + +inline std::string retrieveDesyncReport( + c10::intrusive_ptr& store, + const std::string& pgName, + int myRank, + int worldSize) { + std::string report; + + uint64_t thisSeq = 0; + std::string thisCol; + + std::vector missingRanks; + TraceMap traceMap; + + for (const auto rank : c10::irange(worldSize)) { + // Build traceMapStart. + uint64_t seqStart = 0; + { + std::string traceKeyStart = getTraceStartKey(pgName, rank); + if (!store->check({traceKeyStart})) { + missingRanks.push_back(rank); + continue; + } + std::string col; + if (!parseTraceValue(store, traceKeyStart, seqStart, col)) { + return report; + } + traceMap[seqStart].emplace(rank, std::make_pair(col, kEventStart)); + if (rank == myRank) { + thisSeq = seqStart; + thisCol = std::move(col); + } + } + + // Build traceMapEnd. + { + std::string traceKeyEnd = getTraceEndKey(pgName, rank); + if (!store->check({traceKeyEnd})) { + continue; + } + uint64_t seq = 0; + std::string col; + if (!parseTraceValue(store, traceKeyEnd, seq, col)) { + return report; + } + if (seq == seqStart) { + traceMap[seq][rank].second = kEventEnd; + } + } + } + + TORCH_INTERNAL_ASSERT( + !missingRanks.empty() || !traceMap.empty(), + "Trace shouldn't be empty while enabled GLOO_ASYNC_TIMEOUT_DEBUG"); + TORCH_INTERNAL_ASSERT( + !thisCol.empty(), + "Timeout rank [", + myRank, + "] must have collective tracking iteam in c10::Store trace"); + TORCH_INTERNAL_ASSERT( + traceMap[thisSeq][myRank].second == kEventStart, + "Timeout rank [", + myRank, + "] last trace item must be kEventStart. thisSeq = ", + thisSeq, + ", col = ", + thisCol); + + report += c10::str( + "\n\t - [", myRank, "] Timeout at collective: ", thisCol, ", #", thisSeq); + + if (!missingRanks.empty()) { + report += analyzeMissingRanks(missingRanks); + } else { + report += analyzeLaggingRanks(traceMap); + report += dumpSnapshot(traceMap); + } + + return report; +} + +inline std::string pickle_str(const c10::IValue& v) { + std::vector result; + { + auto writer = [&](const char* data, size_t size) { + result.insert(result.end(), data, data + size); + }; + torch::jit::Pickler pickler( + writer, nullptr, nullptr, nullptr, nullptr, false); + pickler.protocol(); + pickler.pushIValue(v); + pickler.stop(); + } + return std::string(result.begin(), result.end()); +} + +inline std::string get_python_cpp_trace() { + // usage: + // LOG(INFO) << "stacktrace: " + // << get_python_cpp_trace(); + // warn: might be slow in getting cpp traces + // because of slow/broken addr2line + // in different system libs + std::shared_ptr tb = + torch::CapturedTraceback::gather( + /*python=*/true, /*script=*/true, /*cpp=*/true); + torch::SymbolizedTracebacks s_tbs = torch::symbolize({tb.get()}); + const auto& s_tb = s_tbs.tracebacks.at(0); + constexpr auto TB_FMT_CSTR = FMT_COMPILE("#{} {} from {}:{}\n"); + fmt::memory_buffer buf; + auto buf_iter = std::back_inserter(buf); + for (auto idx : c10::irange(s_tb.size())) { + auto frame_id = s_tb[idx]; + const auto& frame = s_tbs.all_frames.at(frame_id); + fmt::format_to( + buf_iter, + TB_FMT_CSTR, + idx, + frame.funcname, + frame.filename, + frame.lineno); + } + return fmt::to_string(buf); +} + +inline c10::Dict new_dict() { + return c10::Dict( + c10::AnyType::get(), c10::AnyType::get()); +} + +inline c10::List new_list() { + return c10::List(c10::AnyType::get()); +} + +inline std::string ranks_str(const std::vector& ranks) { + return fmt::format("[{}]", fmt::join(ranks, ", ")); +} + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Types.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Types.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c02edd2ef0eb6f4a04b6abe2976d1c9cd20e2e90 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Types.hpp @@ -0,0 +1,190 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include +#include + +#include +#include + +#include +#include + +namespace c10d { + +// Base class for supplementary data potentially needed by ReduceOps +struct TORCH_API _SupplementBase : torch::CustomClassHolder { + ~_SupplementBase() override = default; +}; + +// Supplementary data specific to NCCL PREMUL_SUM +// The point of use in ProcessGroupNCCL knows how to unpack it. +struct NCCLPreMulSumSupplement : _SupplementBase { + double double_factor{0.0}; + at::Tensor tensor_factor; + NCCLPreMulSumSupplement(double f) : double_factor{f} {} + NCCLPreMulSumSupplement(at::Tensor t) : tensor_factor{std::move(t)} { + TORCH_CHECK_EQ(tensor_factor.numel(), 1); + } +}; + +// Other ReduceOps that need different supplementary data can also +// derive from _SupplementBase. +struct TORCH_API ReduceOp : torch::CustomClassHolder { + // note(crcrpar): RedOpType could be defined outside of `ReduceOp` + enum RedOpType : uint8_t { + SUM = 0, + AVG = 1, + PRODUCT = 2, + MIN = 3, + MAX = 4, + BAND = 5, // Bitwise AND + BOR = 6, // Bitwise OR + BXOR = 7, // Bitwise XOR + PREMUL_SUM = 8, // Multiply by a user-supplied constant before summing. + UNUSED = 9 + }; + + ReduceOp() = default; + + ReduceOp(RedOpType op) : op_(op) { + TORCH_INTERNAL_ASSERT( + op_ != PREMUL_SUM, + "Use `torch.distributed._make_nccl_premul_sum` to create an instance of ReduceOp with PREMUL_SUM"); + } + + ReduceOp( + RedOpType op, + const c10::intrusive_ptr<_SupplementBase>& optional_supplement) { + if (optional_supplement) { + op_ = op; + } else { + supplement_ = optional_supplement; + } + } + + // The heap resource supplement_, if it exists, is managed by a + // c10::intrusive_ptr, so constructors and operator= can be simple + ReduceOp(const ReduceOp& other) = default; + ReduceOp& operator=(const ReduceOp& other) = default; + + ReduceOp(ReduceOp&& other) = default; + ReduceOp& operator=(ReduceOp&& other) = default; + ~ReduceOp() override = default; + + operator RedOpType() const { + return op_; + } + + bool operator==(const std::uint8_t other) { + TORCH_INTERNAL_ASSERT(other < 9, "Invalid other op value"); + return other == op_; + } + + bool operator==(const ReduceOp::RedOpType other) { + return *this == static_cast(other); + } + + // todo(crcrpar): Handle `RedOpType::PREMUL_SUM` with its scaling factor. + bool operator==(const ReduceOp& other) { + return *this == other.op_; + } + + RedOpType op_ = SUM; + // supplement_ is "type-erased" storage for optional supplementary + // data the op might need. + // The point of use will know the derived type supplement_ really is, + // and downcast its pointer to extract the data as the needed type(s). + // Right now, only PREMUL_SUM needs supplementary data, but the same + // mechanism could extend to support other nontrivial reduce ops with + // different supplementary payloads. + c10::intrusive_ptr<_SupplementBase> supplement_; +}; + +template +ReduceOp makeNCCLPreMulSum(const T& factor) { + ReduceOp rop; + rop.op_ = ReduceOp::PREMUL_SUM; + rop.supplement_ = c10::make_intrusive(factor); + return rop; +} + +TORCH_API bool isComplexViewAsRealAllowed(const ReduceOp& reduceOp); + +constexpr auto kUnsetTimeout = std::chrono::milliseconds(-1); + +struct BroadcastOptions { + int64_t rootRank = 0; + int64_t rootTensor = 0; + std::chrono::milliseconds timeout = kUnsetTimeout; + bool asyncOp = true; +}; + +struct AllreduceOptions { + ReduceOp reduceOp = ReduceOp::SUM; + std::chrono::milliseconds timeout = kUnsetTimeout; + bool asyncOp = true; + std::optional sparseIndices = std::nullopt; +}; + +struct AllreduceCoalescedOptions : AllreduceOptions {}; + +struct ReduceOptions { + ReduceOp reduceOp = ReduceOp::SUM; + int64_t rootRank = 0; + int64_t rootTensor = 0; + std::chrono::milliseconds timeout = kUnsetTimeout; + bool asyncOp = true; +}; + +struct AllgatherOptions { + std::chrono::milliseconds timeout = kUnsetTimeout; + bool asyncOp = true; +}; + +struct GatherOptions { + int64_t rootRank = 0; + std::chrono::milliseconds timeout = kUnsetTimeout; + bool asyncOp = true; +}; + +struct ScatterOptions { + int64_t rootRank = 0; + std::chrono::milliseconds timeout = kUnsetTimeout; + bool asyncOp = true; +}; + +struct ReduceScatterOptions { + ReduceOp reduceOp = ReduceOp::SUM; + std::chrono::milliseconds timeout = kUnsetTimeout; + bool asyncOp = true; +}; + +struct AllToAllOptions { + std::chrono::milliseconds timeout = kUnsetTimeout; + bool asyncOp = true; +}; + +struct BarrierOptions { + std::vector device_ids; + std::chrono::milliseconds timeout = kUnsetTimeout; + std::optional device; + bool asyncOp = true; +}; + +struct DistributedBackendOptions { + c10::intrusive_ptr<::c10d::Store> store; + int group_rank; + int group_size; + std::chrono::duration timeout; + std::string group_id; + std::vector global_ranks_in_group; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/UCCTracing.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/UCCTracing.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6e53aa7a21fb3a67135d15b2add0fe344d05dab6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/UCCTracing.hpp @@ -0,0 +1,63 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef USE_C10D_UCC + +#include + +namespace c10d { + +#define RECORD_COMMS_TRACE( \ + _comms_tracer, _work, _opType, _rank, _comm_size, _inTensors, _outTensors) \ + do { \ + if (torch_ucc_config.enable_comms_logger) { \ + _comms_tracer->recordComms( \ + opTypeToString(_opType), \ + (uintptr_t)_work.get(), \ + _rank, \ + _comm_size, \ + _inTensors, \ + _outTensors); \ + } \ + } while (0) + +// interfaces to collect communication traces +class TORCH_API CommTraceLogger : public torch::CustomClassHolder { + private: + std::vector comms_trace_; + std::vector curBlocks_; /* unused */ + std::vector curOutSplitSizes_; + std::vector curInSplitSizes_; + int curRoot_ = -1; + unsigned long seqnum = 0; + + public: + void setCurBlock(const std::string& name); /* unused */ + void popBlock(); /* unused */ + // record root info if applicable, e.g., broadcast, gather, scatter + void recordOptionalInfo(int root = -1); + // record input/output splits of Alltoallv + void recordOptionalInfo( + const std::vector& outputSplitSizes = {}, + const std::vector& inputSplitSizes = {}); + // record essential comms information + void recordComms( + const std::string& collName, + const uintptr_t workReq = 0, + const int rank = -1, + const int world_size = -1, + const std::vector& inputTensors = {}, + const std::vector& outputTensor = {}); + // return collected comms traces + std::vector& getCommsTrace() { + return comms_trace_; + } +}; + +} // namespace c10d + +#endif // USE_C10D_UCC + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/UCCUtils.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/UCCUtils.hpp new file mode 100644 index 0000000000000000000000000000000000000000..66357622a880f36d1cad25d5a1642478482bcf05 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/UCCUtils.hpp @@ -0,0 +1,192 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef USE_C10D_UCC + +#include +#include +#include + +namespace c10d { + +// Macro to generate the error message on a non-successful UCC return value. +#define TORCH_UCC_GET_ERROR_MSG(_err, _error_msg, _result) \ + do { \ + _err = c10::str( \ + "[", \ + std::string(__FILE__), \ + ":", \ + std::to_string(__LINE__), \ + "] ", \ + logger->getLogPrefix(), \ + _error_msg, \ + ", error code ", \ + _result, \ + ": ", \ + ucc_status_string(_result), \ + ", system error code ", \ + errno); \ + } while (0) + +// Macro to throw on a non-successful UCC return value. +#define TORCH_UCC_CHECK(_cmd, _error_msg) \ + do { \ + ucc_status_t result = _cmd; \ + if (result != UCC_OK) { \ + std::string err; \ + TORCH_UCC_GET_ERROR_MSG(err, _error_msg, result); \ + TORCH_CHECK(false, err); \ + } \ + } while (0) + +// Macro and throw on a non-successful UCC return value and free its request. +#define TORCH_UCC_CHECK_REQUEST(_request, _cmd, _error_msg) \ + do { \ + ucc_status_t result = _cmd; \ + if (result != UCC_OK) { \ + std::string err; \ + TORCH_UCC_GET_ERROR_MSG(err, _error_msg, result); \ + if (_request != nullptr) { \ + ucc_collective_finalize(_request); \ + } \ + TORCH_CHECK(false, err); \ + } \ + } while (0) + +// Macros to print logs with unified format +#define TORCH_UCC_LOG_ERROR(_phase, _msg) \ + LOG(ERROR) << logger->getLogPrefix(_phase) << "[ERROR] " << _msg; +#define TORCH_UCC_LOG_INFO(_phase, _msg) \ + LOG(INFO) << logger->getLogPrefix(_phase) << "[INFO] " << _msg; +#define TORCH_UCC_LOG_DEBUG(_phase, _msg) \ + VLOG(1) << logger->getLogPrefix(_phase) << "[DEBUG] " << _msg; + +enum torch_ucc_phase_t { + TORCH_UCC_UNKNOWN = -1, + TORCH_UCC_INIT, + TORCH_UCC_HEALTH_CHECK, + TORCH_UCC_READY, + TORCH_UCC_COLL_POST, + TORCH_UCC_COLL_PROGRESS, + TORCH_UCC_FINALIZE, +}; + +const std::map ucc_phase_map = { + {TORCH_UCC_UNKNOWN, "UNKNOWN"}, + {TORCH_UCC_INIT, "INIT"}, + {TORCH_UCC_HEALTH_CHECK, "HEALTH_CHECK"}, + {TORCH_UCC_READY, "READY"}, + {TORCH_UCC_COLL_POST, "COLL_POST"}, + {TORCH_UCC_COLL_PROGRESS, "COLL_PROGRESS"}, + {TORCH_UCC_FINALIZE, "FINALIZE"}, +}; + +class CommTraceLogger; + +class TORCH_API ProcessGroupUCCLogger : public torch::CustomClassHolder { + public: + ProcessGroupUCCLogger(); + ProcessGroupUCCLogger(std::string log_prefix, torch_ucc_phase_t phase); + + std::string getLogPrefix(torch_ucc_phase_t phase = TORCH_UCC_UNKNOWN); + void setLogPrefix(std::string log_prefix); + inline void setPhase(torch_ucc_phase_t phase) { + local_phase = phase; + } + + void initCommsTracer(); + void flushComms(int rank, int world_size); + std::shared_ptr trace_generator = nullptr; + + protected: + std::string log_prefix; + torch_ucc_phase_t local_phase = TORCH_UCC_UNKNOWN; + bool initialized_CommTraceLogger = false; +}; + +struct torch_ucc_oob_coll_info_t { + c10::intrusive_ptr store; + uint32_t comm_id; + int rank; + int size; + void* rbuf; + size_t msglen; + std::string getKey(std::string key) { + return std::to_string(comm_id) + key; + } +}; + +class CommBase { + public: + CommBase(const c10::intrusive_ptr& logger_) + : logger(logger_) {} + virtual void progress() = 0; + virtual void free_request(ucc_coll_req_h request) = 0; + virtual ~CommBase() {} + c10::intrusive_ptr logger; +}; +class CommUCC : public CommBase { + public: + ucc_lib_h lib{nullptr}; + ucc_context_h context{nullptr}; + + public: + void progress() override; + CommUCC( + std::shared_ptr oob, + const c10::intrusive_ptr& logger); + void free_request(ucc_coll_req_h request) override; + ~CommUCC(); +}; + +ucc_status_t oob_allgather( + void* sbuf, + void* rbuf, + size_t msglen, + void* coll_info, + void** req); + +ucc_status_t oob_allgather_test(void* req); + +ucc_status_t oob_allgather_free(void* req); + +// trim: remove spaces before and after the string view +// implementation borrowed from https://stackoverflow.com/a/17976541 +inline std::string_view trim(std::string_view s) { + auto wsfront = std::find_if_not( + s.begin(), s.end(), [](int c) { return std::isspace(c); }); + auto wsback = std::find_if_not(s.rbegin(), s.rend(), [](int c) { + return std::isspace(c); + }).base(); + return ( + wsback <= wsfront ? "" : s.substr(wsfront - s.begin(), wsback - wsfront)); +} + +inline std::string tolower(std::string_view s) { + std::string result; + result.reserve(s.size()); + for (auto c : s) { + result.push_back(std::tolower(c)); + } + return result; +} + +inline std::vector parse_list(std::string list) { + std::vector result; + list = tolower(trim(list)); + while (!list.empty()) { + const auto end_pos = list.find_first_of(','); + const auto token = trim(list.substr(0, end_pos)); + result.push_back(std::string(token)); + list = (end_pos != std::string_view::npos) ? list.substr(end_pos + 1) : ""; + } + return result; +} + +} // namespace c10d + +#endif // USE_C10D_UCC + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/UnixSockUtils.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/UnixSockUtils.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4293911d1faea1f3595eea7af19f7094afcfac60 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/UnixSockUtils.hpp @@ -0,0 +1,30 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace c10d::tcputil { + +#define CONNECT_SOCKET_OFFSET 2 + +inline int poll(struct pollfd* fds, unsigned long nfds, int timeout) { + return ::poll(fds, nfds, timeout); +} + +inline void addPollfd( + std::vector& fds, + int socket, + short events) { + fds.push_back({.fd = socket, .events = events}); +} + +inline struct ::pollfd getPollfd(int socket, short events) { + struct ::pollfd res = {.fd = socket, .events = events}; + return res; +} + +} // namespace c10d::tcputil + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Utils.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Utils.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fedb64349bbbb088ea87d493c37c0e8efaef2e65 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Utils.hpp @@ -0,0 +1,750 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +typedef SSIZE_T ssize_t; +#pragma comment(lib, "Ws2_32.lib") +#else +#include +#include +#include +#include +#include +#endif + +#include + +#include +#include +#include +#include +#include + +namespace c10d { + +TORCH_API size_t getTensorsNumel(const std::vector& tensors); + +// Retrieve tensor shapes from a given tensor. +TORCH_API std::vector getTensorShapes( + const std::vector& tensors); + +// Use -2 to represent unset state of env vars +#define C10D_ENV_NOT_SET -2 + +#define WARN_ENV_VAR_ONCE(deprecated_env, new_env) \ + TORCH_WARN_ONCE( \ + "Environment variable " + deprecated_env + " is deprecated; use " + \ + new_env + " instead"); + +// Turns at::IntArrayRef into "(1, 2, 3, 4)". +inline std::string toString(at::IntArrayRef l) { + std::stringstream ss; + ss << '('; + for (const auto i : c10::irange(l.size())) { + if (i > 0) { + ss << ", "; + } + ss << l[i]; + } + ss << ')'; + return ss.str(); +} + +inline std::string toString(const c10::Layout& layout) { + std::stringstream ss; + ss << layout; + return ss.str(); +} + +inline void assertSameType( + const at::DeprecatedTypeProperties& type, + const std::vector& tensors) { + for (const auto i : c10::irange(tensors.size())) { + if (!tensors[i].options().type_equal(type.options())) { + const std::string expected = type.toString(); + const std::string actual = tensors[i].toString(); + throw std::invalid_argument( + // NOLINTNEXTLINE(performance-inefficient-string-concatenation) + "mixed types (" + expected + " and " + actual + ")"); + } + } +} + +inline std::vector split( + char separator, + const std::string& string) { + std::vector pieces; + std::stringstream ss(string); + std::string item; + while (std::getline(ss, item, separator)) { + pieces.push_back(std::move(item)); + } + return pieces; +} + +inline std::string getCvarString( + const std::vector& env, + const char* def) { + std::string ret(def); + + if (env.empty()) { + TORCH_CHECK(false, "No environment variables passed"); + return ret; + } + + /* parse environment variable in reverse order, so the early + * versions of a variable get higher priority than the latter + * versions of the same variable */ + for (ssize_t i = static_cast(env.size()) - 1; i >= 0; i--) { + auto val = c10::utils::get_env(env[i].c_str()); + if (!val.has_value()) { + continue; + } else if (i) { + WARN_ENV_VAR_ONCE(env[i], env[0]); + } + + ret = val.value(); + } + + return ret; +} + +inline int getCvarInt(const std::vector& env, int def) { + int ret = def; + + if (env.empty()) { + TORCH_CHECK(false, "No environment variables passed"); + return ret; + } + + /* parse environment variable in reverse order, so the early + * versions of a variable get higher priority than the latter + * versions of the same variable */ + for (ssize_t i = static_cast(env.size()) - 1; i >= 0; i--) { + const auto val = c10::utils::get_env(env[i].c_str()); + if (!val.has_value()) { + continue; + } else if (i) { + WARN_ENV_VAR_ONCE(env[i], env[0]); + } + + try { + ret = std::stoi(val.value()); + } catch (std::exception&) { + TORCH_CHECK(false, "Invalid value for environment variable: " + env[i]); + } + } + + return ret; +} + +inline bool getCvarBool(const std::vector& env, bool def) { + bool ret = def; + + if (env.empty()) { + TORCH_CHECK(false, "No environment variables passed"); + return ret; + } + + /* parse environment variable in reverse order, so the early + * versions of a variable get higher priority than the latter + * versions of the same variable */ + for (ssize_t i = static_cast(env.size()) - 1; i >= 0; i--) { + auto val = c10::utils::get_env(env[i].c_str()); + if (!val.has_value()) { + continue; + } else if (i) { + WARN_ENV_VAR_ONCE(env[i], env[0]); + } + + for (auto& x : val.value()) { + // NOLINTNEXTLINE(*-narrowing-conversions) + x = std::tolower(x); + } + + if (val == "y" || val == "yes" || val == "1" || val == "t" || + val == "true") { + ret = true; + } else if ( + val == "n" || val == "no" || val == "0" || val == "f" || + val == "false") { + ret = false; + } else { + TORCH_CHECK(false, "Invalid value for environment variable: " + env[i]); + return ret; + } + } + + return ret; +} + +inline void assertSameSizes( + const at::IntArrayRef& sizes, + const std::vector& tensors) { + for (const auto i : c10::irange(tensors.size())) { + if (!tensors[i].sizes().equals(sizes)) { + const auto expected = toString(sizes); + const auto actual = toString(tensors[i].sizes()); + throw std::invalid_argument( + // NOLINTNEXTLINE(performance-inefficient-string-concatenation) + "mixed sizes (" + expected + " and " + actual + ")"); + } + } +} + +inline void assertSameSizeAndType(const std::vector& tensors) { + // Ensure we have at least one tensor + if (tensors.empty()) { + throw std::invalid_argument("argument is empty"); + } + + // Ensure all tensors have identical type and shape + auto options = tensors[0].options(); + auto sizes = tensors[0].sizes(); + for (const auto i : c10::irange(1, tensors.size())) { + if (!tensors[i].options().type_equal(options)) { + const auto expected = toString(options); + const auto actual = toString(tensors[i].options()); + throw std::invalid_argument( + // NOLINTNEXTLINE(performance-inefficient-string-concatenation) + "argument contains mixed types (" + expected + " and " + actual + + ")"); + } + if (!tensors[i].sizes().equals(sizes)) { + const auto expected = toString(sizes); + const auto actual = toString(tensors[i].sizes()); + throw std::invalid_argument( + // NOLINTNEXTLINE(performance-inefficient-string-concatenation) + "argument contains mixed types (" + expected + " and " + actual + + ")"); + } + } +} + +inline void assertTypeMatch( + const std::function& fn, + const at::DeprecatedTypeProperties& type, + const at::ArrayRef tensors, + size_t index) { + if (!tensors[index].options().type_equal(type.options())) { + fn("invalid tensor type at index " + std::to_string(index) + " (expected " + + type.toString() + ", got " + tensors[index].toString() + ")"); + } +} + +inline void assertTypeMatch( + const std::function& fn, + const at::TensorOptions& options, + const at::ArrayRef tensors, + size_t index) { + if (!tensors[index].options().type_equal(options)) { + fn("invalid tensor type at index " + std::to_string(index) + " (expected " + + toString(options) + ", got " + toString(tensors[index].options()) + ")"); + } +} + +inline void assertSizesMatch( + const std::function& fn, + const at::IntArrayRef& sizes, + const at::ArrayRef tensors, + size_t index) { + if (tensors[index].sizes() != sizes) { + fn("invalid tensor size at index " + std::to_string(index) + " (expected " + + toString(sizes) + ", got " + toString(tensors[index].sizes()) + ")"); + } +} + +inline void assertLayoutMatch( + const std::function& fn, + const c10::Layout& expected, + const at::ArrayRef tensors, + size_t index) { + const auto& actual = tensors[index].layout(); + if (actual != expected) { + fn("invalid tensor layout at index " + std::to_string(index) + + " (expected " + toString(expected) + ", got " + toString(actual) + ")"); + } +} + +inline void assertLayoutMatch( + const std::function& fn, + const at::ArrayRef tensors) { + const auto& layout = tensors[0].layout(); + for (const auto i : c10::irange(1, tensors.size())) { + assertLayoutMatch(fn, layout, tensors, i); + } +} + +inline void assertNonEmpty( + const std::function& fn, + const at::ArrayRef tensors) { + if (tensors.empty()) { + fn("requires non-empty tensor list"); + } +} + +inline void assertSingleElement( + const std::function& fn, + const at::ArrayRef tensors) { + if (tensors.size() != 1) { + fn("requires a single-element tensor list"); + } +} + +inline void assertSingleElementInput( + const std::function& fn, + const at::ArrayRef tensors) { + if (tensors.size() != 1) { + fn("requires a single-element input tensor list"); + } +} + +inline void assertSingleElementOutput( + const std::function& fn, + const at::ArrayRef tensors) { + if (tensors.size() != 1) { + fn("requires a single-element output tensor list"); + } +} + +inline void assertRootRank( + const std::function& fn, + int64_t rank, + int64_t size) { + if (rank < 0 || rank >= size) { + fn("invalid root rank: " + std::to_string(rank)); + } +} + +inline void assertRootTensor( + const std::function& fn, + int64_t rank, + int64_t size) { + if (rank < 0 || rank >= size) { + fn("invalid root tensor: " + std::to_string(rank)); + } +} + +inline void assertDense( + const std::function& fn, + const at::ArrayRef tensors) { + const auto& layout = tensors[0].layout(); + if (layout != at::kStrided) { + fn("only supports dense tensors"); + } +} + +inline void assertCPU( + const std::function& fn, + const at::ArrayRef tensors) { + const auto& device = tensors[0].device(); + if (device.type() != at::kCPU) { + fn("only supports CPU tensors"); + } +} + +inline void assertSameDevice( + const std::function& fn, + const at::ArrayRef tensors) { + if (tensors.size() < 2) { + return; + } + const auto& device = tensors[0].device(); + for (const auto i : c10::irange(1, tensors.size())) { + if (tensors[i].device() != device) { + fn("tensors should be on the same device"); + } + } +} + +inline void assertTypeAndSizesMatch( + const std::function& fn, + const at::ArrayRef tensors, + const at::DeprecatedTypeProperties& type, + const at::IntArrayRef& sizes) { + for (const auto i : c10::irange(tensors.size())) { + assertTypeMatch(fn, type, tensors, i); + assertSizesMatch(fn, sizes, tensors, i); + } +} + +inline void assertTypeAndSizesMatch( + const std::function& fn, + const at::ArrayRef tensors, + const at::TensorOptions& options, + const at::IntArrayRef& sizes) { + for (const auto i : c10::irange(tensors.size())) { + assertTypeMatch(fn, options, tensors, i); + assertSizesMatch(fn, sizes, tensors, i); + } +} + +inline void assertTypeAndSizesMatch( + const std::function& fn, + const at::ArrayRef tensors) { + const auto& options = tensors[0].options(); + const auto sizes = tensors[0].sizes(); + assertTypeAndSizesMatch(fn, tensors.slice(1), options, sizes); +} + +// Copied from ATen/core/functional.h. +template +inline auto fmap(T& inputs, const F& fn) + -> std::vector { + std::vector r; + r.reserve(inputs.size()); + for (auto& input : inputs) { + r.push_back(fn(input)); + } + return r; +} + +// Copied from torch/csrc/utils/tensor_flatten.h. +inline at::Tensor flattenDenseTensors(at::TensorList tensors) { + static const auto flatten = [](const at::Tensor& t) { + return t.contiguous().view({-1}); + }; + if (tensors.size() == 1) { + return flatten(tensors[0]); + } + return at::cat(::c10d::fmap(tensors, flatten)); +} + +inline at::Tensor newLikeFlat( + std::vector>& tensors, + size_t deviceIdx) { + if (tensors.empty() || tensors[0].empty()) { + TORCH_CHECK(false, "Received an empty list"); + } + if (deviceIdx >= tensors.size()) { + TORCH_CHECK(false, "Invalid device index"); + } + auto& t = tensors[deviceIdx][0]; + auto device = t.device(); + for (const auto i : c10::irange(1, tensors[deviceIdx].size())) { + if (tensors[deviceIdx][i].device() != device) { + TORCH_CHECK(false, "Expecting all tensors on the same device"); + } + } + at::DeviceGuard gpuGuard(device); + std::vector sizes{static_cast(tensors[deviceIdx].size())}; + std::vector strides{t.numel()}; + sizes.insert(sizes.end(), t.sizes().begin(), t.sizes().end()); + strides.insert(strides.end(), t.strides().begin(), t.strides().end()); + return at::empty_strided( + sizes, strides, t.options().memory_format(std::nullopt)); +} + +inline at::Tensor newLikeFlat(std::vector& tensors) { + if (tensors.empty()) { + TORCH_CHECK(false, "Received an empty list"); + } + auto& t = tensors[0]; + at::DeviceGuard gpuGuard(t.device()); + std::vector sizes{static_cast(tensors.size())}; + sizes.insert(sizes.end(), t.sizes().begin(), t.sizes().end()); + return at::empty(sizes, t.options()); +} + +inline std::vector> getSizes( + const std::vector& tensors) { + std::vector> sizes(tensors.size()); + for (const auto i : c10::irange(tensors.size())) { + sizes[i] = tensors[i].sizes().vec(); + } + return sizes; +} + +inline std::vector getDevices(const std::vector& tensors) { + std::vector devices(tensors.size(), -1); + if (tensors[0].device().is_cuda()) { + for (const auto i : c10::irange(tensors.size())) { + // NOLINTNEXTLINE(bugprone-signed-char-misuse) + devices[i] = tensors[i].storage().device().index(); + } + } + return devices; +} + +template +inline T* getDataPointer(const at::Tensor& tensor) { + // This method is only used in ProcessGroupGloo for now. Call sites must make + // sure that the input tensor is contiguous. It is OK if the tensor does not + // start from the beginning of the storage. For example, it could come from + // chunk(..., dim=0)[1]. Hence, we need to use data_ptr() instead of + // tensor.storage().data() + // NB: not using tensor.data() because tensor is not aware of gloo::TYPE + return static_cast(tensor.data_ptr()); +} + +template +std::vector getDataPointers(const std::vector& tensors) { + std::vector ptrs(tensors.size()); + for (const auto i : c10::irange(tensors.size())) { + ptrs[i] = getDataPointer(tensors[i]); + } + return ptrs; +} + +// For alltoall split size sanity check +inline void checkSplitSizes( + const std::vector& split_sizes, + const at::Tensor& tensor, + int group_size) { + if (split_sizes.empty()) { + TORCH_CHECK( + tensor.size(0) % group_size == 0, + "Tensor's dim 0 does not divide equally across group size"); + } else { + TORCH_CHECK( + split_sizes.size() == static_cast(group_size), + "Number of tensor splits not equal to group size"); + const auto sum = c10::sum_integers(split_sizes); + TORCH_CHECK( + sum == tensor.size(0), "Split sizes doesn't match total dim 0 size"); + } +} + +// Compute alltoall lengths and offsets, handling multi-dimension tensors +template +size_t computeLengthsAndOffsets( + const std::vector& split_sizes, + const at::Tensor& tensor, + std::vector* lengths, + std::vector* offsets) { + size_t group_size = lengths->size(); + bool equal_splits = false; + size_t dim0_size = tensor.size(0); + size_t row_size = (dim0_size ? tensor.numel() / dim0_size : 1); + size_t split_size = 0; + size_t offset = 0; + + if (split_sizes.empty()) { + equal_splits = true; + split_size = tensor.size(0) / group_size; + } + for (const auto i : c10::irange(group_size)) { + size_t length = row_size * (equal_splits ? split_size : split_sizes[i]); + (*lengths)[i] = length; + (*offsets)[i] = offset; + // TODO: see if we should add overflow protection for offset + offset += length; + } + return offset; +} + +template +size_t computeLengthsAndOffsets( + const std::vector& tensors, + std::vector* lengths, + std::vector* offsets) { + size_t group_size = lengths->size(); + size_t offset = 0; + for (const auto i : c10::irange(group_size)) { + size_t length = tensors[i].numel(); + (*lengths)[i] = length; + (*offsets)[i] = offset; + offset += length; + } + return offset; +} + +// Get the start and stride of the global rank from a list of global ranks +// If the global ranks do not follow the consecutive rule, the stride will be -1 +void TORCH_API getGlobalRankStartAndStride( + const std::vector& globalRanksInGroup, + int& globalRankStart, + int& globalRankStride); + +using RankType = uint32_t; +using SizeType = uint64_t; + +// `errno` is only meaningful when it fails. E.g., a successful `fork()` sets +// `errno` to `EINVAL` in child process on some macos +// (https://stackoverflow.com/a/20295079), and thus `errno` should really only +// be inspected if an error occurred. +// +// `success_cond` is an expression used to check if an error has happened. So +// for `fork()`, we can use `SYSCHECK(pid = fork(), pid != -1)`. The function +// output is stored in variable `__output` and may be used in `success_cond`. +#ifdef _WIN32 +#define SYSCHECK(expr, success_cond) \ + while (true) { \ + auto __output = (expr); \ + auto errno_local = WSAGetLastError(); \ + (void)__output; \ + if (!(success_cond)) { \ + if (errno == EINTR) { \ + continue; \ + } else if ( \ + errno_local == WSAETIMEDOUT || errno_local == WSAEWOULDBLOCK) { \ + C10_THROW_ERROR(DistNetworkError, "Socket Timeout"); \ + } else { \ + C10_THROW_ERROR(DistNetworkError, c10::utils::str_error(errno_local)); \ + } \ + } else { \ + break; \ + } \ + } +#else +#define SYSCHECK(expr, success_cond) \ + while (true) { \ + auto __output = (expr); \ + (void)__output; \ + if (!(success_cond)) { \ + if (errno == EINTR) { \ + continue; \ + } else if (errno == EAGAIN || errno == EWOULDBLOCK) { \ + C10_THROW_ERROR(DistNetworkError, "Socket Timeout"); \ + } else { \ + C10_THROW_ERROR(DistNetworkError, c10::utils::str_error(errno)); \ + } \ + } else { \ + break; \ + } \ + } +#endif + +// Most functions indicate error by returning `-1`. This is a helper macro for +// this common case with `SYSCHECK`. +// Since SOCKET_ERROR = -1 in MSVC, so also leverage SYSCHECK_ERR_RETURN_NEG1 +#define SYSCHECK_ERR_RETURN_NEG1(expr) SYSCHECK(expr, __output != -1) + +namespace tcputil { + +// Send and receive +template +void sendBytes( + int socket, + const T* buffer, + size_t length, + bool moreData = false) { + size_t bytesToSend = sizeof(T) * length; + if (bytesToSend == 0) { + return; + } + + auto currentBytes = reinterpret_cast(buffer); + + int flags = 0; + +#ifdef MSG_MORE + if (moreData) { // there is more data to send + flags |= MSG_MORE; + } +#endif + +// Ignore SIGPIPE as the send() return value is always checked for error +#ifdef MSG_NOSIGNAL + flags |= MSG_NOSIGNAL; +#endif + + while (bytesToSend > 0) { + ssize_t bytesSent = 0; + SYSCHECK_ERR_RETURN_NEG1( + bytesSent = ::send(socket, currentBytes, bytesToSend, flags)) + if (bytesSent == 0) { + C10_THROW_ERROR( + DistNetworkError, + "Failed to send, sent 0 bytes. " + "Connection was likely closed. " + "Did the remote server shutdown or crash?"); + } + + bytesToSend -= bytesSent; + currentBytes += bytesSent; + } +} + +template +void recvBytes(int socket, T* buffer, size_t length) { + size_t bytesToReceive = sizeof(T) * length; + if (bytesToReceive == 0) { + return; + } + + auto currentBytes = reinterpret_cast(buffer); + + while (bytesToReceive > 0) { + ssize_t bytesReceived = 0; + SYSCHECK_ERR_RETURN_NEG1( + bytesReceived = recv(socket, currentBytes, bytesToReceive, 0)) + if (bytesReceived == 0) { + C10_THROW_ERROR( + DistNetworkError, + "Failed to recv, got 0 bytes. " + "Connection was likely closed. " + "Did the remote server shutdown or crash?"); + } + + bytesToReceive -= bytesReceived; + currentBytes += bytesReceived; + } +} + +// send a vector's length and data +template +void sendVector(int socket, const std::vector& vec, bool moreData = false) { + SizeType size = vec.size(); + sendBytes(socket, &size, 1, true); + sendBytes(socket, vec.data(), size, moreData); +} + +// receive a vector as sent in sendVector +template +std::vector recvVector(int socket) { + SizeType valueSize = 0; + recvBytes(socket, &valueSize, 1); + std::vector value(valueSize); + recvBytes(socket, value.data(), value.size()); + return value; +} + +// this is only for convenience when sending rvalues +template +void sendValue(int socket, const T& value, bool moreData = false) { + sendBytes(socket, &value, 1, moreData); +} + +template +T recvValue(int socket) { + T value; + recvBytes(socket, &value, 1); + return value; +} + +// send a string's length and data +inline void sendString( + int socket, + const std::string& str, + bool moreData = false) { + SizeType size = str.size(); + sendBytes(socket, &size, 1, true); + sendBytes(socket, str.data(), size, moreData); +} + +// receive a string as sent in sendString +inline std::string recvString(int socket) { + SizeType valueSize = 0; + recvBytes(socket, &valueSize, 1); + std::vector value(valueSize); + recvBytes(socket, value.data(), value.size()); + return std::string(value.data(), value.size()); +} + +} // namespace tcputil +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/WinSockUtils.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/WinSockUtils.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4e94641b9b8ed2ce362b092398a6af0243aa4a81 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/WinSockUtils.hpp @@ -0,0 +1,30 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace c10d::tcputil { + +#define CONNECT_SOCKET_OFFSET 1 + +inline int poll(struct pollfd* fdArray, unsigned long fds, int timeout) { + return WSAPoll(fdArray, fds, timeout); +} + +inline void addPollfd( + std::vector& fds, + int socket, + short events) { + fds.push_back({(SOCKET)socket, events}); +} + +inline struct ::pollfd getPollfd(int socket, short events) { + struct ::pollfd res = {(SOCKET)socket, events}; + return res; +} + +} // namespace c10d::tcputil + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Work.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Work.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4f70b517c3f56898c8a33ca75a497c54ac956755 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/Work.hpp @@ -0,0 +1,194 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +constexpr auto kNoTimeout = std::chrono::milliseconds(0); + +namespace c10d { + +constexpr const char* const kSeqNumStoreKey = "SEQ_NUM_STORE_KEY"; + +enum class OpType : std::uint8_t { + BROADCAST = 0, + ALLREDUCE = 1, + ALLREDUCE_COALESCED = 2, + REDUCE = 3, + ALLGATHER = 4, + _ALLGATHER_BASE = 5, + ALLGATHER_COALESCED = 6, + GATHER = 7, + SCATTER = 8, + REDUCE_SCATTER = 9, + ALLTOALL_BASE = 10, + ALLTOALL = 11, + SEND = 12, + RECV = 13, + RECVANYSOURCE = 14, + BARRIER = 15, + _REDUCE_SCATTER_BASE = 16, + COALESCED = 17, + _ALLREDUCE_SPARSE = 18, + REDUCE_SCATTER_TENSOR_COALESCED = 19, + UNKNOWN = 100, +}; + +// TODO: support different types of failures/errors +enum class WorkResult : std::uint8_t { + SUCCESS = 0, + TIMEOUT = 1, + COMM_ERROR = 2, + UNKNOWN = 100, +}; + +// Converts OpType to human readable string. +TORCH_API std::string opTypeToString(OpType opType); + +// Whether or not an OP is an p2p op (SEND, RECV, RECVANYSOURCE) +TORCH_API bool isP2POp(OpType opType, bool batchP2P = false); + +// Please do not use Work API, it is going away, to be +// replaced by ivalue::Future. +// Python binding for this class might change, please do not assume +// this will be bound using pybind. +class TORCH_API Work : public torch::CustomClassHolder { + public: + Work( + int rank = -1, + OpType opType = OpType::UNKNOWN, + const char* profilingTitle = nullptr, + const std::optional>& inputTensors = + std::nullopt); + + ~Work() override; + + // Checks if request has completed. Non-blocking operation. + virtual bool isCompleted(); + + // Returns if the work completed successfully. + // If false, the exception function can be called to get details. + virtual bool isSuccess() const; + + // Returns exception if isSuccess() returned false. + virtual std::exception_ptr exception() const; + + // Returns source rank if this objects represents a recv-from-any. + virtual int sourceRank() const; + + // Returns result tensors, if applicable. + // If work is not supposed to have result, we return empty list. + virtual std::vector result(); + + // Ensures that operations on the output tensors that are invoked + // after this function returns are correctly sequenced after the + // asynchronous completion of this work. + // + // For CUDA tensors, it inserts stream synchronization such that + // the streams of the caller wait for completion of the + // asynchronous operations on the destination tensors. + // + // For CPU tensors, it is currently a nop. + // + // This function should only be used if the caller polls for + // completion through the `isCompleted` function, it has returned + // true, and the `isSuccess` function also has returned true. + // + virtual void synchronize(); + + // Waits until request completes. Blocking operation. + // Throws if the work completed with an exception. + // Returns false if the work is aborted. + // Otherwise, it always returns true, indicating the work is completed. + // + // Functionally equivalent to: + // + // while (!isCompleted()) { /* nop */ } + // auto success = isSuccess(); + // if (!success) { std::rethrow_exception(exception()); } + // return success; + // + virtual bool wait(std::chrono::milliseconds timeout = kNoTimeout); + + // Blocks the current stream until the work is completed. + // This is equivalent to synchronize for CUDA tensors but works for both CPU + // tensors and CUDA tensors by using a spinlock CUDA kernel. + // This will immediately return. + // If no stream is active it will throw an error. + virtual void blockCurrentStream(); + + virtual void abort(); + + // Returns a Future object that will be associated with the completion of + // work. Only NCCL backend is currently supported. + virtual c10::intrusive_ptr getFuture(); + + // Get a Future object that would be marked as either success or failure + // This API can be used by the user to track the completion of the work + // and handle the exception if any. + virtual c10::intrusive_ptr getFutureResult(); + + virtual float getDuration() const; + + virtual uint64_t getSequencenumber() const; + + OpType retrieveOpType() const; + + static c10::intrusive_ptr create_from_future( + const c10::intrusive_ptr& /*future*/); + + protected: + // Completes the work object and optionally sets the exception in a + // thread-safe manner. Notifies all waiting condition variables as well. + void finish(std::exception_ptr exception = nullptr); + + // Similar to finish, but throws an exception if one is already set or + // provided by the user. + void finishAndThrow(std::exception_ptr exception); + + mutable std::mutex mutex_; + std::condition_variable cv_; + bool completed_ = false; + std::exception_ptr exception_; + + // Current rank of the node. + const int rank_; + + // Operation type that this work object refers to. + OpType opType_; + + // When profiling, the callback to record end of operation event. This + // callback needs to be called when collective operation is complete. + std::function recordFunctionEndCallback_; +}; + +struct TORCH_API WorkInfo { + WorkInfo( + const OpType& opType, + const uint64_t seq, + const std::chrono::time_point& timeStarted, + const std::chrono::time_point& timeFinished, + const std::chrono::duration& activeDuration) + : opType(opType), + seq(seq), + timeStarted(timeStarted), + timeFinished(timeFinished), + activeDuration(activeDuration) {} + + OpType opType; + uint64_t seq; + std::chrono::time_point timeStarted; + std::chrono::time_point timeFinished; + std::chrono::duration activeDuration; +}; + +TORCH_API void set_comm_profiling_name(const std::string& name); +TORCH_API const std::string& get_comm_profiling_name(); + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/c10d.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/c10d.h new file mode 100644 index 0000000000000000000000000000000000000000..45daf59b55ab849b2e72bdf275a6c09315413ef0 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/c10d.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::distributed::c10d { + +PyMethodDef* python_functions(); + +} // namespace torch::distributed::c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/comm.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/comm.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e5099eb2980e5d3f38ab7aa723f5f92880b73d91 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/comm.hpp @@ -0,0 +1,147 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace c10d { + +// Broadcast many tensors to all processes in the process group. +TORCH_API void broadcast_coalesced( + const c10::intrusive_ptr& process_group, + at::TensorList tensors, + size_t buffer_size, + int rank = 0); + +// This class passes bucket contents tensor to DDP communication hook. +class TORCH_API GradBucket { + public: + explicit GradBucket( + size_t index, + size_t bucket_count, + at::Tensor tensor, + std::vector offsets, + std::vector lengths, + std::vector sizes_vec, + std::vector parameters, + std::optional sparse_grad_indices) + : index_(index), + bucket_count_(bucket_count), + buffer_(std::move(tensor)), + offsets_(std::move(offsets)), + lengths_(std::move(lengths)), + sizes_vec_(std::move(sizes_vec)), + parameters_(std::move(parameters)), + sparse_grad_indices_(std::move(sparse_grad_indices)) {} + + // Returns the index of the bucket, which is unique across all the buckets. + size_t getIndex() const { + return index_; + } + + const at::Tensor& getBuffer() const { + return buffer_; + } + + // Returns a mutable buffer compared with the above method. + at::Tensor& getBufferRef() { + return buffer_; + } + + // Overwrites the buffer at a specific index. + void setBuffer(at::Tensor& buffer) { + buffer_ = buffer; + } + + // Each tensor in the list that getGradients corresponds to a + // parameter. + std::vector getGradients() const; + + // Returns model parameters belonging to this bucket. They are returned in the + // same order as gradient tensors via getGradients(). For example, + // getParameters[i] will have its gradient stored in + // getGradients[i] + const std::vector getParameters() const { + return parameters_; + } + + // Returns whether this bucket is the last bucket to allreduce in an + // iteration. + bool isLast() const { + return index_ == bucket_count_ - 1; + } + + std::optional& getSparseGradIndices() { + return sparse_grad_indices_; + } + + private: + size_t index_; + size_t bucket_count_; + at::Tensor buffer_; + + // Per-variable info in buffer_. + std::vector offsets_; + std::vector lengths_; + std::vector sizes_vec_; + + // Model parameters for this bucket. + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const std::vector parameters_; + + // Predefined sparse indices for this bucket (only used for sparse tensors). + // The gradients will be updated to have indices with these tensor values + std::optional sparse_grad_indices_; +}; + +// Base class of both `PythonCommHook` and `CppCommHook`. +// Requires implementing 1) `runHook` method that communicates gradients +// asynchronously, and 2) `parseHookResult` method that converts the hook +// result into a tensor. +class TORCH_API CommHookInterface { + public: + virtual ~CommHookInterface() = default; + + // Passes the input grad bucket to the registered communication hook. + // Once the tensor in the bucket are ready, kicks off the hook asynchronously + // and returns a future that holds the communication results. + virtual c10::intrusive_ptr runHook( + GradBucket& bucket) = 0; + + // Returns the resulting tensor once the communication hook result is + // ready. The resulting tensor will then be copied to the grads of + // individual parameters. + virtual at::Tensor parseHookResult(const c10::IValue& result) = 0; +}; + +namespace detail { +// This helper function is called both by CppCommHookInterface below and inside +// reducer. +TORCH_API at::Tensor parseCppCommHookResult(const c10::IValue& result); +} // namespace detail + +// This CppCommHook interface only requires implementing runHook method that +// potentially uses a state. +template +class CppCommHookInterface : public CommHookInterface { + public: + explicit CppCommHookInterface(T state) : state_(std::move(state)) {} + + ~CppCommHookInterface() override = default; + + at::Tensor parseHookResult(const c10::IValue& result) override { + return detail::parseCppCommHookResult(result); + } + + protected: + T state_; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/control_collectives/ControlCollectives.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/control_collectives/ControlCollectives.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5beaa289331f4c3b81d3a279dddb8a3be6b51b38 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/control_collectives/ControlCollectives.hpp @@ -0,0 +1,64 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +namespace c10d { + +using namespace std::chrono_literals; + +class TORCH_API ControlCollectives : public torch::CustomClassHolder { + public: + virtual void barrier( + const std::string& key, + std::chrono::milliseconds timeout = 5min, + bool block = true) = 0; + + virtual void broadcastSend( + const std::string& key, + const std::vector& data, + std::chrono::milliseconds timeout = 5min) = 0; + virtual std::vector broadcastRecv( + const std::string& key, + std::chrono::milliseconds timeout = 5min) = 0; + + virtual void gatherSend( + const std::string& key, + const std::vector& data, + std::chrono::milliseconds timeout = 5min) = 0; + virtual std::vector> gatherRecv( + const std::string& key, + const std::vector& data, + std::chrono::milliseconds timeout = 5min) = 0; + + virtual std::vector scatterSend( + const std::string& key, + const std::vector>& data, + std::chrono::milliseconds timeout = 5min) = 0; + virtual std::vector scatterRecv( + const std::string& key, + std::chrono::milliseconds timeout = 5min) = 0; + + virtual std::vector> allGather( + const std::string& key, + const std::vector& data, + std::chrono::milliseconds timeout = 5min) = 0; + + virtual int64_t allSum( + const std::string& key, + int64_t data, + std::chrono::milliseconds timeout = 5min) = 0; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/control_collectives/StoreCollectives.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/control_collectives/StoreCollectives.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5782eb49f5755c1f2270428dd171260ad1d28a02 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/control_collectives/StoreCollectives.hpp @@ -0,0 +1,73 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +namespace c10d { + +class TORCH_API StoreCollectives : public ControlCollectives { + public: + explicit StoreCollectives( + c10::intrusive_ptr store, + int rank, + int worldSize); + + void barrier( + const std::string& key, + std::chrono::milliseconds timeout = 5min, + bool block = true) override; + + void broadcastSend( + const std::string& key, + const std::vector& data, + std::chrono::milliseconds timeout = 5min) override; + std::vector broadcastRecv( + const std::string& key, + std::chrono::milliseconds timeout = 5min) override; + + void gatherSend( + const std::string& key, + const std::vector& data, + std::chrono::milliseconds timeout = 5min) override; + std::vector> gatherRecv( + const std::string& key, + const std::vector& data, + std::chrono::milliseconds timeout = 5min) override; + + std::vector scatterSend( + const std::string& key, + const std::vector>& data, + std::chrono::milliseconds timeout = 5min) override; + std::vector scatterRecv( + const std::string& key, + std::chrono::milliseconds timeout = 5min) override; + + std::vector> allGather( + const std::string& key, + const std::vector& data, + std::chrono::milliseconds timeout = 5min) override; + + int64_t allSum( + const std::string& key, + int64_t data, + std::chrono::milliseconds timeout = 5min) override; + + private: + void enforceUnique(const std::string& key); + + private: + c10::intrusive_ptr store_; + int rank_; + int worldSize_; + + c10::FastSet seenKeys_; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/control_plane/Handlers.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/control_plane/Handlers.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bf79294f23d5515edbe5c98dc20b6b1ae16fdb5a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/control_plane/Handlers.hpp @@ -0,0 +1,82 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include + +namespace c10d::control_plane { + +// Request represents a request to the handler. This conceptually maps to an +// HTTP request but could be called via other transports. +class TORCH_API Request { + public: + virtual ~Request() = default; + + virtual const std::string& body() const = 0; + + virtual const std::multimap& params() const = 0; + + std::string getParam(const std::string& key) const { + auto it = params().find(key); + if (it != params().end()) { + return it->second; + } + return ""; + } +}; + +// Response represents a response to the handler. This conceptually maps to an +// HTTP response but could be called via other transports. +class TORCH_API Response { + public: + virtual ~Response() = default; + + // Set the response body to the provided string. + // TODO: add support for chunked responses + virtual void setContent( + std::string&& content, + const std::string& content_type) = 0; + + // Set the response status code. + // These should match standard HTTP status codes. + virtual void setStatus(int status) = 0; +}; + +using HandlerFunc = std::function; + +// Registers a handler. The name needs to be unique and can be called by using +// getHandler directly or via WorkerServer for remote requests. +// These handlers are called from a background C++ thread concurrently with the +// main thread. These handlers need to be thread safe and not cause issues +// during Python training. +TORCH_API void registerHandler(const std::string& name, HandlerFunc f); + +// Fetches a handler by name. +TORCH_API HandlerFunc getHandler(const std::string& name); + +TORCH_API std::vector getHandlerNames(); + +// Registers a handler statically. +// See registerHandler for more details. +class TORCH_API RegisterHandler { + public: + RegisterHandler(const std::string& name, HandlerFunc f) { + registerHandler(name, std::move(f)); + } + + // disable move, copy + RegisterHandler(const RegisterHandler&) = delete; + RegisterHandler(RegisterHandler&&) = delete; + RegisterHandler& operator=(const RegisterHandler&) = delete; + RegisterHandler& operator=(RegisterHandler&&) = delete; +}; + +} // namespace c10d::control_plane + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/control_plane/WaitCounterHandler.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/control_plane/WaitCounterHandler.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b6e73ec065fe5b1b094f4fabd97ad887a9b94b68 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/control_plane/WaitCounterHandler.hpp @@ -0,0 +1,20 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace c10d { +namespace control_plane { + +// Returns all wait counter values as a JSON string +std::string getWaitCounterValuesJson(); + +// Ensures the wait counter backend is registered +void ensureWaitCounterBackendRegistered(); + +} // namespace control_plane +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/control_plane/WorkerServer.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/control_plane/WorkerServer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9ffaa77726734d694015d8900ae759b762deff6b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/control_plane/WorkerServer.hpp @@ -0,0 +1,37 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include +#include + +C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED("-Wdeprecated-literal-operator") +#include +C10_DIAGNOSTIC_POP() + +namespace c10d::control_plane { + +class TORCH_API WorkerServer : public c10::intrusive_ptr_target { + public: + WorkerServer(const std::string& hostOrFile, int port = -1); + ~WorkerServer() override; + + void shutdown(); + + int port() { + return port_; + } + + private: + httplib::Server server_; + std::thread serverThread_; + int port_; +}; + +} // namespace c10d::control_plane + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/cuda/CUDAEventCache.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/cuda/CUDAEventCache.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e289e3d0aff7561ab197ce8c3e18ccf33d2c9ff9 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/cuda/CUDAEventCache.hpp @@ -0,0 +1,34 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace c10d { + +class TORCH_API CUDAEventCache + : public std::enable_shared_from_this { + public: + CUDAEventCache(); + std::shared_ptr create(bool timing); + static std::shared_ptr get(at::DeviceIndex device); + + private: + std::mutex cacheMutex_; + // NOTE: We intentionally store raw pointers so that + // we do not attempt to destroy the event objects on process exit, + // because cuda may be gone. + std::array, 2> + eventsArray_; // 0 for timing=false, 1 for timing=true +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/cuda/StreamBlock.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/cuda/StreamBlock.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8195a6faa33d4f86c771ff08b254022e43b3cacd --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/cuda/StreamBlock.hpp @@ -0,0 +1,43 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include + +namespace c10d::cuda { + +enum StreamBlockStatus : int32_t { + UNKNOWN = 0, + RUNNING = 1, + TIMED_OUT = 2, + ABORTED = 3, +}; + +/* +StreamBlock implements a baton that will block a the active CUDA stream +until aborted by the main process. +*/ +class TORCH_API StreamBlock { + public: + virtual ~StreamBlock() = default; + virtual void abort() = 0; + virtual StreamBlockStatus status() = 0; +}; + +std::unique_ptr block_stream(std::chrono::milliseconds timeout); + +// Declare a registry so we can call the CUDA StreamBlock API from CPU only code +// (i.e. ProcessGroup/Work objects in libtorch_cpu). +// The implementation lives defined in StreamBlock.cu. +TORCH_DECLARE_REGISTRY( + StreamBlockRegistry, + StreamBlock, + std::chrono::milliseconds); + +} // namespace c10d::cuda + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/cuda/utils.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/cuda/utils.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d8a2520f4fd00d62e506f65e8645c1b035fee2c7 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/cuda/utils.hpp @@ -0,0 +1,15 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +// This file contains utility functions common for CUDA, which can be used by +// ProcessGroupNCCL or SymmetricMemory. + +namespace c10d::cuda { + +bool deviceSupportsMulticast(int device_idx); + +} // namespace c10d::cuda + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/debug.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/debug.h new file mode 100644 index 0000000000000000000000000000000000000000..cf343d0eef5a8b1a06ab96d0fbf0a19aaa61f87f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/debug.h @@ -0,0 +1,28 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// Copyright (c) Meta Platforms, Inc. and its affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include + +namespace c10d { + +enum class DebugLevel { Off = 0, Info = 1, Detail = 2 }; + +TORCH_API void setDebugLevel(DebugLevel level); + +// Sets the debug level based on the value of the `TORCH_DISTRIBUTED_DEBUG` +// environment variable. +TORCH_API void setDebugLevelFromEnvironment(); + +TORCH_API DebugLevel debug_level() noexcept; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/default_comm_hooks.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/default_comm_hooks.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c56d6097a4d48dfe170ebab6b5e49d7f8504e83e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/default_comm_hooks.hpp @@ -0,0 +1,57 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace c10d { + +enum class BuiltinCommHookType : uint8_t { + ALLREDUCE = 1, + FP16_COMPRESS = 2, +}; + +class AllReduceCommHook + : public CppCommHookInterface> { + public: + explicit AllReduceCommHook(const c10::intrusive_ptr& state) + : CppCommHookInterface>(state) {} + + ~AllReduceCommHook() override = default; + + c10::intrusive_ptr runHook(GradBucket& bucket) override; +}; + +class FP16CompressCommHook + : public CppCommHookInterface> { + public: + explicit FP16CompressCommHook(const c10::intrusive_ptr& state) + : CppCommHookInterface>(state) {} + + ~FP16CompressCommHook() override = default; + + c10::intrusive_ptr runHook(GradBucket& bucket) override; +}; + +// Almost same as AllReduceCommHook, but without division inside the hook. +// This enables the optimization of fusing copy and division and saves one scan +// over all the input parameters, when no communication hook is provided by the +// user. Only used internally and not released as a public built-in +// communication hook. +class _AllReduceBySumCommHook + : public CppCommHookInterface> { + public: + explicit _AllReduceBySumCommHook( + const c10::intrusive_ptr& state) + : CppCommHookInterface>(state) {} + + ~_AllReduceBySumCommHook() override = default; + + c10::intrusive_ptr runHook(GradBucket& bucket) override; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/error.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/error.h new file mode 100644 index 0000000000000000000000000000000000000000..e4e1a3e2d2be49904528720168ffc383b4332f9e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/error.h @@ -0,0 +1,58 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// Copyright (c) Facebook, Inc. and its affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include +#include + +#include + +namespace fmt { + +template <> +struct formatter { + constexpr auto parse(format_parse_context& ctx) const { + return ctx.begin(); + } + + template + auto format(const std::error_category& cat, FormatContext& ctx) const { + if (std::strcmp(cat.name(), "generic") == 0) { + return fmt::format_to(ctx.out(), "errno"); + } else { + return fmt::format_to(ctx.out(), "{} error", cat.name()); + } + } +}; + +template <> +struct formatter { + constexpr auto parse(format_parse_context& ctx) const { + return ctx.begin(); + } + + template + auto format(const std::error_code& err, FormatContext& ctx) const { + return fmt::format_to( + ctx.out(), "({}: {} - {})", err.category(), err.value(), err.message()); + } +}; + +} // namespace fmt + +namespace c10d::detail { + +inline std::error_code lastError() noexcept { + return std::error_code{errno, std::generic_category()}; +} + +} // namespace c10d::detail + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/exception.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/exception.h new file mode 100644 index 0000000000000000000000000000000000000000..a79a93048797ceba3740f83fbef2b05ff5516121 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/exception.h @@ -0,0 +1,45 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// @allow-raw-throw +// Copyright (c) Facebook, Inc. and its affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include +#include + +// Utility macro similar to C10_THROW_ERROR, the major difference is that this +// macro handles exception types defined in the c10d namespace, whereas +// C10_THROW_ERROR requires an exception to be defined in the c10 namespace. +#define C10D_THROW_ERROR(err_type, ...) \ + throw ::c10d::err_type( \ + {__func__, __FILE__, static_cast(__LINE__)}, \ + c10::str(__VA_ARGS__)) + +#define C10D_CHECK_WITH(error_t, cond, ...) \ + if (C10_UNLIKELY_OR_CONST(!(cond))) { \ + C10D_THROW_ERROR( \ + error_t, TORCH_CHECK_MSG(cond, "", c10::str(__VA_ARGS__))); \ + } + +namespace c10d { + +using c10::DistNetworkError; +using c10::DistStoreError; + +class TORCH_API SocketError : public DistNetworkError { + using DistNetworkError::DistNetworkError; +}; + +class TORCH_API TimeoutError : public DistNetworkError { + using DistNetworkError::DistNetworkError; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/logger.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/logger.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9cb5cf16044d0e6fc6b6a8fdd8774a17c7cfcaf4 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/logger.hpp @@ -0,0 +1,176 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include + +namespace c10d { + +// A struct to hold the latest status of the process group. +struct ProcessGroupStatus { + // the sequential number of the last collective enqueued into workMetaList_ + // This is useful for identifying a rank that has not join a collective + // initialized to be -1 to indicate no collective has been enqueued + int64_t lastEnqueuedSeq{-1}; + // the sequential number of the last collective started as the kernel + int64_t lastStartedSeq{-1}; + // the sequential number of the last collective completed marked by + // the watchdog thread + // initialized to be -1 to indicate no collective has been completed + int64_t lastCompletedSeq{-1}; + + // the name of the last collective enqueued into workMetaList_ + std::string lastEnqueuedWorkName; + // the name of the last collective started as the kernel + std::string lastStartedWorkName; + // the name of the last collective completed + std::string lastCompletedWorkName; + + // the sizes of the last work enqueued + size_t lastEnqueuedNumelIn; + size_t lastEnqueuedNumelOut; + // the sizes of the last work completed + size_t lastCompletedNumelIn; + size_t lastCompletedNumelOut; + // the sizes of the last work started + size_t lastStartedNumelIn; + size_t lastStartedNumelOut; +}; + +class TORCH_API Logger { + public: + explicit Logger(std::shared_ptr reducer); + // Set logging data that can be got during DistributedDataParallel + // construction time. + void set_construction_data_and_log( + const std::string& module_name, + const std::vector& device_ids, + int output_device, + bool broadcast_buffers, + bool has_sync_bn, + bool static_graph); + + void set_static_graph(); + + // An interface for users to get DDPLoggingData and log them + // in the applications. Explanation of logging fields are in + // "struct DDPLoggingData" of "torch/c10/util/Logging.h". + at::DDPLoggingData get_ddp_logging_data(); + + // Stream insertion operator for logging data to stream under + // TORCH_DISTRIBUTED_DEBUG. + friend std::ostream& operator<<(std::ostream& output, const Logger& logger); + + ~Logger() noexcept(false) { + // Log if DDP graph is static in Logger dtor instead of Reducer dtor since + // Logger is deleted before Reducer. + log_if_graph_static(reducer_->ddp_graph_static()); + } + + // Set environment variables. + void set_env_variables(); + // Set parameters stats. + void set_parameter_stats(); + // Get size of each bucket (Bytes). + std::vector get_bucket_sizes(); + // Get variable indices for each bucket. + std::vector> get_per_bucket_variable_indices(); + // Set comm. hook, if used + void set_comm_hook(const std::string& hook); + // Set running with uneven input detection (model.join() context manager) + void set_uneven_input_join(); + + // Reset performance stats at current iteration + void reset_performance_stats(); + + // Calculate avg stats using cpu timer and gpu timer + // that has been recorded in reducer. + void calculate_avg_time( + int64_t& avg_time, + int64_t& time_duration, + Timer& timer, + Timer::Event start_event, + Timer::Event end_event); + + // Set the absolute time of the event that has been recorded in reducer. + void set_event_time(int64_t& event_time, Timer& timer, Timer::Event event); + // Set stats that can be collected only during + // training loop. It is called at the beginning of forward call + // to record the run time stats of sampled iterations that previously ran. + // GPU performance stats are collected only for single process + // single device program and single device module right now. + // TODO to support single process multiple devices and multi device modules, + // events need to be created and recorded on multiple devices. + void set_runtime_stats_and_log(); + + // Called when DDP/reducer is failing with an error. The + // logging data structure will have two fields filled: "has_error" indicating + // that this iteration encountered an error and other fields are not valid, + // and "error", a string which contains the error message that DDP failed + // with. + template + void set_error_and_log(const std::string& ddp_error, const Args&... args) { + ddp_logging_data_->ints_map["has_error"] = 1; + auto err = c10::str(ddp_error, args...); + ddp_logging_data_->strs_map["error"] = err; + // Report the iteration we are erroring at so user knows how many examples + // successfully processed before this error was hit. + ddp_logging_data_->ints_map["iteration"] = reducer_->num_iterations_; + at::LogPyTorchDDPUsage(*ddp_logging_data_); + } + + // When running without static graph, called when reducer is destroyed to log + // if graph was actually static and is a candidate for static graph + // optimization. + void log_if_graph_static(bool is_static); + + private: + // ddp_logging_data_ is used to hold all the ddp related logging + // data fields. + std::unique_ptr ddp_logging_data_; + std::shared_ptr reducer_; + // track the number of iterations when runtime stats are collected so far. + long num_iterations_stats_recorded_ = 0; +}; + +// a generic logging data struct that holds different types of logging data. +// starting with key value pairs of strings and integers, +// It can be extended to more types as needed. +struct C10dLoggingData { + // logging fields that are string types. + std::map strings; + // logging fields that are int64_t types. + std::map integers; +}; + +class TORCH_API C10dLogger { + public: + C10dLogger(const C10dLogger&) = default; + C10dLogger(C10dLogger&&) = delete; + C10dLogger& operator=(const C10dLogger&) = default; + C10dLogger& operator=(C10dLogger&&) = delete; + virtual ~C10dLogger() = default; + virtual void log(const C10dLoggingData& data); + static C10dLogger* getLogger(); + static void registerLogger(std::unique_ptr /*logger*/); + + protected: + // singletion, hide constructor from the public + C10dLogger(std::string logDestination) + : logDestination_(std::move(logDestination)) {} + + // the name of the destination this logger should log to + std::string logDestination_; + + private: + static std::unique_ptr logger_; + static std::atomic registered_; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/logging.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/logging.h new file mode 100644 index 0000000000000000000000000000000000000000..596e4686212800c6ac419ac9fd77519d90257160 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/logging.h @@ -0,0 +1,52 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// Copyright (c) Meta Platforms, Inc. and its affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include + +#include +#include +#include + +namespace c10d::detail { + +enum class LogLevel { Trace, Debug, Info, Warning, Error }; + +TORCH_API bool isLogLevelEnabled(LogLevel level) noexcept; + +template +// NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) +std::string formatLogMessage(fmt::string_view fmt, T&&... args) { + return fmt::vformat(fmt, fmt::make_format_args(args...)); +} + +} // namespace c10d::detail + +#define C10D_ERROR(...) \ + if (c10d::detail::isLogLevelEnabled(c10d::detail::LogLevel::Error)) \ + LOG(ERROR) << "[c10d] " << c10d::detail::formatLogMessage(__VA_ARGS__) + +#define C10D_WARNING(...) \ + if (c10d::detail::isLogLevelEnabled(c10d::detail::LogLevel::Warning)) \ + LOG(WARNING) << "[c10d] " << c10d::detail::formatLogMessage(__VA_ARGS__) + +#define C10D_INFO(...) \ + if (c10d::detail::isLogLevelEnabled(c10d::detail::LogLevel::Info)) \ + LOG(INFO) << "[c10d] " << c10d::detail::formatLogMessage(__VA_ARGS__) + +#define C10D_DEBUG(...) \ + if (c10d::detail::isLogLevelEnabled(c10d::detail::LogLevel::Debug)) \ + LOG(INFO) << "[c10d - debug] " << c10d::detail::formatLogMessage(__VA_ARGS__) + +#define C10D_TRACE(...) \ + if (c10d::detail::isLogLevelEnabled(c10d::detail::LogLevel::Trace)) \ + LOG(INFO) << "[c10d - trace] " << c10d::detail::formatLogMessage(__VA_ARGS__) + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/python_callback_work.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/python_callback_work.hpp new file mode 100644 index 0000000000000000000000000000000000000000..27c25dc8235c65258a8fa05d88eca27ceb87416a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/python_callback_work.hpp @@ -0,0 +1,33 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace c10d { + +// PythonCallbackWork is a subclass of Work that wraps a Python callback +// function that implements wait(). This allows asynchronous work to +// be integrated with Python code, enabling custom completion logic or +// post-processing in Python. +class PythonCallbackWork : public Work { + public: + explicit PythonCallbackWork(py::function callback); + + ~PythonCallbackWork() override; + + bool wait(std::chrono::milliseconds timeout) override; + + c10::intrusive_ptr getFuture() override; + + private: + py::function callback_; + c10::intrusive_ptr future_; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/python_comm_hook.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/python_comm_hook.h new file mode 100644 index 0000000000000000000000000000000000000000..e6e985f87ced478c67147c8405303e682aac7403 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/python_comm_hook.h @@ -0,0 +1,39 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include +#include +#include +#include + +namespace c10d { + +class TORCH_PYTHON_API PythonCommHook : public CommHookInterface { + public: + // Takes a state and a callable hook. The inputs are Python objects. + // The state is passed to the hook in runHook method, and it can be used to + // maintain and update any state information during the execution of the hook. + // The hook performs user-specified processing and returns a future indicating + // asynchronous communication of gradients. + PythonCommHook(py::object state, py::object hook) + : state_(std::move(state)), hook_(std::move(hook)) {} + + ~PythonCommHook() override; + + c10::intrusive_ptr runHook(GradBucket& bucket) override; + + at::Tensor parseHookResult(const c10::IValue& result) override; + + private: + // Only needed for stateful communication. + py::object state_; + py::object hook_; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/quantization/quantization.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/quantization/quantization.h new file mode 100644 index 0000000000000000000000000000000000000000..08e8f2948af7ec89093fb8c7701bf7e2fe21a696 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/quantization/quantization.h @@ -0,0 +1,20 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// Copyright (c) Meta Platforms, Inc. and affiliates. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include + +namespace torch::distributed::c10d::quantization { + +at::Tensor _float_to_bfloat16_cpu(const at::Tensor& input); +at::Tensor _bfloat16_to_float_cpu(const at::Tensor& input); + +} // namespace torch::distributed::c10d::quantization + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/quantization/quantization_gpu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/quantization/quantization_gpu.h new file mode 100644 index 0000000000000000000000000000000000000000..9c21a8f5a07cfab89ce47f08d201abb1f7e1bb32 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/quantization/quantization_gpu.h @@ -0,0 +1,20 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// Copyright (c) Meta Platforms, Inc. and affiliates. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include + +namespace torch::distributed::c10d::quantization { + +at::Tensor _float_to_bfloat16_cuda(const at::Tensor& input); +at::Tensor _bfloat16_to_float_cuda(const at::Tensor& input); + +} // namespace torch::distributed::c10d::quantization + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/quantization/quantization_utils.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/quantization/quantization_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..a2a6a171ba92a0741a7cc6f1990987917ff1b657 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/quantization/quantization_utils.h @@ -0,0 +1,39 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// Copyright (c) Meta Platforms, Inc. and affiliates. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include + +#include + +inline std::string torch_tensor_device_name(const at::Tensor& ten) { + return c10::DeviceTypeName(ten.device().type()); +} + +#define TENSOR_NDIM_EQUALS(ten, dims) \ + TORCH_CHECK( \ + (ten).ndimension() == (dims), \ + "Tensor '" #ten "' must have " #dims \ + " dimension(s). " \ + "Found ", \ + (ten).ndimension()) + +#define TENSOR_ON_CPU(x) \ + TORCH_CHECK( \ + !x.is_cuda(), \ + #x " must be a CPU tensor; it is currently on device ", \ + torch_tensor_device_name(x)) + +#define TENSOR_ON_CUDA_GPU(x) \ + TORCH_CHECK( \ + x.is_cuda(), \ + #x " must be a CUDA tensor; it is currently on device ", \ + torch_tensor_device_name(x)) + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/reducer.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/reducer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ee1f83bea3da04a63ef43d4ecb8ad2442e9a9d64 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/reducer.hpp @@ -0,0 +1,624 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef _WIN32 +#include +#endif + +namespace c10d { + +constexpr int kDefaultFirstBucketBytes = 1024 * 1024; +constexpr int kDefaultBucketBytesCap = 25 * 1024 * 1024; +// Collect runtime stats once for every kDDPRuntimeLoggingSampleRate iterations. +constexpr int kDDPRuntimeLoggingSampleRate = 100; + +// Forward declaration +class Logger; + +// Local accumulator type for a single bucket. +struct BucketAccumulator { + std::vector indices; + size_t size = 0; + size_t size_limit = 0; +}; + +class TORCH_API Reducer { + public: + // The constructor takes a list of variables (i.e. parameters) for this + // process's single model replica (as DDP assumes single-process + // single-device). The bucket assignment for this reducer, `bucket_indices`, + // is specified as a list of buckets, each of which is specified as a list of + // indices into the bucket's `variables` list. + explicit Reducer( + std::vector params, + std::vector> bucket_indices, + c10::intrusive_ptr process_group, + std::vector expect_sparse_gradients, + int64_t bucket_bytes_cap, + bool find_unused_parameters, + bool gradient_as_bucket_view, + std::unordered_map param_names, + int64_t first_bucket_bytes_cap, + bool skip_all_reduce_unused_params, + bool use_python_reducer, + std::vector bucket_bytes_cap_list, + bool batched_grad_copy = false); + + ~Reducer() noexcept(false); + + // To (re-)initialize bucket assignment, pass a list of buckets, each of + // which is specified by a list of indices in the bucket's `variables` list. + // This function performs validation that the variables within a bucket + // all live on the same device and have the same dimensionality. + void initialize_buckets(std::vector> bucket_indices); + + void autograd_hook(size_t index); + + // This function is called when the forward function has produced an output, + // and the user wishes to reduce gradients in the backwards pass. + // If they don't, and wish to accumulate gradients before reducing them, + // a call to this function can simply be omitted. + void prepare_for_backward(const std::vector& outputs); + + // Called at the beginning of forward() inside DistributedDataParallel, + // right now it captures the starting time of forward in each iteration. + void prepare_for_forward(); + + // Returns the relative time in nanoseconds when gradients were ready, + // with respect to the time `prepare_for_backward` was called. The + // vector is for parameters for a single model replica. + std::vector get_backward_stats() const { + return backward_stats_; + } + + // Registers a hook to the reducer. The hook is `CommHookInterface` + // type to allow both Python and CPP hooks. This function can only + // be called once before calling backward. + // Cannot combine with the call of `register_builtin_comm_hook`. + void register_comm_hook(std::unique_ptr iface); + + // Registers a built-in C++ comm hook to the reducer. This function can only + // be called once before calling backward. + // Cannot combine with the call of `register_comm_hook`. + void register_builtin_comm_hook(c10d::BuiltinCommHookType comm_hook_type); + + // Informs reducer that optimizer is running in backward, so gradients + // don't need to be copied from buckets as the optimizer would've already + // been applied. + void set_optimizer_in_backward() { + optim_in_backward_ = true; + } + + // Runs allreduce or installed communication hook given GradBucket instance. + c10::intrusive_ptr run_comm_hook( + GradBucket& grad_bucket); + + // Runs default allreduce hook. + c10::intrusive_ptr run_allreduce_hook( + GradBucket& grad_bucket); + + // Returns gradient buckets in sequential order of buckets_. This is the order + // in which buckets are reduced across processes. If return_zero_tensors=true, + // will return zero tensors of the same shape instead of the true tensors. + std::vector get_grad_buckets( + bool return_zero_tensors = true) const; + + // Rebuild buckets based on rebuilt_params_ and rebuilt_param_indices_ + // according to when tensors received grads in the backward pass. + // TODO this function makes broadcast communication call and + // could be overlapped with next forward() call, thus + // it could be async. Will make it async when rebuilding buckets for + // find_unused_parameters = true case, as we could rebuild buckets more than + // once for find_unused_parameters = true case, where subgraphs are trained + // and parameter indices order may change more frequently. + // For find_unused_parameters = false case, buckets are only rebuilt once, + // the performance cost is negligible. Returns true if the buckets were + // rebuilt. + bool rebuild_buckets(); + + void setSparseMetadata(std::map& metadata); + + // Install futures that should be awaited at end of backwards. Currently these + // are only used by user-defined custom buffer reduction hooks, but can be + // generalized to any user-originating futures that need to be awaited. + void install_futures( + const c10::List>& futs); + + // Returns true if we should rebuild buckets, else false. We only rebuild + // buckets once after the first iteration and never rebuild them if + // find_unused_parameters_. + inline bool should_rebuild_buckets() const { + return (static_graph_ || !find_unused_parameters_) && !has_rebuilt_bucket_; + } + + // Pushes all parameters to be rebuilt. + void push_rebuilt_params_for_all_indices(); + + // Creates and sets ForwardPassWorkHandle given a Work and the + // corresponding tensor being reduced. + void set_forward_pass_work_handle( + c10::intrusive_ptr forwardPassWorkHandle, + bool useStaticWorldSize); + + // Retrieve on-device tensors used to track locally unused parameters. It is + // a tensor where index i = 1 if the Variable with that index has been used. + at::Tensor get_local_used_map_on_device() const; + + // An function for users to set sample_rate of collecting + // runtime stats. The time stats will be recorded for the + // first 10 iterations, after 10 iterations time stats will be + // recorded once every "sample_rate" training iterations. + void set_ddp_runtime_logging_sample_rate(int sample_rate); + + // Specify the training graph is static. + void set_static_graph(); + + // Delay all reduce to be after all gradients' calculation is complete. + void delay_all_reduce(); + + void set_mixed_precision_param_dtype(c10::ScalarType dtype); + + // Weak reference to associated DDP logger. The reference is weak to avoid + // refcycle between reducer and logger. + void set_logger(std::weak_ptr logger); + + // When graph is not explicitly set by user as static and has unused + // parameters, this will return whether the graph has been static until the + // current iteration, which means unused params set has not changed. + bool ddp_graph_static(); + + // Removes autograd hooks registered by the Reducer on the model parameters. + void remove_autograd_hooks(); + + // Checks whether or not the reducer has finalized the current backward + // iteration. + void check_finalized(); + + // Updates the underlying process group used by DDP with the new process + // group. + void update_process_group( + c10::intrusive_ptr new_process_group); + + // Resets reducer state. + void reset_state(); + + protected: + // Forward declaration. + struct Bucket; + + void push_rebuilt_params(const size_t& index); + + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + mutable std::mutex mutex_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const std::vector params_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + c10::intrusive_ptr<::c10d::ProcessGroup> process_group_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + std::vector expect_sparse_gradients_; + + std::vector> + grad_accumulators_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + std::unordered_map gradAccToVariableMap_; + std::vector>> + hooks_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) + + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + bool expect_autograd_hooks_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + bool require_finalize_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + size_t next_bucket_; + + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + bool has_marked_unused_parameters_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const bool find_unused_parameters_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const bool gradient_as_bucket_view_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const bool batched_grad_copy_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + std::vector unused_parameters_; + // Previous iteration's unused params, used for checking if unused parameters + // change between iterations. Only filled during the first backwards call. + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + std::vector prev_iteration_unused_parameters_; + // Whether graph is static or not. When user does not explicitly set static + // graph, the only possible dynamism is set of unused parameters changing + // between iterations which is tracked by this flag. + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + bool ddp_graph_static_{true}; + // Locally used parameter maps indicating if parameters are used locally + // during the current iteration or no_sync session if no_sync is on. + // Each map is a one-dim int32 tensor of number of parameters. These tensors + // are marked in autograd_hook to indicate the corresponding param has been + // used, and get allreduced in the end of backward step of current iteration + // or no_sync session for figuring out the globally unused parameters. + // + // local_used_map_: CPU tensor for bookkeeping locally used params + // local_used_map_dev_: dev tensor for reducing globally unused params + at::Tensor local_used_map_; + at::Tensor local_used_map_dev_; + // Indicate that reduction is done and D2H copy is done as well. + bool local_used_map_reduced_; + + // Weak pointer to associated DDP logger. + std::weak_ptr logger_; + // List of futures installed by Reducer::install_futures that should be + // awaited at the end of backwards pass. + std::optional>> + installed_futures_{std::nullopt}; + // Mixed precision parameter dtype for bucket type checking. + std::optional mixed_precision_param_dtype_{std::nullopt}; + + // Work handle for allreduce on local_used_map_ + c10::intrusive_ptr local_used_work_; + + void mark_variable_ready_dense(size_t variable_index); + + void mark_variable_ready_sparse(size_t variable_index); + + void mark_variable_ready(size_t variable_index); + + void mark_bucket_ready(size_t bucket_index); + + void finalize_bucket_dense(Bucket& bucket); + + void finalize_backward(); + + // Returns list of model parameters corresponding to the given bucket. + // bucket_index is a key to cache after buckets are rebuilt, after which this + // mapping never changes. + std::vector get_variables_for_bucket( + size_t bucket_index, + const Bucket& bucket) const; + + // Asserts that the reduction for the previous iteration has finished before + // rebuilding buckets or kicking off the next one. + void ensure_prior_reduction_finished(); + + // Broadcast rebuilt buckets from rank 0 to other ranks before initializing + // the buckets + void sync_bucket_indices(std::vector>& bucket_indices); + + // We'd like to use DistAutogradContext::GradCallback here but dist autograd + // doesn't exist under Windows. So we just directly use the concrete type but + // to preserve and enforce our original intent we do a static assert when dist + // autograd is available. + using GradCallback = std::function; +#ifndef _WIN32 + static_assert( + std::is_same_v< + GradCallback, + torch::distributed::autograd::DistAutogradContext::GradCallback>); +#endif + void runGradCallbackForVariable(at::Tensor& variable, const GradCallback& cb); + + // Flushes deferred grad-to-bucket copies for a single bucket when + // batched_grad_copy_ is enabled. Called from mark_variable_ready (when + // bucket.pending == 0) and from delay_all_reduce (after all variables + // are marked ready). + void flush_deferred_copies(Bucket& bucket, size_t bucket_index); + + // This function is called inside `initialize_buckets()`. It initializes both + // `bucket_views_in` and `bucket_views_out` with views for each variable's + // gradient into the bucket's flattened `gradients` tensor. Views serve as + // entry points to `copy_()` each grad's data in/out of the flattened + // `gradients` tensor. + void initialize_bucket_views(Bucket& bucket); + + // This function is called inside `finalize_backward`, it happens only if + // DDP communication hook was registered to recreate just bucket_views_out + // with the result of `future_work`. + void populate_bucket_views_out(Bucket& bucket, at::Tensor& tensor); + + // If gradient_as_bucket_view_ is false, after allreduce buckets, + // copy bucket results back to grads. + void copy_bucket_to_grad( + at::Tensor& variable, + Reducer::Bucket& bucket, + size_t intra_bucket_index, + bool global_unused); + // Check layout of grad and bucket_view before copying the grad to bucket. + void check_grad_layout(const at::Tensor& grad, const at::Tensor& bucket_view); + + // A bucket contains [1..N] gradients to be reduced, where the gradients + // have the same dtype and device. + // Coalescing gradients together before reducing can result in lower overhead + // and/or faster time to completion. Coalescing requires the constituent + // gradients to have the same dtype and device, and the resulting flattened + // tensor uses that common dtype and device. The flattened tensor is filled + // as the corresponding gradients are computed (triggered by autograd hooks), + // and the buckets are reduced in a predetermined order consistent across + // processes. + struct Bucket { + // Gradients of the bucket flattened into a 1-dimensional tensor + at::Tensor gradients; + + // Views into the `gradients` tensor for each individual gradient + // Each view is created with layout (size and stride) matching the + // gradient's expected layout (see the "Gradient Layout Contract" in + // torch/csrc/autograd/functions/accumulate_grad.h). + // `bucket_views_in[i].copy_(grad)` and `grad.copy_(bucket_views_out[i])` + // provide convenient ways to copy gradient data in/out of `gradients`, + // respectively. + // We keep both `bucket_views_in` and `bucket_views_out` because + // registering a DDP communication hook may re-initialize + // `bucket_views_out` with the value of the hook's `future_work` but we + // still need separate views into the bucket's original flattened gradient + // to copy in gradient data. + std::vector bucket_views_in; + std::vector bucket_views_out; + + // Variables whose gradients are held in this bucket + // We use refcounted tensors here so that we can easily unflatten the + // bucket's flattened `gradients` tensor into the participating variables + // after reduction has completed. + std::vector variables; + + // Per-variable offset/length into the flattened `gradients` tensor and + // the corresponding `GradBucket` instance for communication hooks + std::vector offsets; + std::vector lengths; + + // Per-variable sizes slicing into the bucket's `gradients` tensor + std::vector sizes_vec; + + // Number of gradients left to be computed before the bucket is ready to + // be reduced + size_t pending; + + // Global indices of participating variables in the bucket + std::vector variable_indices; + + // Future work handle for DDP communication hook + // If no hook is registered, a temporary vanilla allreduce hook is used. + c10::intrusive_ptr future_work; + + // if this bucket contains complex parameters + bool is_complex_bucket = false; + + // If this bucket should expect a single sparse gradient + // If `true`, then this implies that `bucket.variables.size() == 1`. + bool expect_sparse_gradient = false; + + // Sparse indices tensor + std::optional sparse_tensor_indices = std::nullopt; + + // TODO(@pietern) + // Memory copies from gradient tensors into the bucket are potentially + // done on different CUDA streams. We record an event for every copy + // so that we can synchronize with them prior to kicking off the reduction. + // std::vector events; + + // Intra-bucket indices of variables whose grad-to-bucket copies are + // deferred for batching. Flushed as _foreach_copy_ + flat div_ when + // pending == 0. Only used when batched_grad_copy is enabled. + std::vector deferred_copy_indices; + }; + + std::vector buckets_; + + // A variable locator locates a particular variable in the reducer's buckets + struct VariableLocator { + // Index of the bucket containing the variable in the `buckets_` vector + size_t bucket_index; + // Index of the variable in the bucket, which may be used consistently + // across `bucket_views_in`, `bucket_views_out`, `variables`, `offsets`, + // `lengths`, `sizes_vec`, and `variable_indices` in `Bucket` + size_t intra_bucket_index; + + VariableLocator() = default; + + VariableLocator(size_t bucket_index_, size_t intra_bucket_index_) + : bucket_index(bucket_index_), + intra_bucket_index(intra_bucket_index_) {} + }; + + // Map the index of a variable to its location in the bucket structure. + std::vector variable_locators_; + + // track the number of iterations to synchronize grads in training so far. + long num_iterations_; + // track distinct iteration of backward call. This is distinct from + // num_iterations_, for example in the case of multiple forward before + // backward. + long num_bwd_calls_; + // whether the first autograd hook for a distinct backward pass has been + // called. + bool first_autograd_hook_called_; + // track the number of buckets that have been ready for + // communication calls like allReduce or communication hooks. + int num_buckets_ready_; + // track the number of buckets that have been reduced. + int num_buckets_reduced_; + + // Timing information. + int64_t backward_compute_start_time_ = -1; + std::unique_ptr timer_; + + // We collect the relative timestamp of every gradient being ready + // when executing autograd. This can be used to derive a timeline of + // the point in time buckets were ready, or ideal bucket assignment/ordering. + std::vector backward_stats_; + + bool should_collect_runtime_stats(); + void record_forward_compute_start_time(); + void record_backward_compute_start_time(); + void record_backward_compute_end_time(); + void record_backward_comm_start_time(); + void record_backward_comm_end_time(); + + int get_ddp_runtime_logging_sample_rate(); + int ddp_runtime_logging_sample_rate_ = kDDPRuntimeLoggingSampleRate; + + bool is_multi_device_module_ = false; + + // Following variables are to help build dynamic bucket order + bool has_rebuilt_bucket_; + std::vector rebuilt_params_; + std::vector rebuilt_param_indices_; + const int64_t bucket_bytes_cap_; + +#ifndef _WIN32 + struct RpcContext { + using ContextPtr = torch::distributed::autograd::ContextPtr; + // The shared_ptr is to hold the context instance. + ContextPtr context_ptr_holder; + std::atomic context_ptr{nullptr}; + + void set(ContextPtr&& new_context_ptr); + }; + RpcContext rpc_context_; +#endif + + // A struct containing work handle and tensor for allreduce scheduled in + // forward pass, if applicable. + struct ForwardPassAllreduceWork { + c10::intrusive_ptr workHandle; + at::Tensor resultTensor; + // whether we should divide by the initial world_size or the no. of + // remaining DDP ranks. + bool useStaticWorldSize; + }; + + // Handle for the currently scheduled allreduce in the forward pass, if + // applicable. + ForwardPassAllreduceWork forwardPassWorkHandle_; + + // Division factor for reduction of gradients. + // Equal to the process group size, with an exception of handling uneven + // input. + int div_factor_; + + bool static_graph_; + + bool skip_all_reduce_unused_params_; + + // Key: size_t (index), Value: the number of times that a variable's + // autograd_hook() should be triggered before marking this variable's grad as + // ready for communication. Map will not change after 1st iteration. + std::unordered_map numGradHooksTriggeredMap_; + // Key: size_t (index), Value: the number of times that a variable's + // autograd_hook() are left to be triggered before marking this variable's + // grad as ready for communication. Map will change after 1st iteration to + // track a grad is ready for communication or not. + std::unordered_map numGradHooksTriggeredMapPerIteration_; + + private: + // reset counting for buckets before backward starts + void reset_bucket_counting(); + // search unused parameters beore backward starts + void search_unused_parameters( + const std::vector& outputs); + void set_divide_factor(); + // kick off all reduce for the ready bucket + void all_reduce_bucket(Bucket& bucket); + // kick off all reduce to local used map, it can help find global unused + // parameters + void all_reduce_local_used_map(); + // initialize locally used parameter maps + void initialize_local_used_map(); + // get current cuda stream + const c10::Stream get_current_stream(); + bool dynamic_graph_find_unused(); + bool static_graph_first_iteration(); + bool static_graph_after_first_iteration(); + + bool is_unused_bucket(Bucket& bucket); + bool should_skip_all_reduce_bucket(Bucket& bucket); + + // comm_hook_ is used to access the DDP communication hook if registered. + std::unique_ptr comm_hook_; + + // Sparse metadata contains the indices that will be used + // when calling into sparse allreduce. + // This is only used in the sparse allreduce collective calls + std::unique_ptr> sparse_metadata_; + + // Debug level setting. It is parsed once when Reducer is constructed, and + // remains the same across a single invocation of DDP training. + DebugLevel ddp_debug_level_; + // Mapping of variable index to fully qualified name of model to notify users + // about errors when certain parameters do not get gradient. + std::unordered_map param_names_; + // Variable indices stored sequentially in order of when the gradient is ready + // for the current backwards pass. + std::vector grad_ready_order_indices_; + // Bytes capacity of first bucket, can be configured by user + int64_t first_bucket_bytes_cap_; + // Per iteration set of parameter indices that have been marked ready. + std::unordered_set perIterationReadyParams_; + // Retrieves parameter names that have not been marked as ready as part of + // previous iteration. + std::vector getUnmarkedParamsForIteration(); + // Retrieves parameter indices that have not been marked as ready as part of + // previous iteration. + std::vector getUnmarkedParamIndicesForIteration(); + // Raises appropriate error if mark_variable_ready is called on the same + // variable twice, which is unexpected. + void checkAndRaiseMarkedTwiceError(size_t curVariableIndex); + // Retrieves parameter corresponding to the given VariableIndex. + at::Tensor& get_param_from_index(size_t index); + // Python reducer keeps C++ reducer initialized. To remove this flag, + // we need to refactor the DDP wrapper's initialization. + bool use_python_reducer_; + + const std::vector bucket_bytes_cap_list_; + + // Cached bucket index to model parameter mapping. Populated after buckets + // are rebuilt after which this mapping is static. + mutable std::unordered_map> + cached_variables_for_bucket_; + + bool optim_in_backward_{false}; + friend class Logger; +}; + +// This is equivalent to take_tensors but returns indices into the +// tensor list argument for bucket assignment. Also, it is aware +// of device placement and will not allow buckets to span devices. +// The index of tensors[i] assigned to bucket is tensor_indices[i], +// when tensor_indices is empty, the index of tensors[i] assigned to +// bucket is i. +TORCH_API std::tuple>, std::vector> +compute_bucket_assignment_by_size( + const std::vector& tensors, + const std::vector& bucket_size, + const std::vector& expect_sparse_gradient = {}, + const std::vector& tensor_indices = {}, + const std::optional>& logger = {}); + +// Verify models across all processes are the same as model on rank 0 with +// respect to no. of params and matching dtype/size/layout. +TORCH_API void verify_params_across_processes( + const c10::intrusive_ptr& process_group, + const std::vector& params, + const std::optional>& logger); +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/reducer_timer.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/reducer_timer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7b4320325c5ef027f4ad47a789b67e5168ee7dd7 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/reducer_timer.hpp @@ -0,0 +1,86 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include + +namespace c10d { +constexpr int kUnsetTime = -1; + +inline int64_t current_time_in_nanos() { + return c10::getTime(); +} + +class TORCH_API Timer { + private: + // The timestamp of forward call start time in each iteration. + int64_t forward_start_time = kUnsetTime; + // The timestamp of backward computation start and end time in each + // iteration. + int64_t backward_compute_start_time = kUnsetTime; + int64_t backward_compute_end_time = kUnsetTime; + // The timestamp of first communication call start time in each iteration. + int64_t backward_comm_start_time = kUnsetTime; + // The timestamp of last communication call end time in each iteration. + int64_t backward_comm_end_time = kUnsetTime; + + public: + enum class Event : uint8_t { + kForwardStart, + kBackwardComputeStart, + kBackwardComputeEnd, + kBackwardCommStart, + kBackwardCommEnd, + }; + + // Record the current event, i.e., mark it as having occurred now. Default + // CPU implementation. + virtual void record(Event event) { + getTimeRef(event) = current_time_in_nanos(); + } + + // Return the difference between when two events occurred, in nanoseconds. + // Or nullopt if one of them hasn't been recorded. + virtual std::optional measureDifference(Event start, Event end) = 0; + + virtual ~Timer() = default; + + // Return host-side timestamp, or nullopt if it has not yet been recorded. + std::optional getTimestamp(Event event) { + auto time = getTimeRef(event); + if (time == kUnsetTime) { + return std::nullopt; + } else { + return time; + } + } + + // Return host-side time member variable corresponding to the given event. + int64_t& getTimeRef(Event event) { + switch (event) { + case Event::kForwardStart: + return forward_start_time; + case Event::kBackwardComputeStart: + return backward_compute_start_time; + case Event::kBackwardComputeEnd: + return backward_compute_end_time; + case Event::kBackwardCommStart: + return backward_comm_start_time; + case Event::kBackwardCommEnd: + return backward_comm_end_time; + default: + TORCH_INTERNAL_ASSERT(false); + } + } +}; + +TORCH_DECLARE_TYPED_REGISTRY( + TimerRegistry, + c10::DeviceType, + Timer, + std::unique_ptr, + c10::Device); +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/sequence_num.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/sequence_num.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fa88322a6fa02adc0285afecf0fa128048f310f4 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/sequence_num.hpp @@ -0,0 +1,71 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace c10d { +constexpr int kUnsetSeqNum = 0; + +namespace { +constexpr int kByteOffset = 8; +} // namespace + +// Converts from int to char vec to write in store +template +inline std::vector toVec(uint64_t num, int numBytes) { + std::vector values; + // Read off bytes from right to left, pushing them into + // char array. + for (const auto i : c10::irange(numBytes)) { + uint8_t x = (num >> (kByteOffset * i)) & 0xff; + values.push_back(static_cast(x)); + } + return values; +} + +// Converts from char vec (such as from store read) to int. +template +inline uint64_t fromVec(const std::vector& values) { + uint64_t num = 0; + // Set each byte at the correct location on num + for (const auto i : c10::irange(values.size())) { + uint8_t x = static_cast(values[i]); + num |= (static_cast(x) << (kByteOffset * i)); + } + return num; +} + +class TORCH_API SequenceNum { + public: + SequenceNum(); + explicit SequenceNum(const uint64_t num); + // Retrieve num_. Will throw if not set. + uint64_t get() const; + // Increment num_. Will throw if not set. + void increment(); + // Increment num_ and return the old value. Will throw if not set. + uint64_t getAndIncrement(); + // Sets num_ + void set(const uint64_t num); + // Returns true if this SequenceNum is properly initialized with a value, else + // false. + bool isSet() const; + + SequenceNum& operator=(const SequenceNum& other); + + SequenceNum(const SequenceNum& other); + + private: + std::optional num_; + mutable std::mutex lock_; +}; + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/socket.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/socket.h new file mode 100644 index 0000000000000000000000000000000000000000..8d2ec93016c028f4d7c79410ab5c3a11cfa5264f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/socket.h @@ -0,0 +1,110 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// Copyright (c) Meta Platforms, Inc. and its affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace c10d::detail { + +class SocketOptions { + public: + SocketOptions& prefer_ipv6(bool value) noexcept { + prefer_ipv6_ = value; + + return *this; + } + + bool prefer_ipv6() const noexcept { + return prefer_ipv6_; + } + + SocketOptions& connect_timeout(std::chrono::milliseconds value) noexcept { + connect_timeout_ = value; + + return *this; + } + + std::chrono::milliseconds connect_timeout() const noexcept { + return connect_timeout_; + } + + // Sets the backoff policy to use for socket connect ops. + SocketOptions& connect_backoff(std::shared_ptr value) noexcept { + connect_backoff_ = std::move(value); + + return *this; + } + + const std::shared_ptr& connect_backoff() const noexcept { + return connect_backoff_; + } + + private: + bool prefer_ipv6_ = true; + std::chrono::milliseconds connect_timeout_{std::chrono::seconds{30}}; + std::shared_ptr connect_backoff_{ + std::make_shared(std::chrono::milliseconds(1000))}; +}; + +class SocketImpl; + +class Socket { + public: + // This function initializes the underlying socket library and must be called + // before any other socket function. + static void initialize(); + + static Socket listen(std::uint16_t port, const SocketOptions& opts = {}); + + static Socket listenFromFd(int fd, std::uint16_t expected_port); + + static Socket connect( + const std::string& host, + std::uint16_t port, + const SocketOptions& opts = {}); + + Socket() noexcept = default; + + Socket(const Socket& other) = delete; + + Socket& operator=(const Socket& other) = delete; + + Socket(Socket&& other) noexcept; + + Socket& operator=(Socket&& other) noexcept; + + ~Socket(); + + Socket accept() const; + + int handle() const noexcept; + + std::uint16_t port() const; + + bool waitForInput(std::chrono::milliseconds timeout); + + std::string repr() const; + + private: + explicit Socket(std::unique_ptr&& impl) noexcept; + + std::unique_ptr impl_; +}; +} // namespace c10d::detail + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/socket_fmt.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/socket_fmt.h new file mode 100644 index 0000000000000000000000000000000000000000..f333c8fa12d8ad4f321072b9379c24529c7d3507 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/socket_fmt.h @@ -0,0 +1,35 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// (c) Meta Platforms, Inc. and affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +/* +This file should not be included from other .h files and only used in cpp files +as it exposes the underlying platform specific socket headers. +*/ + +#include + +#ifdef _WIN32 +#include + +#include +#include +#else +#include +#endif + +namespace c10d::detail { + +// Returns a human-readable representation of the given socket address. +std::string formatSockAddr(const struct ::sockaddr* addr, socklen_t len); + +} // namespace c10d::detail + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/CUDASymmetricMemory.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/CUDASymmetricMemory.hpp new file mode 100644 index 0000000000000000000000000000000000000000..813594d55b02f174457d598a8d1b672995f87248 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/CUDASymmetricMemory.hpp @@ -0,0 +1,160 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace c10d::symmetric_memory { + +// Resource wrapper that owns a (vaddr, allocation handle) pair. Upon +// destruction, it unmaps the vaddr and releases the allocation handle. +struct AllocationRef : public c10::intrusive_ptr_target { + void* ptr; + HandleType handle; + size_t block_size; + int device_idx; + bool is_multicast; + + AllocationRef( + void* ptr, + HandleType handle, + size_t block_size, + int device_idx, + bool is_multicast = false); + + ~AllocationRef(); +}; + +// Forward declaration of CUDAPeerAllocInfo +class CUDAPeerAllocInfo; + +class CUDASymmetricMemory : public SymmetricMemory { + public: + // This is mostly a shallow copy that shares the pointer to + // `CUDAPeerAllocInfo` which corresponds to the base Block. The + // CUDASymmetricMemory handle is specified by the offset to the base ptr. + CUDASymmetricMemory( + const c10::intrusive_ptr& pai, + size_t offset); + + ~CUDASymmetricMemory() override {}; + + std::vector get_buffer_ptrs() override; + std::vector get_signal_pad_ptrs() override; + void** get_buffer_ptrs_dev() override; + void** get_signal_pad_ptrs_dev() override; + size_t get_buffer_size() override; + size_t get_offset() override; + + bool has_multicast_support() override; + void* get_multicast_ptr() override; + + void barrier(int channel, size_t timeout_ms) override; + void put_signal(int dst_rank, int channel, size_t timeout_ms) override; + void wait_signal(int src_rank, int channel, size_t timeout_ms) override; + + int get_rank() override; + int get_world_size() override; + c10::Device get_device() override; + bool world_within_direct_access() override; + + private: + int local_device_idx_; + int rank_; + int world_size_; + c10::intrusive_ptr pai_; + size_t offset_{0}; // in byte +}; + +// A class to hold the base pointers and signal pad pointers for a group of +// peers. One `CUDAPeerAllocInfo` object can be shared by multiple +// `CUDASymmetricMemory` objects when latter reside on the same allocation +// and rendezvous over the same group. (The `CUDASymmetricMemory` objects may +// have different offsets compared to the base address.) +class CUDAPeerAllocInfo : public c10::intrusive_ptr_target { + public: + CUDAPeerAllocInfo( + std::vector> alloc_refs, + std::vector buffers, + std::vector signal_pads, + HandleType mc_handle, + void* mc_addr, + size_t buffer_size, + int local_device_idx, + int rank, + int world_size, + std::string group_name); + + private: + std::vector> alloc_refs_; + std::vector buffers_; + std::vector signal_pads_; + HandleType mc_handle_; + void* mc_addr_; + size_t buffer_size_; + int local_device_idx_; + int rank_; + int world_size_; + void** buffers_dev_; + void** signal_pads_dev_; + std::string group_name_; + + friend class CUDASymmetricMemory; +}; + +// Metadata associated with each allocation performed by +// `CUDASymmetricMemoryAllocator`. +struct Block : public c10::intrusive_ptr_target { + c10::intrusive_ptr alloc_ref; + int device_idx; + size_t block_size; + size_t buffer_size; + size_t signal_pad_offset; + std::optional default_group_name; + std::map> symm_mems; + + Block( + c10::intrusive_ptr alloc_ref, + int device_idx, + size_t block_size, + size_t buffer_size, + size_t signal_pad_offset, + const std::optional& group_name); +}; + +class CUDASymmetricMemoryAllocator : public SymmetricMemoryAllocator { + public: + void* alloc( + size_t size, + int device_idx, + const std::optional& group_name) override; + + void free(void* ptr) override; + size_t get_alloc_size(void* ptr) override; + c10::intrusive_ptr rendezvous( + void* ptr, + const std::optional& group_name) override; + bool has_multicast_support(int device_idx) override; + bool has_allocation(void* ptr) override; + c10::DeviceType supported_device_type() override; + std::string name() override; + + private: + c10::intrusive_ptr find_block(void* ptr); + c10::intrusive_ptr find_block_covering(void* ptr, size_t& offset); + + std::shared_mutex mutex_; + std::unordered_map> ptr_to_block_; + c10::cuda::CUDACachingAllocator::Expandable_Segments_Handle_Type + handle_type_ = c10::cuda::CUDACachingAllocator:: + Expandable_Segments_Handle_Type::UNSPECIFIED; +}; + +} // namespace c10d::symmetric_memory + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/CUDASymmetricMemoryTypes.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/CUDASymmetricMemoryTypes.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b12c53f4410bea2b4301d33fb91dca6f1616f405 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/CUDASymmetricMemoryTypes.hpp @@ -0,0 +1,48 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include + +#if defined(USE_ROCM) +#include +#endif + +namespace c10d::symmetric_memory { + +// Key type for the symmetric memory map. `void*` for tensor storage ptr, +// `std::string` for group name. +using SymmMemKey = std::pair; +// Hash function for the symmetric memory map. c10::hash has a std::pair +// specialization (line 323-329 of hash.h) that delegates to the tuple hasher +// which combines hashes of each element. +using SymmMemKeyHash = c10::hash; + +// Covers NVL72 +constexpr int max_cuda_p2p_domain_size = 72; +// Maximum number of channels +constexpr int symm_max_nblocks = 32; + +// Maximally, a rank will need to sync with all other ranks, over all +// channels. Each signal is 32 bits, which is the minimum unit for atomic cas. +// Default signal pad size, can be overridden via set_signal_pad_size(). +constexpr size_t default_signal_pad_size = + symm_max_nblocks * max_cuda_p2p_domain_size * sizeof(uint32_t); + +#if !defined(USE_ROCM) && defined(PYTORCH_C10_DRIVER_API_SUPPORTED) +using HandleType = CUmemGenericAllocationHandle; +#elif defined(USE_ROCM) +using HandleType = hipMemGenericAllocationHandle_t; +#else +using HandleType = void*; +#endif + +} // namespace c10d::symmetric_memory + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/CUDASymmetricMemoryUtils.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/CUDASymmetricMemoryUtils.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5cd60c7368f80b16841848b00085bd488724fa78 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/CUDASymmetricMemoryUtils.hpp @@ -0,0 +1,121 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +namespace c10d { +namespace symmetric_memory { + +bool device_has_multicast_support(int device_idx); + +bool allow_overlapping_devices(); + +// Query environment variable to get the backend used for CUDA Symmetric Memory. +std::string getSymmMemBackendCUDA(); + +class IpcChannel { + public: + IpcChannel(); + ~IpcChannel(); + + void send_fd(int dst_pid, int fd); + int recv_fd(); + + std::vector all_gather_fds( + int rank, + const std::vector& pids, + int fd); + + int broadcast_fds( + int rank, + int src_rank, + const std::vector& pids, + int fd); + + private: + static std::string get_socket_name(int pid); + + std::string socket_name_; + int socket_; +}; + +// A set of store-based exchange methods with a preset prefix typically type of +// the SymmetricMemory. Most used as static instances at respective +// SymmetricMemory implementation files. +class StoreExchange { + public: + StoreExchange(std::string store_prefix) + : store_prefix_(std::move(store_prefix)) {} + + // Put template function in header file so that compiler can easily access it. + template + std::vector all_gather( + const c10::intrusive_ptr& store, + int rank, + int world_size, + T val) { + static_assert(std::is_trivially_copyable_v); + + std::vector peer_keys; + peer_keys.reserve(world_size); + for (int r = 0; r < world_size; ++r) { + std::ostringstream oss; + oss << store_prefix_ << '/' << seq_id_ << '/' << r; + peer_keys.push_back(oss.str()); + } + ++seq_id_; + + { + std::vector payload( + reinterpret_cast(&val), + reinterpret_cast(&val) + sizeof(T)); + store->set(peer_keys[rank], payload); + } + + std::vector peer_vals; + peer_vals.reserve(world_size); + for (int r = 0; r < world_size; ++r) { + if (r == rank) { + peer_vals.push_back(val); + continue; + } + store->wait({peer_keys[r]}); + auto payload = store->get(peer_keys[r]); + TORCH_CHECK(payload.size() == sizeof(T)); + T peer_val{}; + std::memcpy(&peer_val, payload.data(), sizeof(T)); + peer_vals.push_back(peer_val); + } + return peer_vals; + } + + void barrier( + const c10::intrusive_ptr& store, + int rank, + int world_size) { + // TODO: implement an efficient one? + all_gather(store, rank, world_size, 0); + } + + private: + const std::string store_prefix_; + size_t seq_id_ = 0; +}; + +// Returns a pointer of virtual address that is mapped to the physical memory +// held by the handle. +void map_block( + void** ptr, + c10d::symmetric_memory::HandleType handle, + size_t size, + int device_idx); + +} // namespace symmetric_memory +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/DMAConnectivity.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/DMAConnectivity.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1fbf2d774c5543fcf496bb87f2599fbace5c46b7 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/DMAConnectivity.hpp @@ -0,0 +1,43 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace c10d { + +struct TORCH_API DMAConnectivity : c10::intrusive_ptr_target { + c10::DeviceType device_type; + std::string connection_type; + + // This is an NxN matrix representing the connectivity between N devices, + // where each element matrix[i][j] indicates the connectivity between device + // i and device j. A value of 0 denotes that there is no connection between + // device i and j. The meaning of non-zero values are specific to the + // connection type (e.g., for NVLink it represents the number of NVLinks). + std::vector> matrix; + + explicit DMAConnectivity( + c10::DeviceType device_type, + std::string connection_type, + std::vector> matrix); +}; + +struct DMAConnectivityDetector : c10::intrusive_ptr_target { + virtual c10::intrusive_ptr detect() = 0; + ~DMAConnectivityDetector() override = default; +}; + +C10_EXPORT void register_dma_connectivity_detector( + c10::DeviceType device_type, + const std::string& connection_type, + c10::intrusive_ptr detector); + +TORCH_API c10::intrusive_ptr detect_dma_connectivity( + c10::DeviceType device_type, + const std::string& connection_type); + +} // namespace c10d + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/NCCLSymmetricMemory.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/NCCLSymmetricMemory.hpp new file mode 100644 index 0000000000000000000000000000000000000000..423606d09f3b5a32a31dbdf176cf2d16927bf607 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/NCCLSymmetricMemory.hpp @@ -0,0 +1,67 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include + +#ifdef NCCL_HAS_SYMMEM_SUPPORT + +namespace c10d { +namespace symmetric_memory { + +class NCCLPeerAllocInfo; + +class NCCLSymmetricMemory : public SymmetricMemory { + public: + NCCLSymmetricMemory(c10::intrusive_ptr pai, size_t offset); + + ~NCCLSymmetricMemory() override = default; + + std::vector get_buffer_ptrs() override; + + std::vector get_signal_pad_ptrs() override; + + void** get_buffer_ptrs_dev() override; + + void** get_signal_pad_ptrs_dev() override; + + size_t get_buffer_size() override; + + std::string get_group_name(); + + bool has_multicast_support() override; + + void* get_multicast_ptr() override; + + void barrier(int channel, size_t timeout_ms) override; + + void put_signal(int dst_rank, int channel, size_t timeout_ms) override; + + void wait_signal(int src_rank, int channel, size_t timeout_ms) override; + + int get_rank() override; + + int get_world_size() override; + + c10::Device get_device() override; + + ncclWindow_t get_window(); + + ncclWindow_t get_signal_pad_handle(); + + size_t get_offset() override; + + private: + c10::intrusive_ptr pai_; + size_t offset_; + int rank_; + int world_size_; + int device_idx_; +}; + +} // namespace symmetric_memory +} // namespace c10d +#endif // NCCL_HAS_SYMMEM_SUPPORT + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/SymmetricMemory.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/SymmetricMemory.hpp new file mode 100644 index 0000000000000000000000000000000000000000..38c98774bcf563c4990b1bb6e90f1acf6657e4c3 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/SymmetricMemory.hpp @@ -0,0 +1,225 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace c10d::symmetric_memory { + +// SymmetricMemory represents symmetric allocations across a group of devices. +// The allocations represented by a SymmetricMemory object are accessible by +// all devices in the group. The class can be used for op-level custom +// communication patterns (via the get_buffer APIs and the synchronization +// primitives), as well as custom communication kernels (via the buffer and +// signal_pad device pointers). +// +// To acquire a SymmetricMemory object, each rank first allocates +// identical-sized memory via SymmetricMemoryAllocator::alloc(), then invokes +// SymmetricMemoryAllocator::rendezvous() on the memory to establish the +// association across peer buffers. The rendezvous is a one-time process, and +// the mapping between a local memory memory and the associated SymmetricMemory +// object is unique. +// +// NOTE [symmetric memory signal pad] +// Signal pads are P2P-accessible memory regions designated for +// synchronization. SymmetricMemory offers built-in synchronization primitives +// such as barriers, put_signal, and wait_signal, which are all based on signal +// pads. Users may utilize signal pads for their own synchronization logic, +// provided that the signal pads remain zero-filled following successful +// synchronization. +// +// NOTE [symmetric memory synchronization channel] +// Synchronization channels allow users to use a single SymmetricMemory object +// to perform isolated synchronizations on different streams. For example, +// consider the case in which two barriers are issued on two streams for +// different purposes. Without the concept of channels, we cannot guarantee the +// correctness of the barriers since signals issued from barrier on stream A +// can be received by the barrier on stream B. By specifying different channels +// for these two barriers, they can operate correctly in parallel. +class TORCH_API SymmetricMemory : public torch::CustomClassHolder { + public: + ~SymmetricMemory() override = default; + + virtual std::vector get_buffer_ptrs() = 0; + virtual std::vector get_signal_pad_ptrs() = 0; + + // get_buffer_ptrs_dev() and get_signal_pad_ptrs_dev() each return a pointer + // to a device array of size world_size, containing buffer pointers and + // signal pad pointers, respectively. + virtual void** get_buffer_ptrs_dev() = 0; + virtual void** get_signal_pad_ptrs_dev() = 0; + virtual size_t get_buffer_size() = 0; + size_t get_signal_pad_size(); + + virtual size_t get_offset() = 0; + + virtual bool has_multicast_support() = 0; + virtual void* get_multicast_ptr() = 0; + + at::Tensor get_buffer( + int rank, + c10::IntArrayRef sizes, + c10::ScalarType dtype, + int64_t storage_offset); + + at::Tensor get_signal_pad( + int rank, + c10::IntArrayRef sizes, + std::optional dtype = std::nullopt, + int64_t storage_offset = 0); + + at::Tensor get_remote_tensor( + int peer, + c10::IntArrayRef sizes, + c10::ScalarType dtype); + + virtual void barrier(int channel, size_t timeout_ms) = 0; + virtual void put_signal(int dst_rank, int channel, size_t timeout_ms) = 0; + virtual void wait_signal(int src_rank, int channel, size_t timeout_ms) = 0; + + virtual int get_rank() = 0; + virtual int get_world_size() = 0; + virtual c10::Device get_device() = 0; + + virtual const std::vector& get_rank_to_global_rank() { + TORCH_CHECK(false, "NYI"); + } + + virtual int* get_rank_to_global_rank_dev() { + TORCH_CHECK(false, "NYI"); + } + + // Returns true if *all* peers within the group are accessible via direct + // memory load and store. + virtual bool world_within_direct_access() { + TORCH_CHECK(false, "NYI"); + } +}; + +class SymmetricMemoryAllocator : public c10::intrusive_ptr_target { + public: + ~SymmetricMemoryAllocator() override = default; + + virtual void* alloc( + size_t size, + int device_idx, + const std::optional& group_name) = 0; + + virtual void free(void* ptr) = 0; + virtual size_t get_alloc_size(void* ptr) = 0; + virtual c10::intrusive_ptr rendezvous( + void* ptr, + const std::optional& group_name) = 0; + virtual bool has_multicast_support(int device_idx) = 0; + virtual c10::DeviceType supported_device_type() = 0; + virtual std::string name() = 0; + virtual bool has_allocation(void* ptr) { + return false; + } +}; + +C10_EXPORT bool is_finalizing(); + +C10_EXPORT void register_allocator( + c10::DeviceType device_type, + c10::intrusive_ptr allocator); + +C10_EXPORT void register_availability( + const std::string& name, + c10::intrusive_ptr allocator); + +C10_EXPORT bool has_allocator(c10::DeviceType device_type); + +C10_EXPORT c10::intrusive_ptr get_allocator( + c10::DeviceType device_type); + +// Set a store for rendezvousing symmetric allocations on a group of devices +// identified by `group_name`. The concept of groups is logical; users can +// utilize predefined groups (e.g., a group of device identified by a +// ProcessGroup) or create custom ones. Note that a SymmetricMemoryAllocator +// backends might employ a more efficient communication channel for the actual +// rendezvous process and only use the store for bootstrapping purposes. +TORCH_API void set_group_info( + const std::string& group_name, + int rank, + int world_size, + c10::intrusive_ptr store); + +struct GroupInfo { + int rank; + int world_size; + c10::intrusive_ptr store; +}; + +C10_EXPORT GroupInfo& get_group_info(const std::string& group_name); + +// Identical to empty_strided, but allows symmetric memory access to be +// established for the allocated tensor via SymmetricMemory::rendezvous(). This +// function itself is not a collective operation. It invokes +// SymmetricMemoryAllocator::alloc() for the requested device under the hood. +// +// NOTE [symmetric memory persistent allocation] +// If an `alloc_id` is supplied, empty_strided_p2p will perform persistent +// allocation. This makes the function cache allocated memory and ensure that +// invocations with the same `alloc_id` receive tensors backed by the same +// memory address. For safety, if a previous persistent allocation is still +// active (i.e., the storage of the returned tensor is still alive), persistent +// allocations with the same `alloc_id` will fail. This determinism coupled +// with memory planning of communication buffers (e.g., by Inductor) allows +// communication algorithms to reliably reuse previously established remote +// memory access. +TORCH_API at::Tensor empty_strided_p2p( + c10::IntArrayRef size, + c10::IntArrayRef stride, + c10::ScalarType dtype, + c10::Device device, + const std::optional& group_name, + std::optional alloc_id); + +// Establishes symmetric memory access on tensors allocated via +// empty_strided_p2p() and empty_strided_p2p_persistent(). rendezvous() is a +// one-time process, and the mapping between a local memory region and the +// associated SymmetricMemory object is unique. Subsequent calls to +// rendezvous() with the same tensor, or tensors allocated with +// empty_strided_p2p_persistent() using the same alloc_id, will receive the +// cached SymmetricMemory object. +// +// The function has a collective semantic and must be invoked simultaneously +// from all rendezvous participants. +TORCH_API c10::intrusive_ptr rendezvous( + const at::Tensor& tensor, + const std::optional& group_name = std::nullopt); + +TORCH_API bool has_multicast_support( + c10::DeviceType device_type, + int device_idx); + +TORCH_API bool is_symm_mem_tensor(const at::Tensor& tensor); + +TORCH_API void set_backend(const std::string& name); + +TORCH_API std::optional get_backend(c10::Device device); + +// Get the current signal pad size for symmetric memory allocations. +// Returns the user-configured size if set, otherwise returns the default size. +TORCH_API size_t get_signal_pad_size(); + +// Set the signal pad size for future symmetric memory allocations. +// This must be called before any symmetric memory allocations are made. +// The size should be proportional to the number of blocks the user launches +// and the world size. +TORCH_API void set_signal_pad_size(size_t size); + +C10_EXPORT void register_mempool_allocator( + c10::DeviceType device_type, + std::shared_ptr allocator); + +TORCH_API std::shared_ptr get_mempool_allocator( + c10::Device device); + +} // namespace c10d::symmetric_memory + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/env.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/env.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ec10b3d7f4a84d66f1bb54ce582c56155d7f9257 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/env.hpp @@ -0,0 +1,22 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include + +namespace c10d::symmetric_memory { + +static int getenv_nblocks() { + static int num_blocks = -1; // Uninitialized + if (num_blocks == -1) { + auto str = c10::utils::get_env("TORCH_SYMMMEM_NBLOCKS"); + if (str.has_value()) { + num_blocks = std::stoi(str.value()); + } else { + num_blocks = -2; // Not set + } + } + return num_blocks; +} + +} // namespace c10d::symmetric_memory +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/intra_node_comm.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/intra_node_comm.hpp new file mode 100644 index 0000000000000000000000000000000000000000..661d205e79e86760b0f03f5013fac343c3775241 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/intra_node_comm.hpp @@ -0,0 +1,98 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace c10d::intra_node_comm { + +using namespace c10d::symmetric_memory; + +constexpr size_t kMaxDevices = 8; +constexpr size_t kDefaultBufferSize = 10ull * 1024 * 1024; + +using NvlMesh = std::array, kMaxDevices>; + +enum class Topology : uint8_t { + UNKNOWN = 0, + FULLY_CONNECTED = 1, +}; + +enum class AllReduceAlgo : uint8_t { + NONE = 0, + ONE_SHOT = 1, + TWO_SHOT = 2, +}; + +// NOTE: this class will be be removed soon in favor of SymmetricMemory +class TORCH_API IntraNodeComm : public c10::intrusive_ptr_target { + public: + IntraNodeComm( + c10::intrusive_ptr store, + size_t rank, + size_t worldSize, + std::optional bufferSize = std::nullopt, + std::string groupName = ""); + + ~IntraNodeComm() override; + + static bool isEnabled(); + + /** + * Performs rendezvous. + * If rendezvous fails, the IntraNodeComm object will be in an invalid + * state and it is the caller's responsibility to dispose it. + */ + bool rendezvous(); + + /** + * Selects a AllReduceAlgo that we think will outperform nccl. + * Returns AllReduceAlgo::NONE if we don't think we can outperform nccl. + */ + AllReduceAlgo selectAllReduceAlgo(const at::Tensor& input); + + at::Tensor allReduce(const at::Tensor& input, AllReduceAlgo algo); + + private: + at::Tensor oneShotAllReduce( + const at::Tensor& input, + at::cuda::CUDAStream& stream); + + at::Tensor twoShotAllReduce( + const at::Tensor& input, + at::cuda::CUDAStream& stream); + + c10::intrusive_ptr store_; + size_t rank_; + size_t worldSize_; + size_t bufferSize_; + std::string groupName_; + + /** + * Members initialized after rendezvous + */ + bool isInitialized_ = false; + int deviceIdx_{0}; + Topology topology_ = Topology::UNKNOWN; + void* symmetricMemoryPtr_ = nullptr; + c10::intrusive_ptr symmetricMemory_ = nullptr; +}; + +class IntraNodeCommWork : public c10d::Work { + public: + bool wait(std::chrono::milliseconds timeout = kNoTimeout) override { + return true; + } +}; + +TORCH_API int64_t getIntraNodeCommUsageCounter(); + +bool isIntraNodeCommSupported(); +} // namespace c10d::intra_node_comm + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/macros.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/macros.hpp new file mode 100644 index 0000000000000000000000000000000000000000..84b176a9dae3df9c7cec8f6feeb42534705f1694 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/macros.hpp @@ -0,0 +1,29 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// Macros for type dispatch and common utilities for symmetric memory +#pragma once + +#include + +// Convert ATen floating point types to NV floating point types +// at::kBFloat16 -> __nv_bfloat16 +// at::kHalf -> __half +// Float is the same. + +#define AT_DISPATCH_CASE_CONVERT(enum_type, scalar_type, ...) \ + case enum_type: { \ + AT_PRIVATE_CHECK_SELECTIVE_BUILD(enum_type); \ + using scalar_t = scalar_type; \ + return __VA_ARGS__(); \ + } + +#define AT_DISPATCH_NV_FLOATS(scalar_type, name, ...) \ + AT_DISPATCH_SWITCH( \ + scalar_type, \ + name, \ + AT_DISPATCH_CASE_CONVERT(at::kBFloat16, __nv_bfloat16, __VA_ARGS__); \ + AT_DISPATCH_CASE_CONVERT(at::kHalf, __half, __VA_ARGS__); \ + AT_DISPATCH_CASE(at::kFloat, __VA_ARGS__)); + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/nccl_dev_cap.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/nccl_dev_cap.hpp new file mode 100644 index 0000000000000000000000000000000000000000..10674d46201a1e26f404eac979e4a0261d6a4e55 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/nccl_dev_cap.hpp @@ -0,0 +1,31 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#if USE_NCCL + +#include +#include + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 27, 0) +#define NCCL_HAS_SYMMEM_SUPPORT +#endif + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 28, 0) +#if !defined(USE_ROCM) +#define NCCL_HAS_SYMMEM_DEVICE_SUPPORT +#include +#endif +#endif + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 29, 0) +#define NCCL_HAS_ONE_SIDED_API +#endif + +#if NCCL_VERSION_CODE >= NCCL_VERSION(2, 29, 7) +#define NCCL_DEVICE_HAS_REDUCE_COPY +#endif +#endif // USE_NCCL + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/nccl_devcomm_manager.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/nccl_devcomm_manager.hpp new file mode 100644 index 0000000000000000000000000000000000000000..57d34924e9c0fc6abb36b9bc2883690216f0c910 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/nccl_devcomm_manager.hpp @@ -0,0 +1,248 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef NCCL_HAS_SYMMEM_DEVICE_SUPPORT + +namespace c10d::symmetric_memory { + +// Manages NCCL device communicators for symmetric memory operations. +// This is a singleton class that maintains a registry of device communicators +// organized by process group name and an optional key (typically the caller +// function name). This allows different functions within the same process group +// to use different device communicators, which is useful for concurrent +// collective operations. +// +// The registry uses a two-level map structure: +// - First level: keyed by process group name +// - Second level: keyed by an optional key (defaults to caller function name) +// +// Device communicators are stored by value in the registry, but methods return +// references wrapped in std::optional for safe access. +class NCCLDevCommManager { + public: + // Constructor + // @param device The CUDA device this manager is associated with + explicit NCCLDevCommManager(const c10::Device device) : device_(device) {} + + // Get the singleton instance for the given device. + // This ensures there's only one manager per device. If called with a + // different device than the one used to create the singleton, it will throw. + // @param device The CUDA device to get the manager for + // @return Reference to the singleton manager instance + static NCCLDevCommManager& get(const c10::Device device) { + static NCCLDevCommManager manager(device); + TORCH_CHECK_VALUE( + manager.device_ == device, + "Detected use of NCCLDevCommManager on multiple devices. This is not supported."); + return manager; + } + + // Get an NCCL device communicator for a group, for the caller function. By + // default, we search for the device communicator using the caller function + // name as the key. If you previously registered a device communicator with a + // different key, you should provide that key instead. + // Returns std::nullopt if the device communicator is not found. + // Example: + // void foo(const std::string& group_name) { + // // Try to get first. + // auto devcomm_opt = get_devcomm(group_name); + // if (!devcomm_opt) { + // // Not found, create then register. + // ncclDevComm devcomm = ncclDevCommCreate(...); + // devcomm_opt = register_devcomm(group_name, devcomm); + // } + // ncclDevComm& devcomm_ref = *devcomm_opt; + // // Use devcomm_ref + // } + std::optional> get_devcomm( + const std::string& group_name, + const std::string& key = __builtin_FUNCTION()) { + std::lock_guard lock(mutex_); + // First, look up the group in the registry + auto group_it = devcomm_registry_.find(group_name); + if (group_it == devcomm_registry_.end()) { + return std::nullopt; + } + // Then, look up the key within that group's map + auto key_it = group_it->second.find(key); + if (key_it == group_it->second.end()) { + return std::nullopt; + } + // Return a reference wrapper to the device communicator + // Using reference_wrapper because std::optional cannot hold references + // directly + return std::make_optional(std::ref(key_it->second)); + } + + // Get a host-side NCCL communicator for a group. + // This is the regular host-side communicator, not the device communicator. + // @param group_name The process group name + // @return The host-side NCCL communicator + // @throws TORCH_CHECK if the communicator is not found + ncclComm_t get_comm(const std::string& group_name) { + std::lock_guard lock(mutex_); + auto it = group_to_comm_.find(group_name); + if (it == group_to_comm_.end()) { + TORCH_CHECK( + false, + "NCCL host communicator for group ", + group_name, + " not found. Have you rendezvoused any tensor with this group?"); + } + return it->second; + } + + // Register a device communicator for a group. If `key` is not + // specified, we use the caller function name as the default `key`, to + // distinguish between different collective functions within the same group. + // You can provide your own `key` if your function uses two different + // device communicators on the same group at the same time, for example, + // when concurrent collective operations are used. + // Returns a reference to the newly registered device communicator. + // @throws TORCH_CHECK if the device communicator is already registered for + // the given group and key combination. + // Example: + // void foo(const std::string& group_name) { + // // Try to get first. + // auto devcomm_opt = get_devcomm(group_name); + // if (!devcomm_opt) { + // // Not found, create then register. + // ncclDevComm devcomm = ncclDevCommCreate(...); + // devcomm_opt = register_devcomm(group_name, devcomm); + // } + // ncclDevComm& devcomm_ref = *devcomm_opt; + // // Use devcomm_ref + // } + // void bar(const std::string& group_name) { + // ncclDevComm devcomm0 = ncclDevCommCreate(...); + // ncclDevComm devcomm1 = ncclDevCommCreate(...); + // // You can provide your own `key` if you want to, for example, to + // // distinguish between concurrent collective operations. + // register_devcomm(group_name, devcomm0, "bar0"); + // register_devcomm(group_name, devcomm1, "bar1"); + // } + std::optional> register_devcomm( + const std::string& group_name, + ncclDevComm devcomm, + const std::string& key = __builtin_FUNCTION()) { + std::lock_guard lock(mutex_); + // Ensure the group exists in the registry, creating an empty map if needed + auto [group_it, inserted] = devcomm_registry_.try_emplace( + group_name, std::unordered_map()); + auto& group_map = group_it->second; + // Try to insert the device communicator with the given key + // Use std::move to avoid copying the device communicator + auto [key_it, key_inserted] = + group_map.try_emplace(key, std::move(devcomm)); + if (!key_inserted) { + // Already registered - this is a programming error, so throw + TORCH_CHECK( + false, + "NCCL device communicator for group ", + group_name, + " with key ", + key, + " already registered."); + } + // Return a reference to the newly registered device communicator + return std::make_optional(std::ref(key_it->second)); + } + + // Register a host-side NCCL communicator for a group. + // This should be called before registering any device communicators for the + // same group, as device communicators need the host communicator for cleanup. + // @param group_name The process group name + // @param comm The host-side NCCL communicator to register + // @throws TORCH_CHECK if the group is already registered with a different + // communicator. + void register_comm(const std::string& group_name, ncclComm_t comm) { + std::lock_guard lock(mutex_); + auto [it, inserted] = group_to_comm_.try_emplace(group_name, comm); + // If the communicator is already registered, check if it is the same one. + // If not, throw an error. + TORCH_CHECK( + inserted || it->second == comm, // this is just a pointer comparison + "NCCL host communicator for group ", + group_name, + " already registered."); + } + + // Destructor: Clean up all registered device communicators. + // This is a best-effort cleanup. If the CUDA context has already been + // destroyed, the cleanup will be skipped. All errors are caught and ignored + // to prevent exceptions from propagating during destruction. + ~NCCLDevCommManager() noexcept { + // Best effort to destroy the device communicators. Skip if CUDA context has + // exited. + try { + c10::cuda::CUDAGuard guard(device_); + // Make sure all kernels have completed before destroying the device + // communicator. This is important to ensure no kernels are still using + // the device communicator when we destroy it. + C10_CUDA_CHECK(cudaDeviceSynchronize()); + // Iterate through all groups and their device communicators + for (auto& [group_name, group_map] : devcomm_registry_) { + // Find the host communicator for the group. + // Device communicators need the host communicator for destruction. + auto comm_it = group_to_comm_.find(group_name); + if (comm_it != group_to_comm_.end()) { + // Destroy each device communicator in this group + for (auto& [_, devcomm] : group_map) { + // Destroy the device communicator using the host communicator + ncclDevCommDestroy(comm_it->second, &devcomm); + } + } + } + } catch (...) { + // Ignore the error - we're in a destructor and can't throw + // Log a warning for debugging purposes + LOG(WARNING) + << "Failed to destroy the NCCL device communicator, skipping"; + } + } + + private: + // Device where the NCCL device communicator manager is created. + // The manager is device-specific and cannot be used across multiple devices. + const c10::Device device_; + + // Mutex to protect the registry maps. + std::mutex mutex_; + + // A map from process group name to the host-side NCCL communicator. + // The host communicator is required for creating and destroying device + // communicators. It should be registered before any device communicators + // for the same group. + std::unordered_map group_to_comm_; + + // A two-level map for device communicators: + // - First level: keyed by process group name + // - Second level: keyed by an optional key (defaults to caller function name + // via __builtin_FUNCTION()) + // + // This structure allows multiple device communicators per process group, + // which is useful when different functions need separate device communicators + // for concurrent operations. The key defaults to the caller's function name, + // but can be customized for cases where a single function needs multiple + // device communicators. + std::unordered_map> + devcomm_registry_; +}; + +} // namespace c10d::symmetric_memory +#endif // NCCL_HAS_SYMMEM_DEVICE_SUPPORT + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/nccl_extension.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/nccl_extension.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c256e2b25116ea92d4d80361eca4e9e7dd438f0b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/nccl_extension.hpp @@ -0,0 +1,38 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace c10d::nccl_extension { + +TORCH_API bool is_nccl_symmem_available(); + +TORCH_API void nccl_put(at::Tensor& tensor, const int64_t peer); + +TORCH_API void nccl_get(at::Tensor& tensor, const int64_t peer); + +TORCH_API void nccl_wait_for_signal(at::Tensor& sigpad, int64_t signal); + +TORCH_API void nccl_put_with_signal( + at::Tensor& tensor, + int64_t signal, + int64_t peer); + +// Simultaneously reduce N blocks of a 2-D input tensor from a shared symmetric +// memory buffer, routing each to a specific destination rank. Blocks are +// described by inclusive-prefix-sum offsets along `dim` (0 or 1); all blocks +// must have equal size. +TORCH_API void nccl_reduce_scatter_offset( + const at::Tensor& input, + at::TensorList out, + const std::string& group_name, + int64_t dim, + std::optional offsets, + std::optional dst_ranks, + const std::string& red_op); +} // namespace c10d::nccl_extension + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/nvshmem_extension.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/nvshmem_extension.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6a524af7b6f85cca05fa65c9f4738af65d961f3d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/nvshmem_extension.hpp @@ -0,0 +1,90 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#define NVSHMEM_CHECK(stmt, msg) \ + do { \ + int result = (stmt); \ + TORCH_CHECK( \ + result == 0, \ + std::string(__FILE__) + ":" + std::to_string(__LINE__) + " " + msg + \ + ". Error code: " + std::to_string(result)); \ + } while (0) + +namespace c10d::nvshmem_extension { + +// Check if NVSHMEM is available +TORCH_API bool is_nvshmem_available(); + +// Initializes the device state in CUmodule so that it’s able to perform NVSHMEM +// operations. +TORCH_API void nvshmemx_cumodule_init(uintptr_t module); + +TORCH_API void nvshmem_put(at::Tensor& tensor, const int64_t peer); + +TORCH_API void nvshmem_get(at::Tensor& tensor, const int64_t peer); + +at::Tensor nvshmem_broadcast( + at::Tensor& input, + const int64_t root, + const std::string& group_name); + +TORCH_API void nvshmem_wait_for_signal( + at::Tensor& sigpad, + int64_t signal, + int64_t peer); + +TORCH_API void nvshmem_put_with_signal( + at::Tensor& tensor, + at::Tensor& sigpad, + int64_t signal, + int64_t peer); + +at::Tensor nvshmem_all_to_all( + at::Tensor& input, + at::Tensor& out, + std::string group_name); + +void all_to_all_vdev( + at::Tensor& input, + at::Tensor& out, + at::Tensor& in_splits, + at::Tensor& out_splits_offsets, + std::string group_name); + +void all_to_all_vdev_2d( + at::Tensor& input, + at::Tensor& out, + at::Tensor& in_splits, + at::Tensor& out_splits_offsets, + std::string group_name, + std::optional major_align = std::nullopt); + +void all_to_all_vdev_2d_offset( + at::Tensor& input, + at::Tensor& out, + at::Tensor& in_splits_offsets, + at::Tensor& out_splits_offsets, + std::string group_name); + +void tile_reduce( + at::Tensor& in_tile, + at::Tensor& out_tile, + int64_t root, + std::string group_name, + std::string reduce_op = "sum"); + +void multi_root_tile_reduce( + at::ArrayRef in_tiles, + at::Tensor& out_tile, + at::ArrayRef roots, + std::string group_name, + std::string reduce_op = "sum"); + +} // namespace c10d::nvshmem_extension + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/nvshmem_team_manager.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/nvshmem_team_manager.hpp new file mode 100644 index 0000000000000000000000000000000000000000..606ef22400b1fd9829967ba6bc425f871a4261bf --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/c10d/symm_mem/nvshmem_team_manager.hpp @@ -0,0 +1,179 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +// Starting from NVSHMEM 3.3.9, nvshmem_host.h exists so that we can cleanly +// include only the nvshmem host library headers: +// #include +// It translates into the following two lines: +#if !defined(USE_ROCM) +#include +#include +#else +#include +#endif +// For maximum compatibility, we use the "host/" style for now. + +namespace c10d::nvshmem_extension { + +// This corresponds to max nblocks +constexpr int MAX_N_TEAMS = 128; + +// A pool of teams for each group. These are duplicate teams. +using TeamPool = std::vector; + +// Manage all the team business. Singleton. +class TeamManager { + public: + // Constructor + explicit TeamManager(const c10::Device device) : device_(device) {} + + // Get single, global manager. + static TeamManager& get(const c10::Device device) { + static TeamManager manager(device); + TORCH_CHECK( + manager.device_ == device, + "Detected use of TeamManager on multiple devices. This is not supported."); + return manager; + } + + // Get a team for a group. + nvshmem_team_t get_team( + const std::string& group_name, + const std::vector& global_ranks) { + auto [team_pool, pool_updated] = + group_to_team_pool(group_name, global_ranks, 1); + // Return the fist available team + return team_pool[0]; + } + + // Get n teams for a group. + // The first element of the returned pair is the team pool on host side. + // The second element of the returned pair is the team pool on device side. + // This API must be call with a device guard. + std::pair get_n_teams( + const std::string& group_name, + const std::vector& global_ranks, + const int need_n) { + // A device guard is required for malloc and memcpy below + c10::cuda::CUDAGuard guard(device_); + // Get the team pool with the requested number of teams + auto [team_pool, pool_updated] = + group_to_team_pool(group_name, global_ranks, need_n); + // Check if the pool already exists in device memory + nvshmem_team_t* team_pool_dev = nullptr; + constexpr auto pool_bytes = sizeof(nvshmem_team_t) * MAX_N_TEAMS; + auto it = team_pool_devptrs_.find(group_name); + if (it == team_pool_devptrs_.end()) { + // If not, allocate a new pool in device memory + team_pool_dev = reinterpret_cast( + c10::cuda::CUDACachingAllocator::raw_alloc(pool_bytes)); + team_pool_devptrs_[group_name] = team_pool_dev; + } else { + team_pool_dev = it->second; + } + // Update the pool in device memory if host side pool is updated + if (pool_updated) { + TORCH_INTERNAL_ASSERT(team_pool.size() == MAX_N_TEAMS); + auto stream = at::cuda::getCurrentCUDAStream(); + C10_CUDA_CHECK(cudaMemcpyAsync( + team_pool_dev, + team_pool.data(), + pool_bytes, + cudaMemcpyHostToDevice, + stream)); + } + return std::make_pair(std::cref(team_pool), team_pool_dev); + } + + ~TeamManager() noexcept { + // Free the team pools in device memory + // Note that we do it in a best effort manner because the team pool is + // managed by a static TeamManager and the destruction order of static + // objects is undetermined. If the destructor is called after the CUDA + // context is destroyed, cudaFree would fail. + try { + // cudaFree generally implies a device synchronization, meaning it will + // block until all preceding CUDA operations on the device have completed + // before freeing the memory. Thus we don't need to worry about freeing + // the memory before CUDA kernels complete. + for (auto& [_, team_pool_dev] : team_pool_devptrs_) { + c10::cuda::CUDACachingAllocator::raw_delete(team_pool_dev); + } + } catch (...) { + // Ignore the error + std::cerr << "Failed to free the team pool in device memory, skipping\n"; + } + } + + private: + // Get the team pool for a group. If the pool doesn't exist, create it. If the + // pool exists but is not large enough, create more teams. + // The first element of the returned pair is the team pool on host side. + // The second element of the returned pair is a boolean indicating if the pool + // is updated. + std::pair group_to_team_pool( + const std::string& group_name, + const std::vector& global_ranks, + const int need_n) { + TORCH_CHECK(need_n < MAX_N_TEAMS, "Too many teams requested"); + // Guarding the NVSHMEM API calls below just to be safe + c10::cuda::CUDAGuard guard(device_); + + // Insert a new team pool if not exists + auto [it, inserted] = group_name_to_team_pool_.emplace( + group_name, TeamPool(MAX_N_TEAMS, NVSHMEM_TEAM_INVALID)); + auto& team_pool = it->second; + bool pool_updated = inserted; + + // Create new teams if what's requested is more than what we have + int stride = 0; // stride in globe, uninitialized + for (int i = 0; i < need_n; ++i) { + if (team_pool[i] != NVSHMEM_TEAM_INVALID) { + continue; + } + // Some checks before we create new teams + if (stride == 0) { // Check only once + TORCH_CHECK(global_ranks.size() > 1); + stride = global_ranks[1] - global_ranks[0]; + for (size_t r = 1; r < global_ranks.size(); ++r) { + TORCH_CHECK(global_ranks[r] - global_ranks[r - 1] == stride); + } + } + nvshmem_team_t team = NVSHMEM_TEAM_INVALID; + nvshmem_team_split_strided( + NVSHMEM_TEAM_WORLD, + global_ranks[0], + stride, + global_ranks.size(), + nullptr, + 0, + &team); + TORCH_CHECK(team != NVSHMEM_TEAM_INVALID, "Failed to create a new team"); + team_pool[i] = team; + pool_updated = true; + } + return std::make_pair(std::cref(team_pool), pool_updated); + } + + private: + // Device where the team manager is created + const c10::Device device_; + // A map from group name to team pool for that group. + std::unordered_map group_name_to_team_pool_; + // A map from group name to team pool array in device memory. + std::unordered_map team_pool_devptrs_; +}; + +} // namespace c10d::nvshmem_extension + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/python_placement.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/python_placement.h new file mode 100644 index 0000000000000000000000000000000000000000..a15d330768b9788f18b96b6620c750ab0abdf9da --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/python_placement.h @@ -0,0 +1,12 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::distributed { +void initPlacementBindings(PyObject* module); +} // namespace torch::distributed + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/agent_utils.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/agent_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..25f915f21a7cc914b352ba4b8208e3ce4617d9a7 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/agent_utils.h @@ -0,0 +1,47 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::distributed::rpc { + +// All RPC peers should call into this function at the same time. Each peer +// provides its own id and name, and this function uses the given Store to +// gather global name-to-id mapping on all peers. +TORCH_API std::unordered_map collectNames( + ::c10d::PrefixStore store, + const worker_id_t selfId, + const std::string& selfName, + const int worldSize); + +// Ranks in dynamic RPC groups will initially call into this to establish the +// name-to-id mapping for the current peers in the group. The current rank will +// put its own worker info in the store and discover all the ranks that came +// before it. NOTE: This needs to be called with the Dynamic RPC group +// membership management token held. +TORCH_API std::unordered_map collectCurrentNames( + ::c10d::PrefixStore store, + const worker_id_t selfId, + const std::string& selfName); + +// Remove name from Store, used in dynamic RPC groups. +// NOTE: This needs to be called with the Dynamic RPC group +// membership management token held. +TORCH_API void removeCurrentName( + ::c10d::PrefixStore store, + const worker_id_t selfId, + const std::string& selfName); + +// This performs a synchronization of all call counts by using store. +// All RPC peers wait for others to join to exit at the same time. +TORCH_API int syncCallCount( + ::c10d::PrefixStore store, + const int worldSize, + int activeCalls = 0); + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/message.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/message.h new file mode 100644 index 0000000000000000000000000000000000000000..f6e71490f27f885d1a2e4e897a29fe50a1cb0ea5 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/message.h @@ -0,0 +1,198 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::distributed::rpc { + +// An enum denoting common RPC errors to allow specific error handling for them. +// NOLINTNEXTLINE(performance-enum-size) +enum RPCErrorType { + UNKNOWN_ERROR = 0, /* Indicates that error type could not be parsed */ + TIMEOUT = 1, /* Indicates that the RPC has timed out */ + INTENTIONAL_FAILURE = 2 /* Deliberate failure, such as those injected by + FaultyAgent for testing */ +}; + +// The enum values are bitwise ORed with MessageType +// They are bit flags starting from 0x100 and should have +// value such as 0x100, 0x200, 0x400, 0x800, 0xF00, etc. +// NOLINTNEXTLINE(performance-enum-size) +enum MessageTypeFlags { + REQUEST_TYPE = 0x100, + RESPONSE_TYPE = 0x200, +}; + +// Message types must have values between 0x00 to 0xff +// NOLINTNEXTLINE(performance-enum-size) +enum MessageType { + // messages for dist.rpc on builtin operators + SCRIPT_CALL = 0x00 | MessageTypeFlags::REQUEST_TYPE, + SCRIPT_RET = 0x01 | MessageTypeFlags::RESPONSE_TYPE, + + // messages for dist.rpc on Python UDF + PYTHON_CALL = 0x02 | MessageTypeFlags::REQUEST_TYPE, + PYTHON_RET = 0x03 | MessageTypeFlags::RESPONSE_TYPE, + + // messages for dist.remote on builtin operators and Python UDF + SCRIPT_REMOTE_CALL = 0x04 | + MessageTypeFlags::REQUEST_TYPE, // A remote call on a builtin operator + PYTHON_REMOTE_CALL = + 0x05 | MessageTypeFlags::REQUEST_TYPE, // A remote call on a Python UDF + REMOTE_RET = + 0x06 | MessageTypeFlags::RESPONSE_TYPE, // Response for remote calls for + // UDF, builtin, or script + + // RRef related internal messages + SCRIPT_RREF_FETCH_CALL = + 0x07 | MessageTypeFlags::REQUEST_TYPE, // A UserRRef fetches value + // from owner + PYTHON_RREF_FETCH_CALL = + 0x08 | MessageTypeFlags::REQUEST_TYPE, // A UserRRef fetches + // value from owner + SCRIPT_RREF_FETCH_RET = 0x09 | + MessageTypeFlags::RESPONSE_TYPE, // An OwnerRRef sends ivalue to user + PYTHON_RREF_FETCH_RET = 0x0a | + MessageTypeFlags::RESPONSE_TYPE, // An OwnerRRef sends py::object to user + RREF_USER_DELETE = 0x0b | + MessageTypeFlags::REQUEST_TYPE, // A UserRRef tells the owner to deref + RREF_FORK_REQUEST = + 0x0c | MessageTypeFlags::REQUEST_TYPE, // A child UserRRef tells the owner + // about itself + RREF_CHILD_ACCEPT = + 0x0d | MessageTypeFlags::REQUEST_TYPE, // A child UserRRef tells parent + // that owner knows it + RREF_ACK = + 0x0e | MessageTypeFlags::RESPONSE_TYPE, // ACK to internal RRef messages + + // Messages with autograd info + FORWARD_AUTOGRAD_REQ = 0x0f | MessageTypeFlags::REQUEST_TYPE, + FORWARD_AUTOGRAD_RESP = 0x10 | MessageTypeFlags::RESPONSE_TYPE, + + // Messages to propagate gradients on the backward pass. + BACKWARD_AUTOGRAD_REQ = 0x11 | MessageTypeFlags::REQUEST_TYPE, + BACKWARD_AUTOGRAD_RESP = 0x12 | MessageTypeFlags::RESPONSE_TYPE, + + // Messages to tell workers to clean up their autograd context. + CLEANUP_AUTOGRAD_CONTEXT_REQ = 0x13 | MessageTypeFlags::REQUEST_TYPE, + CLEANUP_AUTOGRAD_CONTEXT_RESP = 0x14 | MessageTypeFlags::RESPONSE_TYPE, + + // Messages that tell workers to run requests with profiling enabled. + RUN_WITH_PROFILING_REQ = 0x15 | MessageTypeFlags::REQUEST_TYPE, + RUN_WITH_PROFILING_RESP = 0x16 | MessageTypeFlags::RESPONSE_TYPE, + + // Messages to support RRef.backward(). + RREF_BACKWARD_REQ = 0x17 | MessageTypeFlags::REQUEST_TYPE, + RREF_BACKWARD_RESP = 0x18 | MessageTypeFlags::RESPONSE_TYPE, + + // Other internal message types + EXCEPTION = 0x37 | MessageTypeFlags::RESPONSE_TYPE, + UNKNOWN = 0x3c +}; + +// A message to be sent/received by an RpcAgent. +// +// A Message object contains 4 fields: +// payload (std::vector): a binary chunk of data. +// tensors (std::vector): all tensors. Tensor data are not +// included in the payload, and it is up to the RpcAgent implementation +// to determine how to serialize them. This design is helpful for +// communicating super large tensors where serializing all the data at +// once leads to excessively large memory footprint. An implementation +// can then serialize and send tensors chunk-by-chunk, in the streaming +// fashion. +// type (MessageType): type of the message. +// id (int64_t): message id, this is used to match request and response. +// Other implementation can ignore it if they have their own +// ways to do matching. +// +// Layers above ``RpcAgent`` only converts ScriptCall, ScriptResp, PythonCall, +// and PythonResp into a Message, and it is up to the RpcAgent +// implementation to determine how to serialize a message. +class TORCH_API Message final : public torch::CustomClassHolder { + private: + // Keep these private in order to force users to go through make_intrusive and + // thus prevent creating a Message that's not held by an intrusive_ptr. + Message(); + + Message( + std::vector&& payload, + std::vector&& tensors, + MessageType type); + + Message( + std::vector&& payload, + std::vector&& tensors, + MessageType type, + int64_t id); + + friend c10::intrusive_ptr; + + public: + Message(const Message& other) = delete; + Message(Message&& other) = delete; + Message& operator=(Message const& rhs) = delete; + Message& operator=(Message&& rhs) = delete; + ~Message() override = default; + + // Destructively retrieves the payload. + std::vector&& movePayload() &&; + std::vector&& moveTensors() &&; + + std::vector& payload(); + const std::vector& payload() const; + std::vector& tensors(); + const std::vector& tensors() const; + MessageType type() const; + + bool isRequest() const; + bool isResponse() const; + bool isShutdown() const; + + // id is an optional field to match request/response. If an RpcAgent + // implementation is able to do the matching without using this id, it can be + // dropped during message serialization. + int64_t id() const; + void setId(int64_t id); + + std::vector> getStorages() const; + + private: + std::vector payload_; + std::vector tensors_; + MessageType type_ = MessageType::UNKNOWN; + int64_t id_ = -1; +}; + +// Create a response Message of type Exception. +// The exception string representation will be used as the message's payload. +// A message ID corresponding to the request that resulted in this response can +// be provided for matching requests/responses. +TORCH_API c10::intrusive_ptr createExceptionResponse( + const std::exception& e, + int64_t id); + +// Create a response Message of type Exception. +// The passed in string representation will be used as the message's payload. +// A message ID corresponding to the request that resulted in this response can +// be provided for matching requests/responses. +TORCH_API c10::intrusive_ptr createExceptionResponse( + const std::string& exceptionStr, + int64_t id); + +inline std::tuple< + c10::intrusive_ptr, + std::vector>> +withStorages(c10::intrusive_ptr message) { + auto storages = message->getStorages(); + return std::make_tuple(std::move(message), std::move(storages)); +} + +using JitFuture = c10::ivalue::Future; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/metrics/RpcMetricsHandler.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/metrics/RpcMetricsHandler.h new file mode 100644 index 0000000000000000000000000000000000000000..d46a0e9be89a5957fd498fe2fbd17c7e02767e4b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/metrics/RpcMetricsHandler.h @@ -0,0 +1,45 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include + +namespace torch::distributed::rpc { +// All metrics are prefixed with the following key. +// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays) +constexpr char kRpcMetricsKeyPrefix[] = "torch.distributed.rpc."; +// APIs for logging time-series metrics for RPC-based distributed +// training. Implementations of this class should provide thread safety so that +// metrics can be logged from multiple threads without the user needing to +// coordinate serialization. +class RpcMetricsHandler { + public: + // Accumulates the metric value specified by the name for purposes of + // computing aggregate statistics over time. + virtual void accumulateMetric(const std::string& name, double value) = 0; + // Increment a count for the metric given by the name. + virtual void incrementMetric(const std::string& name) = 0; + virtual ~RpcMetricsHandler() = default; +}; + +// Configuration struct for metrics handling. +struct RpcMetricsConfig { + explicit RpcMetricsConfig(std::string handlerName, bool enabled) + : handlerName_(std::move(handlerName)), enabled_(enabled) {} + + // Handler name + std::string handlerName_; + // Whether metrics exporting should be enabled or not. + bool enabled_; +}; + +// A registry for different implementations of RpcMetricsHandler. Classes +// implementing the above interface should use this to register implementations. +TORCH_DECLARE_REGISTRY( + RpcMetricsHandlerRegistry, + torch::distributed::rpc::RpcMetricsHandler); + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/profiler/remote_profiler_manager.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/profiler/remote_profiler_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..ba39ea8a02305f64f642b6927ee43b35459d10b8 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/profiler/remote_profiler_manager.h @@ -0,0 +1,60 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include +#include + +namespace torch::distributed::rpc { +extern const std::string REMOTE_PROFILING_KEY_PREFIX; + +class TORCH_API RemoteProfilerManager { + public: + // Retrieves the lazily-initialized RemoteProfilerManager singleton instance. + static RemoteProfilerManager& getInstance(); + // Sets the current, thread-local profiling key. + void setCurrentKey(std::string key); + // Returns whether the current profiling key is set. + bool isCurrentKeySet() const; + // Unsets the current, thread-local profiling key to allow other RPCs to reset + // it. + void unsetCurrentKey(); + // inserts a pair (globallyUniqueId, key) to an in-memory map. The + // corresponding ID is used in RPC deserialization to prefix remotely profiled + // events with the right key. + void saveRPCKey( + ProfilingId globallyUniqueId, + const std::string& rpcProfilingKey); + // Retrieves the profiling key corresponding to the given globallyUniqueId. + // Throws if it is not found. + std::string retrieveRPCProfilingKey(const ProfilingId& globallyUniqueId); + // Generates the next globally unique ID for profiling. + ProfilingId getNextProfilerId(); + // Retrieves the currently set thread-local profiling key. Throws if it is not + // set. + std::string& getCurrentProfilingKey(); + // erases the globallyUniqueId from the map. This can help save memory in the + // case that many RPCs are being profiled. + void eraseKey(const ProfilingId& globallyUniqueId); + + RemoteProfilerManager(const RemoteProfilerManager& other) = delete; + RemoteProfilerManager operator=(const RemoteProfilerManager& other) = delete; + RemoteProfilerManager(RemoteProfilerManager&&) = delete; + RemoteProfilerManager& operator=(RemoteProfilerManager&&) = delete; + + private: + RemoteProfilerManager(); + ~RemoteProfilerManager() = default; + local_id_t getNextLocalId(); + std::unordered_map + profiledRpcKeys_; + static thread_local std::optional currentThreadLocalKey_; + std::mutex mutex_; + local_id_t currentLocalId_; +}; +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/profiler/server_process_global_profiler.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/profiler/server_process_global_profiler.h new file mode 100644 index 0000000000000000000000000000000000000000..f86461f6f895bee8a46b54b9f57dd88b66362ad6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/profiler/server_process_global_profiler.h @@ -0,0 +1,134 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include + +namespace torch::distributed::rpc::profiler::processglobal { + +using namespace torch::autograd::profiler; + +// Process global profiler state. +// +// This class holds information about a profiling range, from "enable" to +// "disable". +// An instance of this ``State`` will be +// pushed into a global stack, so nested profiling range is supported. +// +// It has 2 members. +// One is ``autograd::profiler::ProfilerConfig``. It's set by user and +// will be copied to thread-local profiler state of RPC threads. +// The other is a container that aggregates recorded +// ``autograd::profiler::Event``s from all thread-local profilers on RPC +// threads. +class State { + public: + explicit State(ProfilerConfig config) : config_(std::move(config)) {} + ~State() = default; + + const ProfilerConfig& config() const { + return config_; + } + + void pushResult(thread_event_lists result) { + std::unique_lock lock(resultsMutex_); + + // NB: When a thread wants to push an entry into the this container, + // main control logic might have exited the process-global profile range. + results_.emplace_back(std::move(result)); + } + + std::vector results(); + + private: + // Each result comes from a profile range. In each profile range, there is a + // "__profiler_start" marker event that all following events calculate time + // relative to it, so it's required to call + // parse_cpu_trace(result) for results of all profile range. + std::mutex resultsMutex_; + std::vector results_; + const ProfilerConfig config_ = ProfilerConfig(ProfilerState::Disabled); +}; + +class StateStackEntry; + +#if defined(__MACH__) +// Compiler error: 'shared_timed_mutex' is unavailable: introduced in +// macOS 10.12 +using mutexType = std::mutex; +// Compiler error: 'shared_lock' is unavailable: introduced in +// macOS 10.12 +using rLockType = std::unique_lock; +using wLockType = std::unique_lock; +#else +using mutexType = std::shared_timed_mutex; +using rLockType = std::shared_lock; +using wLockType = std::unique_lock; +#endif + +// This is the global stack of ``State``s. +TORCH_API extern std::shared_ptr currentStateStackEntryPtr; +TORCH_API extern mutexType currentStateStackEntryMutex; + +// This class is used to implement a stack of ``State``s. +// It has 2 members. +// One is `prevPtr`, a shared_ptr pointing to previous element in the +// stack. +// The other is ``statePtr``, a shared_ptr pointing to ``State``. +class StateStackEntry { + public: + StateStackEntry( + std::shared_ptr prevPtr, + std::shared_ptr statePtr) + : prevPtr_(std::move(prevPtr)), statePtr_(std::move(statePtr)) {} + + static void pushRange(std::shared_ptr profilerProcessGlobalStatePtr); + static std::shared_ptr popRange(); + + static std::shared_ptr current() { + rLockType rlock(currentStateStackEntryMutex); + + return currentStateStackEntryPtr; + } + + std::shared_ptr prevPtr() const { + return prevPtr_; + } + + std::shared_ptr statePtr() const { + return statePtr_; + } + + private: + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const std::shared_ptr prevPtr_{nullptr}; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const std::shared_ptr statePtr_{nullptr}; +}; + +// Push the result to ``State``s of current profile range and recursively outer +// profile ranges. +TORCH_API void pushResultRecursive( + std::shared_ptr stateStackEntryPtr, + const thread_event_lists& result); + +// User-facing API. +// +// Enter a server-side process-global profiling range. +// Profiling range can be neste, so it's ok to call this API for multiple +// times. This enables all RPC threads running server-side request callbacks. +TORCH_API void enableServer(const ProfilerConfig& new_config); +// +// Exit a server-side process-global profiling range. +// Profiling range can be neste, so it's possible that profiler is still on +// after calling this API. +// This enables all RPC threads running server-side request callbacks. +TORCH_API std::vector disableServer(); + +} // namespace torch::distributed::rpc::profiler::processglobal + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/py_rref.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/py_rref.h new file mode 100644 index 0000000000000000000000000000000000000000..c5735e844b6e1f62dbfc779a76db78857e111593 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/py_rref.h @@ -0,0 +1,86 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace torch::distributed::rpc { + +// NOLINTNEXTLINE(performance-enum-size) +enum RRefProxyType { RPC_SYNC, RPC_ASYNC, REMOTE }; + +// Python wrapper of an RRef shared_ptr that supports Python +// pickle and unpickle. +class PYBIND11_EXPORT PyRRef { + public: + // The first ctor can only be called while holding GIL. See its implementation + // for more explanations. + explicit PyRRef(const py::object& value, const py::object& type_hint); + explicit PyRRef(c10::intrusive_ptr rref); + PyRRef(const PyRRef&) = default; + ~PyRRef(); + + bool isOwner() const; + bool confirmedByOwner() const; + WorkerInfo owner() const; + std::string ownerName() const; + py::object toHere( + const float timeoutSeconds = + torch::distributed::rpc::kUnsetRpcTimeout) const; + py::object localValue() const; + std::string str() const; + py::tuple pickle() const; + static PyRRef unpickle(const py::tuple& t); + c10::IValue toIValue() const; + // Future that is associated with the creation of this RRef on the remote end. + // This is only used to get the future corresponding to the rref for profiling + // use cases. + c10::intrusive_ptr getFuture() const; + // Keeps track of the future responsible for profiling owner creation + // acknowledgement + c10::intrusive_ptr getProfilingFuture() const; + // Sets the future responsible for profiling owner creation acknowledgement. + // This future is set from python to be a future that returns when profiling + // callbacks have been run. + void setProfilingFuture(c10::intrusive_ptr profilingFuture); + + // create a proxy on this RRef, which can be used to launch RPC on the owner + // of this RRef to run functions on the object referenced by this RRef. + py::object createRRefProxy( + const RRefProxyType& mode, + float timeoutSeconds = rpc::kUnsetRpcTimeout) const; + + // get the type of the data object referenced by this RRef. Timeout argument + // is only used in the first invocation of this function as an argument to the + // RPC to the owner node of the RRef. + py::object getRRefType( + float timeout = rpc::kUnsetRpcTimeout, + bool blocking = true); + + // Run the backward pass with the RRef as the root. + void backward(int64_t autogradContextId, bool retainGraph); + + // Helper static function to run backward on a given rref. + static void backward( + int64_t autogradContextId, + bool retainGraph, + const c10::intrusive_ptr& rref); + + // Specialization of backward if the rref is an OwnerRRef. + static void backwardOwnerRRef( + int64_t autogradContextId, + bool retainGraph, + IValue value); + + private: + c10::intrusive_ptr rref_; + std::optional> profilingFuture_; + std::optional type_; +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/python_call.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/python_call.h new file mode 100644 index 0000000000000000000000000000000000000000..ea339cae11b4dedb5a2aefa2b702443bc53708a4 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/python_call.h @@ -0,0 +1,34 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::distributed::rpc { + +// RPC call representing calling a Python function over RPC. +class TORCH_API PythonCall final : public RpcCommandBase { + public: + PythonCall(SerializedPyObj&& serializedPyObj, bool isAsyncExecution); + + c10::intrusive_ptr toMessageImpl() && override; + + static std::unique_ptr fromMessage(const Message& message); + + const SerializedPyObj& serializedPyObj() const; + + inline bool isAsyncExecution() const { + return isAsyncExecution_; + } + + private: + SerializedPyObj serializedPyObj_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const bool isAsyncExecution_; +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/python_functions.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/python_functions.h new file mode 100644 index 0000000000000000000000000000000000000000..ba69781bdcb0a200b52d30da80cabeb52ff8608d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/python_functions.h @@ -0,0 +1,71 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +namespace torch::distributed::rpc { + +// Converts an internal ivalue::Future of Message into a user-facing +// ivalue::Future of py::object type by creating a new ivalue::Future and call +// its markCompleted as a callback in the given ivalue::Future. +// If hasValue is true, the Message will be converted into a py::object and then +// wrap it with an IValue. If hasValue is false, this ivalue::Future is only +// used for signaling and launching callbacks. In this case, the message will be +// discarded and then set the ivalue::Future using an empty IValue or the given +// FutureError if there is an error. +c10::intrusive_ptr toPyJitFuture( + const c10::intrusive_ptr& messageJitFuture, + bool hasValue = true); + +c10::intrusive_ptr pyRpcBuiltin( + const WorkerInfo& dst, + const std::string& opName, + const py::args& args, + const py::kwargs& kwargs, + const float rpcTimeoutSeconds); + +c10::intrusive_ptr pyRpcPythonUdf( + const WorkerInfo& dst, + std::string& pickledPythonUDF, + std::vector& tensors, + const float rpcTimeoutSeconds, + const bool isAsyncExecution); + +c10::intrusive_ptr pyRpcTorchscript( + const std::string& dstWorkerName, + const std::string& qualifiedNameStr, + const py::tuple& argsTuple, + const py::dict& kwargsDict, + const float rpcTimeoutSeconds, + const bool isAsyncExecution); + +PyRRef pyRemoteBuiltin( + const WorkerInfo& dst, + const std::string& opName, + const float rpcTimeoutSeconds, + const py::args& args, + const py::kwargs& kwargs); + +PyRRef pyRemotePythonUdf( + const WorkerInfo& dst, + std::string& pickledPythonUDF, + std::vector& tensors, + const float rpcTimeoutSeconds, + const bool isAsyncExecution); + +PyRRef pyRemoteTorchscript( + const std::string& dstWorkerName, + const std::string& qualifiedNameStr, + const float rpcTimeoutSeconds, + const bool isAsyncExecution, + const py::args& args, + const py::kwargs& kwargs); + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/python_remote_call.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/python_remote_call.h new file mode 100644 index 0000000000000000000000000000000000000000..b34cb40349850c4c643e9e5d899b53293f220a2b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/python_remote_call.h @@ -0,0 +1,50 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +namespace torch::distributed::rpc { + +class TORCH_API PythonRemoteCall : public RpcCommandBase { + public: + PythonRemoteCall( + SerializedPyObj&& serializedPyObj, + at::IValue retRRefId, + at::IValue retForkId, + const bool isAsyncExecution); + + inline const SerializedPyObj& serializedPyObj() const { + return serializedPyObj_; + } + + inline const at::IValue& retRRefId() const { + return retRRefId_; + } + + inline const at::IValue& retForkId() const { + return retForkId_; + } + + inline bool isAsyncExecution() const { + return isAsyncExecution_; + } + + c10::intrusive_ptr toMessageImpl() && override; + static std::unique_ptr fromMessage(const Message& message); + + private: + SerializedPyObj serializedPyObj_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const at::IValue retRRefId_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const at::IValue retForkId_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const bool isAsyncExecution_; +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/python_resp.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/python_resp.h new file mode 100644 index 0000000000000000000000000000000000000000..cc47fbe631a219bcd16a847d1bb849fa812068cf --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/python_resp.h @@ -0,0 +1,28 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::distributed::rpc { + +// RPC call representing the response of a Python UDF over RPC. +class TORCH_API PythonResp final : public RpcCommandBase { + public: + explicit PythonResp(SerializedPyObj&& serializedPyObj); + + c10::intrusive_ptr toMessageImpl() && override; + + static std::unique_ptr fromMessage(const Message& message); + + const SerializedPyObj& serializedPyObj() const; + + private: + SerializedPyObj serializedPyObj_; +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/python_rpc_handler.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/python_rpc_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..8cd486389d7b0efe1fe438478a9d3313d15c1e2d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/python_rpc_handler.h @@ -0,0 +1,134 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +namespace torch::distributed::rpc { + +// Singleton class provides interface to execute python UDF remote call +// and deserialize the returned results by running python function +// in internal_rpc_utilities. +// The singleton object is constructed at first when RPC agent is +// constructed, where the python function in +// torch/distributed/internal_rpc_utils.py are imported only once. +class PYBIND11_EXPORT PythonRpcHandler { + public: + struct RRefProxyFunctions { + py::object rrefProxyCtor_; + py::object rpcSync_; + py::object rpcAsync_; + py::object remote_; + }; + + struct RRefTypeFunctions { + py::object onOwner_; + py::object onUser_; + }; + + static PythonRpcHandler& getInstance(); + + // Run a pickled Python UDF and return the result py::object + py::object runPythonUdf(const py::object& pythonUdf); + + // Serialized a py::object into a string + SerializedPyObj serialize(const py::object& obj); + + // Deserialize a string into a py::object + py::object deserialize(const SerializedPyObj& serializedObj); + + // Check if obj is RemoteException, then throw it + void handleException(const py::object& obj); + // Alternative if the caller is already holding the GIL. + void handleExceptionGILHeld(const py::object& obj); + // Check if obj is an RemoteException instance. + bool isRemoteException(const py::object& obj); + + // Explicitly clean up py::objects to avoid segment faults when + // py::objects with CPython are cleaned up later at program exit + // See similar issues reported https://github.com/pybind/pybind11/issues/1598 + // and https://github.com/pybind/pybind11/issues/1493 + // Our local tests also caught this segment faults if py::objects are cleaned + // up at program exit. The explanation is: CPython cleans up most critical + // utilities before cleaning up PythonRpcHandler singleton, so when + // PythonRpcHandler singleton cleans up py::objects and call dec_ref(), it + // will crash. + // The solution is to clean up py::objects earlier when Rpc agent join(). + // Be note that py::objects can not be cleaned up when Rpc agent is destroyed + // as well, as Rpc agent is global variable and it will have same issue as + // PythonRpcHandler. + void cleanup(); + + std::shared_ptr jitCompilationUnit(); + + // Parse the string to recover the jit_type, this is used for RRef python + // pickling/unpickling type recovery. The type string inference rule is as + // follows: + // 1. first try to parse if this is primitive types. + // i.e. TensorType, IntType, PyObjectType, etc. + // 2. if not primitive type, we query the python_cu to see if it is a + // class type or interface type registered in python + // We use a ScriptTypeParser instance with custom PythonTypeResolver + // to resolve types according to the above rules. + TypePtr parseTypeFromStr(const std::string& typeStr); + + // Return a set of Python functions for RRef helpers. + const RRefProxyFunctions& getRRefProxyFunctions() const; + + // Return a set of Python functions to retrieve the type of the object + // referenced by a given RRef. + const RRefTypeFunctions& getRRefTypeFunctions() const; + + PythonRpcHandler(const PythonRpcHandler&) = delete; + PythonRpcHandler& operator=(const PythonRpcHandler&) = delete; + PythonRpcHandler(PythonRpcHandler&&) = delete; + PythonRpcHandler& operator=(PythonRpcHandler&&) = delete; + + private: + void init(); + PythonRpcHandler(); + ~PythonRpcHandler() = default; + + // Ref to `torch.distributed.rpc.internal._run_function`. + py::object pyRunFunction_; + + // Ref to `torch.distributed.rpc.internal.serialize`. + py::object pySerialize_; + + // Ref to `torch.distributed.rpc.internal.deserialize`. + py::object pyDeserialize_; + + // Ref to 'torch.distributed.rpc.internal._handle_exception' + py::object pyHandleException_; + + // Python functions for RRef proxy + RRefProxyFunctions rrefProxyFunctions_; + + // Ref to 'torch.distributed.rpc.api._rref_typeof_on_' + RRefTypeFunctions rrefTypeFunctions_; + + // Shared ptr to python compilation unit in jit, it is constructed in python + // side (see _python_cu = torch._C.CompilationUnit() in jit/__init__.py) + // and imported in C++ (see get_python_cu() in + // csrc/jit/python/pybind_utils.h). We import the compilation unit here only + // once for less cost and thread safety. + std::shared_ptr jitCompilationUnit_; + + // jit type parser to parse type_str back to TypePtr for RRef type + // recovery when pickling and unpickling RRef + std::shared_ptr typeParser_; + + // Indicates whether or not we have properly initialized the handler. + bool initialized_{false}; + + // Lock to protect initialization. + std::mutex init_lock_; +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/request_callback.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/request_callback.h new file mode 100644 index 0000000000000000000000000000000000000000..f0b0a52371b27e14b530df19a47491337c856d63 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/request_callback.h @@ -0,0 +1,37 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::distributed::rpc { + +// Functor which is invoked to process an RPC message. This is an abstract class +// with some common functionality across all request handlers. Users need to +// implement this interface to perform the actual business logic. +class TORCH_API RequestCallback { + public: + // Invoke the callback. + c10::intrusive_ptr operator()( + Message& request, + std::vector streams) const; + + virtual ~RequestCallback() = default; + + protected: + // RpcAgent implementation should invoke ``RequestCallback`` to process + // received requests. There is no restriction on the implementation's + // threading model. This function takes an rvalue reference of the Message + // object. It is expected to return the future to a response message or + // message containing an exception. Different rpc agent implementations are + // expected to ensure delivery of the response/exception based on their + // implementation specific mechanisms. + virtual c10::intrusive_ptr processMessage( + Message& request, + std::vector streams) const = 0; +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/request_callback_impl.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/request_callback_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..7bea64f4b19c05dec4201eead386978cf6a32c64 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/request_callback_impl.h @@ -0,0 +1,66 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +namespace torch::distributed::rpc { + +class TORCH_API RequestCallbackImpl : public RequestCallbackNoPython { + public: + std::unique_ptr deserializePythonRpcCommand( + std::unique_ptr rpc, + const MessageType& messageType) const override; + + c10::intrusive_ptr processPythonCall( + RpcCommandBase& rpc, + const std::vector& streams) const override; + + c10::intrusive_ptr processScriptCall( + RpcCommandBase& rpc, + const std::vector& streams) const override; + + c10::intrusive_ptr processScriptRemoteCall( + RpcCommandBase& rpc, + const std::vector& streams) const override; + + c10::intrusive_ptr processPythonRemoteCall( + RpcCommandBase& rpc, + const std::vector& streams) const override; + + c10::intrusive_ptr processPythonRRefFetchCall( + RpcCommandBase& rpc) const override; + + void handleRRefDelete(c10::intrusive_ptr& rref) const override; + + c10::intrusive_ptr processRpcWithErrors( + RpcCommandBase& rpc, + const MessageType& messageType, + const std::vector& streams) const override; + + bool cudaAvailable() const override; + + c10::intrusive_ptr processRRefBackward( + RpcCommandBase& rpc) const override; + + // Helpers to run user-defined functions, operators and other computations. + + c10::intrusive_ptr runJitFunction( + const c10::QualifiedName& name, + std::vector& stack, + const std::vector& streams, + bool isAsyncExecution) const; + + c10::intrusive_ptr runPythonFunction( + const py::object& function, + const std::vector& streams, + bool isAsyncExecution) const; +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/request_callback_no_python.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/request_callback_no_python.h new file mode 100644 index 0000000000000000000000000000000000000000..e8632437b14fefed1c3de5c8ea390059c98c87a1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/request_callback_no_python.h @@ -0,0 +1,120 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace torch::distributed::rpc { + +// RequestCallback implementation with no Python dependencies. +class TORCH_API RequestCallbackNoPython : public RequestCallback { + public: + c10::intrusive_ptr processMessage( + Message& request, + std::vector streams) const override; + + protected: + virtual std::unique_ptr deserializePythonRpcCommand( + std::unique_ptr rpc, + const MessageType& messageType) const; + + virtual c10::intrusive_ptr processScriptCall( + RpcCommandBase& rpc, + const std::vector& streams) const; + + virtual c10::intrusive_ptr processPythonCall( + RpcCommandBase& rpc, + const std::vector& streams) const; + + c10::intrusive_ptr assignOwnerRRef( + const RRefId& rrefId, + const RRefId& forkId, + const c10::intrusive_ptr& valueFuture) const; + + virtual c10::intrusive_ptr processScriptRemoteCall( + RpcCommandBase& rpc, + const std::vector& streams) const; + + virtual c10::intrusive_ptr processPythonRemoteCall( + RpcCommandBase& rpc, + const std::vector& streams) const; + + c10::intrusive_ptr retrieveOwnerRRef(const RRefId& rrefId) const; + + c10::intrusive_ptr processScriptRRefFetchCall( + RpcCommandBase& rpc) const; + + virtual c10::intrusive_ptr processPythonRRefFetchCall( + RpcCommandBase& rpc) const; + + c10::intrusive_ptr processRRefUserDelete( + RpcCommandBase& rpc) const; + + c10::intrusive_ptr processRRefChildAccept( + RpcCommandBase& rpc) const; + + c10::intrusive_ptr processRRefForkRequest( + RpcCommandBase& rpc) const; + + c10::intrusive_ptr processForwardAutogradReq( + RpcCommandBase& rpc, + const std::vector& streams) const; + + c10::intrusive_ptr processBackwardAutogradReq( + RpcCommandBase& rpc, + const std::vector& streams) const; + + c10::intrusive_ptr processCleanupAutogradContextReq( + RpcCommandBase& rpc) const; + + c10::intrusive_ptr processRunWithProfilingReq( + RpcCommandBase& rpc) const; + + virtual void handleRRefDelete(c10::intrusive_ptr& rref) const; + + c10::intrusive_ptr processRpc( + RpcCommandBase& rpc, + const MessageType& messageType, + const std::vector& streams) const; + + virtual c10::intrusive_ptr processRpcWithErrors( + RpcCommandBase& rpc, + const MessageType& messageType, + const std::vector& streams) const; + + c10::intrusive_ptr handleError( + const std::exception& e, + const MessageType messageType, + int64_t messageId) const; + + virtual bool cudaAvailable() const; + + virtual c10::intrusive_ptr processRRefBackward( + RpcCommandBase& rpc) const; + + // Helpers to run user-defined functions, operators and other computations. + + c10::intrusive_ptr runJitOperator( + const jit::Operator& op, + std::vector& stack, + const std::vector& streams) const; + + // Helpers to convert various kinds of objects into already-completed futures. + + c10::intrusive_ptr asFuture(IValue value, TypePtr type) const; + + c10::intrusive_ptr asFuture( + c10::intrusive_ptr message) const; + + c10::intrusive_ptr asFuture(std::exception_ptr err) const; +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rpc.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rpc.h new file mode 100644 index 0000000000000000000000000000000000000000..9e0ced778117bcf6dc19a32b2a7fc90749172e88 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rpc.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::distributed::rpc { + +PyMethodDef* python_functions(); + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rpc_agent.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rpc_agent.h new file mode 100644 index 0000000000000000000000000000000000000000..7ce5590994cca2b262f3015e183d36c616f69137 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rpc_agent.h @@ -0,0 +1,345 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace torch::distributed::rpc { + +using DeviceMap = std::unordered_map; + +// Default RPC timeout +constexpr float kDefaultRpcTimeoutSeconds = 60; +// Unset RPC timeout. This is the value agent::send() will have if user does not +// pass in a specific timeout, and indicates that we must use the default +// timeout for RPCs. +constexpr float kUnsetRpcTimeout = -1; +constexpr auto kDefaultInitMethod = "env://"; +constexpr float kSecToMsConversion = 1000; +constexpr auto kRpcTimeoutErrorStr = + "RPC ran for more than set timeout ({} ms) and will now be marked with an error"; +constexpr auto kDefaultNumWorkerThreads = 16; + +using steady_clock_time_point = + std::chrono::time_point; +// Input is qualified name string, output is JIT StrongTypePtr +// Same as jit::TypeResolver, did not import jit::TypeResolver to here +// because it could introduce cyclic dependencies. +using TypeResolver = + std::function; + +struct TORCH_API RpcBackendOptions { + RpcBackendOptions() + : RpcBackendOptions(kDefaultRpcTimeoutSeconds, kDefaultInitMethod) {} + + RpcBackendOptions(float rpcTimeoutSeconds, std::string initMethod) + : rpcTimeoutSeconds(rpcTimeoutSeconds), + initMethod(std::move(initMethod)) { + TORCH_CHECK(rpcTimeoutSeconds >= 0, "RPC Timeout must be non-negative"); + } + + float rpcTimeoutSeconds; + std::string initMethod; +}; + +// A globally unique ID to identify an RpcAgent +struct TORCH_API WorkerInfo : torch::CustomClassHolder { + WorkerInfo(std::string name, int64_t id); + + WorkerInfo(std::string name, worker_id_t id); + + bool operator==(const WorkerInfo& rhs) { + return (id_ == rhs.id_) && (name_ == rhs.name_); + } + + static constexpr size_t MAX_NAME_LEN = 128; + + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const std::string name_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const worker_id_t id_; +}; + +struct TORCH_API RegisterWorkerInfoOnce { + RegisterWorkerInfoOnce(); +}; + +TORCH_API std::ostream& operator<<( + std::ostream& os, + const WorkerInfo& workerInfo); + +// Struct for options to configure the RPC Retry protocol. +struct TORCH_API RpcRetryOptions { + // Using a default constructor like all other Options structs in the RPC + // codebase. TORCH_CHECKs for input validation are done in the + // sendWithRetries function. + RpcRetryOptions() = default; + // Maximum number of times we will retry the RPC + int maxRetries{5}; + // Initial duration between consecutive RPC send attempts + std::chrono::milliseconds rpcRetryDuration{std::chrono::milliseconds(1000)}; + // Constant for exponential backoff used while calculating future wait + // durations + float retryBackoff{1.5}; +}; + +// Struct that stores all the metadata needed to retry a given RPC. +struct TORCH_API RpcRetryInfo { + RpcRetryInfo( + const WorkerInfo& to, + c10::intrusive_ptr message, + c10::intrusive_ptr originalFuture, + int retryCount, + RpcRetryOptions options) + : to_(to), + message_(std::move(message)), + originalFuture_(std::move(originalFuture)), + retryCount_(retryCount), + options_(options) {} + + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const WorkerInfo& to_; + c10::intrusive_ptr message_; + // Future that is returned to the caller of sendWithRetries(). + c10::intrusive_ptr originalFuture_; + // Number of send attempts completed so far. + int retryCount_; + RpcRetryOptions options_; +}; + +// ``RpcAgent`` is the base class for sending and receiving RPC messages. It +// provides a unified ``send`` API for both request and response messages, and +// will invoke the given ``RequestCallback`` to process received requests. It +// should immediately become ready to serve request and accept response after +// construction. +class TORCH_API RpcAgent { + public: + // `WorkerInfo` is the globally unique identifier for this RpcAgent instance. + // It contains a ``name_`` field and an ``id_`` field. ``name_`` is the + // globally unique name for this ``RpcAgent``. It is up to the ``RpcAgent`` + // implementation to determine how to resolve names. ``id_`` is the globally + // unique ID for this ``RpcAgent``. This should be determined by the + // ``RpcAgent`` implementation. + // The ``RequestCallback`` will be invoked to handle received requests. This + // ``RpcAgent`` base class makes no assumption on the thread-safeness of the + // ``RequestCallback``. ``RpcAgent`` implementations need to make sure that + // its threading model conform to ``RequestCallback``'s requirement. + // NB: RpcAgent implementations should not start serving requests until + // ``start()`` is called, as there could be other contexts that have not been + // initialized yet at this time. + RpcAgent( + WorkerInfo id, + std::unique_ptr cb, + std::chrono::milliseconds rpcTimeout); + + virtual ~RpcAgent(); + + // Send a message to the ``RpcAgent`` of id ``to`` and returns a + // ``JitFuture`` ptr. The implementation must be asynchronous, i.e., it + // cannot block until it receives the response. + // + // If ``message.isRequest()`` is true, the ``JitFuture`` will be + // completed when the response arrives. For other message types, the Future + // should be ignored by the caller. + virtual c10::intrusive_ptr send( + const WorkerInfo& to, + c10::intrusive_ptr message, + const float rpcTimeoutSeconds = kUnsetRpcTimeout, + const DeviceMap& deviceMap = {}) = 0; + + // Retries sending the message up to maxRetries times until an ACK is + // received. The duration between consecutive sends is increased over + // time using an exponential backoff algorithm. + // + // Sends ``message`` to the ``RpcAgent`` of id ``to`` and returns a + // ``JitFuture`` ptr, just like send(). Caller can specify the maximum + // number of retries for this RPC (default is 5), initial duration between + // sends (default is 1000ms), and backoff constant (default is 1.5) by + // passing in the RpcRetryOptions struct. This API might end up + // executing a method twice on the remote end (it does not guarantee + // exactly-once semantics). Therefore, the user must ensure their requests + // are idempotent. + c10::intrusive_ptr sendWithRetries( + const WorkerInfo& to, + c10::intrusive_ptr message, + RpcRetryOptions retryOptions = RpcRetryOptions()); + + // Return a reference to the ``WorkerInfo`` of this RpcAgent. + // NB: not using ``std::optional`` here because we might + // need to create a separate RPC API lib and avoid forcing all ``RpcAgent`` + // implementations to depend on libtorch. + const WorkerInfo& getWorkerInfo() const; + + // Return a reference to the ``WorkerInfo`` of the given ``workerName``. + virtual const WorkerInfo& getWorkerInfo( + const std::string& workerName) const = 0; + + virtual const WorkerInfo& getWorkerInfo(worker_id_t id) const = 0; + + virtual std::vector getWorkerInfos() const = 0; + + // Retrieve the timeout for all RPCs. + inline std::chrono::milliseconds getRpcTimeout() const { + return rpcTimeout_.load(); + } + + // Set the timeout for all RPCs + inline void setRpcTimeout(const std::chrono::milliseconds& rpcTimeout) { + rpcTimeout_.store(rpcTimeout); + } + + // Call sync and join all internal threads. This method should be called + // before every RPC process exits. + virtual void join(bool shutdown = false, float timeout = 0) = 0; + + // Synchronize the this process with other ``RpcAgent`` processes. Block until + // all ``RpcAgent``s reach this method and send all pending messages. + virtual void sync() = 0; + + // Sets up backend-agnostic state for accepting requests. Currently, this + // entails setting rpcAgentRunning_ to true, creating the retry thread, and + // calling the backend's startImpl. + void start(); + + // Derived classes must override this function to start accepting requests. + // This is used to initialize any backend-specific state. Users must call + // start, not startImpl, to initialize the RPC Agent. + virtual void startImpl() = 0; + + // Stop accepting requests and shutdown the RPC framework as soon as possible + // by terminating all RPC threads. + void shutdown(); + + // Derived classes must override this function to start accepting requests. + // THis is used to clean up any backend-specific state. Users must call + // shutdown, not shutdownImpl, to shutdown the RPC Agent. + virtual void shutdownImpl() = 0; + + // Check if current RPC agent is set. + static bool isCurrentRpcAgentSet(); + + // Retrieve the valid current RPC agent. + static std::shared_ptr getCurrentRpcAgent(); + + // Set the current RPC agent. + static void setCurrentRpcAgent(std::shared_ptr rpcAgent); + + // Retrieve metrics as KV map + virtual std::unordered_map getMetrics() = 0; + + // Retrieve debug info in addition to metrics as KV map + virtual std::unordered_map getDebugInfo(); + + // Flag to control whether GIL wait times + // should be profiled or not. + void enableGILProfiling(bool flag); + + // Retrieve whether we should profile GIL wait times or not. + bool isGILProfilingEnabled(); + + // Set type resolver that will be passed to JIT pickler to resolver type Ptr + // based on type str. + void setTypeResolver(std::shared_ptr typeResolver); + + // Get the type resolver + std::shared_ptr getTypeResolver(); + + // Retrieves the device map for the provided destination worker. + virtual DeviceMap getDeviceMap(const WorkerInfo& dst) const; + + // Retrieve the (non-CPU) devices that are supported by the agent. + virtual const std::vector& getDevices() const; + + protected: + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const WorkerInfo workerInfo_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const std::unique_ptr cb_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + std::atomic rpcTimeout_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + std::atomic profilingEnabled_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + std::shared_ptr typeResolver_; + // Atomic boolean indicating whether this agent is running. It controls + // whether several background threads should be running. It is set in + // RpcAgent::start() and unset in the derived class shutdown(). + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + std::atomic rpcAgentRunning_; + + private: + static std::shared_ptr currentRpcAgent_; + // Add GIL wait time data point to metrics + virtual void addGilWaitTime(const std::chrono::microseconds gilWaitTime) = 0; + friend class PythonRpcHandler; + + // Map that stores metadata for RPC's that may need to be re-tried as well as + // the timepoint at which we should re-try them. + std::map< + steady_clock_time_point, + std::unordered_set>> + rpcRetryMap_; + + // Thread that checks for retryable RPC's in the rpcRetryMap_ and sleeps until + // the next unACKed RPC's timeout has expired. + std::thread rpcRetryThread_; + + // Function that rpcRetryThread_ calls in a loop as long as RpcAgent is + // running. + void retryExpiredRpcs(); + + // This is the callback attached to futures corresponding to send retries. + // This handles 3 cases: 1). send was completed, 2). send failed with an + // error and we've done maxRetries failed send attempts, and 3). send + // failed with an error and we have more retries to go. In case 1, we mark + // the original future as complete. In case 2, we mark the future with an + // error and do not retry again. In case 3, we move the RpcRetryInfo struct + // to another time point in the map to schedule the RPC for a future send. + void rpcRetryCallback( + JitFuture& message, + steady_clock_time_point newTime, + std::shared_ptr earliestRpc); + + // Function that uses the exponential backoff algorithm to compute the next + // time point to retry a given RPC. + inline steady_clock_time_point computeNewRpcRetryTime( + RpcRetryOptions& options, + int retryCount) { + // The exponential backoff algorithm being used here is: + // newTime = timeNow + (retryDuration * (backoffConstant ^ retryCount)). + std::chrono::milliseconds timedelta = + std::chrono::duration_cast( + options.rpcRetryDuration * pow(options.retryBackoff, retryCount)); + return std::chrono::time_point_cast( + std::chrono::steady_clock::now() + timedelta); + } + + // Condition Variable to signal when the rpcRetryMap_ has been populated. + std::condition_variable rpcRetryMapCV_; + + // Mutex to protect RpcRetryMap_. + std::mutex rpcRetryMutex_; +}; + +} // namespace torch::distributed::rpc + +namespace std { +template <> +struct hash { + std::size_t operator()( + const torch::distributed::rpc::WorkerInfo& worker_info) const noexcept { + return worker_info.id_; + } +}; +} // namespace std + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rpc_command_base.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rpc_command_base.h new file mode 100644 index 0000000000000000000000000000000000000000..2ea338813b121c913e1cd0d78fdf5dfe22c03bb1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rpc_command_base.h @@ -0,0 +1,28 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::distributed::rpc { + +// Base class for all RPC request and responses. +class RpcCommandBase { + public: + // Need to override this to serialize the RPC. This should destructively + // create a message for the RPC (Hence the &&). + c10::intrusive_ptr toMessage() && { + JitRRefPickleGuard jitPickleGuard; + return std::move(*this).toMessageImpl(); + } + virtual c10::intrusive_ptr toMessageImpl() && = 0; + virtual ~RpcCommandBase() = 0; +}; + +inline RpcCommandBase::~RpcCommandBase() = default; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rref_context.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rref_context.h new file mode 100644 index 0000000000000000000000000000000000000000..6f1703a51e6f67be61b2591e3728eda4da5d5566 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rref_context.h @@ -0,0 +1,340 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +namespace torch::distributed::rpc { + +namespace callback { +// It's the callback for RemoteCall. +void TORCH_API +confirmPendingUser(const JitFuture& jitFuture, const ForkId& expectedForkId); + +// It's the callback for finishing creating owner rref, it returned deletedRRef, +// so that the deletedRRef can be handled under GIL in python_functions.cpp if +// deletedRRef contains python object. +c10::intrusive_ptr TORCH_API +finishCreatingOwnerRRef(const JitFuture& jitFuture, const RRefId& rrefId); +} // namespace callback + +// Manages RRef lifetime and keeps track of RRef forks. +class TORCH_API RRefContext { + public: + static RRefContext& getInstance(); + // NB: This method must be called before destructing RRefContext singleton. + // Similar to delForkOfOwner, this method returns a vector of OwnerRRefs that + // hold py::object. The call-site is also responsible for resetting those + // shared_ptr objects with a GIL. See comments at delForkOfOwner() for more + // details. + static std::vector> destroyInstance( + bool ignoreRRefLeak = true); + + static void handleException(const JitFuture& jitFuture); + + // handle exception without throw ::c10::Error again + static void handleExceptionSilent(const JitFuture& jitFuture); + + RRefContext(const RRefContext&) = delete; + RRefContext(RRefContext&& other) = delete; + void operator=(const RRefContext&) = delete; + RRefContext& operator=(RRefContext&& other) = delete; + + ~RRefContext(); + + // get the worker id of the current worker + inline worker_id_t getWorkerId() const { + return agent_->getWorkerInfo().id_; + } + + // get the worker name of the current worker + inline const std::string& getWorkerName() const { + return agent_->getWorkerInfo().name_; + } + + // generate a globally unique ID + inline GloballyUniqueId genGloballyUniqueId() { + return GloballyUniqueId(getWorkerId(), nextLocalId_++); + } + + inline const std::shared_ptr& agent() const { + return agent_; + } + + // create a ``UserRRef`` owned by the worker ``ownerId`` + c10::intrusive_ptr createUserRRef( + worker_id_t ownerId, + const TypePtr& type); + + // Convert an RRefForkData into an RRef. This RRef could be user or owner. + // This RRef could have already existed before, or could be created in this + // method, we pass type here to validate or help the rref creation. + c10::intrusive_ptr getOrCreateRRef( + const RRefForkData& rfd, + const TypePtr& type); + + // Get the ``OwnerRRef`` of id ``rrefId``. If it does not exist, create a new + // one. This function is called in two places: + // 1. when processing ``rpc.remote()``, i.e., ``SCRIPT_REMOTE_CALL`` + // ``PYTHON_REMOTE_CALL``. + // 2. when unpickling ``OwnerRRef``. + // What's common in these two cases are, 1) the RRefId is already generated + // 2) the TypePtr is presented. So it can always create the ``OwnerRRef`` if + // it is not yet available. + c10::intrusive_ptr getOrCreateOwnerRRef( + const RRefId& rrefId, + const TypePtr& type); + + // Create an empty owner rref of type. + // This method is called to first time generate an ``OwnerRRef``, e.g., + // 1) ``rpc.RRef(obj)`` + // 2) create the ``OwnerRRef`` on `rpc.remote()` caller side. + // What's common in these two cases are, 1) the RRefId hasn't been generated + // 2) the TypePtr is presented. + c10::intrusive_ptr createOwnerRRef(const TypePtr& type); + + // Returns a Future of the OwnerRRef, which will be marked completed when + // ``OwnerRRef`` is created. This method is used when the TypePtr is not + // available, e.g., when processing to_here(). The forceCreated flag can be + // used to ensure that the rref is created on the owner, otherwise throw in + // cases where the user of this API expects this to return a completed future. + // Note that the return value is a intrusive_ptr to a c10::ivalue::Future that + // holds the RRef. + c10::intrusive_ptr getOwnerRRef( + const RRefId& rrefId, + bool forceCreated = false); + + // Adding the RRefId of an OwnerRRef into the forks_ map. This is useful when + // making a remote call to self, which as for now, still goes through serde + // and invokes request callback. In this case, the OwnerRRef has already been + // created on the send side, and we need to pass it to the receive side, + // instead of creating a new OwnerRRef. This is done by adding the OwnerRRef + // into owners_. However, that alone is not enough, as it could be deleted + // when all UserRRef die, which would then remove the OwnerRRef from owners_ + // and this could happen before the self remote call finishes. To prevent + // that, this API adds the RRefId as a ForkId, which will then delete the + // ForkId when the self remote is done. + void addSelfAsFork(c10::intrusive_ptr& rref); + + // Register a fork of the ``OwnerRRef``, and inserts a intrusive_ptr of the + // ``OwnerRRef`` in a map to keep it alive. + void addForkOfOwner(const RRefId& rrefId, const ForkId& forkId); + // Performs the same function as addForkOfOwner but ignores duplicate + // requests. This idempotent function is used with RREF_FORK_REQUEST calls, + // whereas all other message types use the non-idempotent variant. + void addForkOfOwnerIfNotPresent(const RRefId& rrefId, const ForkId& forkId); + // Delete a fork of the ``OwnerRRef``. NB: this could trigger deletion on the + // IValue or py::object. For the later, this method will acquire GIL. + // NB: If this fork deletion triggered deleting OwnerRRef, this method will + // return a shared_ptr to the OwnerRRef, which is likely to be the last + // shared_ptr instance for it. Therefore, deleting this shared_ptr + // will also trigger deleting the object it points to. If OwnerRRef holds a + // py::object, deleting it require GIL. The call site should guarded it with + // a GIL and reset the shared_ptr. The GIL-guarded deletion is intentionally + // left out of this function to avoid creating dependency on pybind. + c10::intrusive_ptr delForkOfOwner( + const RRefId& rrefId, + const ForkId& forkId); + + // Invoked when pickling an RRef to setup child/fork properly + RRefForkData prepareChildFork(const c10::intrusive_ptr& rref); + // Invoked when unpickling an RRef to send RREF_FORK_REQUEST to owner and + // send RREF_CHILD_ACCEPT to the parent. + // NB: forkId is necessary here as the rref could be an OwnerRRef + void notifyOwnerAndParentOfFork( + const ForkId& forkId, + worker_id_t parent, + const c10::intrusive_ptr& rref); + + // When a UserRRef is forked to another worker (user or owner), it is added + // into pendingChildren_ to be held alive until it receives RREF_CHILD_ACCEPT + // from the child. + // NB: This is necessary for both user and owner child. As we do not have FIFO + // communication between workers, we need this strategy to make sure that all + // previously submitted rpc/remote calls are acked before sending out the + // RREF_USER_DELETE message. Otherwise, the OwnerRRef could be deleted too + // soon. + void addPendingChild( + const ForkId& forkId, + const c10::intrusive_ptr& rref); + void delPendingChild(const ForkId& forkId); + + // When a UserRRef is created, it is added into pendingUsers_ to be held alive + // until it receives RREF_USER_ACCEPT from the owner. + void addPendingUser( + const ForkId& forkId, + const c10::intrusive_ptr& rref); + void delPendingUser(const ForkId& forkId); + void addConfirmedUser( + const ForkId& forkId, + const c10::intrusive_ptr& rref); + + // Retrieve a pending user given the fork ID. Throws if the user has already + // been confirmed (i.e. is no longer in the pendingUsers_ map). + c10::intrusive_ptr getPendingUser(const ForkId& forkId); + + // Start recording new pending UserRRefs. All pending UserRRefs introduced + // after this point will be put into the thread_local userTable_, which will + // then be consumed and cleared in waitForThreadLocalPendingRRefs(). + void recordThreadLocalPendingRRefs(); + // End recording new pending UserRRefs, and clear the thread_local userTable_. + // Returns a Future which will be marked as completed when all pending + // UserRRefs in the current userTable_ are confirmed by their owners. The bool + // value in the Future is unused. + // This method is useful to make sure RRefs in user function arguments are + // confirmed before launching user code. + // NB: Callers of this method does not need to keep the returned Future alive, + // because this Future is already captured in callbacks of the + // PendingUserState. If there is no pending UserRRefs, this method returns a + // completed future. + c10::intrusive_ptr waitForThreadLocalPendingRRefs(); + // Only call this function when there are errors during a recording session, + // and it is likely that waitForThreadLocalPendingRRefs() cannot be invoked + // properly. + // TODO: make this a context guard + void clearRecordedPendingRRefsOnError(); + + void delUser( + const worker_id_t owner, + const RRefId& rrefId, + const ForkId& forkId); + void delAllUsersAndUnforkedOwners(std::chrono::milliseconds timeoutMillis); + + std::unordered_map getDebugInfo(); + + private: + struct PendingUserState { + PendingUserState(c10::intrusive_ptr rref) + : rref_(std::move(rref)), + confirmationFuture_(c10::make_intrusive(BoolType::get())) { + } + + inline void confirm() { + c10::static_intrusive_pointer_cast(rref_)->confirm(); + confirmationFuture_->markCompleted(); + } + + c10::intrusive_ptr rref_; + // Use Future.wait() and Future.markCompleted() to block and unblock user + // functions. The bool value wrapped by the future_ is not used. + c10::intrusive_ptr confirmationFuture_; + }; + + RRefContext(std::shared_ptr /*agent*/); + + c10::intrusive_ptr createUserRRef( + worker_id_t ownerId, + const RRefId& rrefId, + const ForkId& forkId, + const TypePtr& type); + + void finishForkRequest(const ForkId& forkId, worker_id_t parent); + + // If there is any leak on any RRef, this method will throw an error. + void checkRRefLeaks(bool ignoreRRefLeak); + + static std::atomic nextLocalId_; + + const std::shared_ptr agent_; + mutable std::mutex mutex_; + // Keep OwnerRRefs alive until there is no living UserRRefs. + std::unordered_map, RRefId::Hash> owners_; + // A map to track OwnerRRefs that are requested but not yet created. This can + // happen if the to_here() message is processed on the owner before the + // corresponding creator rpc.remote() message. If this happens, instead of + // to_here() RPC thread to block waiting for the OwnerRRef creation, the + // RRefContext returns a Future, so that the RPC request processing logic can + // attach subsequent code as a callback to that Future. + // NB: the OwnerRRefs in this map must be cleared when the corresponding + // OwnerRRef is created. Note that the values in this map are intrusive_ptrs + // to c10::ivalue::Future that will be marked completed with the owner RRef. + std::unordered_map, RRefId::Hash> + pendingOwners_; + // Tracks known living UserRRefs of an OwnerRRef + std::unordered_map< + RRefId, + std::unordered_set, + RRefId::Hash> + forks_; + + // This cond var is used by deleteAllUsers(), a event notification is sent if + // number of pending UserRRef or UserRRef children is reduced, or + // number of owned OwnerRRef is reduced. + std::condition_variable deleteAllUsersCV_; + // The follow 3 maps keep UserRRefs alive by holding a intrusive_ptr to the + // RRef instances. A UserRRef must be added into this map if any of the + // following two conditions is true: + // + // (1) A UserRRef has not been accepted by owner yet. + // + // It can be used or shared, but cannot be deleted, and hence kept alive + // in this map. A message of type RREF_USER_ACCEPT will move the + // corresponding RRef from pendingUsers_ map to confirmedUsers_ map. + std::unordered_map, ForkId::Hash> + pendingUsers_; + // UserRRefs are added into this map when it is confirmed by the owner. + // When destroying RRefContext this map helps to find local UserRRefs + // and send delete messages if they are still not deleted by Python + // garbage collection. + std::unordered_map, ForkId::Hash> + confirmedUsers_; + + // (2) A UserRRef has forked a child UserRRef which has not been accepted by + // the owner yet. + // + // In this case, this UserRRef cannot send out RREF_USER_DELETE message, + // as it could potentially trigger the OwnerRRef been deleted before the + // owner learns about the forked child. + std::unordered_map, ForkId::Hash> + pendingChildren_; + + // The RRef context performs its operations through async RPC requests, in + // order to not block the user code. Therefore the RRef context's state may be + // lagging a bit behind what it is intended to be, while it waits for these + // requests to complete. To allow syncing when needed, we store the count of + // these pending requests, so that users can wait for it to reach zero. + std::atomic numPendingFutures_{0}; + + std::mutex destroyedMutex_; + bool destroyed_{false}; + + // Thread local states to keep UserRRefs deserialized from user function + // arguments. + static thread_local std::vector> userTable_; + // A flag indicating whether subsequently created UserRRefs should be added to + // the thread_local userTable_. The flag is set to true before serializing + // RPC arguments and then set to false before running the corresponding + // user code. See addPendingUser and delPendingUser for more details. + // NB: The reason for having this flag is because addPendingUser are called in + // two cases, and we only want to track the 2nd case. + // (1) RRef as the return value: when calling rpc.remote, the UserRRef on the + // caller side is added to the context using addPendingUser. + // (2) RRef as an argument: When running an RPC using RRefs as arguments, the + // RRef is forwarded to the callee as new UserRRefs (if the callee is not + // the owner). In this case, we block running the user function until all + // UserRRefs are confirmed by the owner. + // This contract guarantees that no UserRRefs can be used remotely without + // confirmation. Note that, however, the UserRRef created by rpc.remote can + // still be passed to local functions as arguments and used there. This is by + // design, because this feature is especially useful when, say a master node + // creates multiple UserRRefs in a loop and then shares them with other nodes. + // Blocking every iteration in the loop until RRefs are confirmed will slow + // this down. This nuance on UserRRef can be interpreted as we only make + // exceptions for UserRRef creators. And using the UserRRef on its creator + // without confirmation is OK, because the creator would either call to_here + // or forward the UserRRef, and both would then require confirmations from the + // owner. + static thread_local bool recording_; +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rref_impl.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rref_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..ae01733c5d9dab82ad33d47164120d1037ecb3f8 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rref_impl.h @@ -0,0 +1,426 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace torch::distributed::rpc { + +class RRef; +class RRefContext; +class UserRRef; + +constexpr int OWNER_IDX = 0; // index of ownerId in the tuple +constexpr int RREFID_ON_IDX = 1; // index of RRefId.createdOn_ in the tuple +constexpr int RREFID_ID_IDX = 2; // index of RRefId.localId_ in the tuple +constexpr int FORKID_ON_IDX = 3; // index of ForkId.createdOn_ in the tuple +constexpr int FORKID_ID_IDX = 4; // index of ForkId.localId_ in the tuple +constexpr int PARENT_IDX = 5; // index of parent in the tuple +constexpr int TYPE_IDX = 6; // index of parent in the tuple + +// NB: if more fields are added, make sure this field is also bumped +constexpr int RFD_TUPLE_SIZE = 7; // number of RRefForkData fields in py::tuple + +// Represents fork of an RRef to be sent over the wire. +struct TORCH_API RRefForkData { + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const worker_id_t ownerId_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const RRefId rrefId_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const ForkId forkId_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const worker_id_t parent_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const std::string typeStr_; + + RRefForkData( + worker_id_t ownerId, + const RRefId& rrefId, + const ForkId& forkId, + worker_id_t parent, + std::string typeStr); +}; + +// Note [RRef Protocol] +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// [Background] +// +// RRef stands for Remote REFerence. Each RRef is owned by a single worker +// (i.e., owner) and can be used by multiple users. The owner stores the real +// data referenced by its RRefs. RRef needs to support fast and scalable RPC. +// Hence, in the design, we avoid using a single global master to keep RRef +// states, instead owners will keep track of the global reference counts +// for its RRefs. Every RRef can be uniquely identified by a global RRefId, +// which is assigned at the time it is first created either on a user or on the +// owner. +// +// On the owner worker, there is only one OwnerRRef instance, which contains the +// real data, while on user workers, there can be as many UserRRefs as +// necessary, and UserRRef does not hold the data. All usage on the OwnerRRef +// should retrieve the unique OwnerRRef instance using the globally unique +// RRefId. //A UserRRef will be created when it is used as an argument or return +// value in dist.rpc or dist.remote call, but RRef forking and reference +// counting (RC) are completely transparent to applications. Every UserRRef will +// also have its globally unique ForkId. +// +// [Assumptions] +// +// 1. Transient Network Failures +// +// TODO: current RRef implementation does not tolerate failures +// +// The RRef design handles transient network failures by retrying +// messages. Node crashes or permanent network partition is beyond the scope. +// When those incidents occur, the application may take down all workers, revert +// to the previous checkpoint, and resume training. +// +// 2. Non-idempotent UDFs +// +// We assume UDFs are not idempotent and therefore cannot be retried. However, +// internal RRef control messages are idempotent and retried upon message +// failure. +// +// TODO: RRef internal messages are not yet idempotent +// +// 3. Out of Order Message Delivery +// +// We do not assume message delivery order between any pair of nodes, because +// both sender and receiver are using multiple threads. There is no guarantee on +// which message will be processed first. +// +// [RRef Lifetime] +// +// The goal of the protocol is to delete an OwnerRRef at an appropriate time. +// The right time to delete an OwnerRRef is when there are no living UserRRefs +// and Python GC also agrees to delete the OwnerRRef instance on the owner. The +// tricky part is to determine if there are any living UserRRefs. +// +// A user can get a UserRRef in three situations: +// +// (1). Receiving a UserRRef from the owner. +// (2). Receiving a UserRRef from another user. +// (3). Creating a new UserRRef owned by another worker. +// +// (1) is the simplest case where the owner initiates the fork, and hence it can +// easily increment local RC. The only requirement is that any UserRRef must +// notify the owner before destruction. Hence, we need the first guarantee: +// +// G1. The owner will be notified when any UserRRef is deleted. +// +// As messages might come delayed or out-of-order, we need more one guarantee to +// make sure the delete message is not sent out too soon. Let us first introduce +// a new concept. If A sends an RPC to B that involves an RRef, we call the RRef +// on A the parent RRef and the RRef on B the child RRef. +// +// G2. Parent RRef cannot be deleted until the child RRef is confirmed by the +// owner. +// +// Under (1), where the caller is UserRRef and callee is OwnerRRef, it simply +// means that the user will not send out the delete message until all previous +// messages are ACKed. Note that ACKed does not mean the owner finishes +// executing the function, instead, it only means the owner has retrieved its +// local OwnerRRef and about to pass it to the function, which is sufficient to +// keep the OwnerRRef alive even if the delete message from the user arrives at +// the owner before the function finishes execution. +// +// With (2) and (3), it is possible that the owner only partially knows the RRef +// fork graph or not even knowing it at all. For example, the RRef could be +// constructed on a user, and before the owner receives the RPC call, the +// creator user might have already shared the RRef with other users, and those +// users could further share the RRef. One invariant is that the fork graph of +// any RRef is always a tree rooted at the owner, because forking an RRef always +// creates a new RRef instance, and hence every RRef has a single parent. One +// nasty detail is that when an RRef is created on a user, technically the owner +// is not its parent but we still consider it that way and it does not break the +// argument below. +// +// The owner's view on any node (fork) in the tree has three stages: +// +// 1) unknown -> 2) known -> 3) deleted. +// +// The owner's view on the entire tree keeps changing. The owner deletes its +// OwnerRRef instance when it thinks there are no living UserRRefs, i.e., when +// OwnerRRef is deleted, all UserRRefs could be either indeed deleted or +// unknown. The dangerous case is when some forks are unknown and others are +// deleted. +// +// G2 trivially guarantees that no parent UserRRef Y can be deleted before the +// owner knows all of Y's children UserRRefs. +// +// However, it is possible that the child UserRRef Z may be deleted before the +// owner knows its parent Y. More specifically, this can happen when all of Z's +// messages are processed by the owner before all messages from Y, including the +// delete message. Nevertheless, this does not cause any problem. Because, at +// least one of Y's ancestor will be alive, and it will prevent the owner from +// deleting the OwnerRRef. Consider the following example: (NB: this scenario +// will no longer relevant when we block UDF until all RRefs are confirmed by +// the owner) +// +// OwnerRRef -> A -> Y -> Z +// +// OwnerRRef forks to A, then A forks to Y, and Y forks to Z. Z can be deleted +// without OwnerRRef knowing Y. However, the OwnerRRef will at least know A, as +// the owner directly forks the RRef to A. A won't die before the owner knows Y. +// +// Things get a little trickier if the RRef is created on a user: +// +// OwnerRRef +// ^ +// | +// A -> Y -> Z +// +// If Z calls to_here on the UserRRef, the owner at least knows A when Z is +// deleted, because otherwise to_here wouldn't finish. If Z does not call +// to_here, it is possible that the owner receives all messages from Z before +// any message from A and Y. In this case, as the real data of the OwnerRRef has +// not been created yet, there is nothing to be deleted either. It is the same +// as Z does not exist at all Hence, it's still OK. +// +// See #26759 for more details and discussions. +// +// TODO: make RRef an IValue, and edit createStackForSchema accordingly +// TODO: make RRef system messages idempotent and retry on failures. +// +// ``RRef`` is the base type for both ``UserRRef`` and ``OwnerRRef``. +// Each ``RRef`` has a globally unique ``RRefId``. +class TORCH_API RRef : public RRefInterface { + public: + // RRef is made NOT copyable NOT movable to prevent messing up reference + // counting. + explicit RRef(const RRef& other) = delete; + explicit RRef(RRef&& other) = delete; + RRef& operator=(RRef&& other) = delete; + + ~RRef() override = default; + + // returns the worker id of the owner + inline worker_id_t owner() const override { + return ownerId_; + } + + // returns the worker name of the owner + inline std::string ownerName() const override { + return RpcAgent::getCurrentRpcAgent()->getWorkerInfo(ownerId_).name_; + } + + // returns the worker info of the owner + inline WorkerInfo ownerWorkerInfo() const { + return RpcAgent::getCurrentRpcAgent()->getWorkerInfo(ownerId_); + } + + // Returns the globally unique RRefId of this RRef + inline const RRefId& rrefId() const { + return rrefId_; + } + + inline bool isPyObj() const { + return type_ == PyObjectType::get(); + } + inline const TypePtr type() const override { + return type_; + } + + // Save the future corresponding to the creation of this RRef on a remote + // node. Note that this is only set when processing requests invoked with + // rpc.remote. This is only used to get the future corresponding to the rref + // for profiling use cases. + inline void registerOwnerCreationFuture(c10::intrusive_ptr fut) { + ownerCreationFuture_ = std::move(fut); + } + + // Get the future corresponding to the creation of this rref. + inline c10::intrusive_ptr getOwnerCreationFuture() const { + return ownerCreationFuture_; + } + + // Check if creation of this RRef on owner node has timed out. + inline bool getTimedOut() const { + return timedOut_.load(); + } + + // Dispatches an error to the correct handler based on its RPCErrorType. + void handleError(RPCErrorType errorType, const JitFuture& JitFuture); + + // Send delete UserRRef request to Owner, + // if the request hasn't been sent yet. + // There are 2 cases to call it, + // 1, Python GC decides end of UserRRef lifetime, calling destructor. + // 2, RPC module graceful shutdown calls it on all UserRRefs tracked + // in the RRefContext. + virtual void tryDel() {} + + protected: + // Indicates that the creation of this RRef on owner node has timed out. + inline void setTimedOut() { + timedOut_ = true; + } + friend class RRefContext; + + RRef(worker_id_t ownerId, const RRefId& rrefId, TypePtr type); + + virtual RRefForkData fork() const; + + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const worker_id_t ownerId_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const RRefId rrefId_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + std::atomic timedOut_{false}; + + // type field to denote the type of the element that the RRef is holding + // it could be any TypePtr that JIT support, including PyObjectType + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const TypePtr type_; + // Future corresponding to request to create RRef on remote node. + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + c10::intrusive_ptr ownerCreationFuture_; +}; + +// ``UserRRef`` represents a user of an RRef. Besides the ``RRefId``, each user +// also has a globally unique ``ForkId`` to identify this user. ``UserRRef`` +// never owns the real value, the only way to get the value of the ``RRef`` is +// to call ``to_here()`` and get a copy.. +class TORCH_API UserRRef final : public RRef { + public: + UserRRef(const UserRRef& other) = delete; + UserRRef(UserRRef&& other) = delete; + UserRRef& operator=(const UserRRef& other) = delete; + UserRRef& operator=(UserRRef&& other) = delete; + + UserRRef( + worker_id_t ownerId, + const RRefId& rrefId, + const ForkId& forkId, + TypePtr type); + + inline bool isOwner() const override { + return false; + } + + inline bool confirmedByOwner() const override { + return confirmedByOwner_; + } + + // Returns the globally unique ForkId of this RRef + const ForkId& forkId() const; + + // Get of copy of the value from the ``OwnerRRef``. If the value is not ready + // yet, this call will block. + IValue toHere( + const float timeoutSeconds = + torch::distributed::rpc::kUnsetRpcTimeout) const; + + void tryDel() override; + + // Will be called when refcount reaches 0. + // Upon destruction, this ``UserRRef`` will tell the owner to deref. + void release_resources() override; + + // Will be called when both refcount and weakcount reach 0. See + // https://github.com/pytorch/pytorch/blob/9116f02bebf3a5260feef5732d36c54ecb3b4033/c10/util/intrusive_ptr.h#L204 + // This is called on destructing the wrapping intrusive_ptr_target instance + // and it's data members. + ~UserRRef() override; + + private: + friend class RRefContext; + + RRefForkData fork() const override; + inline void confirm() { + confirmedByOwner_ = true; + } + + const ForkId forkId_; + + // Indicates if this user has sent delete message to it's owner. + // Note, thread safety is needed because delete message could be sent by + // either the destructor called by Python garbage collection or RRefContext + // proactive cleanup on RPC graceful shutdown. + std::mutex deletedOnOwnerMutex_; + bool deletedOnOwner_{false}; + // Indicating whether this UserRRef has been confirmed by its owner. + std::atomic confirmedByOwner_; +}; + +// Keep the template only on the derived class because ``RRefContext`` needs to +// erase the type on ``RRef`` and keep them in one map. +class TORCH_API OwnerRRef final : public RRef { + public: + OwnerRRef(const OwnerRRef& other) = delete; + OwnerRRef(OwnerRRef&& other) = delete; + OwnerRRef& operator=(const OwnerRRef& other) = delete; + OwnerRRef& operator=(OwnerRRef&& other) = delete; + + OwnerRRef( + worker_id_t ownerId, + const RRefId& rrefId, + TypePtr type, + std::vector devices); + + OwnerRRef( + worker_id_t ownerId, + const RRefId& rrefId, + TypePtr type, + std::optional value, + std::vector devices); + + inline bool isOwner() const override { + return true; + } + + // OwnerRRef is always confirmed, while UserRRef is only confirmed when the + // owner knows about it. + inline bool confirmedByOwner() const override { + return true; + } + + // Get a constant reference of the real value. This method will block if the + // value is not ready. This method does not need GIL as it does not create + // any new py::object. It will throw if there is an error. + const IValue& getValue() const; + + // Set the value of this ``OwnerRRef``. This method does not need GIL as it + // does not create any new py::object. + void setValue(IValue&& value); + // Sets the value of this ``OwnerRRef`` to contain an exception. + void setError(std::exception_ptr eptr); + + // Has a value or error been set? + bool hasValue() const; + // Gets a future that is satisfied when the value or error is set. + c10::intrusive_ptr getFuture(); + + private: + friend class RRefContext; + + c10::intrusive_ptr future_; +}; + +TORCH_API std::ostream& operator<<(std::ostream& os, const RRef& rref); + +// Helper function that casts from c10::RRefInterface to OwnerRRef +inline TORCH_API c10::intrusive_ptr fromRRefInterface( + const c10::intrusive_ptr& rrefInterface) { + return c10::static_intrusive_pointer_cast(rrefInterface); +} + +// Helper function that casts from OwnerRRef to c10::RRefInterface +inline TORCH_API c10::intrusive_ptr fromOwnerRRef( + const c10::intrusive_ptr& ownerRRef) { + return c10::static_intrusive_pointer_cast(ownerRRef); +} + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rref_proto.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rref_proto.h new file mode 100644 index 0000000000000000000000000000000000000000..b96713516e679436aee835898be9d554283e0a3e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/rref_proto.h @@ -0,0 +1,168 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace torch::distributed::rpc { + +// Temporary solution of RRef operations. +// TODO: Remove all these messages and use rpc + registered functions instead. +class TORCH_API RRefMessageBase : public RpcCommandBase { + public: + RRefMessageBase(const RRefId& rrefId, MessageType type) + : rrefId_(rrefId), type_(type) {} + + const RRefId& rrefId(); + + protected: + // NOLINTNEXTLINE(cppcoreguidelines*) + const RRefId rrefId_; + // NOLINTNEXTLINE(cppcoreguidelines*) + const MessageType type_; +}; + +class TORCH_API ForkMessageBase : public RRefMessageBase { + public: + ForkMessageBase(const RRefId& rrefId, const ForkId& forkId, MessageType type) + : RRefMessageBase(rrefId, type), forkId_(forkId) {} + + const ForkId& forkId(); + + c10::intrusive_ptr toMessageImpl() && override; + static std::pair fromMessage( + const Message& message, + MessageType type); + + protected: + // NOLINTNEXTLINE(cppcoreguidelines*) + const ForkId forkId_; +}; + +// UserRRef uses this message to fetch the remote RRef value from the owner. +class TORCH_API ScriptRRefFetchCall final : public RRefMessageBase { + public: + ScriptRRefFetchCall(worker_id_t fromWorkerId, const RRefId& rrefId) + : RRefMessageBase(rrefId, MessageType::SCRIPT_RREF_FETCH_CALL), + fromWorkerId_(fromWorkerId) {} + + inline worker_id_t fromWorkerId() const { + return fromWorkerId_; + } + + c10::intrusive_ptr toMessageImpl() && override; + static std::unique_ptr fromMessage( + const Message& message); + + private: + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const worker_id_t fromWorkerId_; +}; + +class TORCH_API PythonRRefFetchCall final : public RRefMessageBase { + public: + PythonRRefFetchCall(worker_id_t fromWorkerId, const RRefId& rrefId) + : RRefMessageBase(rrefId, MessageType::PYTHON_RREF_FETCH_CALL), + fromWorkerId_(fromWorkerId) {} + + c10::intrusive_ptr toMessageImpl() && override; + static std::unique_ptr fromMessage( + const Message& message); + + private: + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const worker_id_t fromWorkerId_; +}; + +// OwnerRRef uses this message to send the RRef value to a remote UserRRef +class TORCH_API RRefFetchRet : public RpcCommandBase { + public: + RRefFetchRet(std::vector values, MessageType type) + : values_(std::move(values)), type_(type) {} + + const std::vector& values(); + c10::intrusive_ptr toMessageImpl() && override; + + private: + std::vector values_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const MessageType type_; +}; + +class TORCH_API ScriptRRefFetchRet final : public RRefFetchRet { + public: + explicit ScriptRRefFetchRet(std::vector values) + : RRefFetchRet(std::move(values), MessageType::SCRIPT_RREF_FETCH_RET) {} + + static std::unique_ptr fromMessage( + const Message& message); +}; + +class TORCH_API PythonRRefFetchRet final : public RRefFetchRet { + public: + explicit PythonRRefFetchRet(std::vector values) + : RRefFetchRet(std::move(values), MessageType::PYTHON_RREF_FETCH_RET) {} + + static std::unique_ptr fromMessage( + const Message& message); +}; + +// UserRRef (regardless it's the creator or not) uses this message to notify +// OwnerRRef on delete. +class TORCH_API RRefUserDelete final : public ForkMessageBase { + public: + RRefUserDelete(const RRefId& rrefId, const ForkId& forkId) + : ForkMessageBase(rrefId, forkId, MessageType::RREF_USER_DELETE) {} + + static std::unique_ptr fromMessage(const Message& message); +}; + +class TORCH_API RemoteRet final : public ForkMessageBase { + public: + RemoteRet(const RRefId& rrefId, const ForkId& forkId) + : ForkMessageBase(rrefId, forkId, MessageType::REMOTE_RET) {} + + static std::unique_ptr fromMessage(const Message& message); +}; + +// A child RRef uses this message to notify its parent that the child has been +// confirmed by the owner. +class TORCH_API RRefChildAccept final : public RpcCommandBase { + public: + explicit RRefChildAccept(const ForkId& forkId) : forkId_(forkId) {} + + const ForkId& forkId() const; + + c10::intrusive_ptr toMessageImpl() && override; + static std::unique_ptr fromMessage(const Message& message); + + private: + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const ForkId forkId_; +}; + +// A child RRef uses this message to send a fork request to the owner. +class TORCH_API RRefForkRequest final : public ForkMessageBase { + public: + RRefForkRequest(const RRefId& rrefId, const ForkId& forkId) + : ForkMessageBase(rrefId, forkId, MessageType::RREF_FORK_REQUEST) {} + + static std::unique_ptr fromMessage(const Message& message); +}; + +class TORCH_API RRefAck final : public RpcCommandBase { + public: + RRefAck() = default; + + c10::intrusive_ptr toMessageImpl() && override; + static std::unique_ptr fromMessage(const Message& message); +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/script_call.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/script_call.h new file mode 100644 index 0000000000000000000000000000000000000000..b4073693ec762921a3816b558a8c76913b940357 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/script_call.h @@ -0,0 +1,72 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace torch::distributed::rpc { + +using torch::jit::Operator; + +// A ScriptCall instance represents an invocation of a builtin operator for a +// TorchScript function. If it is a builtin operator, it +// contains a shared ptr to the `Operator` and a list of arguments. +// If it is a TorchScript function, it contains a non empty qualifiedName string +// to the TorchScript function schema name and a list of arguments. +class TORCH_API ScriptCall : public RpcCommandBase { + public: + // Constructor for builtin operator call. + ScriptCall(std::shared_ptr op, std::vector&& stack); + // Constructor for TorchScript function call. + ScriptCall( + const c10::QualifiedName& qualifiedName, + std::vector&& stack, + const bool isAsyncExecution = false); + + bool hasOp() const; + std::shared_ptr op() const; + bool hasQualifiedName() const; + const c10::QualifiedName& qualifiedName() const; + // return the argument stack of this builtin operator + const std::vector& stack() const; + std::vector& stackRef(); + inline bool isAsyncExecution() const { + return isAsyncExecution_; + } + + c10::intrusive_ptr toMessageImpl() && override; + static std::unique_ptr fromMessage(const Message& message); + + ~ScriptCall() override = default; + + protected: + virtual void toIValues(std::vector& ivalues) const; + static std::unique_ptr fromIValues( + std::vector& ivalues); + + private: + // Given an operator symbol and a string schema, return the matched operator. + static std::shared_ptr matchOperator(const std::string& str_schema); + + static const std::string BUILTIN_OP_NAMESPACE_; + static const std::string ATEN_PREFIX_; + + // This field has value if this ScriptCall represents invocation of a builtin + // operator. + std::optional> op_; + // This field has non empty string if this ScriptCall represents invocation of + // an annotated torchscript function defined by users. + std::optional qualifiedName_; + std::vector stack_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const bool isAsyncExecution_; +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/script_remote_call.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/script_remote_call.h new file mode 100644 index 0000000000000000000000000000000000000000..6ae72a328d457a150ae78f30c8c4c1d18c4b2664 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/script_remote_call.h @@ -0,0 +1,59 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +namespace torch::distributed::rpc { + +using torch::jit::Operator; + +// A ScriptRemoteCall instance represents an invocation of `dist.remote` on a +// builtin operator. Currently, it does not support using RRef as arguments yet. +// Besides the operator and a vector of arguments, ScriptRemoteCall also +// contains the RRefId and the ForkId of the return value RRef. +class TORCH_API ScriptRemoteCall final : public ScriptCall { + public: + // Constructor for builtin operator call. + ScriptRemoteCall( + std::shared_ptr op, + std::vector&& stack, + const RRefId& retRRefId, + const ForkId& retForkId); + + // Constructor for TorchScript function call. + ScriptRemoteCall( + const c10::QualifiedName& qualifiedName, + std::vector&& stack, + const RRefId& retRRefId, + const ForkId& retForkId, + const bool isAsyncExecution); + + inline const RRefId& retRRefId() const { + return retRRefId_; + } + + inline const ForkId& retForkId() const { + return retForkId_; + } + + static std::unique_ptr fromIValues( + std::vector& ivalues); + + c10::intrusive_ptr toMessageImpl() && override; + static std::unique_ptr fromMessage(const Message& message); + + private: + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const RRefId retRRefId_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const ForkId retForkId_; +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/script_resp.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/script_resp.h new file mode 100644 index 0000000000000000000000000000000000000000..e4fb8e7ca92d1389f1501908ad7062b0a223a204 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/script_resp.h @@ -0,0 +1,27 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::distributed::rpc { + +// Return value of a builtin operator or a TorchScript function. +class TORCH_API ScriptResp final : public RpcCommandBase { + public: + explicit ScriptResp(at::IValue&& values); + + const at::IValue& value(); + c10::intrusive_ptr toMessageImpl() && override; + static std::unique_ptr fromMessage(const Message& message); + + private: + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const at::IValue value_; +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/tensorpipe_agent.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/tensorpipe_agent.h new file mode 100644 index 0000000000000000000000000000000000000000..b5f3a788d0cb86657effd94171062c84f0efc0e9 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/tensorpipe_agent.h @@ -0,0 +1,498 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef USE_TENSORPIPE + +#include +#include + +#include +#include +#include +#include +#include + +// Forward-declare the TensorPipe classes we need, to avoid including its +// headers in PyTorch's ones and thus have it become a public dependency. + +namespace tensorpipe { + +class Context; +class Error; +class Listener; +class Message; +class Pipe; + +namespace transport { +class Context; +} // namespace transport + +namespace channel { +class Context; +} // namespace channel + +} // namespace tensorpipe + +namespace torch::distributed::rpc { + +// These priorities instruct TensorPipe on which transport/channel to pick +// during handshake. Higher priorities will take precedence over lower ones. +// The transport with lowest priority will be the one used to bootstrap pipes. + +constexpr int64_t kShmTransportPriority = 200; +constexpr int64_t kIbvTransportPriority = 100; +// The UV transport just uses TCP and should work everywhere, thus keep it last. +constexpr int64_t kUvTransportPriority = 0; + +constexpr int64_t kCmaChannelPriority = 1200; +constexpr int64_t kMultiplexedUvChannelPriority = 1100; +// The basic channel reuses a transport as a channel, and is thus our fallback. +constexpr int64_t kBasicChannelPriority = 1000; + +// CPU channel have higher priority than CUDA channels, since the latter might +// handle CPU-to-CPU transfers, but will always be less efficient than their +// CPU-only counterparts. +constexpr int64_t kCudaIpcChannelPriority = 300; +constexpr int64_t kCudaGdrChannelPriority = 200; +constexpr int64_t kCudaXthChannelPriority = 400; +constexpr int64_t kCudaBasicChannelPriority = 0; + +using steady_clock_time_point = + std::chrono::time_point; + +struct TORCH_API TransportRegistration { + std::shared_ptr transport; + int64_t priority; + std::string address; +}; + +TORCH_DECLARE_REGISTRY(TensorPipeTransportRegistry, TransportRegistration); + +struct TORCH_API ChannelRegistration { + std::shared_ptr channel; + int64_t priority; +}; + +TORCH_DECLARE_REGISTRY(TensorPipeChannelRegistry, ChannelRegistration); + +struct TORCH_API TensorPipeRpcBackendOptions : public RpcBackendOptions { + TensorPipeRpcBackendOptions( + int numWorkerThreads, + std::optional> transports, + std::optional> channels, + float rpc_timeout, + std::string init_method, + std::unordered_map device_maps = {}, + std::vector devices = {}) + : RpcBackendOptions(rpc_timeout, std::move(init_method)), + numWorkerThreads(numWorkerThreads), + transports(std::move(transports)), + channels(std::move(channels)), + deviceMaps(std::move(device_maps)), + devices(std::move(devices)) { + TORCH_CHECK( + numWorkerThreads > 0, + "num_worker_threads must be positive, got ", + numWorkerThreads); + + if (this->transports.has_value()) { + for (const std::string& transportName : this->transports.value()) { + TORCH_CHECK( + TensorPipeTransportRegistry()->Has(transportName), + "Unknown transport: ", + transportName); + } + } + + if (this->channels.has_value()) { + for (const std::string& channelName : this->channels.value()) { + TORCH_CHECK( + TensorPipeChannelRegistry()->Has(channelName), + "Unknown channel: ", + channelName); + } + } + } + + void setDeviceMap(const std::string& workerName, const DeviceMap& deviceMap) { + auto iter = deviceMaps.find(workerName); + if (iter == deviceMaps.end()) { + deviceMaps[workerName] = deviceMap; + } else { + for (auto& entry : deviceMap) { + // c10::Device has no default constructor, hence map[device] doesn't + // work In C++-17 we can use insert_or_assign. + auto entryIter = iter->second.find(entry.first); + if (entryIter == iter->second.end()) { + iter->second.emplace(entry.first, entry.second); + } else { + entryIter->second = entry.second; + } + } + } + } + + int numWorkerThreads; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const std::optional> transports; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const std::optional> channels; + std::unordered_map deviceMaps; + std::vector devices; +}; + +// Struct to track the network source metrics +struct TORCH_API NetworkSourceInfo { + worker_id_t srcRank; + std::vector srcMachineAddr; +}; + +// Struct to track aggregated network metrics +struct TORCH_API AggregatedNetworkData { + uint64_t numCalls{0}; + uint64_t totalSentBytes{0}; + uint64_t totalRecvBytes{0}; + uint64_t totalErrors{0}; +}; + +// TensorPipeAgent leverages TensorPipe (https://github.com/pytorch/tensorpipe) +// to transparently move tensors and payloads through the fastest available +// transport or channel. It acts like a hybrid RPC transport, providing shared +// memory (linux) and TCP (linux & mac) support. CUDA support is in progress. +class TORCH_API TensorPipeAgent : public RpcAgent { + public: + TensorPipeAgent( + const c10::intrusive_ptr<::c10d::Store>& store, + std::string selfName, + worker_id_t selfId, + std::optional worldSize, + TensorPipeRpcBackendOptions opts, + std::unordered_map reverseDeviceMaps, + std::vector devices, + std::unique_ptr cb); + + TensorPipeAgent(const TensorPipeAgent&) = delete; + TensorPipeAgent& operator=(const TensorPipeAgent&) = delete; + + c10::intrusive_ptr send( + const WorkerInfo& to, + c10::intrusive_ptr message, + const float rpcTimeoutSeconds = kUnsetRpcTimeout, + const DeviceMap& deviceMap = {}) override; + + // join() and sync() would be deprecated - + // https://github.com/pytorch/pytorch/issues/27647 + void join(bool shutdown = false, float timeout = 0) override; + void sync() override {} + void startImpl() override; + void shutdownImpl() override; + + ~TensorPipeAgent() override; + + const WorkerInfo& getWorkerInfo(const std::string& workerName) const override; + const WorkerInfo& getWorkerInfo(worker_id_t workerId) const override; + std::vector getWorkerInfos() const override; + void updateGroupMembership( + const WorkerInfo& workerInfo, + const std::vector& devices, + const std::unordered_map& reverseDeviceMaps, + bool isJoin); + + std::unordered_map getMetrics() override; + + void addGilWaitTime(const std::chrono::microseconds gilWaitTime) override; + + TensorPipeRpcBackendOptions getBackendOptions() const; + + const c10::intrusive_ptr<::c10d::Store> getStore() const; + + DeviceMap getDeviceMap(const WorkerInfo& dest) const override; + + const std::vector& getDevices() const override; + + using NetworkDataDict = + std::unordered_map; + + // Returns metrics tracked by the NetworkDataDict + NetworkDataDict getNetworkData(); + // Returns NetworkSourceInfo struct + NetworkSourceInfo getNetworkSourceInfo(); + + static const std::string& guessAddress(); + + // For testing purposes. + size_t timeoutMapSize(); + size_t numPendingResponses(); + size_t messageIdToTimeoutMapSize(); + + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const bool isStaticGroup_; + + protected: + // TensorPipe write function that could be used to write response + // messages by server, and write request messages by client. This + // is a protected method since it is overwritten by FaultyTensorPipeAgent + virtual void pipeWrite( + const std::shared_ptr& /*pipe*/, + const c10::intrusive_ptr& message, + std::vector&& devices, + std::vector streams, + std::function /*fn*/) noexcept; + + private: + // Removes the given messageId with the given expirationTime from the + // timeoutMap_. + void removeFromTimeoutMap(uint64_t messageId); + + // Populates workerIdToInfo_ and workerNameToInfo_ using addressStore_ + void prepareNames(bool isStaticGroup); + + // Check the static group attribute with the value set in store + void checkAndSetStaticGroup(const c10::intrusive_ptr<::c10d::Store>& store); + + const std::string& findWorkerURL(const WorkerInfo& worker) const; + + // Only use for Dynamic RPC groups, method to have worker leave group + void leaveGroup(); + + // TensorPipe read function that could be used to read response messages + // by client, and read request messages by server. + void pipeRead( + const std::shared_ptr& /*pipe*/, + std::function, + std::vector)> /*fn*/) noexcept; + + // Callback of listener accept() + void onListenerAccepted( + const tensorpipe::Error& error, + std::shared_ptr& pipe); + + // Respond to a call from a peer + void respond(std::shared_ptr& pipe); + + void sendCompletedResponseMessage( + std::shared_ptr& pipe, + JitFuture& futureResponseMessage, + uint64_t messageId, + std::vector stream); + + // Collects metrics from successful RPC calls + void trackNetworkData( + uint64_t requestSize, + uint64_t responseSize, + const std::string& destWorkerName); + + // Collects metrics from failed RPC calls + void trackNetworkError( + uint64_t requestSize, + const std::string& destWorkerName); + + inline std::vector getDevicesForRemote( + const std::string& remoteName, + const Message& message) const; + + // When a request+response completes, we need to mark the future message as + // complete. However, if its timeout has already expired, it already has an + // error set. There is no atomic "test-and-set" way to mark a future complete + // only if it isn't yet. It does exist for errors (setErrorIfNeeded) but, even + // then, it ends up printing a log message, which may worry the user. To solve + // both issues we use a separate atomic flag to know the status of the future. + struct AtomicJitFuture { + explicit AtomicJitFuture(const std::vector& devices) { + jitFuture = c10::make_intrusive( + at::AnyClassType::get(), devices); + } + + std::atomic_flag isComplete = ATOMIC_FLAG_INIT; + c10::intrusive_ptr jitFuture; + }; + + // Maintains state per client pipe to track pending response messages and + // error states. pendingResponseMessage_ should be protected by a mutex since + // it can be raced with user send() call. + // TODO: To achieve better performance we can have a pipe pool per + // client that can be configured using RpcBackendOptions. + struct ClientPipe { + explicit ClientPipe(std::shared_ptr pipe) + : pipe_(std::move(pipe)) {} + std::shared_ptr pipe_; + mutable std::mutex mutex_; + bool inError_{false}; + // Map from Message Request ID's to corresponding futures. + std::unordered_map> + pendingResponseMessage_; + }; + + const c10::intrusive_ptr<::c10d::Store> store_; + + const TensorPipeRpcBackendOptions opts_; + // For dynamic RPC, the reverse device maps are updated whenever a new rank + // joins or leaves the group + std::unordered_map reverseDeviceMaps_; + // Local devices used by this agent. If application didn't specify this + // field, it will be initialized using corresponding local devices in + // opts_.deviceMaps and reverseDeviceMaps_; + std::vector devices_; + + ThreadPool threadPool_; + std::shared_ptr context_; + std::shared_ptr listener_; + + mutable std::mutex connectedPipesMutex_; + std::unordered_map connectedPipes_; + + // Maps keyed on name and id for easy WorkerInfo lookup. + std::unordered_map workerIdToInfo_; + std::unordered_map workerNameToInfo_; + std::unordered_map workerNameToURL_; + + ::c10d::PrefixStore rankToNameStore_; + ::c10d::PrefixStore nameToAddressStore_; + // Store keys that will used to count joined processes and active calls during + // the shutdown process + ::c10d::PrefixStore shutdownStore_; + int worldSize_ = 0; + std::atomic nextMessageID_{0}; + + // Metadata used for tracking of whether certain RPCs have timed out or not. + struct TimeoutMessageMetadata { + TimeoutMessageMetadata( + uint64_t messageId_, + std::shared_ptr responseFuture_, + std::chrono::milliseconds timeout_) + : messageId(messageId_), + responseFuture(std::move(responseFuture_)), + timeout(timeout_) {} + uint64_t messageId; + std::shared_ptr responseFuture; + std::chrono::milliseconds timeout; + }; + + // Map to store the expiration times for each message. + std::map> + timeoutMap_; + + // Map to store the messageId to expiry time. + std::unordered_map messageIdToTimeout_; + + // Thread that will poll the timeoutMap_ for timed out messages and mark them + // with an error accordingly + std::thread timeoutThread_; + + // Function run by the timeoutThread_ to check for timed out RPCs + void pollTimeoutRpcs(); + + // Mutex to guard the timeoutMap_ + std::mutex timeoutMapMutex_; + + // Condition Variable to signal population of the timeoutMap_ + std::condition_variable timeoutThreadCV_; + + // Returns the expiration time for an RPC by adding the current time to the + // passed in timeout. + inline steady_clock_time_point computeRpcMessageExpiryTime( + std::chrono::milliseconds timeout) const { + return std::chrono::time_point_cast( + std::chrono::steady_clock::now() + timeout); + } + + // Handle error on an outgoing pipe + void handleClientError( + ClientPipe& clientPipe, + const tensorpipe::Error& error); + + // This is a generic struct for capturing Time-Series Metrics. It keeps a + // running sum and count of data points (observations), and can return an + // average of the data points seen so far. This is currently only used for + // tracking the GIL Wait Time in RPC Agents, but can be used for other metrics + // as well. + struct TimeSeriesMetricsTracker { + // Running sum of the data points seen so far + uint64_t currentSum_; + // Running count of the data points seen so far + uint64_t currentCount_; + + explicit TimeSeriesMetricsTracker( + uint64_t currentSum = 0, + uint64_t currentCount = 0); + + // Adds a data point (which is basically one observation for the metric + // being tracked) to the running sum and count. + void addData(uint64_t dataPoint); + // Returns the average of all the data points seen so far. + float computeAverage() const; + }; + + // Map of Time-Series metrics tracked by the RPC Agent + std::unordered_map timeSeriesMetrics_; + // Mutex to guard timeSeriesMetrics_ + std::mutex metricsMutex_; + + // Custom lock guard used to check if the RPC group is dynamic and lock the + // mutex if so + struct GroupMembershipLockGuard { + GroupMembershipLockGuard(std::mutex& mutex, bool isStaticGroup) + : ref_(mutex), isStaticGroup_(isStaticGroup) { + if (isStaticGroup_) { + ref_.lock(); + } + } + + ~GroupMembershipLockGuard() { + if (isStaticGroup_) { + ref_.unlock(); + } + } + + GroupMembershipLockGuard(const GroupMembershipLockGuard&) = delete; + + private: + std::mutex& ref_; + bool isStaticGroup_; + }; + // Mutex to guard access to group membership data + // e.g. updates to (workerIdToInfo_, workerNameToInfo_, workerNameToURL_) + mutable std::mutex groupMembershipMutex_; + + // Map to Track Network Data + NetworkDataDict networkData_; + // Mutex to guard networkData_ + std::mutex networkDataMutex_; + + // A mutex and a cv to guard access to the call counts and watch for changes. + std::mutex callCountMutex_; + std::condition_variable callCountCV_; + // Running total of un-processed, un-errored RPC calls sent + int32_t clientActiveCalls_{0}; + // Running total of un-processed RPC requests received + int32_t serverActiveCalls_{0}; + // Running total of RPC requests that will be completed asynchronously + int32_t serverActiveAsyncCalls_{0}; + + // Whether a global graceful shutdown has begun, in which case we'll silence + // error messages due to remote workers closing their pipes. + std::atomic shuttingDown_{false}; + + // Helpers to modify the counts while correctly dealing with the mutex and cv. + void increaseCallCount(int32_t& count); + void decreaseCallCount(int32_t& count); + + // Helpers to set the state of the requests. + void markFutureAsComplete( + std::shared_ptr atomicFuture, + c10::intrusive_ptr message, + std::vector streams); + void markFutureWithError( + std::shared_ptr atomicFuture, + std::string errorMsg); +}; + +} // namespace torch::distributed::rpc + +#endif // USE_TENSORPIPE + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/tensorpipe_utils.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/tensorpipe_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..025e143190c2df7c2898f03187e70064619bbf3c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/tensorpipe_utils.h @@ -0,0 +1,124 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef USE_TENSORPIPE + +#include + +namespace tensorpipe { +class Message; +class Allocation; +class Descriptor; +} // namespace tensorpipe + +namespace torch::distributed::rpc { + +TORCH_API const c10::Stream& getStreamForDevice( + const std::vector& streams, + const c10::Device& device); + +// Inspired by c10/core/impl/DeviceGuardImplInterface.h. + +class TensorpipeDeviceTypeConverter { + public: + // Ideally we'd want this to also return a tensorpipe::Message::Tensor object + // but we cannot forward-declare that class (because it's nested), and we + // cannot include the TensorPipe headers because it's a private dependency. + // Thus we bend over backwards and entrust this method with appending that + // object to the `tensors` field of the tensorpipe::Message object we pass. + virtual std::optional> prepareTensorForSending( + const c10::Storage& storage, + const std::vector& streams, + tensorpipe::Message& message) const = 0; + + // Same as above: this method cannot return a tensorpipe::Allocation::Tensor, + // thus it appends it to the `tensors` field of the tensorpipe::Allocation. + virtual at::DataPtr allocateTensorForReceiving( + c10::DeviceIndex deviceIndex, + size_t length, + const std::vector& streams, + tensorpipe::Allocation& allocation) const = 0; + + virtual ~TensorpipeDeviceTypeConverter() = default; +}; + +extern TORCH_API std::array< + std::atomic, + static_cast(DeviceType::COMPILE_TIME_MAX_DEVICE_TYPES)> + device_type_converter_registry; + +class TORCH_API TensorpipeDeviceTypeConverterRegistrar { + public: + TensorpipeDeviceTypeConverterRegistrar( + DeviceType /*type*/, + const TensorpipeDeviceTypeConverter* /*impl*/); +}; + +#define C10_REGISTER_TENSORPIPE_DEVICE_TYPE_CONVERTER( \ + DevType, TensorpipeDeviceTypeConverter) \ + static ::torch::distributed::rpc::TensorpipeDeviceTypeConverterRegistrar \ + C10_ANONYMOUS_VARIABLE(g_##DeviceType)( \ + ::c10::DeviceType::DevType, new TensorpipeDeviceTypeConverter()); + +inline const TensorpipeDeviceTypeConverter* getDeviceTypeConverter( + DeviceType type) { + return device_type_converter_registry[static_cast(type)].load(); +} + +// A struct that holds pointers that keep alive all the memory that will be +// accessed by TensorPipe during a write operation. +struct TensorpipeWriteBuffers { + // Allocate on heap so pointers stay valid as we move the holder. + std::unique_ptr type; + std::unique_ptr id; + std::vector payload; + std::vector pickle; + // This contains the original tensors and the clones of the sparse tensors. + std::vector tensors; + // This contains the copies of the data of the tensors that didn't own their + // memory, e.g., the ones created from torch::from_blob() with no deleter. + std::vector> copiedTensors; +}; + +// A struct that holds pointers that keep alive all the memory that will be +// accessed by TensorPipe during a read operation. +struct TensorpipeReadBuffers { + // Allocate on heap so pointers stay valid as we move the holder. + std::unique_ptr type; + std::unique_ptr id; + std::vector payload; + std::vector pickle; + std::vector tensors; +}; + +// Convert an RPC message into a TensorPipe message, plus a holder to all the +// data that must be kept alive while the write is performed asynchronously. +TORCH_API std::tuple +tensorpipeSerialize( + const c10::intrusive_ptr& rpcMessage, + std::vector devices, + const std::vector& streams); + +// Allocate the buffers that will hold the incoming data. They will be managed +// by the returned holder, which must be kept alive until the asynchronous read +// has finished. Pointers to these buffers will be stored in the returned +// tensorpipe::Allocation struct. +TORCH_API std::pair +tensorpipeAllocate( + const tensorpipe::Descriptor& tpDescriptor, + const std::vector& streams); + +// Convert a TensorPipe message back into an RPC message. This requires the data +// to be available and can thus only be performed once the asynchronous read has +// completed. The holder can be destroyed once this function returns. +TORCH_API c10::intrusive_ptr tensorpipeDeserialize( + const tensorpipe::Descriptor& tpDescriptor, + TensorpipeReadBuffers&& holder); + +} // namespace torch::distributed::rpc + +#endif // USE_TENSORPIPE + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/testing/faulty_tensorpipe_agent.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/testing/faulty_tensorpipe_agent.h new file mode 100644 index 0000000000000000000000000000000000000000..c0adb349f2095a721970b5bfdd9acd7141abe827 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/testing/faulty_tensorpipe_agent.h @@ -0,0 +1,109 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef USE_TENSORPIPE + +#include +#include + +namespace torch::distributed::rpc { + +struct TORCH_API FaultyTensorPipeRpcBackendOptions + : public TensorPipeRpcBackendOptions { + FaultyTensorPipeRpcBackendOptions( + int num_worker_threads, + float rpc_timeout, + std::string init_method, + std::vector messages_to_fail, + std::unordered_map messages_to_delay, + int num_fail_sends = 0) + : TensorPipeRpcBackendOptions( + num_worker_threads, + std::optional>(), + std::optional>(), + rpc_timeout, + std::move(init_method)), + messagesToFail(std::move(messages_to_fail)), + messagesToDelay(std::move(messages_to_delay)), + numFailSends(num_fail_sends) { + TORCH_CHECK(numFailSends >= 0, "numFailSends should be non-negative"); + } + + std::vector messagesToFail; + std::unordered_map messagesToDelay; + int numFailSends; +}; + +class TORCH_API FaultyTensorPipeAgent : public TensorPipeAgent { + public: + FaultyTensorPipeAgent( + const c10::intrusive_ptr<::c10d::Store>& store, + std::string selfName, + worker_id_t selfId, + int worldSize, + FaultyTensorPipeRpcBackendOptions opts, + std::unordered_map reverseDeviceMaps, + std::vector devices, + std::unique_ptr callback); + + // Faulty send function for this class. + c10::intrusive_ptr send( + const WorkerInfo& to, + c10::intrusive_ptr message, + const float rpcTimeoutSeconds = torch::distributed::rpc::kUnsetRpcTimeout, + const DeviceMap& deviceMap = {}) override; + + // Add delay to writes + void pipeWrite( + const std::shared_ptr& pipe, + const c10::intrusive_ptr& rpcMessage, + std::vector&& devices, + std::vector streams, + std::function fn) noexcept override; + + protected: + // This function checks the messageTypesToFail_ to determine whether to use + // the faulty send or not. + bool shouldFailMessage(MessageType type) const; + + private: + // This function parses the list of strings passed in by the python tests and + // resolves the Message Types that must use the faulty send. + std::vector parseMessagesToFailInput( + const std::vector& messagesToFail) const; + + // Returns amount of time in seconds to delay sending of the given message + // type. + float getDelayForMessage(MessageType type) const; + + // Parse message types that we should inject arbitrary delays for. + std::unordered_map> parseMessagesToDelay( + const std::unordered_map& messageTypesToDelay) const; + + // Number of sends to intentionally fail before allowing one to succeed. + const int numFailSends_; + + // Vector of the MessageTypes that we must use the faulty send for. This is + // parsed based on a list of strings passed in by the python tests. + const std::vector messageTypesToFail_; + + // Mapping of message types to amount we should delay send for in the ::send() + // function. + std::unordered_map> messageTypesToDelay_; + + // Map to track the number of sends we've failed for each RPC. + std::unordered_map failMessageCountMap_; + + // Mutex to guard failMessageCountMap_ + std::mutex failMapMutex_; + + MessageType messageStringToType(const std::string& messageString) const; +}; + +} // namespace torch::distributed::rpc + +#endif // USE_TENSORPIPE + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/testing/testing.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/testing/testing.h new file mode 100644 index 0000000000000000000000000000000000000000..baf94a5397fe21394cf9ab024800a29cbc4fe9d6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/testing/testing.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::distributed::rpc::testing { + +PyMethodDef* python_functions(); + +} // namespace torch::distributed::rpc::testing + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/torchscript_functions.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/torchscript_functions.h new file mode 100644 index 0000000000000000000000000000000000000000..37c6975d05559d13de07463d279ea11cab121f79 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/torchscript_functions.h @@ -0,0 +1,42 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace torch::distributed::rpc { + +// This function sends an rpc call to run torchscript function, currently the +// torchscript function could only be a user defined python function with +// "@torch.jit.script" annotation. The torchscript function could not be +// a class constructor, class method, instance method or a script module. +// dst: destination worker name +// qualifiedName: torchscript function qualified name string like +// "moduleName::torchscriptFunctionName", e.g, +// "dist_autograd_test::my_py_add" +// stack: a bag of IValue args passed to torchscriptFunctionName +// It returns c10::intrusive_ptr +c10::intrusive_ptr TORCH_API rpcTorchscript( + const std::string& dstWorkerName, + const c10::QualifiedName& qualifiedName, + const c10::FunctionSchema& functionSchema, + std::vector stack, + const float rpcTimeoutSeconds = torch::distributed::rpc::kUnsetRpcTimeout, + const bool isAsyncExecution = false); + +c10::intrusive_ptr TORCH_API remoteTorchscript( + const std::string& dstWorkerName, + const c10::QualifiedName& qualifiedName, + const c10::FunctionSchema& functionSchema, + std::vector& stack, + const float rpcTimeoutSeconds = torch::distributed::rpc::kUnsetRpcTimeout, + const bool isAsyncExecution = false); + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/types.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/types.h new file mode 100644 index 0000000000000000000000000000000000000000..f8ec54b86e986a64fd2f55d2c35e1d5c594f30f4 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/types.h @@ -0,0 +1,75 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::distributed::rpc { + +using worker_id_t = int16_t; +using local_id_t = int64_t; + +bool getAllowJitRRefPickle(); +TORCH_API void enableJitRRefPickle(); +TORCH_API void disableJitRRefPickle(); + +struct TORCH_API JitRRefPickleGuard { + JitRRefPickleGuard(); + JitRRefPickleGuard(JitRRefPickleGuard&& other) = delete; + JitRRefPickleGuard(const JitRRefPickleGuard&) = delete; + JitRRefPickleGuard& operator=(const JitRRefPickleGuard&) = delete; + JitRRefPickleGuard& operator=(JitRRefPickleGuard&&) = delete; + ~JitRRefPickleGuard(); +}; + +struct TORCH_API GloballyUniqueId final { + GloballyUniqueId(worker_id_t createdOn, local_id_t localId); + GloballyUniqueId(const GloballyUniqueId& other) = default; + GloballyUniqueId& operator=(const GloballyUniqueId& other) = delete; + GloballyUniqueId(GloballyUniqueId&& other) = default; + GloballyUniqueId& operator=(GloballyUniqueId&& other) = delete; + ~GloballyUniqueId() = default; + + bool operator==(const GloballyUniqueId& other) const; + bool operator!=(const GloballyUniqueId& other) const; + + at::IValue toIValue() const; + static GloballyUniqueId fromIValue(const at::IValue& /*ivalue*/); + + struct Hash { + size_t operator()(const GloballyUniqueId& key) const { + return (uint64_t(key.createdOn_) << kLocalIdBits) | key.localId_; + } + }; + + static constexpr int kLocalIdBits = 48; + + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const worker_id_t createdOn_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const local_id_t localId_; +}; + +TORCH_API std::ostream& operator<<( + std::ostream& os, + const GloballyUniqueId& globalId); + +using RRefId = GloballyUniqueId; +using ForkId = GloballyUniqueId; +using ProfilingId = GloballyUniqueId; + +struct TORCH_API SerializedPyObj final { + SerializedPyObj(std::string&& payload, std::vector&& tensors) + : payload_(std::move(payload)), tensors_(std::move(tensors)) {} + + std::vector toIValues() &&; + static SerializedPyObj fromIValues(std::vector value); + + std::string payload_; + std::vector tensors_; +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/unpickled_python_call.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/unpickled_python_call.h new file mode 100644 index 0000000000000000000000000000000000000000..da76292342019059afd7d1c868c7cac1e375fd88 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/unpickled_python_call.h @@ -0,0 +1,43 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace torch::distributed::rpc { + +// This class converts the content in a PythonCall into py::object. This is a +// helper class to make sure that all arguments deserialization is done before +// entering RequestCallbackImpl::processRpc(...), so that the deserialization +// related logic can be carried out in one spot instead of scattered in multiple +// places for different message types. +// NB: The reason for not consolidating class into PythonCall is because +// PythonCall is a libtorch type which should not depend on Python types. +class TORCH_API UnpickledPythonCall : public RpcCommandBase { + public: + UnpickledPythonCall( + const SerializedPyObj& serializedPyObj, + bool isAsyncExecution); + ~UnpickledPythonCall() override; + + // toMessage() method is not implemented, as objects of this class should + // never be directly converted into a Message object. + c10::intrusive_ptr toMessageImpl() && override; + const py::object& pythonUdf() const; + + inline bool isAsyncExecution() const { + return isAsyncExecution_; + } + + private: + py::object pythonUdf_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const bool isAsyncExecution_; +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/unpickled_python_remote_call.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/unpickled_python_remote_call.h new file mode 100644 index 0000000000000000000000000000000000000000..afe8a977a615e59b2f77e180275e9fc0e6adc92b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/unpickled_python_remote_call.h @@ -0,0 +1,38 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +namespace torch::distributed::rpc { + +// This class converts the content in a PythonRemoteCall into py::object. This +// is a helper class to make sure that all arguments deserialization is done +// before entering RequestCallbackImpl::processRpc(...), so that the +// deserialization related logic can be carried out in one spot instead of +// scattered in multiple places for different message types. +// NB: The reason for not consolidating class into PythonRemoteCall is because +// PythonRemoteCall is a libtorch type which should not depend on Python types. +class TORCH_API UnpickledPythonRemoteCall final : public UnpickledPythonCall { + public: + explicit UnpickledPythonRemoteCall( + const SerializedPyObj& serializedPyObj, + const at::IValue& retRRefId, + const at::IValue& retForkId, + const bool isAsyncExecution); + + const RRefId& rrefId() const; + const ForkId& forkId() const; + + private: + RRefId rrefId_; + ForkId forkId_; +}; + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/utils.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/utils.h new file mode 100644 index 0000000000000000000000000000000000000000..324d76b2e4dc48b6b12b593fa58c198daa723ad9 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/distributed/rpc/utils.h @@ -0,0 +1,91 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace torch::distributed::rpc { + +// Parse error message and return RPCErrorType based on the message. +TORCH_API RPCErrorType getRPCErrorType(const JitFuture& jitFuture); +// Create an error string given the error description and error type +TORCH_API std::string makeRPCError( + const std::string& rpcErrorStr, + RPCErrorType errorType); + +// Given an RPC message received as a request over the wire, deserialize it into +// the appropriate 'RpcCommandBase' type. +TORCH_API std::unique_ptr deserializeRequest( + const Message& request); + +// Given an RPC message received as a response over the wire, deserialize it +// into the appropriate 'RpcCommandBase' type, if the response is +// FORWARD_AUTOGRAD_RESP type, unwrap it, attach recvBackward() functions +// to received tensors and set the wrappedMsgType to its wrapped message type. +TORCH_API std::unique_ptr deserializeResponse( + const Message& response, + MessageType& wrappedMsgType); + +// Given an RPC message received as a response over the wire, deserialize it +// into the valid IValue if the message is for a script rpc result, +// otherwise deserialize it into dummy none ivalue that will never be used. +// In this deserialization, we also attach recv rpc backward functions if +// needed. +IValue deserializeResptoIValueInternal( + RpcCommandBase& rpc, + MessageType messageType); +TORCH_API IValue deserializeRespToIValue(const Message& message); + +// Note: format is subject to change and intended for RPCs. +// For saving persistently to disk, use torch::save(). +TORCH_API std::string wireSerialize( + const std::vector& payload, + const std::vector& tensors); + +TORCH_API std::pair, std::vector> wireDeserialize( + const void* data, + size_t data_size); + +// We use vector as the type of blobs because it's what rpc::Message uses +// for its payload, even though it has the disadvantage that it cannot be +// allocated with uninitialized memory: it is always zeroed out. + +// Some Tensors are effectively views of larger Tensors, where only a small +// subset of the Storage data is referenced. This normally is good and avoids +// copies when kept locally, but if we naively push the whole Storage over the +// wire, we'll end up with excess network traffic. This change clones tensors if +// we'd save at least half the data, and over a minimum hurdle. +TORCH_API c10::List cloneSparseTensors( + const std::vector& tensors); + +// Combines an original payload and wrapped payload into the original payload. +// Used to generate the overall payload for the wrapped RPC. +TORCH_API void writeWrappedPayload( + std::vector& originalPayload, + std::vector& additionalPayload); + +// Reads the additional, wrapped payload from a wrapped RPC off of the input +// payload. After this, payload will contain the payload of the original, +// un-wrapped RPC. +TORCH_API std::vector readWrappedPayload( + std::vector& payload, + const rpc::Message& message); + +// Takes a list of events from autograd profiler and populates them into +// profiledEvents to be carried over RPC. +TORCH_API void populateRemoteProfiledEvents( + std::vector& profiledEvents, + const torch::autograd::profiler::ProfilerConfig& profilerConfig, + const std::vector>& + eventLists); + +} // namespace torch::distributed::rpc + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/cache_entry.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/cache_entry.h new file mode 100644 index 0000000000000000000000000000000000000000..c178ce57cf456cbd3e7bc3913364e37d80b5c592 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/cache_entry.h @@ -0,0 +1,100 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#ifdef __cplusplus + +#include +#include +#include + +extern "C" { + +#endif + +/* +Our cache resides on the extra scratch space of the code object. The structure +of the cache is as follows: + +-> ExtraState + -> CacheEntry (list) + -> guard_manager (a wrapper that contains the actual guard manager at its +attr named root) + -> code + -> FrameState + +CacheEntry is a linked list node containing the guard_manager for guards +and the optimized code. + +The FrameState is a PyDict that enables sharing between different frames. This +is used to detect dynamism in automatic dynamic shapes. + +These two are encapsulated into a ExtraState. +*/ + +typedef struct CacheEntry CacheEntry; +typedef struct ExtraState ExtraState; + +#ifdef __cplusplus + +C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED( + "-Wdeprecated-copy-with-user-provided-dtor") +C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED("-Wdeprecated-copy-dtor") +// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) +typedef struct VISIBILITY_HIDDEN CacheEntry { + // check the guards: lambda: : bool + py::object guard_manager; + // modified user bytecode (protected by guard_manager's guards) + py::object code; + // CompileId corresponding to this compilation + py::object compile_id; + // root guard manager if exists + void* root_mgr{nullptr}; + // diff guard root guard manager if exists + void* diff_guard_root_mgr{nullptr}; + // backend used to create this cache entry + py::object backend; + // Reference to owning ExtraState + ExtraState* _owner{nullptr}; + // Reference to this CacheEntry's location in owner's linked list + std::list::iterator _owner_loc; + // Reference to string representation of the CompileContext + std::string trace_annotation; + + CacheEntry(const py::handle& guarded_code, PyObject* backend); + CacheEntry(const CacheEntry&) = default; + CacheEntry(CacheEntry&&) = default; + CacheEntry& operator=(const CacheEntry&) = default; + CacheEntry& operator=(CacheEntry&&) = default; + ~CacheEntry(); + + // Warning: returns a reference whose lifetime is controlled by C++ + py::object next(); + + void invalidate(py::object deleted_guard_manager); + // Called from the python side to update the diff guard root manager + void update_diff_guard_root_manager(); +} CacheEntry; +C10_DIAGNOSTIC_POP() +C10_DIAGNOSTIC_POP() + +#endif + +// Returns borrowed reference +PyCodeObject* CacheEntry_get_code(CacheEntry* e); + +// Returns borrowed string representation of CompileContext +const char* CacheEntry_get_trace_annotation(CacheEntry* e); + +// Returns a borrowed reference to CacheEntry as a PyObject +// Warning: lifetime is controlled by C++ +PyObject* CacheEntry_to_obj(CacheEntry* e); + +#ifdef __cplusplus +} // extern "C" +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/compiled_autograd.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/compiled_autograd.h new file mode 100644 index 0000000000000000000000000000000000000000..5120939dfd51c04c87739e98ae83cd091e5708d4 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/compiled_autograd.h @@ -0,0 +1,1574 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// see [Note: Compiled Autograd] + +namespace torch::dynamo::autograd { +using namespace torch::autograd; + +// This is a layer of indirection for calling methods on the Python +// AutogradCompilerInstance (referred to as the "py_compiler") from +// libtorch_cpu (where Python is not available). +// A PyCompilerInterfaceImpl in libtorch_python subclasses it and +// overrides the methods to do the actual calls back to Python. +struct TORCH_API PyCompilerInterface { + PyCompilerInterface() = default; + PyCompilerInterface(const PyCompilerInterface&) = delete; + PyCompilerInterface& operator=(const PyCompilerInterface&) = delete; + PyCompilerInterface(PyCompilerInterface&&) = delete; + PyCompilerInterface& operator=(PyCompilerInterface&&) = delete; + virtual ~PyCompilerInterface() = default; + + // Invokes py_compiler.bind_function + virtual std::string bind_function( + PyObject* py_compiler, + const std::string& fn_name, + // NOLINTNEXTLINE(performance-unnecessary-value-param) + functional_apply_t fn, + // NOLINTNEXTLINE(performance-unnecessary-value-param) + std::vector packed_args_schema, + bool is_custom_function = false, + bool is_traceable = true) const { + TORCH_INTERNAL_ASSERT(false, "Needs to be overridden"); + } + + // Invokes py_compiler.method_name(fn_name, inputs, packed_args, + // output_metadata) + virtual variable_list call_function( + PyObject* py_compiler, + const char* method_name, + const std::string& fn_name, + const variable_list& inputs, + const ivalue_list& packed_args, + const c10::IValue& output_metadata) const { + TORCH_INTERNAL_ASSERT(false, "Needs to be overridden"); + } + virtual variable_list call_copy_slices_prologue( + PyObject* py_compiler, + const variable_list& inputs, + const at::TensorGeometry& base, + const at::TensorGeometry& view) const { + TORCH_INTERNAL_ASSERT(false, "Needs to be overridden"); + } + virtual variable_list call_copy_slices_epilogue( + PyObject* py_compiler, + const std::vector& needs_input_grad, + const at::Tensor& result, + const variable_list& res, + const at::Tensor& grad_slice) const { + TORCH_INTERNAL_ASSERT(false, "Needs to be overridden"); + } + virtual at::Tensor call_unpack( + PyObject* py_compiler, + std::optional hook_id, + size_t hook_input_id) const { + TORCH_INTERNAL_ASSERT(false, "Needs to be overridden"); + } + virtual void call_accumulate_grad( + PyObject* py_compiler, + const at::Tensor& variable, + const at::Tensor& grad, + bool has_post_hooks) const { + TORCH_INTERNAL_ASSERT(false, "Needs to be overridden"); + } +}; + +TORCH_API const std::unique_ptr& getPyCompilerInterface(); +struct TORCH_API PyCompilerGuard { + explicit PyCompilerGuard(std::unique_ptr&& impl); + PyCompilerGuard(const PyCompilerGuard&) = delete; + PyCompilerGuard& operator=(const PyCompilerGuard&) = delete; + PyCompilerGuard(PyCompilerGuard&&) = delete; + PyCompilerGuard& operator=(PyCompilerGuard&&) = delete; + + ~PyCompilerGuard(); +}; + +// including torch/csrc/autograd/engine.h breaks BC by somehow introducing +// symbol resolution issues. Instead requiring downstream users to include +// engine.h to access collect_input_metadata, we provide it here (with a +// different name to avoid ambiguous symbols...) +TORCH_API std::vector> get_input_metadata( + const edge_list& edges); + +struct SizeInput { + // Note: int value is still needed when dynamic to pass as an arg + enum DynType : uint8_t { STATIC = 0, DYNAMIC = 1 }; + SizeInput(DynType dt, int64_t v) : dyn_type(dt), value(v) {} + DynType dyn_type; + int64_t value; +}; + +struct CacheKeyBuffer { + CacheKeyBuffer(const uint8_t* key, uint16_t len) : data(new uint8_t[len]) { + std::memcpy(data.get(), key, len); + } + const uint8_t* get() const { + return data.get(); + } + + private: + // NOLINTNEXTLINE(*c-array*) + std::unique_ptr data; +}; + +struct CacheKey { + // Key to find the next node in the shadow graph. We use C++ RTTI for the + // type of the node (ntype), then a key generated with a visitor pattern. + CacheKey(const std::type_index& ntype, const uint8_t* key, uint16_t len) + : node_type(ntype), key_size(len), key(key) {} + + bool operator<(const CacheKey& other) const { + if (node_type != other.node_type) { + return node_type < other.node_type; + } + if (key_size != other.key_size) { + return key_size < other.key_size; + } + return std::memcmp(key, other.key, key_size) < 0; + } + + bool operator==(const CacheKey& other) const { + return node_type == other.node_type && key_size == other.key_size && + std::memcmp(key, other.key, key_size) == 0; + } + + size_t hash() const noexcept { + // don't bother hashing the key data, common case 1 cache entry per node + return std::hash()(node_type) ^ key_size; + } + + std::type_index node_type; + uint16_t key_size; + const uint8_t* key; +}; + +struct NodeCall { + NodeCall(uint32_t id_, std::shared_ptr node_) + : id(id_), node(std::move(node_)) {} + + void mark_output(int input_nr, int output_idx) { + graph_output.emplace_back(input_nr, output_idx); + } + + uint32_t id; + std::shared_ptr node; + std::vector> tensor_pre_hooks; + std::vector> cpp_tensor_pre_hooks; + std::vector pre_hooks; + std::vector post_hooks; + std::vector post_acc_grad_hooks; + std::vector> graph_output; + bool needed = true; +}; + +struct NodeCalls : public std::unordered_map { + NodeCall& lookup(const std::shared_ptr& function) { + auto it = find(function.get()); + if (it == end()) { + it = emplace(function.get(), NodeCall(_next_id++, function)).first; + nodes.emplace_back(function.get()); + } + return it->second; + } + + const NodeCall& lookup(uint32_t id) const { + TORCH_INTERNAL_ASSERT(id < nodes.size()); + auto it = find(nodes[id]); + TORCH_INTERNAL_ASSERT(it != end()); + return it->second; + } + + void clear() { + _next_id = 0; + std::unordered_map::clear(); + nodes.clear(); + } + + private: + uint32_t _next_id = 0; + std::vector nodes; +}; + +struct TensorArg { + // Represents a de-duplicated tensor that will be passed into the graph + TensorArg(uint32_t i = 0) : id(i) {} + uint32_t index() const { + TORCH_INTERNAL_ASSERT(defined()); + return id - 1; + } + bool defined() const { + return id != 0; + } + uint32_t id; + at::Tensor proxy_tensor; +}; + +struct TensorArgs { + // Manages a collection of TensorArgs and mappings from Tensors/SavedVariables + // to them. This also allows us to unpack SavedVariable exactly once and + // store the unpacked Tensor. + TensorArgs(const std::optional& active_node_call_idx) + : active_node_call_idx(active_node_call_idx) {} + + TensorArg& lookup(const at::Tensor& tensor, bool create = false) { + if (!tensor.defined()) { + return _undefined; + } + auto impl = tensor.unsafeGetTensorImpl(); + auto it = _args.find(impl); + if (it == _args.end()) { + TORCH_INTERNAL_ASSERT(create && inputs.size() == _next_id - 1); + it = _args.emplace(impl, TensorArg(_next_id++)).first; + inputs.emplace_back(tensor); + if (active_node_call_idx.has_value()) { + input_origins.emplace_back(active_node_call_idx.value()); + } + } + return it->second; + } + + TensorArg& lookup(const SavedVariable& sv) { + if (auto it = _saved_variables.find(&sv); it != _saved_variables.end()) { + // unpacked before graph + return *it->second; + } + // unpacked in graph + auto it2 = _saved_variables_proxies.find(&sv); + TORCH_INTERNAL_ASSERT(it2 != _saved_variables_proxies.end()); + return *it2->second; + } + + TensorArg& add(const at::Tensor& tensor) { + return lookup(tensor, true); + } + + TensorArg& add(const SavedVariable& sv, const std::shared_ptr& node) { + // no unpack hooks in this codepath + at::Tensor tensor = sv.unpack(node); + TensorArg& arg = add(tensor); + _saved_variables.emplace(&sv, &arg); + return arg; + } + + // the concrete tensors that will get passed into the graph as inputs + std::vector inputs; + // NodeCall id of each input, only when verbose logging is enabled + std::vector input_origins; + + private: + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const std::optional& active_node_call_idx; + std::unordered_map _args; + // Every TensorArg from this is actually owned by _args (or _undefined) and + // that's why we have an un-owned pointer here. + std::unordered_map _saved_variables; + std::unordered_map _saved_variables_proxies; + TensorArg _undefined; + uint32_t _next_id = 1; // id=0 used by _undefined +}; + +struct LiftedIValueArg { + LiftedIValueArg() = delete; + LiftedIValueArg(const at::IValue* ptr) + : actual_ptr(ptr), proxy(at::IValue::uninitialized()) {} + + const at::IValue* actual_ptr; // lifetime handled by autograd node + at::IValue proxy; +}; + +struct LiftedIValueArgs { + LiftedIValueArgs(const std::optional& active_node_call_idx) + : active_node_call_idx(active_node_call_idx) {} + + at::IValue& next_proxy(const at::IValue* actual_ptr) { + TORCH_INTERNAL_ASSERT(next < args.size()); + auto& iv_arg = args.at(next++); + TORCH_INTERNAL_ASSERT(iv_arg.actual_ptr == actual_ptr); + return iv_arg.proxy; + } + + void add(const at::IValue* iv) { + args.emplace_back(iv); + if (active_node_call_idx.has_value()) { + args_origins.emplace_back(active_node_call_idx.value()); + } + } + + std::vector args; + size_t next = 0; + // NodeCall id of each arg, only when verbose logging is enabled + std::vector args_origins; + + private: + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const std::optional& active_node_call_idx; +}; + +struct AutogradCompilerCall { + AutogradCompilerCall(SizeInput::DynType default_dyn_type) + : active_node_call_idx(std::nullopt), + tensor_args(active_node_call_idx), + lifted_ivalue_args(active_node_call_idx), + default_dyn_type(default_dyn_type) {} + void add_size_input(const c10::SymInt& s) { + all_size_inputs.emplace_back( + default_dyn_type, s.guard_int(__FILE__, __LINE__)); + if (active_node_call_idx.has_value()) { + size_input_origins.emplace_back(active_node_call_idx.value()); + } + } + + size_t emplace_hook(c10::SafePyObject&& fn) { + hooks.emplace_back(std::move(fn)); + return hooks.size() - 1; + } + + size_t emplace_cpp_tensor_pre_hook( + std::function&& fn) { + cpp_tensor_pre_hooks.emplace_back(std::move(fn)); + return cpp_tensor_pre_hooks.size() - 1; + } + + size_t emplace_packed_input(c10::SafePyObject&& input) { + packed_inputs.emplace_back(std::move(input)); + return packed_inputs.size() - 1; + } + + void set_active_node_call_idx(size_t node_call_idx) { + active_node_call_idx = node_call_idx; + } + + std::optional active_node_call_idx; + TensorArgs tensor_args; + std::vector all_size_inputs; + LiftedIValueArgs lifted_ivalue_args; + std::vector dyn_size_inputs; + std::vector hooks; + std::vector> + cpp_tensor_pre_hooks; + std::vector packed_inputs; + NodeCalls node_calls; + SizeInput::DynType default_dyn_type; + // NodeCall id of each size, only when verbose logging is enabled + std::vector size_input_origins; + std::unordered_map> + sv_to_hooks; + // pynode -> backward idx, backward state idx, opaque object indices + std::unordered_map< + const Node*, + std::tuple, std::vector>> + pynode_objs; +}; + +class CompiledNodeArgs { + // CompiledNodeArgs builds a representation of the constant values found + // across all the nodes in the compiled graph, via 'collect' overloads. The + // collected constants are specialized on by concatenation into a cache key. + // Tensor, symint arguments (which are lifted to become graph inputs rather + // than specialized on) are forwarded to the compiler and not included in the + // key. + public: + void collect(const TensorArg& t) { + collect_size(t.id); + if (t.defined()) { + const at::Tensor& tensor = _compiler.tensor_args.inputs[t.index()]; + // including these in the cache key means dynamo-level tensor guards can + // be skipped + collect(tensor.device()); + collect(tensor.dtype()); + collect(tensor.requires_grad()); + } + } + + void collect(const at::Tensor& t) { + collect(_compiler.tensor_args.add(t)); + } + void collect(const SavedVariable& sv, bool is_output) { + if (auto hook_data = sv.retrieve_unpack_hook_data(); + hook_data.has_value()) { + // hooks, unpack in graph + auto& [hook, packed_input] = hook_data.value(); + size_t hook_id = _compiler.emplace_hook(std::move(hook)); + // rely on dynamo to dedup packed tensors from unpacked tensors + size_t input_id = _compiler.emplace_packed_input(std::move(packed_input)); + _compiler.sv_to_hooks.emplace(&sv, std::make_pair(hook_id, input_id)); + } else { + // no hooks, unpack now + collect( + _compiler.tensor_args.add(sv, is_output ? _node_call.node : nullptr)); + } + } + void collect(const c10::SymInt& t) { + _compiler.add_size_input(t); + } + void collect(const std::vector& t, bool is_output) { + collect_size(t.size()); + for (const SavedVariable& i : t) { + collect(i, is_output); + } + } + template + void collect(const std::vector& t) { + collect_size(t.size()); + for (const T& i : t) { + collect(i); + } + } + void collect(const c10::ArrayRef& t, bool is_output) { + collect_size(t.size()); + for (const SavedVariable& i : t) { + collect(i, is_output); + } + } + template + void collect(const c10::ArrayRef& t) { + collect_size(t.size()); + for (const T& i : t) { + collect(i); + } + } + template + void collect(const c10::OptionalArray& t) { + collect(t.list); + } + template + void collect(const std::optional& t) { + if (cond(t.has_value())) { + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + collect(*t); + } + } + template + void collect(const std::pair& t) { + collect(t.first); + collect(t.second); + } + template + void collect(const ska::flat_hash_map& m) { + collect_size(m.size()); + + std::vector keys; + keys.reserve(m.size()); + std::transform( + m.begin(), m.end(), std::back_inserter(keys), [](const auto& entry) { + return entry.first; + }); + std::sort(keys.begin(), keys.end()); + for (const auto& k : keys) { + collect(k); + collect(m.at(k)); + } + } + void collect(const at::IValue& iv, bool nested = false) { + // used by AutogradContext::saved_data from CppNode + if (iv.isList()) { + c10::List list = iv.toList(); + collect_size(list.size()); + for (auto&& value : list) { + collect(value, true); + } + } else if (iv.isGenericDict()) { + c10::Dict ordered_dict = iv.toGenericDict(); + collect_size(ordered_dict.size()); + // NOLINTNEXTLINE(modernize-loop-convert) + for (auto it = ordered_dict.begin(); it != ordered_dict.end(); it++) { + collect(it->key()); + collect(it->value(), true); + } + } else if (iv.isTensor()) { + collect(iv.toTensor()); + } else if ( + !nested && + (iv.isInt() || iv.isSymInt() || iv.isDouble() || iv.isSymFloat())) { + // can't lift ivalues nested in collections + _compiler.lifted_ivalue_args.add(&iv); + } else { + try { + collect(static_cast(at::IValue::hash(iv))); + } catch (const std::runtime_error& e) { + std::string msg = + "Compiled autograd can not trace unhashable IValues, error: " + + std::string(e.what()); + TORCH_CHECK_NOT_IMPLEMENTED(false, msg); + } + } + } + void collect(const c10::Scalar& t) { + auto type = t.type(); + specialize_on_bytes(type); + if (type == c10::ScalarType::Double) { + collect(t.toDouble()); + } else if (type == c10::ScalarType::Long) { + collect(t.toLong()); + } else if (type == c10::ScalarType::Bool) { + collect(t.toBool()); + } else if (type == c10::ScalarType::ComplexDouble) { + auto c = t.toComplexDouble(); + collect(c.real()); + collect(c.imag()); + } else { + TORCH_INTERNAL_ASSERT(false); + } + } + void collect(const c10::TensorOptions& t) { + collect(t.device()); + collect(t.dtype()); + collect(t.layout()); + collect(t.requires_grad()); + collect(t.pinned_memory()); + collect(t.memory_format_opt()); + } + void collect(const at::TensorGeometry& t) { + collect(t.sym_sizes()); + collect(t.sym_strides()); + collect(t.sym_storage_offset()); + } + void collect(const torch::autograd::TypeAndSize& t) { + collect(t.sym_sizes); + collect(t.options); + } + void collect(const c10::Device& t) { + collect(t.type()); + collect(t.index()); + } + void collect(const std::string& t) { + collect_size(t.size()); + for (char c : t) { + collect(c); + } + } + void collect(const caffe2::TypeMeta& t) { + specialize_on_bytes(t.id()); + } + void collect(const std::shared_ptr& t) { + // Note: this is only capturing the ID of the node not everything + // contained inside it. This is used for tracking connections between + // nodes and the actual details of the node itself must be handled by + // a separate call to `node->compiled_args()`. + if (cond((bool)t)) { + collect(_compiler.node_calls.lookup(t)); + } + } + void collect(const NodeCall& t) { + collect_size(t.id); + collect(t.graph_output); + collect_hooks_from(t.node.get()); + } + void collect(const Edge& t) { + if (cond(t.is_valid())) { + collect_size(_compiler.node_calls.lookup(t.function).id); + collect_size(t.input_nr); + collect(t.function->input_metadata(t.input_nr)); // for validate_outputs + } + } + void collect(const InputMetadata& t) { + TORCH_CHECK_NOT_IMPLEMENTED( + !t.is_nested_tensor(), "NestedTensor support not implemented. "); + collect(t.options()); + collect(t.is_tensor_subclass()); + collect(t.shape_as_dim_vector()); + } + void collect(const VariableInfo& t) { + collect(t.layout); + collect(t.device); + collect(t.scalar_type); + collect(t.size); + collect(t.requires_grad); + collect(t.is_empty); + } + bool cond(bool cond) { + collect(cond); + return cond; + } + +#define COLLECT_AS_BYTES(T) \ + void collect(T t) { \ + specialize_on_bytes(t); \ + } + COLLECT_AS_BYTES(c10::ScalarType) + COLLECT_AS_BYTES(c10::DeviceType) + COLLECT_AS_BYTES(c10::Layout) + COLLECT_AS_BYTES(c10::MemoryFormat) + COLLECT_AS_BYTES(int8_t) + COLLECT_AS_BYTES(int16_t) + COLLECT_AS_BYTES(int32_t) + COLLECT_AS_BYTES(int64_t) + COLLECT_AS_BYTES(uint8_t) + COLLECT_AS_BYTES(uint16_t) + COLLECT_AS_BYTES(uint32_t) + COLLECT_AS_BYTES(uint64_t) + COLLECT_AS_BYTES(bool) + COLLECT_AS_BYTES(float) + COLLECT_AS_BYTES(double) +#undef COLLECT_AS_BYTES + + void collect_hooks_from(Node* fn) { + for (auto& i : fn->tensor_pre_hooks()) { + i->compiled_args(*this); + } + for (auto& [_, i] : fn->retains_grad_hooks()) { + i->compiled_args(*this); + } + for (auto& i : fn->pre_hooks()) { + i->compiled_args(*this); + } + for (auto& i : fn->post_hooks()) { + i->compiled_args(*this); + } + collect_size(_node_call.tensor_pre_hooks.size()); + collect_size(_node_call.pre_hooks.size()); + collect_size(_node_call.post_hooks.size()); + for (const auto& h : _node_call.tensor_pre_hooks) { + collect_size(static_cast(h.second)); + } + } + + CacheKey key() const { + Node* node = _node_call.node.get(); + return CacheKey( + typeid(*node), _specialization_key, _specialization_key_size); + } + + void collect_pynode_objs( + const Node* pynode, + c10::SafePyObject&& bwd, + std::optional&& bwd_state, + std::vector&& opaque_objs) { + size_t bwd_idx = _compiler.emplace_hook(std::move(bwd)); + std::optional bwd_state_idx; + if (auto state = std::move(bwd_state); state.has_value()) { + bwd_state_idx = _compiler.emplace_hook(std::move(state.value())); + } + std::vector opaque_indices(opaque_objs.size()); + for (size_t i = 0; i < opaque_objs.size(); i += 1) { + opaque_indices[i] = _compiler.emplace_hook(std::move(opaque_objs[i])); + } + _compiler.pynode_objs.emplace( + pynode, + std::make_tuple(bwd_idx, bwd_state_idx, std::move(opaque_indices))); + } + + void add_tensor_pre_hook(c10::SafePyObject&& obj, int index) { + auto fn_id = _compiler.emplace_hook(std::move(obj)); + collect_size(fn_id); + _node_call.tensor_pre_hooks.emplace_back(fn_id, index); + } + + void add_cpp_single_tensor_pre_hook( + const std::function& hook, + size_t idx) { + auto wrapper = [hook](const at::TensorBase& grad) { + // handle when hook returns nothing + auto out = hook(grad); + if (!out.defined()) { + return grad; + } + return out; + }; + + auto hook_id = _compiler.emplace_cpp_tensor_pre_hook(std::move(wrapper)); + collect_size(hook_id); + _node_call.cpp_tensor_pre_hooks.emplace_back(hook_id, idx); + } + + void add_pre_hook(c10::SafePyObject&& obj) { + auto fn_id = _compiler.emplace_hook(std::move(obj)); + collect_size(fn_id); + _node_call.pre_hooks.emplace_back(fn_id); + } + + void add_post_hook(c10::SafePyObject&& obj) { + auto fn_id = _compiler.emplace_hook(std::move(obj)); + collect_size(fn_id); + _node_call.post_hooks.emplace_back(fn_id); + } + + void add_post_acc_grad_hook(c10::SafePyObject&& obj) { + auto fn_id = _compiler.emplace_hook(std::move(obj)); + collect_size(fn_id); + _node_call.post_acc_grad_hooks.emplace_back(fn_id); + } + + // Need to template the size_t to silence internal 32-bit build errors due to + // a mix of -Werror, -Wtautological-type-limit-compare and + // -Wunknown-pragmas + template + std::enable_if_t, void> collect_size(T s) { + // we expect sizes to be small, so try to cram them into a single byte + constexpr uint8_t encode_as_u64 = std::numeric_limits::max(); + constexpr uint8_t encode_as_u32 = encode_as_u64 - 1; + constexpr uint8_t encode_as_u16 = encode_as_u64 - 2; + if (C10_UNLIKELY(s >= encode_as_u16)) { + // first write a byte indicating the path we followed, then the data + if (s <= std::numeric_limits::max()) { + // 3 bytes + specialize_on_bytes(encode_as_u16); + specialize_on_bytes(static_cast(s)); + } else if (s <= std::numeric_limits::max()) { + // 5 bytes + specialize_on_bytes(encode_as_u32); + specialize_on_bytes(static_cast(s)); + } else { + // 9 bytes + specialize_on_bytes(encode_as_u64); + specialize_on_bytes(s); + } + } else { + // happy case, 1 byte + specialize_on_bytes(static_cast(s)); + } + } + + SizeInput::DynType set_default_dyn_type(SizeInput::DynType default_dyn_type) { + return std::exchange(_compiler.default_dyn_type, default_dyn_type); + } + + CompiledNodeArgs(AutogradCompilerCall& compiler, NodeCall& node_call) + : _compiler(compiler), + _node_call(node_call), + _specialization_key( + // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) + (uint8_t*)std::malloc(_specialization_key_storage)) {} + CompiledNodeArgs(const CompiledNodeArgs&) = delete; + CompiledNodeArgs(CompiledNodeArgs&&) = delete; + CompiledNodeArgs& operator=(const CompiledNodeArgs&) = delete; + CompiledNodeArgs& operator=(CompiledNodeArgs&&) = delete; + ~CompiledNodeArgs() { + // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) + std::free(_specialization_key); + } + + private: + template + void specialize_on_bytes(const T& t) { + while (C10_UNLIKELY( + _specialization_key_size + sizeof(T) > _specialization_key_storage)) { + _specialization_key_storage *= 2; + // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) + _specialization_key = (uint8_t*)std::realloc( + _specialization_key, _specialization_key_storage); + } + std::memcpy(_specialization_key + _specialization_key_size, &t, sizeof(T)); + _specialization_key_size += sizeof(T); + } + + AutogradCompilerCall& _compiler; + NodeCall& _node_call; + size_t _specialization_key_size{0}; + size_t _specialization_key_storage{1024}; + uint8_t* _specialization_key; +}; + +struct TraceState { + TraceState(std::vector>&& ss, size_t num_outputs) + : sym_sizes(std::move(ss)), outputs(num_outputs) {} + + void debug_asserts() { + TORCH_INTERNAL_ASSERT(sym_sizes_index == sym_sizes.size()); + } + std::optional next_sym_size() { + TORCH_INTERNAL_ASSERT(sym_sizes_index < sym_sizes.size()); + return sym_sizes[sym_sizes_index++]; + } + + size_t sym_sizes_index{0}; + std::vector> sym_sizes; + variable_list outputs; +}; + +class SwapSavedVariables { + // SwapSavedVariables is used during the tracing/compilation phase after a + // cache-miss. It swaps any 'lifted' inputs (tensors, symints) to proxy nodes, + // allows tracing to happen, then swaps them back afterwards. + public: + std::tuple, std::vector> + retrieve_pynode_objs(Node* pynode) const { + auto it = compiler.pynode_objs.find(pynode); + TORCH_INTERNAL_ASSERT(it != compiler.pynode_objs.end()); + return it->second; + } + + void before(at::Tensor& t) { + TensorArg& arg = compiler.tensor_args.lookup(t); + stashed_tensors.save(&t, std::move(t)); + if (arg.defined()) { + TORCH_INTERNAL_ASSERT(arg.proxy_tensor.defined()); + t = arg.proxy_tensor; + } + } + void after(at::Tensor& t) { + stashed_tensors.restore(&t); + } + + void before(SavedVariable& t) { + if (auto it = compiler.sv_to_hooks.find(&t); + it != compiler.sv_to_hooks.end()) { + const auto& pyinterface = + torch::dynamo::autograd::getPyCompilerInterface(); + auto proxy_tensor = pyinterface->call_unpack( + get_py_compiler(), it->second.first, it->second.second); + stashed_variables.save(&t, std::move(t)); + bool prior = at::SavedTensorDefaultHooks::set_tracing(true); + t = SavedVariable(proxy_tensor, false); + at::SavedTensorDefaultHooks::set_tracing(prior); + } else { + // no hooks, was already unpacked + TensorArg& arg = compiler.tensor_args.lookup(t); + stashed_variables.save(&t, std::move(t)); + if (arg.defined()) { + bool prior = at::SavedTensorDefaultHooks::set_tracing(true); + TORCH_INTERNAL_ASSERT(arg.proxy_tensor.defined()); + t = SavedVariable(arg.proxy_tensor, false); + at::SavedTensorDefaultHooks::set_tracing(prior); + } + } + } + void after(SavedVariable& t) { + stashed_variables.restore(&t); + } + + void before(c10::SymInt& t) { + stashed_symints.save(&t, c10::SymInt(t)); + auto opt_value = state.next_sym_size(); + if (opt_value.has_value()) { + t = *opt_value; // dynamic shape + } + } + void after(c10::SymInt& t) { + stashed_symints.restore(&t); + } + + void before(at::IValue& iv) { + if (iv.isTensor()) { + before(iv.toTensor()); + } else { + stashed_ivalues.save(&iv, at::IValue(iv)); + if (iv.isInt() || iv.isSymInt() || iv.isDouble() || iv.isSymFloat()) { + iv = compiler.lifted_ivalue_args.next_proxy(&iv); + } + } + } + + void after(at::IValue& t) { + if (t.isTensor()) { + after(t.toTensor()); + } else { + stashed_ivalues.restore(&t); + } + } + + void before(Edge& t) { + if (t.is_valid()) { + // need for symints used by validate_outputs + before(t.function->mutable_input_metadata(t.input_nr)); + } + } + void after(Edge& t) { + if (t.is_valid()) { + after(t.function->mutable_input_metadata(t.input_nr)); + } + } + void before(InputMetadata& t) { + before(t.mutable_shape_as_dim_vector()); + } + void after(InputMetadata& t) { + after(t.mutable_shape_as_dim_vector()); + } + void before(at::TensorGeometry& t) { + before(t.mutable_sizes()); + before(t.mutable_strides()); + before(t.mutable_storage_offset()); + t.recompute(); + } + void after(at::TensorGeometry& t) { + after(t.mutable_sizes()); + after(t.mutable_strides()); + after(t.mutable_storage_offset()); + t.recompute(); + } + void before(torch::autograd::TypeAndSize& t) { + before(t.sym_sizes); + before(t.options); + } + void after(torch::autograd::TypeAndSize& t) { + after(t.sym_sizes); + after(t.options); + } + void before(VariableInfo& t) { + before(t.size); + } + void after(VariableInfo& t) { + after(t.size); + } + + template + void before(std::vector& t) { + for (T& i : t) { + before(i); + } + } + template + void after(std::vector& t) { + for (T& i : t) { + after(i); + } + } + template + void before(c10::SmallVector& t) { + for (T& i : t) { + before(i); + } + } + template + void after(c10::SmallVector& t) { + for (T& i : t) { + after(i); + } + } + + template + void before(c10::OptionalArray& t) { + before(t.list); + } + template + void after(c10::OptionalArray& t) { + after(t.list); + } + + template + void before(std::optional& t) { + if (t.has_value()) { + before(*t); + } + } + template + void after(std::optional& t) { + if (t.has_value()) { + after(*t); + } + } + + template + void before(ska::flat_hash_map& m) { + std::vector keys; + keys.reserve(m.size()); + std::transform( + m.begin(), m.end(), std::back_inserter(keys), [](const auto& entry) { + return entry.first; + }); + std::sort(keys.begin(), keys.end()); + for (auto& k : keys) { + before(m.at(k)); + } + } + + template + void after(ska::flat_hash_map& m) { + for (auto& [_, v] : m) { + after(v); + } + } + +#define NO_OP_VISIT(T) \ + void before(const T&) {} \ + void after(const T&) {} + NO_OP_VISIT(caffe2::TypeMeta) + NO_OP_VISIT(c10::Device) + NO_OP_VISIT(c10::DeviceType) + NO_OP_VISIT(c10::Layout) + NO_OP_VISIT(c10::MemoryFormat) + NO_OP_VISIT(c10::ScalarType) + NO_OP_VISIT(c10::Scalar) + NO_OP_VISIT(c10::TensorOptions) + NO_OP_VISIT(std::string) + NO_OP_VISIT(int64_t) + NO_OP_VISIT(bool) + NO_OP_VISIT(double) +#undef NO_OP_VISIT + + SwapSavedVariables( + AutogradCompilerCall& c, + TraceState& s, + PyObject* p, + const NodeCall& n) + : compiler(c), state(s), py_compiler(p), curr_node_call(n) {} + + PyObject* get_py_compiler() const { + return py_compiler; + } + + const NodeCall& get_curr_node_call() { + return curr_node_call; + } + + void debug_asserts() { + stashed_variables.debug_assert(); + stashed_tensors.debug_assert(); + stashed_symints.debug_assert(); + } + + private: + template + struct Stashed { + Stashed(T&& v) : prior_value(std::move(v)) {} + T prior_value; + // Note: we need count here to support duplicate calls to before() + // which happen when we have multiple autograd::Edge objects pointing + // to the same autograd::Node + int count = 1; + }; + + template + struct StashedVars : public std::unordered_map> { + void save(const T* key, T&& value) { + auto [it, inserted] = this->try_emplace(key, std::move(value)); + if (!inserted) { + // keep the value from the prior save() + it->second.count++; + } + } + void restore(T* var) { + auto it = this->find(var); + TORCH_INTERNAL_ASSERT(it != this->end(), "missing before())"); + if (--it->second.count == 0) { + // restore the value on the last restore() + *var = std::move(it->second.prior_value); + this->erase(it); + } + } + void debug_assert() { + TORCH_INTERNAL_ASSERT(this->empty(), "missing call to after()"); + } + }; + + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + AutogradCompilerCall& compiler; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + TraceState& state; + // This is a borrowed reference, we do not increment ownership, or lower it, + // it's lifecycle is entirely longer than this objects. + PyObject* py_compiler; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const NodeCall& curr_node_call; + + // These mappings are used to save the prior values when we overwrite things + // in before(). In after(), we use these to cleanup after ourselves. + StashedVars stashed_variables; + StashedVars stashed_tensors; + StashedVars stashed_symints; + StashedVars stashed_ivalues; +}; + +// NOTE: [Compiled Autograd and backward functions] +// Built-in autograd nodes have functional apply variants +// (e.g. MulBackward0_apply_functional). Compiled Autograd's initial graph +// capture wants to take a variant of this function and proxy it into the graph. +// Every autograd node defines an apply_with_saved function, that when invoked, +// proxies a call to a function into the Compiled Autograd graph. +// +// Some requirements that we have are: +// - The proxy'ed function must have inputs that are FX-graphable types. +// - Windows has a DLL symbol limit of 65536. +// - Node::apply_with_saved is in libtorch_cpu which does not have direct access +// to Python +// +// There were multiple ways to skin the cat, but what we end up doing is: +// - for e.g. MulBackward0_apply_functional, we create a new C++ function +// MulBackward0_apply_functional_ivalue that accepts vector. +// - We define how to pack and unpack arbitrary C++ types into IValues. +// - apply_with_saved passes MulBackward0_apply_functional_ivalue and +// the IValue arguments to Python via an indirection. +// In Python, these get proxy'ed into a graph. + +// Helper struct for packing/unpacking an arbitrary C++ type into a single +// IValue. There are various full and partial specializations for IValuePacker +// to handle packing specific types (like TensorOptions) into an IValue. +template +struct IValuePacker { + // Defines how to pack T into an IValue. + static at::IValue pack(const T& t) { + return t; + } + // Defines how to unpack an IValue into T. + static T unpack(const at::IValue& t) { + return t.to(); + } + // Returns the TypePtr for the IValue (this is like the "type" of the IValue). + // We use this when passing the packed IValue from Python to C++. + // In Python, the IValue is just a PyObject* with the native type. + // For example, it may be a Python int, a Python List[int], etc. + // When passing this PyObject* into C++, we need to know how to parse it + // into a C++ type that then gets put into an IValue. + // That's what the TypePtr is for: it contains the information to do the + // parsing. See torch::jit::toIValue for more information. + static at::TypePtr packed_type() { + // On windows CPU is support compiled autograd. +#if defined(_WIN32) && (defined(USE_CUDA) || defined(USE_ROCM)) + // NB: the if-constexpr usage triggers compilation errors on Windows + // with certain compiler settings + // (see https://github.com/pytorch/pytorch/pull/144707 for examples). + // It's not clear what the problem is, so we're going to ignore it for now. + TORCH_CHECK_NOT_IMPLEMENTED( + false, "torch.compile not supported on Windows"); +#else + if constexpr (::std::is_same_v) { + return at::TensorType::get(); + } else if constexpr (::std::is_same_v) { + return at::IntType::get(); + } else if constexpr (::std::is_same_v) { + return at::SymIntType::get(); + } else if constexpr (::std::is_same_v) { + return at::BoolType::get(); + } else if constexpr (::std::is_same_v) { + return at::FloatType::get(); + } else if constexpr (::std::is_same_v) { + return at::SymFloatType::get(); + } else if constexpr (::std::is_same_v) { + return at::SymBoolType::get(); + } else if constexpr (::std::is_same_v) { + return at::LayoutType::get(); + } else if constexpr (::std::is_same_v) { + return at::StringType::get(); + } else if constexpr (::std::is_same_v) { + return at::DeviceObjType::get(); + } else if constexpr (::std::is_same_v) { + return at::NumberType::get(); + } else if constexpr (::std::is_same_v) { + return at::MemoryFormatType::get(); + } else if constexpr (::std::is_same_v) { + return at::ScalarTypeType::get(); + } else { + // If you got here, you have probably added a member of a new type + // to a built-in C++ autograd node. + // Unfortunately, we don't know how to handle this type yet. + // To get this new type to work with Compiled Autograd, please + // either change it to be an IValue-constructible type, or + // define how to pack and unpack an object of this time into an IValue + // by creating a specialization of IValuePacker for this type. + // See NOTE: [Compiled Autograd and backward functions] for context. + TORCH_CHECK_NOT_IMPLEMENTED( + false, "IValuePacker not implemented for type"); + return at::NoneType::get(); + } +#endif + } +}; + +template <> +struct IValuePacker { + static at::IValue pack(const size_t& t) { + // We generally use size_t as the size of a list of Tensors or number of + // dimensions. The number of dimensions generally do not exceed 64 + // (TensorIterator has that limitation), and lists of Tensors generally do + // not exceed the int64_t max (you'd probably run out of RAM or run into + // significant Tensor overhead). If you run into this limitation the fix is + // to figure out how to pack size_t into int64_t. Note that size_t has some + // weird behavior on Mac OS. + uint64_t maximum_value = std::numeric_limits::max(); + TORCH_INTERNAL_ASSERT( + static_cast(t) <= maximum_value, + "size_t too large to pack into IValue"); + return static_cast(t); // pack as int64_t + } + static size_t unpack(const at::IValue& t) { + return static_cast(t.toInt()); + } + static at::TypePtr packed_type() { + return IValuePacker::packed_type(); + } +}; + +template <> +struct IValuePacker> { + static at::IValue pack(const std::vector& t) { + return t; + } + static std::vector unpack(const at::IValue& t) { + // We need this because there's no t.to>() override? + return t.toSymIntVector(); + } + static at::TypePtr packed_type() { + return at::ListType::create(at::SymIntType::get()); + } +}; + +template <> +struct IValuePacker { + static at::IValue pack(const VariableInfo& t) { + auto tuple = std::make_tuple( + t.layout, t.device, t.scalar_type, t.size, t.requires_grad, t.is_empty); + return tuple; + } + static VariableInfo unpack(const at::IValue& t) { + auto tuple = t.toTuple(); + const auto& tuple_elements = tuple->elements(); + const auto elements = tuple_elements.asArrayRef(); + TORCH_INTERNAL_ASSERT(elements.size() == 6); + VariableInfo v; + v.layout = elements[0].toLayout(); + v.device = elements[1].toDevice(); + v.scalar_type = elements[2].toScalarType(); + v.size = elements[3].toSymIntVector(); + v.requires_grad = elements[4].toBool(); + v.is_empty = elements[5].toBool(); + return v; + } + static at::TypePtr packed_type() { + return at::TupleType::create({ + at::LayoutType::get(), + at::DeviceObjType::get(), + at::ScalarTypeType::get(), + at::ListType::create(at::SymIntType::get()), + at::BoolType::get(), + at::BoolType::get(), + }); + } +}; + +template <> +struct IValuePacker { + static at::IValue pack(const caffe2::TypeMeta& t) { + return at::typeMetaToScalarType(t); // pack as at::ScalarType + } + static caffe2::TypeMeta unpack(const at::IValue& t) { + return caffe2::TypeMeta::fromScalarType(t.to()); + } + static at::TypePtr packed_type() { + return IValuePacker::packed_type(); + } +}; + +inline std::optional optTypeMetaToScalarType( + const std::optional& t) { + if (t.has_value()) { + return at::typeMetaToScalarType(t.value()); + } else { + return std::nullopt; + } +} + +using packed_tensoroptions_t = std::tuple< + std::optional, + std::optional, + std::optional, + std::optional, + std::optional, + std::optional>; + +inline packed_tensoroptions_t pack_TensorOptions(const at::TensorOptions& t) { + auto tuple = std::make_tuple( + t.requires_grad_opt(), + t.memory_format_opt(), + t.device_opt(), + optTypeMetaToScalarType(t.dtype_opt()), + t.layout_opt(), + t.pinned_memory_opt()); + return tuple; +} +inline at::TensorOptions unpack_TensorOptions( + const packed_tensoroptions_t& tuple) { + at::TensorOptions result; + auto maybe_requires_grad = std::get<0>(tuple); + if (maybe_requires_grad.has_value()) { + result = result.requires_grad(maybe_requires_grad); + } + auto maybe_memory_format = std::get<1>(tuple); + if (maybe_memory_format.has_value()) { + result = result.memory_format(maybe_memory_format); + } + auto maybe_device = std::get<2>(tuple); + if (maybe_device.has_value()) { + result = result.device(maybe_device.value()); + } + auto maybe_dtype = std::get<3>(tuple); + if (maybe_dtype.has_value()) { + result = + result.dtype(caffe2::TypeMeta::fromScalarType(maybe_dtype.value())); + } + auto maybe_layout = std::get<4>(tuple); + if (maybe_layout.has_value()) { + result = result.layout(maybe_layout); + } + auto maybe_pinned_memory = std::get<5>(tuple); + if (maybe_pinned_memory.has_value()) { + result = result.pinned_memory(maybe_pinned_memory); + } + return result; +} + +template <> +struct IValuePacker { + static at::IValue pack(const at::TensorOptions& t) { + return pack_TensorOptions(t); + } + static at::TensorOptions unpack(const at::IValue& t) { + auto tuple = t.to(); + return unpack_TensorOptions(tuple); + } + static at::TypePtr packed_type() { + return at::TupleType::create( + {at::OptionalType::create(at::BoolType::get()), + at::OptionalType::create(at::MemoryFormatType::get()), + at::OptionalType::create(at::DeviceObjType::get()), + at::OptionalType::create(at::ScalarTypeType::get()), + at::OptionalType::create(at::LayoutType::get()), + at::OptionalType::create(at::BoolType::get())}); + } +}; + +template <> +struct IValuePacker { + static at::IValue pack(const TypeAndSize& t) { + auto tuple = std::make_tuple(t.sym_sizes, pack_TensorOptions(t.options)); + return tuple; + } + static TypeAndSize unpack(const at::IValue& t) { + auto tuple = + t.to, packed_tensoroptions_t>>(); + TypeAndSize result; + result.sym_sizes = std::get<0>(tuple); + result.options = unpack_TensorOptions(std::get<1>(tuple)); + return result; + } + static at::TypePtr packed_type() { + return at::TupleType::create( + {IValuePacker>::packed_type(), + IValuePacker::packed_type()}); + } +}; + +template +struct IValuePacker> { + static at::IValue pack(const std::optional& t) { + if (t.has_value()) { + return IValuePacker::pack(t.value()); + } else { + return std::nullopt; + } + } + static std::optional unpack(const at::IValue& t) { + if (t.isNone()) { + return std::nullopt; + } else { + return IValuePacker::unpack(t); + } + } + static at::TypePtr packed_type() { + return at::OptionalType::create(IValuePacker::packed_type()); + } +}; + +template +struct IValuePacker> { + static at::IValue pack(const std::vector& t) { + if constexpr (::std::is_constructible_v) { + return t; + } + if (t.empty()) { + auto lst = c10::impl::GenericList(at::AnyType::get()); + return lst; + } + auto type_ptr = IValuePacker::pack(t[0]).type(); + auto lst = c10::impl::GenericList(type_ptr); + for (const auto& elt : t) { + lst.emplace_back(IValuePacker::pack(elt)); + } + return lst; + } + static std::vector unpack(const at::IValue& t) { + if constexpr (::std::is_constructible_v) { + return t.to<::std::vector>(); + } + std::vector result; + auto lst = t.toList(); + for (size_t i = 0; i < lst.size(); ++i) { + const at::IValue& elt = lst.get(i); + result.emplace_back(IValuePacker::unpack(elt)); + } + return result; + } + static at::TypePtr packed_type() { + return at::ListType::create(IValuePacker::packed_type()); + } +}; + +template +struct IValuePacker> { + static at::IValue pack(const c10::List& t) { + return IValuePacker>::pack(t.vec()); + } + static c10::List unpack(const at::IValue& t) { + return c10::List(IValuePacker>::unpack(t)); + } + static at::TypePtr packed_type() { + return IValuePacker>::packed_type(); + } +}; + +template +struct IValuePacker> { + static at::IValue pack(const std::array& t) { + std::vector result(t.begin(), t.end()); + return IValuePacker>::pack(result); + } + static std::array unpack(const at::IValue& t) { + std::array result; + auto packed = IValuePacker>::unpack(t); + for (size_t i = 0; i < packed.size(); i++) { + result[i] = packed[i]; + } + return result; + } + static at::TypePtr packed_type() { + return IValuePacker>::packed_type(); + } +}; + +template <> +struct IValuePacker { + static at::IValue pack(const at::TensorGeometry& t) { + auto tuple = std::make_tuple( + t.sym_sizes().vec(), t.sym_strides().vec(), t.sym_storage_offset()); + return tuple; + } + static at::TensorGeometry unpack(const at::IValue& t) { + auto tuple = t.to, + std::vector, + at::SymInt>>(); + return at::TensorGeometry( + std::get<0>(tuple), std::get<1>(tuple), std::get<2>(tuple)); + } + static at::TypePtr packed_type() { + return at::TupleType::create( + {IValuePacker>::packed_type(), + IValuePacker>::packed_type(), + at::SymIntType::get()}); + } +}; + +template <> +struct IValuePacker { + static at::IValue pack(const InputMetadata& t) { + TORCH_INTERNAL_ASSERT(!t.is_nested_tensor()); + auto tuple = std::make_tuple( + pack_TensorOptions(t.options()), + t.shape_as_dim_vector().vec(), + t.is_tensor_subclass(), + t.grad_dtype()); + return tuple; + } + static InputMetadata unpack(const at::IValue& t) { + auto tuple = t.to, + bool, + std::optional>>(); + + return InputMetadata( + unpack_TensorOptions(std::get<0>(tuple)), + SymIntSmallVec(std::get<1>(tuple)), + std::get<2>(tuple), + false, + std::get<3>(tuple)); + } + static at::TypePtr packed_type() { + return at::TupleType::create( + {IValuePacker::packed_type(), + IValuePacker>::packed_type(), + at::BoolType::get(), + IValuePacker>::packed_type()}); + } +}; + +template +struct IValuePacker> { + static at::IValue pack(const at::OptionalArray& t) { + return IValuePacker>>::pack(t.list); + } + static at::OptionalArray unpack(const at::IValue& t) { + auto result = IValuePacker>>::unpack(t); + if (result.has_value()) { + return {result.value()}; + } else { + return {}; + } + } + static at::TypePtr packed_type() { + return IValuePacker>>::packed_type(); + } +}; + +// This is a helper struct for packing and unpacking multiple arguments into +// an ivalue_list. It leverages IValuePacker. +struct PackedArgs { + PackedArgs() = default; + + explicit PackedArgs(std::vector stack_) + : stack(std::move(stack_)) {} + + const std::vector& vec() const { + return stack; + } + + template + void pack(const T& t) { + stack.emplace_back(IValuePacker::pack(t)); + } + template + T unpack() { + return IValuePacker::unpack(std::move(stack[idx++])); + } + + void pack_saved_data(const ska::flat_hash_map& dct) { + std::vector keys; + std::vector values; + for (const auto& [key, value] : dct) { + keys.emplace_back(key); + values.emplace_back(value); + } + pack(keys); + for (const auto& value : values) { + pack(value); + } + } + + ska::flat_hash_map unpack_saved_data() { + ska::flat_hash_map dct; + auto keys = unpack>(); + for (const auto& key : keys) { + dct.insert({key, std::move(stack[idx++])}); + } + return dct; + } + + private: + std::vector stack; + int64_t idx = 0; +}; + +} // namespace torch::dynamo::autograd + +template <> +struct std::hash { + size_t operator()(const torch::dynamo::autograd::CacheKey& k) const noexcept { + return k.hash(); + } +}; + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/cpp_shim.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/cpp_shim.h new file mode 100644 index 0000000000000000000000000000000000000000..d764297efb4acb23aaadfea5a2658f8b5a3512f1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/cpp_shim.h @@ -0,0 +1,20 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +struct _PytorchRecordFunctionState; +typedef struct _PytorchRecordFunctionState _PytorchRecordFunctionState; + +_PytorchRecordFunctionState* _pytorch_record_function_enter(const char* name); +void _pytorch_record_function_exit(_PytorchRecordFunctionState* state); + +#ifdef __cplusplus +} // extern "C" +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/cpython_defs.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/cpython_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..d2d361c2b8ec4fd4b6331738ee01f9bc3d54356a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/cpython_defs.h @@ -0,0 +1,45 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +// Functions that need to be copied from the CPython source +// should go in cpython_defs.c. Copying is required when, e.g., +// we need to call internal CPython functions that are not exposed. + +#if IS_PYTHON_3_11_PLUS + +typedef struct _PyInterpreterFrame _PyInterpreterFrame; + +PyFunctionObject* _PyFunction_CopyWithNewCode( + PyFunctionObject* o, + PyCodeObject* code); + +void THP_PyFrame_Clear(_PyInterpreterFrame* frame); + +_PyInterpreterFrame* THP_PyThreadState_BumpFramePointerSlow( + PyThreadState* tstate, + size_t size); + +void THP_PyThreadState_PopFrame( + PyThreadState* tstate, + _PyInterpreterFrame* frame); + +#endif + +// pointers to _PyOpcode_Caches for C++ +#ifdef __cplusplus +extern "C" { +#endif + +extern const uint8_t* THP_PyOpcode_Caches; +extern int THP_PyOpcode_Caches_size; +void init_THPCaches(); + +#ifdef __cplusplus +} // extern "C" +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/cpython_includes.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/cpython_includes.h new file mode 100644 index 0000000000000000000000000000000000000000..ea994e6fce119bcb14ed14239d80fe4faa4de1b9 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/cpython_includes.h @@ -0,0 +1,76 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +// Problem in CPython includes when mixing core and non-core build +// The fix was not backported to 3.12 so this is needed here +// https://github.com/python/cpython/issues/105268 +#if IS_PYTHON_3_12_PLUS +#undef _PyGC_FINALIZED +#endif + +// see https://bugs.python.org/issue35886 +#define Py_BUILD_CORE + +#ifndef __cplusplus +// C-only headers +#include + +#endif // __cplusplus + +#if IS_PYTHON_3_11_PLUS +#include + +#include +#if IS_PYTHON_3_14_PLUS && !defined(_WIN32) +#include +#include +#include +#include +#elif IS_PYTHON_3_14_PLUS && defined(_WIN32) +#include // _PyInterpreterFrame +#endif + +#endif + +#undef Py_BUILD_CORE + +#ifdef __cplusplus +extern "C" { +#endif + +#if IS_PYTHON_3_14_PLUS + +#define F_CODE(x) \ + ((PyCodeObject*)THP_PyStackRef_AsPyObjectBorrow(&(x)->f_executable)) +#define PREV_INSTR(x) (x)->instr_ptr + +#else + +#if IS_PYTHON_3_13_PLUS +#define F_CODE(x) ((PyCodeObject*)(x)->f_executable) +#define PREV_INSTR(x) (x)->instr_ptr +#else +#define F_CODE(x) ((PyCodeObject*)(x)->f_code) +#define PREV_INSTR(x) (x)->prev_instr +#endif // IS_PYTHON_3_13_PLUS + +#endif // IS_PYTHON_3_14_PLUS + +#if IS_PYTHON_3_14_PLUS +#define FUNC(x) \ + ((PyFunctionObject*)THP_PyStackRef_AsPyObjectBorrow(&(x)->f_funcobj)) +#elif IS_PYTHON_3_12_PLUS +#define FUNC(x) ((PyFunctionObject*)(x)->f_funcobj) +#else +#define FUNC(x) ((PyFunctionObject*)(x)->f_func) +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/debug_macros.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/debug_macros.h new file mode 100644 index 0000000000000000000000000000000000000000..49ef7b69fe4ab8a5a6948644c98008c11518489d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/debug_macros.h @@ -0,0 +1,107 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#ifdef __cplusplus +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _WIN32 +#define unlikely(x) (x) +#else +#define unlikely(x) __builtin_expect((x), 0) +#endif + +#define NULL_CHECK(val) \ + if (unlikely((val) == NULL)) { \ + fprintf(stderr, "NULL ERROR: %s:%d\n", __FILE__, __LINE__); \ + PyErr_Print(); \ + abort(); \ + } else { \ + } + +// CHECK might be previously declared +#undef CHECK +#define CHECK(cond) \ + if (unlikely(!(cond))) { \ + fprintf(stderr, "DEBUG CHECK FAILED: %s:%d\n", __FILE__, __LINE__); \ + abort(); \ + } else { \ + } + +// Uncomment next line to print debug message +// #define TORCHDYNAMO_DEBUG 1 +#ifdef TORCHDYNAMO_DEBUG + +#define DEBUG_CHECK(cond) CHECK(cond) +#define DEBUG_NULL_CHECK(val) NULL_CHECK(val) +#define DEBUG_TRACE(msg, ...) \ + fprintf(stderr, "TRACE[%s:%d] " msg "\n", __func__, __LINE__, __VA_ARGS__) +#define DEBUG_TRACE0(msg) \ + fprintf(stderr, "TRACE[%s:%d] " msg "\n", __func__, __LINE__) + +#else + +#define DEBUG_CHECK(cond) +#define DEBUG_NULL_CHECK(val) +#define DEBUG_TRACE(msg, ...) +#define DEBUG_TRACE0(msg) + +#endif + +inline _PyFrameEvalFunction _debug_set_eval_frame( + PyThreadState* tstate, + _PyFrameEvalFunction eval_frame) { + _PyFrameEvalFunction prev = + _PyInterpreterState_GetEvalFrameFunc(tstate->interp); + _PyInterpreterState_SetEvalFrameFunc(tstate->interp, eval_frame); + return prev; +} + +// Inspect PyObject*'s from C/C++ at the Python level, in pdb. +// e.g. +// +// PyObject* obj1 = PyList_New(...); +// PyObject* obj2 = PyObject_CallFunction(...); +// INSPECT(obj1, obj2); +// (pdb) p args[0] +// # list +// (pdb) p args[1] +// # some object +// (pdb) p args[1].some_attr +// # etc. +// +// Implementation: set eval frame callback to default, call +// torch._dynamo.utils._breakpoint_for_c_dynamo, reset eval frame callback. +#define INSPECT(...) \ + { \ + PyThreadState* cur_tstate = PyThreadState_Get(); \ + _PyFrameEvalFunction prev_eval_frame = \ + _debug_set_eval_frame(cur_tstate, &_PyEval_EvalFrameDefault); \ + PyObject* torch__dynamo_utils_module = \ + PyImport_ImportModule("torch._dynamo.utils"); \ + NULL_CHECK(torch__dynamo_utils_module); \ + PyObject* breakpoint_for_c_dynamo_fn = PyObject_GetAttrString( \ + torch__dynamo_utils_module, "_breakpoint_for_c_dynamo"); \ + NULL_CHECK(breakpoint_for_c_dynamo_fn); \ + PyObject_CallFunctionObjArgs( \ + breakpoint_for_c_dynamo_fn, __VA_ARGS__, NULL); \ + _debug_set_eval_frame(cur_tstate, prev_eval_frame); \ + Py_DECREF(breakpoint_for_c_dynamo_fn); \ + Py_DECREF(torch__dynamo_utils_module); \ + } + +#ifdef __cplusplus +} // extern "C" +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/eval_frame.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/eval_frame.h new file mode 100644 index 0000000000000000000000000000000000000000..cd0bd96ab976dc831cf1a7d40158a3c7aebccf7e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/eval_frame.h @@ -0,0 +1,67 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include + +#include +#include +#ifdef __cplusplus + +extern "C" { + +PyObject* torch_c_dynamo_eval_frame_init(void); + +#endif + +// All the eval APIs change in 3.11 so we need to decide which one to use on the +// fly https://docs.python.org/3/c-api/init.html#c._PyFrameEvalFunction +#if IS_PYTHON_3_11_PLUS +#define THP_EVAL_API_FRAME_OBJECT _PyInterpreterFrame +#else +#define THP_EVAL_API_FRAME_OBJECT PyFrameObject +#endif // IS_PYTHON_3_11_PLUS + +// We need to be able to return the _PyInterpreterFrame to python so create +// a python binding for it + +typedef struct THPPyInterpreterFrame { + PyObject_HEAD + THP_EVAL_API_FRAME_OBJECT* frame; // Borrowed reference + PyObject* locals; +} THPPyInterpreterFrame; + +THPPyInterpreterFrame* THPPyInterpreterFrame_New( + THP_EVAL_API_FRAME_OBJECT* frame); + +extern bool is_skip_guard_eval_unsafe; +extern int fullgraph_compiled_frame_count; +extern bool fullgraph_error_on_nested_compile; + +void clear_old_frame_if_python_312_plus( + PyThreadState* tstate, + THP_EVAL_API_FRAME_OBJECT* frame); + +void eval_frame_callback_set(PyObject* obj); + +const char* get_frame_name(THP_EVAL_API_FRAME_OBJECT* frame); + +PyObject* dynamo_eval_frame_default( + PyThreadState* tstate, + THP_EVAL_API_FRAME_OBJECT* frame, + int throw_flag); + +PyObject* dynamo_eval_custom_code( + PyThreadState* tstate, + THP_EVAL_API_FRAME_OBJECT* frame, + PyCodeObject* code, + const char* trace_annotation, + int throw_flag); + +#ifdef __cplusplus + +} // extern "C" + +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/eval_frame_cpp.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/eval_frame_cpp.h new file mode 100644 index 0000000000000000000000000000000000000000..348643b2d6094f98bcd2610b81bbfb6cb9494e40 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/eval_frame_cpp.h @@ -0,0 +1,55 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include + +#include +#include +#include + +#ifdef __cplusplus + +#include + +extern "C" { + +#endif + +PyObject* dynamo__custom_eval_frame( + PyThreadState* tstate, + THP_EVAL_API_FRAME_OBJECT* frame, + int throw_flag, + PyObject* callback); + +PyObject* dynamo_set_code_exec_strategy(PyObject* dummy, PyObject* obj); +void dynamo_skip_code_recursive(PyCodeObject* code); + +void dynamo_set_c_recursion_limit(int32_t limit); +int32_t dynamo_get_c_recursion_limit(); + +#ifdef __cplusplus + +} // extern "C" + +// Bytecode debugger callback functions +void set_bytecode_debugger_callback(py::object callback); +py::object get_bytecode_debugger_callback(); + +// Breakpoint code object tracking +void register_breakpoint_code(py::object code); + +// NullStackValue - sentinel class for representing NULL values on Python stack +class NullStackValue { + public: + static NullStackValue& get_singleton(); +}; + +py::object get_null_stack_value(); +py::list _get_frame_value_stack_with_depth( + const py::handle& frame_obj, + int depth); + +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/extra_state.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/extra_state.h new file mode 100644 index 0000000000000000000000000000000000000000..04d8789fd3aaba74bda9291f7042b75152c89e2d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/extra_state.h @@ -0,0 +1,213 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include + +#ifdef __cplusplus + +#include +#include +#include + +namespace py = pybind11; + +extern "C" { + +#else + +#include + +#endif + +enum FrameAction { + DEFAULT, // look through the cache, compile if not found + SKIP, // eager + RUN_ONLY, // look through the cache, run eager if not found +}; + +typedef struct FrameExecStrategy { + enum FrameAction cur_action; // action to take for current frame + enum FrameAction recursive_action; // action to take for recursive frames +} FrameExecStrategy; + +// Points to the extra scratch space on the code object +extern Py_ssize_t extra_index; + +// function to call when cache lookup errors +extern PyObject* guard_error_hook; + +typedef PyObject FrameState; +typedef struct CacheEntry CacheEntry; + +// ExtraState encasulates CacheEntry and FrameState. ExtraState is the highest +// level of abstraction of what is stored on the extra code object. Previously, +// we saved different parts on different extra indexes. We prefer this way +// because of cleaner abstraction and faster SetExtra access. + +#ifdef __cplusplus + +typedef struct VISIBILITY_HIDDEN PrecompileEntry { + py::object guard_manager; + py::object code; + void* root_mgr; + + PrecompileEntry(py::object gm, py::object c); +} PrecompileEntry; + +typedef struct VISIBILITY_HIDDEN ExtraState { + // A pointer to the orig_code object to prevent race conditions in invalidate + // function. + PyCodeObject* orig_code; + std::list precompile_entries; + // List of cache entries for compiled code objects + std::list cache_entry_list; + // Frame state to detect dynamic shape dims + py::dict frame_state; + // Actions to apply to all frames with this code object + FrameExecStrategy strategy{DEFAULT, DEFAULT}; + + ExtraState(PyCodeObject* orig_code_arg); + CacheEntry* get_first_entry(); + void move_to_front(CacheEntry* cache_entry); + void move_to_back(CacheEntry* cache_entry); + void invalidate(CacheEntry* cache_entry, py::object deleted_guard_manager); +} ExtraState; + +#else + +typedef struct ExtraState ExtraState; +typedef struct PrecompileEntry PrecompileEntry; + +#endif + +// Helper to extra the cache_entry from the extra state. +// Ownership contract +// args +// - extra_state: Borrowed +// return +// - CacheEntry: Borrowed. +CacheEntry* extract_cache_entry(ExtraState* extra_state); + +// Returns either the previously stored frame state or an empty dict. +// Ownership contract +// args +// - extra_state: Borrowed +// return +// - extra_state->frame_state: Borrowed. +FrameState* extract_frame_state(ExtraState* extra_state); + +// Returns the FrameExecStrategy stored in extra_state. +// Ownership contract +// args +// - extra_state: Borrowed +FrameExecStrategy extra_state_get_exec_strategy(ExtraState* extra_state); + +// Set the FrameExecStrategy to be done to all frames with code object +// corresponding to this extra_state. Ownership contract +// - extra_state: Borrowed +void extra_state_set_exec_strategy( + ExtraState* extra_state, + FrameExecStrategy strategy); + +// Ownership contract +// args +// - code: Borrowed +// return +// - extra_state: Borrowed. +ExtraState* get_extra_state(PyCodeObject* code); + +// This is passed as freefunc to _PyEval_RequestCodeExtraIndex. This acts as a +// deleter for the object on extra scratch space. This function is called +// internally in _PyCode_SetExtra and also during the code deallocation. + +// Destroys the extra state by deleting cache_entry, frame state and finally +// freeing the constructed extra state. + +// Developer note - You should not call this function directly. This is called +// directly inside set_extra_state. If you are in a situation trying to call +// this function, consider if set_extra_state should be called. +void destroy_extra_state(void* obj); + +// Clears the existing object sitting on the extra scratch spance and sets it +// up with the new state. Note that _PyCode_SetExtra calls the +// destroy_extra_state deleter internally, and therefore we don't call it +// explicitly here. + +// Ownership contract +// args +// - extra_state: Stolen +// return +// - there is no return, but the extra_state is stolen, so it becomes +// set_extra_state responsibility to clean it up. It will be deleted during +// the reset_code, when the set_extra_state is called with NULL. + +// Invariant - Dont set the extra state for the extra state that is already on +// the code object. Otherwise, we will first free up the old extra state +// (which is also the new extra state) and write something invalid on the +// scratch space. +void set_extra_state(PyCodeObject* code, ExtraState* extra_state); + +// Creates a new extra state and put it on the extra scratch space of the code +// object. + +// Ownership contract +// args +// - code: Borrowed +// return: +// - extra_state: New reference. +// These references are then further passed to set_extra_state which becomes +// the final owner of these references. +ExtraState* init_and_set_extra_state(PyCodeObject* code); + +// Lookup the cache held by extra_state. +// Ownership contract +// args +// - extra_state: Borrowed +// return: +// - Py_None or PyCodeObject: Borrowed reference. +// - Py_None or PyObject: Trace id of the compiled code. +void lookup( + ExtraState* extra_state, + FrameLocalsMapping* f_locals, + PyObject* backend, + PyObject** maybe_cached_code, + const char** trace_annotation, + bool is_skip_guard_eval_unsafe); + +// Create a new cache entry at extra_state holding on to guarded_code. +// Ownership contract +// args +// - extra_state: Borrowed +// - guarded_code: Borrowed +// return: +// - cache_entry: Borrowed reference +CacheEntry* create_cache_entry( + ExtraState* extra_state, + PyObject* guraded_code, + PyObject* callback); + +// Extracts the backend fn from the callback. +PyObject* get_backend(PyObject* callback); + +#ifdef __cplusplus + +} // extern "C" + +// Returns the list of CacheEntry corresponding to code_obj. +// Warning: returns references whose lifetimes are controlled by C++ +py::list _debug_get_cache_entry_list(const py::handle& code_obj); +void _reset_precompile_entries(const py::handle& code_obj); +void _load_precompile_entry( + const py::handle& code_obj, + py::object guard_manager, + py::object dynamo_code); +py::list _debug_get_precompile_entries(const py::handle& code_obj); +void _set_lru_cache(py::object boolean); + +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/framelocals_mapping.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/framelocals_mapping.h new file mode 100644 index 0000000000000000000000000000000000000000..a604a35ff5a988ddfd6fc65c61b6200ee1d1814f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/framelocals_mapping.h @@ -0,0 +1,97 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#ifdef __cplusplus + +#include +#include + +#include +#include + +extern "C" { + +#if IS_PYTHON_3_11_PLUS +using FrameLocalsFrameType = _PyInterpreterFrame; +#else +using FrameLocalsFrameType = PyFrameObject; +#endif // IS_PYTHON_3_11_PLUS + +/** + * Utility to view a frame's localsplus (locals + cells + freevars) + * in C/C++ and Python, without changing the state of the frame. + * + * Notes on usage: + * - C/C++ can directly read the frame's localsplus using an index. + * - Cell/free variables are unboxed. + * - Can be converted into a dict for use in Python. + * The dict is constructed once per FrameLocalsMapping, lazily. + * - Lifetime should not exceed the lifetime of the frame + * + * How do guards use FrameLocalsMapping? + * - When a guard accesses a frame's localsplus, we find the index of the + * variable name in the frame's code object and create a + * FrameLocalsGuardAccessor. + * - We create a FrameLocalsMapping for the frame that we pass on to guard eval. + * - LeafGuards/GuardManagers/GuardAccessors now need to define how they + * handle FrameLocalsMapping. By default, the FrameLocalsMapping is converted + * to a Python dict and the guard check is performed on the resulting dict. + * - Some guard checks don't actually depend on the input arguments, e.g. they + * only check global state. In this case, no dict conversion of + * FrameLocalsMapping is done. + * - FrameLocalsGuardAccessor is like DictGetItemGuardAccessor, except it knows + * how to handle FrameLocalsMapping - by using the framelocals variable name + * index that it was given when it was built. + */ +typedef struct VISIBILITY_HIDDEN FrameLocalsMapping { + private: + py::object _code_obj; + // can't use localsplus directly due to closure variables: + // - in 3.11+, the closure vars in the frame's closure object and + // the corresponding localsplus entry is nullptr + // - regardless of Python version, we need to unbox the cell variable + std::vector _framelocals; + + py::object _dict{py::none()}; + + void _realize_dict(); + + public: + explicit FrameLocalsMapping(FrameLocalsFrameType* frame); + + PyObject* get(int idx); + + bool dict_realized() const { + return _dict.is_none(); + } + + // Borrowed reference + PyDictObject* to_dict() { + if (this->dict_realized()) { + _realize_dict(); + } + return (PyDictObject*)_dict.ptr(); + } +} FrameLocalsMapping; + +#else + +// opaque type for C +typedef struct FrameLocalsMapping FrameLocalsMapping; + +#endif + +// Borrowed reference +PyDictObject* framelocals_mapping_to_dict(FrameLocalsMapping* map); + +#ifdef __cplusplus +} // extern "C" + +py::tuple code_framelocals_names(py::handle code); +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/guards.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/guards.h new file mode 100644 index 0000000000000000000000000000000000000000..7e98d64bbfb5a6871f53e643d40458b4c145a7f0 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/guards.h @@ -0,0 +1,120 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include + +namespace torch::dynamo { + +PyObject* torch_c_dynamo_guards_init(); + +// interfaces for extra_state and eval_frame.c because RootGuardManager class is +// not visible there. +void* convert_to_root_guard_manager(py::object root); +bool run_root_guard_manager(void* root, FrameLocalsMapping* f_locals); + +extern thread_local bool tls_is_in_mode_without_ignore_compile_internals; + +void set_is_in_mode_without_ignore_compile_internals(bool value); + +// If we're in a mode with ignore_compile_internals=False, we WON'T mask +// Python keys from guard checking (they should be visible, so eager fallback is +// possible). Otherwise (invisible mode or no mode), we WILL mask Python keys to +// avoid guard failures on the dispatch keyset at runtime. +bool get_is_in_mode_without_ignore_compile_internals(); + +struct LocalState { + // TLS state that changes operators + c10::impl::LocalDispatchKeySet dispatch_modifier; + c10::DispatchKeySet override_dispatch_key_set; + bool grad_mode_enabled; + bool should_mask_python_keys; + + at::DispatchKeySet apply(at::DispatchKeySet ks) const { + if (override_dispatch_key_set.empty()) { + auto result = + (ks | dispatch_modifier.included_) - dispatch_modifier.excluded_; + + if (should_mask_python_keys) { + result = result - + c10::DispatchKeySet( + {c10::DispatchKey::Python, + c10::DispatchKey::PythonTLSSnapshot, + c10::DispatchKey::PythonDispatcher}); + } + + return result; + } else { + return override_dispatch_key_set; + } + } + + LocalState() + : dispatch_modifier(c10::impl::tls_local_dispatch_key_set()), + override_dispatch_key_set(c10::BackendComponent::InvalidBit), + grad_mode_enabled(at::GradMode::is_enabled()), + should_mask_python_keys( + !get_is_in_mode_without_ignore_compile_internals()) {} + + void overrideDispatchKeySet(c10::DispatchKeySet ks) { + override_dispatch_key_set = ks; + } +}; + +class TensorCheck { + public: + TensorCheck( + const LocalState& state, + PyTypeObject* pt, + const at::Tensor& v, + c10::DispatchKeySet dispatch_key_set, + std::vector> dynamic_dims_sizes, + std::vector> dynamic_dims_strides); + + TensorCheck( + const LocalState& state, + PyTypeObject* pt, + c10::DispatchKeySet dispatch_key_set, + at::ScalarType dtype, + at::DeviceIndex device_index, + bool requires_grad, + std::vector> dynamic_dims_sizes, + std::vector> dynamic_dims_strides); + + bool check(const LocalState& state, const at::Tensor& v); + bool check( + const LocalState& state, + const c10::DispatchKeySet& dispatch_key_set, + const at::ScalarType& dtype, + const c10::Device& device, + const c10::SymIntArrayRef& dynamic_dims_sizes, + const c10::SymIntArrayRef& dynamic_dims_strides, + const bool& requires_grad); + std::string check_verbose( + const LocalState& state, + const at::Tensor& v, + const std::string& tensor_name); + + PyTypeObject* pytype; + + private: + uint64_t dispatch_key_; // DispatchKeySet includes device/layout + at::ScalarType dtype_; + // Note(voz): While dispatch_key_ is sufficiently representative of a device + // In that keys are more granular AND device specific - they do not + // necessarily capture device indices correctly. + at::DeviceIndex device_index_; + bool requires_grad_; + // NB: These are unset if dynamic shapes is enabled. + std::vector> sizes_; + std::vector> strides_; + // Not strictly required for dense tensors, but nested tensors need it. + int64_t dim_; +}; + +} // namespace torch::dynamo + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/init.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/init.h new file mode 100644 index 0000000000000000000000000000000000000000..74f5673ff3a012da01afa6b8386db56c48c9516a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/init.h @@ -0,0 +1,16 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +// C2039 MSVC +#include +#include + +#include + +namespace torch::dynamo { +void initDynamoBindings(PyObject* torch); +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/python_compiled_autograd.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/python_compiled_autograd.h new file mode 100644 index 0000000000000000000000000000000000000000..dd48feff5884dacc2b37cb32264a6579f81f8daf --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/python_compiled_autograd.h @@ -0,0 +1,12 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include + +// see [Note: Compiled Autograd] +namespace torch::dynamo::autograd { +PyObject* torch_c_dynamo_compiled_autograd_init(); +} // namespace torch::dynamo::autograd + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/stackref_bridge.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/stackref_bridge.h new file mode 100644 index 0000000000000000000000000000000000000000..6ad3a6390e68e35fdbbce7ce71b86169113094da --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/stackref_bridge.h @@ -0,0 +1,23 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#if IS_PYTHON_3_14_PLUS + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Use a void* to avoid exposing the internal _PyStackRef union on this +// translation unit +PyObject* THP_PyStackRef_AsPyObjectBorrow(void* stackref); + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // IS_PYTHON_3_14_PLUS + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/utils.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/utils.h new file mode 100644 index 0000000000000000000000000000000000000000..3a6063bf47bf724386c321c87fe1baad658fada4 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/dynamo/utils.h @@ -0,0 +1,23 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +// C2039 MSVC +#include +#include + +#include +// The visibility attribute is to avoid a warning about storing a field in the +// struct that has a different visibility (from pybind) than the struct. +#ifdef _WIN32 +#define VISIBILITY_HIDDEN +#else +#define VISIBILITY_HIDDEN __attribute__((visibility("hidden"))) +#endif + +namespace torch::dynamo { +PyObject* torch_c_dynamo_utils_init(); +} // namespace torch::dynamo + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/export/example_upgraders.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/export/example_upgraders.h new file mode 100644 index 0000000000000000000000000000000000000000..1fb15f1f81f0c047e26443519d168d853dea5751 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/export/example_upgraders.h @@ -0,0 +1,20 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +namespace torch::_export { + +/// Register example upgraders for the upgrader system for testing. +/// This function demonstrates common upgrade patterns and is primarily +/// used for testing and demonstration purposes. +void registerExampleUpgraders(); + +/// Deregister example upgraders for the upgrader system for testing. +/// This function cleans up the example upgraders that were registered +/// by registerExampleUpgraders(). +void deregisterExampleUpgraders(); + +} // namespace torch::_export + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/export/pt2_archive_constants.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/export/pt2_archive_constants.h new file mode 100644 index 0000000000000000000000000000000000000000..c7a3894e7bd7e894828b5738e77b0003b35cb448 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/export/pt2_archive_constants.h @@ -0,0 +1,78 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::_export::archive_spec { + +#define FORALL_CONSTANTS(DO) \ + DO(ARCHIVE_ROOT_NAME, "package") \ + /* Archive format */ \ + DO(ARCHIVE_FORMAT_PATH, "archive_format") \ + DO(ARCHIVE_FORMAT_VALUE, "pt2") \ + /* Archive version */ \ + DO(ARCHIVE_VERSION_PATH, "archive_version") \ + DO(ARCHIVE_VERSION_VALUE, "0") /* Sep.4.2024: This is the initial version of \ + the PT2 Archive Spec */ \ + /* \ + * ######## Note on updating ARCHIVE_VERSION_VALUE ######## \ + * When there is a BC breaking change to the PT2 Archive Spec, \ + * e.g. deleting a folder, or changing the naming convention of the \ + * following fields it would require bumping the ARCHIVE_VERSION_VALUE \ + * Archive reader would need corresponding changes to support loading both \ + * the current and older versions of the PT2 Archive. \ + */ \ + /* Model definitions */ \ + DO(MODELS_DIR, "models/") \ + DO(MODELS_FILENAME_FORMAT, "models/{}.json") /* {model_name} */ \ + /* AOTInductor artifacts */ \ + DO(AOTINDUCTOR_DIR, "data/aotinductor/") \ + /* MTIA artifacts */ \ + DO(MTIA_DIR, "data/mtia") \ + /* weights, including parameters and buffers */ \ + DO(WEIGHTS_DIR, "data/weights/") \ + DO(WEIGHT_FILENAME_PREFIX, "weight_") \ + DO(WEIGHTS_PARAM_CONFIG_FORMAT, "data/weights/{}_model_param_config.json") \ + DO(WEIGHTS_CONFIG_FILENAME_FORMAT, "data/weights/{}_weights_config.json") \ + /* constants, including tensor_constants, non-persistent buffers and script \ + * objects */ \ + DO(CONSTANTS_DIR, "data/constants/") \ + DO(CONSTANTS_PARAM_CONFIG_FORMAT, \ + "data/constants/{}_model_constants_config.json") \ + DO(CONSTANTS_CONFIG_FILENAME_FORMAT, \ + "data/constants/{}_constants_config.json") \ + DO(TENSOR_CONSTANT_FILENAME_PREFIX, "tensor_") \ + DO(CUSTOM_OBJ_FILENAME_PREFIX, "custom_obj_") \ + /* example inputs */ \ + DO(SAMPLE_INPUTS_DIR, "data/sample_inputs/") \ + DO(SAMPLE_INPUTS_FILENAME_FORMAT, \ + "data/sample_inputs/{}.pt") /* {model_name} */ \ + DO(TS_SAMPLE_INPUTS_FILENAME_FORMAT, \ + "extra/{}.forward.sample_input.pt") /* {model_name} */ \ + /* ExecuTorch artifacts, including PTE files */ \ + DO(EXECUTORCH_DIR, "data/executorch/") \ + /* extra folder */ \ + DO(EXTRA_DIR, "extra/") \ + DO(MODULE_INFO_PATH, "extra/module_info.json") \ + /* xl_model_weights, this folder is used for storing per-feature-weights for \ + * remote net data in this folder is consume by Predictor, and is not \ + * intended to be used by Sigmoid */ \ + DO(XL_MODEL_WEIGHTS_DIR, "xl_model_weights/") \ + DO(XL_MODEL_WEIGHTS_PARAM_CONFIG_PATH, "xl_model_weights/model_param_config") + +#define DEFINE_GLOBAL(NAME, VALUE) \ + inline constexpr std::string_view NAME = VALUE; +FORALL_CONSTANTS(DEFINE_GLOBAL) +#undef DEFINE_GLOBAL + +#define DEFINE_ENTRY(NAME, VALUE) std::pair(#NAME, VALUE), +inline constexpr std::array kAllConstants{FORALL_CONSTANTS(DEFINE_ENTRY)}; +#undef DEFINE_ENTRY + +#undef FORALL_CONSTANTS +} // namespace torch::_export::archive_spec + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/export/pybind.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/export/pybind.h new file mode 100644 index 0000000000000000000000000000000000000000..a621d3cc80658866a78f6f44a0aecef59c6dabf2 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/export/pybind.h @@ -0,0 +1,12 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include + +namespace torch::_export { + +void initExportBindings(PyObject* module); + +} // namespace torch::_export + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/export/upgrader.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/export/upgrader.h new file mode 100644 index 0000000000000000000000000000000000000000..d0c9d1f72fdb1c2a56014351d011f60fe6af2cec --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/export/upgrader.h @@ -0,0 +1,124 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +namespace torch::_export { + +/// Function type for upgrading JSON fields during schema version migration. +/// Takes a JSON field and returns the upgraded version of that field. +using UpgraderFunction = std::function; + +/// Structure containing upgrader information for a specific keypath. +/// The version is stored as the map key in the registry, so it's not +/// duplicated here. +struct Upgrader { + /// Path to the field that should be upgraded (e.g., {"graph_module", "graph", + /// "nodes"}) Assuming top-level is a JSON object that represents + /// ExportedProgram + std::vector keypath; + + /// Function that performs the actual upgrade transformation + UpgraderFunction upgrade_func; + + /// Constructor for creating an upgrader with keypath and function + Upgrader(std::vector kp, UpgraderFunction func); + + /// Comparator for maintaining bottom-up ordering in the registry. + /// Deeper keypaths are processed first to ensure safe upgrade application + /// without conflicts between parent and child field modifications. + bool operator<(const Upgrader& other) const; +}; + +/// Register an upgrader function for a specific schema version and keypath. +/// +/// This function allows registration of custom upgrade logic that will be +/// applied when upgrading artifacts from the specified version. Upgraders +/// are applied in bottom-up order (deeper keypaths first) to prevent +/// conflicts between parent and child field modifications. +/// +/// @param version The schema version this upgrader applies to +/// @param keypath The key path to the field that should be upgraded +/// @param upgrade_func Function that performs the upgrade transformation +void registerUpgrader( + int version, + const std::vector& keypath, + const UpgraderFunction& upgrade_func); + +/// Register an upgrader function using dot-separated keypath notation. +/// +/// Convenience overload that accepts dot-separated keypath strings for +/// simpler syntax. For example: "graph_module.graph.nodes" instead of +/// {"graph_module", "graph", "nodes"}. +/// +/// @param version The schema version this upgrader applies to +/// @param dot_keypath Dot-separated keypath string (e.g., "graph.nodes") +/// @param upgrade_func Function that performs the upgrade transformation +void registerUpgrader( + int version, + const std::string& dot_keypath, + const UpgraderFunction& upgrade_func); + +/// Deregister an upgrader function for a specific schema version and keypath. +/// +/// This function allows removal of previously registered upgrade logic for +/// the specified version and keypath. This is useful for testing scenarios +/// where you need to clean up registered upgraders or modify upgrader +/// behavior dynamically. +/// +/// @param version The schema version to deregister the upgrader from +/// @param keypath The key path to the field that should be deregistered +/// @return true if an upgrader was found and removed, false otherwise +bool deregisterUpgrader(int version, const std::vector& keypath); + +/// Deregister an upgrader function using dot-separated keypath notation. +/// +/// Convenience overload that accepts dot-separated keypath strings for +/// simpler syntax. For example: "graph_module.graph.nodes" instead of +/// {"graph_module", "graph", "nodes"}. +/// +/// @param version The schema version to deregister the upgrader from +/// @param dot_keypath Dot-separated keypath string (e.g., "graph.nodes") +/// @return true if an upgrader was found and removed, false otherwise +bool deregisterUpgrader(int version, const std::string& dot_keypath); + +/// Utility function for throwing consistent upgrader errors. +/// +/// This function formats error messages in a standardized way for upgrader +/// failures, including version information and optional problematic object +/// details for debugging. +/// +/// @param upgrader_name Name of the upgrader that failed +/// @param from_version Source schema version being upgraded from +/// @param error_message Descriptive error message +/// @param problematic_object Optional JSON object that caused the error +/// @throws std::runtime_error Always throws with formatted error message +void throwUpgraderError( + const std::string& upgrader_name, + int from_version, + const std::string& error_message, + const nlohmann::json& problematic_object = nlohmann::json::object()); + +/// Upgrade a JSON artifact to a specific target version with available +/// upgraders until a target version is reached. +/// +/// This handles major version upgrade only. For minor version upgrade, +/// e.g. adding a new field with default value, it's automatically handled by +/// the default constructor in generated_serialization_types.h. +/// +/// @param artifact The JSON artifact to upgrade(passed by value: function +/// operates on a local copy, original remains unmodified) +/// @param target_version The target schema version to upgrade to +/// @return The upgraded JSON artifact with updated schema version +/// @throws std::runtime_error if artifact is missing schema_version field +/// @throws std::runtime_error if final version doesn't match target version +nlohmann::json upgrade(nlohmann::json artifact, int target_version); + +} // namespace torch::_export + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/functionalization/Module.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/functionalization/Module.h new file mode 100644 index 0000000000000000000000000000000000000000..8d9ef7eee21ea132de0b5ce75a25345bdfc2539f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/functionalization/Module.h @@ -0,0 +1,41 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include +#include + +namespace torch::functionalization { + +// Creates the default bindings for `ViewMeta` specializations. +// +// Defines a constructor using the types in `SerializableTuple`, as well +// as pickle methods. +template +void create_binding_with_pickle(py::module m) { + py::class_, at::functionalization::ViewMeta>( + m, T::name()) + .def(py::init()) + .def( + "as_tuple", + [](const std::shared_ptr& meta) { + return meta->to_serializable_tuple(); + }) + .def(py::pickle( + [](const std::shared_ptr& meta) { + return meta->to_serializable_tuple(); + }, + [](const typename T::SerializableTuple& tpl) { + return std::make_shared(tpl); + })); +} + +void initModule(PyObject* module); +void initGenerated(PyObject* module); + +} // namespace torch::functionalization + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/functorch/init.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/functorch/init.h new file mode 100644 index 0000000000000000000000000000000000000000..e92e68fc321237beb24195636ff4f689105e5733 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/functorch/init.h @@ -0,0 +1,12 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include + +namespace torch::functorch::impl { + +void initFuncTorchBindings(PyObject* module); + +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/fx/node.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/fx/node.h new file mode 100644 index 0000000000000000000000000000000000000000..a4d3f2d4fdcb780ca683a63b5a384c1f6aafc93c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/fx/node.h @@ -0,0 +1,11 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +bool NodeBase_init(PyObject* module); +bool NodeIter_init(PyObject* module); + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_eager/kernel_holder.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_eager/kernel_holder.h new file mode 100644 index 0000000000000000000000000000000000000000..fa5b31156b755524c0bc3d3ceb1bf4b136ea2145 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_eager/kernel_holder.h @@ -0,0 +1,131 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#if !defined(C10_MOBILE) && !defined(ANDROID) +#pragma once + +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace torch::inductor { + +// Represent AOTI kernel. It contains all the parameter metadata of the kernel +// and the AOTI model runner. +struct AOTIKernelMetadata { + // Represent all the parameters of AOTI kernel + std::vector parameter_metadata_list_; + // AOTI model runner to run the AOTI kernel + std::shared_ptr kernel_runner_; + // Whether this kernel was compiled with dynamic shapes. When true, cache + // matching skips exact size/stride comparison on tensors and matches by + // dtype/device/rank instead, allowing a single compiled kernel to serve + // multiple input shapes. + bool is_dynamic_{false}; + AOTIKernelMetadata() : kernel_runner_(nullptr) {} + + // Check whether the given parameter metadata list is the same as the + // parameter metadata list of the AOTI kernel. + bool check( + const std::vector& parameter_metadata_list) const { + if (parameter_metadata_list_.size() != parameter_metadata_list.size()) { + return false; + } + + for (size_t i = 0; i < parameter_metadata_list_.size(); ++i) { + if (is_dynamic_) { + // Dynamic shapes: match by type/dtype/device/rank, skip exact sizes + if (!parameter_metadata_list_[i].dynamic_check( + parameter_metadata_list[i])) { + return false; + } + } else { + if (!(parameter_metadata_list_[i] == parameter_metadata_list[i])) { + return false; + } + } + } + + return true; + } +}; + +// The AOTIPythonKernelHolder class uses the AOT Inductor to generate a kernel +// for a specified operation. To speed up this process, the generated kernel +// library is cached on disk. Detailed information from the input tensors is +// used as the key for caching the kernel library. On subsequent runs, these +// input tensors are used to search the cache. If a cache hit occurs, the cached +// kernel library is loaded and executed. If a cache miss occurs, the AOT +// Inductor is called again to generate the kernel library. +class AOTIPythonKernelHolder : public c10::OperatorKernel { + // A DispatchKey object that represents the dispatch key for the kernel. + c10::DispatchKey dispatch_key_; + // Namespace of the kernel. + std::string ns_; + // Name of the operation the kernel performs. + std::string op_name_with_overload_; + // The device on which the kernel is to be executed. + c10::Device device_; + // The Python interpreter to get OpOverload object with the given op_name and + // op_overload_name. + c10::impl::PyInterpreter* pyinterpreter_; + // Cache the produced kernels by AOTI and its metadata + std::vector aoti_kernel_cache_; + // Whether to compile with dynamic shapes support + bool dynamic_; + + public: + AOTIPythonKernelHolder( + c10::DispatchKey dispatch_key, + std::string_view ns, + std::string_view op_name_with_overload, + bool dynamic = false); + + void operator()( + const c10::OperatorHandle& op, + c10::DispatchKeySet keyset, + torch::jit::Stack* stack); + + private: + bool cache_lookup( + const c10::OperatorHandle& op, + const c10::DispatchKeySet& keyset, + const torch::jit::Stack* stack, + AOTIKernelMetadata& aoti_kernel_metadata); + void cache_miss( + const c10::OperatorHandle& op, + const c10::DispatchKeySet& keyset, + torch::jit::Stack* stack); + void cache_hit( + const AOTIKernelMetadata& aoti_kernel_metadata, + const c10::OperatorHandle& op, + const c10::DispatchKeySet& keyset, + torch::jit::Stack* stack); + // Invoke python utility function on the Inductor side to produce AOTI kernel + // for the given operation. + // Inductor utility function - + // torch._inductor.utils.aoti_compile_with_persistent_cache + std::string produce_aoti_kernel_lib( + const c10::OperatorHandle& op, + const c10::DispatchKeySet& keyset, + const torch::jit::Stack* stack); + // Invoke python utility function on the Inductor side to load AOTI kernel for + // the given operation. + // Inductor utility function - torch._inductor.utils.load_aoti_eager_cache + void init_aoti_kernel_cache(); + // Load the AOTIModelContainerRunner object from the given file path. + std::shared_ptr load_aoti_model_runner( + const std::string& /*so_path*/); +}; + +} // namespace torch::inductor +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_eager/kernel_meta_info.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_eager/kernel_meta_info.h new file mode 100644 index 0000000000000000000000000000000000000000..64fd695595c4e0f36c88972ae97f455a8b27be71 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_eager/kernel_meta_info.h @@ -0,0 +1,156 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#if !defined(C10_MOBILE) && !defined(ANDROID) +#pragma once + +#include +#include +#include + +#include + +namespace torch::inductor { + +// Regarding a aten operation implemented by AOTI, the metadata of the input +// tensors will be cached on the disk to accelerate next run. TensorMetadata +// structure is to represent the metadata of each input tensor. It includes +// whether the tensor is symbolic, the dtype, the device, the sizes and the +// strides of the tensor. When the metadata of the input tensors is the same as +// the cached metadata, the cached kernel library will be loaded and executed. +// Otherwise, the AOT Inductor will be called again to generate the kernel +// library. +// Beyond the TensorMetadata, we build guard/TensorCheck for each input tensor +// as well to support symbolic shape. We intend to utilize TensorCheck to find +// out the proper kernel rather than TensorMetadata comparison. Suppose an +// operation with a single input tensor and two kernels: +// kernel1: TensorMetadata(is_symbolic=false, dtype=Float, device=CPU, +// sizes=[s0, s1, s2], strides=[s1 * s2, s2, 1]) kernel2: +// TensorMetadata(is_symbolic=false, dtype=Float, device=CPU, sizes=[3, s1, +// s2], strides=[s1 * s2, s2, 1]) +// If a tensor with sizes=[3, 4, 5] is passed to the operation, both kernel1 and +// kernel2 support the tensor shape. In this case, we need to use TensorCheck +// plus some heuristic rules to find out the proper kernel. +struct TensorMetadata { + // Indicate whether the tensor is symbolic and it may be concluded by sizes_ + // and strides_ in the future. + bool is_symbolic_; + // Dtype of a tensor(For scalar, we will wrap it as a scalar tensor) + c10::ScalarType dtype_ = c10::ScalarType::Undefined; + // Device of a tensor. + c10::Device device_; + // Dispatch key set of a tensor + c10::DispatchKeySet dispatch_key_set_; + // Sizes of a tensor. Currently, we only support static shape and use int64_t + // to represent the sizes. In the future, we will create symbolic size and use + // SymInt to represent it to support symbolic shape. + std::vector sizes_; + // Strides of a tensor. For symbolic shape support, it is the same as sizes_ + std::vector strides_; + // requires grad + bool requires_grad_ = false; + // TensorCheck for the tensor + std::optional tensor_check_; + + TensorMetadata() + : is_symbolic_(false), + device_(c10::DeviceType::COMPILE_TIME_MAX_DEVICE_TYPES), + sizes_({}), + strides_({}) {} + TensorMetadata(const at::Tensor& src_tensor); + TensorMetadata( + bool is_symbolic, + c10::ScalarType dtype, + c10::Device device, + c10::DispatchKeySet dispatch_key_set, + std::vector sizes, + std::vector strides, + bool requires_grad = false); + + // Build TensorCheck for the tensor by using the data fields in TensorMetadata + void build_guard(const dynamo::LocalState& local_state); + + // Compare two TensorMetadata objects + bool operator==(const TensorMetadata& other) const; + + // Dynamic-shape-aware comparison: matches by dtype/device/rank but + // skips exact sizes/strides comparison. + bool dynamic_check(const TensorMetadata& other) const; +}; + +// ParameterTag is to represent the type of the input parameters of a aten +// operation. Currently, we support the following types: +// 1. TENSOR: a single tensor +// 2. TENSOR_OPTIONAL: a single optional tensor +// 3. TENSOR_LIST: a list of tensors +// 4. TENSOR_LIST_OPTIONAL: a list of optional tensors +// 5. SCALAR: a scalar value +// If we need to support more types in the future, we will add more types in the +// ParameterTag enum. For example, we will extend the enum to support string, +// Dimname and so on to support more types of input parameters of aten +// operations. +enum ParameterTag { + TENSOR, + TENSOR_OPTIONAL, + TENSOR_LIST, + TENSOR_LIST_OPTIONAL, + SCALAR, + STRING, + DEVICE, + INVALID, +}; + +// ParameterMetadataValue is to represent the value of the input parameters of a +// aten operation. +using ParameterMetadataValue = std::variant< + TensorMetadata, + std::vector, + c10::Scalar, + std::string, + c10::Device>; + +// ParameterMetadata is to represent the metadata of the input parameters of a +// aten operation. It includes the tag of the parameter, the value of the +// parameter and the order of the parameter. +struct ParameterMetadata { + // The tag of the parameter. It indicates the type of the parameter. + ParameterTag tag_; + // The value of the parameter. It can be a tensor, a list of tensors or a + // scalar. + ParameterMetadataValue value_; + // The order of the parameter is used to distinguish the parameters with the + // same tag. For example, an operation with two input tensors, the first + // tensor is a optional tensor and the second tensor is a tensor. The first + // tensor will have the order 0 and the second tensor will have the order 1. + uint64_t order_{}; + + ParameterMetadata() : tag_(INVALID) {} + ParameterMetadata(TensorMetadata tensor_metadata, uint64_t input_order); + ParameterMetadata(const at::Tensor& tensor, uint64_t input_order); + ParameterMetadata( + const std::vector& tensor_list, + uint64_t input_order); + ParameterMetadata( + const std::vector& tensor_metadata_list, + uint64_t input_order); + ParameterMetadata(const c10::Scalar& scalar, uint64_t input_order); + ParameterMetadata(const std::string& string_value, uint64_t input_order); + ParameterMetadata(const c10::Device& device, uint64_t input_order); + + bool operator==(const ParameterMetadata& other) const; + + // Dynamic-shape-aware comparison: matches by type/dtype/device/rank but + // skips exact size/stride comparison for tensors, so a single compiled + // kernel can serve multiple input shapes. + bool dynamic_check(const ParameterMetadata& other) const; + + private: + // Helper function to compare two ParameterMetadata objects with the same + // SCALAR tag. + bool equal_to(const c10::Scalar& scalar) const; +}; + +} // namespace torch::inductor +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/array_ref.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/array_ref.h new file mode 100644 index 0000000000000000000000000000000000000000..27cd706592b540eab7f1dab3c76afec0d2789440 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/array_ref.h @@ -0,0 +1,12 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/common.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/common.h new file mode 100644 index 0000000000000000000000000000000000000000..a676e55c9d3b9844b801adbcba8ca3c7473fea95 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/common.h @@ -0,0 +1,21 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include +#include + +#include +#include + +// Round up to the nearest multiple of 64 +[[maybe_unused]] inline int64_t align(int64_t nbytes) { + return (nbytes + 64 - 1) & -64; +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/cpu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..08fe09380478cca15008bdbf611eb30606c4b908 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/cpu.h @@ -0,0 +1,9 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/cuda.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/cuda.h new file mode 100644 index 0000000000000000000000000000000000000000..b7e910bf59b308eb889ea81c56a60dbbad8359e3 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/cuda.h @@ -0,0 +1,9 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/mps.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/mps.h new file mode 100644 index 0000000000000000000000000000000000000000..6ed9ce406262d8402fe0ebbdb16822256051896e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/mps.h @@ -0,0 +1,9 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/xpu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/xpu.h new file mode 100644 index 0000000000000000000000000000000000000000..59c681ea6a49947bb2b079d31a2669aec7b95ff6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_include/xpu.h @@ -0,0 +1,9 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_package/model_package_loader.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_package/model_package_loader.h new file mode 100644 index 0000000000000000000000000000000000000000..07ea91b062aac3878b110440f58cd343b0d75b7d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_package/model_package_loader.h @@ -0,0 +1,64 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#if !defined(C10_MOBILE) && !defined(ANDROID) +#pragma once + +#include +#include +#include + +namespace torch::inductor { +class TORCH_API AOTIModelPackageLoader { + public: + AOTIModelPackageLoader( + const std::string& model_package_path, + const std::string& model_name = "model", + const bool run_single_threaded = false, + const size_t num_runners = 1, + const c10::DeviceIndex device_index = -1); + ~AOTIModelPackageLoader(); + + AOTIModelContainerRunner* get_runner(); + std::unordered_map get_metadata(); + + std::vector run( + const std::vector& inputs, + void* stream_handle = nullptr); + + // boxed_run will steal the ownership of the input tensors + std::vector boxed_run( + std::vector&& inputs, + void* stream_handle = nullptr); + + std::vector get_call_spec(); + void load_constants( + std::unordered_map& constants_map, + bool use_inactive, + bool check_full_update, + bool user_managed = false); + std::vector get_constant_fqns(); + + void update_constant_buffer( + std::unordered_map& tensor_map, + bool use_inactive, + bool validate_full_updates, + bool user_managed = false); + + // Static function to load metadata directly from a model package + static std::unordered_map load_metadata_from_package( + const std::string& model_package_path, + const std::string& model_name); + + private: + std::string temp_dir_; + std::unique_ptr runner_; + std::unordered_map metadata_; + + void load_metadata(const std::string& cpp_filename); +}; + +} // namespace torch::inductor +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_package/pybind.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_package/pybind.h new file mode 100644 index 0000000000000000000000000000000000000000..7c27556e79df2539098ffd878ea9a6aa44658fec --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_package/pybind.h @@ -0,0 +1,12 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include + +namespace torch::inductor { + +void initAOTIPackageBindings(PyObject* module); + +} // namespace torch::inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/model_container_runner.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/model_container_runner.h new file mode 100644 index 0000000000000000000000000000000000000000..fb471fcc1c39891ed984d50a3ef8a35e52489a78 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/model_container_runner.h @@ -0,0 +1,148 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#if !defined(C10_MOBILE) && !defined(ANDROID) +#pragma once + +#include +#include +#include + +// Forward declare DynamicLibrary +namespace at { +struct DynamicLibrary; +} + +namespace torch::inductor { +using TensorConstantMap = std::unordered_map; + +class TORCH_API AOTIModelContainerRunner { + public: + AOTIModelContainerRunner(const AOTIModelContainerRunner& other) = delete; + AOTIModelContainerRunner(AOTIModelContainerRunner&& other) = delete; + AOTIModelContainerRunner& operator=(const AOTIModelContainerRunner& other) = + delete; + AOTIModelContainerRunner& operator=(AOTIModelContainerRunner&& other) = + delete; + virtual ~AOTIModelContainerRunner(); + + std::vector run( + const std::vector& inputs, + void* stream_handle = nullptr); + + // boxed_run will steal the ownership of the input tensors + std::vector boxed_run( + std::vector&& inputs, + void* stream_handle = nullptr); + + std::unordered_map getConstantNamesToOriginalFQNs() + const; + std::unordered_map getConstantNamesToDtypes() const; + + const std::unordered_map extract_constants_map( + bool use_inactive) const; + void update_inactive_constant_buffer(const TensorConstantMap& const_map); + void update_constant_buffer( + std::unordered_map& tensor_map, + bool use_inactive, + bool validate_full_updates, + bool user_managed = false); + void update_constant_buffer( + const TensorConstantMap& const_map, + bool use_inactive, + bool validate_full_updates, + bool user_managed = false); + void run_const_fold( + bool use_inactive, + AOTInductorStreamHandle cuda_stream_handle = nullptr); + void swap_constant_buffer(); + void free_inactive_constant_buffer(); + void update_constant_buffer_from_blob(const std::string& weights_path); + + std::vector get_call_spec(); + + protected: + AOTIModelContainerRunner( + const std::string& model_so_path, + size_t num_models, + const std::string& device_str, + const std::string& cubin_dir, + const bool run_single_threaded); + + // Default constructor for custom device implementations that don't + // use .so files. Derived classes must override run_impl(). + AOTIModelContainerRunner(); + + virtual std::vector run_impl( + std::vector& input_handles, + void* stream_handle); + + std::unique_ptr model_so_; + decltype(&AOTInductorModelContainerCreateWithDevice) create_func_{nullptr}; + decltype(&AOTInductorModelContainerDelete) delete_func_{nullptr}; + decltype(&AOTInductorModelContainerGetNumOutputs) get_num_outputs_func_{ + nullptr}; + decltype(&AOTInductorModelContainerRun) run_func_{nullptr}; + decltype(&AOTInductorModelContainerGetNumConstants) get_num_constants_func_{ + nullptr}; + decltype(&AOTInductorModelContainerGetConstantName) get_constant_name_func_{ + nullptr}; + decltype(&AOTInductorModelContainerGetConstantOriginalFQN) + get_constant_original_fqn_func_{nullptr}; + decltype(&AOTInductorModelContainerGetConstantDtype) get_constant_dtype_func_{ + nullptr}; + decltype(&AOTInductorModelContainerExtractConstantsMap) + extract_constants_map_func_{nullptr}; + decltype(&AOTInductorModelContainerUpdateUserManagedConstantBuffer) + update_user_managed_constant_buffer_func_{nullptr}; + decltype(&AOTInductorModelContainerUpdateConstantBuffer) + update_constant_buffer_func_{nullptr}; + decltype(&AOTInductorModelContainerUpdateInactiveConstantBuffer) + update_inactive_constant_buffer_func_{nullptr}; + decltype(&AOTInductorModelContainerRunConstantFolding) run_const_fold_func_{ + nullptr}; + decltype(&AOTInductorModelContainerSwapConstantBuffer) + swap_constant_buffer_func_{nullptr}; + decltype(&AOTInductorModelContainerFreeInactiveConstantBuffer) + free_inactive_constant_buffer_func_{nullptr}; + decltype(&AOTInductorModelContainerGetCallSpec) get_call_spec_func_{nullptr}; + decltype(&AOTInductorModelContainerGetConstantsBlobSize) + get_constants_blob_size_func_{nullptr}; + decltype(&AOTInductorModelUpdateConstantsFromBlob) + update_constants_from_blob_func_{nullptr}; + + AOTInductorModelContainerHandle container_handle_ = nullptr; + + AOTIProxyExecutorHandle proxy_executor_handle_ = nullptr; + + private: + std::unique_ptr proxy_executor_; +}; + +using CreateAOTIModelRunnerFunc = std::unique_ptr (*)( + const std::string& model_so_path, + size_t num_models, + const std::string& device_str, + const std::string& bin_dir, + const bool run_single_threaded); + +// Return a global map "device name" -> "aoti model runner create function" for +// all registered in AOTI external backends +TORCH_API std::unordered_map& +getAOTIModelRunnerRegistry(); + +// To register a new external backend in AOTI one needs to create an instance of +// this struct. It is not thread-safe. Because it is expected to be called +// during the initialization of the program. +struct TORCH_API RegisterAOTIModelRunner{RegisterAOTIModelRunner( + const std::string& name, + CreateAOTIModelRunnerFunc create_aoti_model_runner_fn){ + getAOTIModelRunnerRegistry()[name] = create_aoti_model_runner_fn; +} // namespace torch::inductor +} +; + +} // namespace torch::inductor +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/model_container_runner_cpu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/model_container_runner_cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..83eecc1c684973fc4c30e5409ee9b4d48f61cf9a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/model_container_runner_cpu.h @@ -0,0 +1,23 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#if !defined(C10_MOBILE) && !defined(ANDROID) +#pragma once + +#include + +namespace torch::inductor { +class TORCH_API AOTIModelContainerRunnerCpu : public AOTIModelContainerRunner { + public: + AOTIModelContainerRunnerCpu( + const std::string& model_so_path, + size_t num_models = 1, + const bool run_single_threaded = false); + + ~AOTIModelContainerRunnerCpu() override; +}; + +} // namespace torch::inductor +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/model_container_runner_cuda.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/model_container_runner_cuda.h new file mode 100644 index 0000000000000000000000000000000000000000..dfdfdaf735409d2f5901b95b13678cd89ef4881c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/model_container_runner_cuda.h @@ -0,0 +1,40 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#if !defined(C10_MOBILE) && !defined(ANDROID) +#pragma once + +#include +#include + +namespace torch::inductor { + +// NOTICE: Following APIs are subject to change due to active development +// We provide NO BC guarantee for these APIs +// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) +class TORCH_CUDA_CPP_API AOTIModelContainerRunnerCuda + : public AOTIModelContainerRunner { + public: + // @param device_str: cuda device string, e.g. "cuda", "cuda:0" + AOTIModelContainerRunnerCuda( + const std::string& model_so_path, + size_t num_models = 1, + const std::string& device_str = "cuda", + const std::string& cubin_dir = "", + const bool run_single_threaded = false); + + ~AOTIModelContainerRunnerCuda() override; + + std::vector run_impl( + std::vector& input_handles, + void* stream_handle) override; + + std::vector run_with_cuda_stream( + const std::vector& inputs, + const at::cuda::CUDAStream& cuda_stream); +}; + +} // namespace torch::inductor +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/model_container_runner_mps.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/model_container_runner_mps.h new file mode 100644 index 0000000000000000000000000000000000000000..2e36e600a6f575e2d8b05cbfdde89fd6837a87d2 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/model_container_runner_mps.h @@ -0,0 +1,23 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#if defined(__APPLE__) +#pragma once + +#include + +namespace torch::inductor { +class TORCH_API AOTIModelContainerRunnerMps : public AOTIModelContainerRunner { + public: + AOTIModelContainerRunnerMps( + const std::string& model_so_path, + size_t num_models = 1, + const bool run_single_threaded = false); + + ~AOTIModelContainerRunnerMps() override; +}; + +} // namespace torch::inductor +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/model_container_runner_xpu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/model_container_runner_xpu.h new file mode 100644 index 0000000000000000000000000000000000000000..2a55999f70b8be633b9d90237b18ad8c6502b349 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/model_container_runner_xpu.h @@ -0,0 +1,42 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#if !defined(C10_MOBILE) && !defined(ANDROID) +#pragma once + +#include +#include + +namespace torch::inductor { + +// NOTICE: Following APIs are subject to change due to active development +// We provide NO BC guarantee for these APIs + +// HERE we use C10_EXPORT because libtorch_python needs this Symbol be exported. +// And `TORCH_API and `TORCH_XPU_API`` do not export the symbol in Windows +// build. +class C10_EXPORT AOTIModelContainerRunnerXpu : public AOTIModelContainerRunner { + public: + // @param device_str: xpu device string, e.g. "xpu", "xpu:0" + AOTIModelContainerRunnerXpu( + const std::string& model_so_path, + size_t num_models = 1, + const std::string& device_str = "xpu", + const std::string& kernel_bin_dir = "", + const bool run_single_threaded = false); + + ~AOTIModelContainerRunnerXpu() override; + + std::vector run_impl( + std::vector& input_handles, + void* stream_handle) override; + + std::vector run_with_xpu_stream( + const std::vector& inputs, + const at::xpu::XPUStream& xpu_stream); +}; + +} // namespace torch::inductor +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/pybind.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/pybind.h new file mode 100644 index 0000000000000000000000000000000000000000..5a0eef2af2edaccf962ce0fc92de97761c2becf1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runner/pybind.h @@ -0,0 +1,12 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include + +namespace torch::inductor { + +void initAOTIRunnerBindings(PyObject* module); + +} // namespace torch::inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/arrayref_tensor.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/arrayref_tensor.h new file mode 100644 index 0000000000000000000000000000000000000000..5080b9ee61f2fc57f1408a26d482c902d41bca17 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/arrayref_tensor.h @@ -0,0 +1,249 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace torch::aot_inductor { + +using MiniIntArrayRef = MiniArrayRef; + +static_assert( + sizeof(MiniIntArrayRef) == sizeof(void*) + sizeof(size_t), + "changing the size of MiniArrayRef breaks ABI compatibility!"); + +inline bool is_contiguous_strides_for_shape( + int64_t ndim, + const int64_t* strides_ptr, + const int64_t* sizes_ptr) { + int64_t z = 1; + for (int64_t d = ndim - 1; d >= 0; d--) { + const auto& size_d = sizes_ptr[d]; + if (size_d != 1) { + if (strides_ptr[d] == z) { + z *= size_d; + } else { + return false; + } + } + } + return true; +} + +// Shim for AOTI generated code to pretend a raw array works like an +// AtenTensorHandle. +template +class ArrayRefTensor { + public: + using value_type = T; + + ArrayRefTensor() = default; + + explicit ArrayRefTensor( + MiniArrayRef arr, + MiniArrayRef sizes, + MiniArrayRef strides, + int32_t device_type, + int32_t device_idx) + : arrayRef_(arr), + sizes_(sizes), + strides_(strides), + device_type_(device_type), + device_idx_(device_idx) { + assert(sizes.size() == strides.size()); + assert(is_contiguous_strides_for_shape( + sizes.size(), strides.data(), sizes.data())); + } + + AtenTensorHandle expensiveCopyToTensor() const { + AtenTensorHandle result = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_empty_strided( + sizes_.size(), + sizes_.data(), + strides_.data(), + aoti_torch_dtype>(), + device_type_, + device_idx_, + &result)); + void* dataPtr = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_data_ptr(result, &dataPtr)); + std::memcpy(dataPtr, data(), numel() * sizeof(T)); + return result; + } + + // We need to look the same as RAIIAtenTensorHandle, which returns + // an owning AtenTensorHandle from release(). So, we allocate one! + AtenTensorHandle release() { + return expensiveCopyToTensor(); + } + + AtenTensorHandle borrowAsTensor() const { + AtenTensorHandle result = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_create_tensor_from_blob_v2( + data(), + sizes_.size(), + sizes_.data(), + strides_.data(), + 0, + aoti_torch_dtype>(), + device_type_, + device_idx_, + &result, + aoti_torch_layout_strided(), + nullptr, + 0)); + return result; + } + + // We don't need to free any memory. + void reset() {} + + auto sizes() const { + return sizes_; + } + + auto strides() const { + return strides_; + } + + auto device_type() const { + return device_type_; + } + + auto device_idx() const { + return device_idx_; + } + + T* data() const { + return arrayRef_.data(); + } + + auto numel() const { + return arrayRef_.size(); + } + + void set_arrayref(MiniArrayRef new_arrayref) { + arrayRef_ = new_arrayref; + } + + private: + MiniArrayRef arrayRef_; + // We expect generated code to have statically available sizes & + // strides for us. + MiniArrayRef sizes_; + MiniArrayRef strides_; + int32_t device_type_ = 0; + int32_t device_idx_ = 0; + // We continue to zero-initialize this field in case we repurpose + // the space later; having predictable contents can only help. + int32_t unusedDoNotRemoveForABICompatibility_ = 0; +}; + +static_assert( + sizeof(ArrayRefTensor) == + 3 * sizeof(MiniIntArrayRef) + 3 * sizeof(int32_t) + + (alignof(ArrayRefTensor) > 4 ? sizeof(int32_t) : 0), + "changing the size of ArrayRefTensor breaks ABI compatibility!"); + +template +inline ArrayRefTensor reinterpret_tensor_wrapper( + const ArrayRefTensor& self, + int64_t ndim, + const int64_t* sizes_ptr, + const int64_t* strides_ptr, + int64_t storage_offset) { + // REVIEW: we should add a way to build the DSO in debug mode during + // tests so we can have checks like this! + assert(is_contiguous_strides_for_shape(ndim, strides_ptr, sizes_ptr)); + return ArrayRefTensor( + MiniArrayRef( + self.data() + storage_offset, self.numel() - storage_offset), + MiniArrayRef(sizes_ptr, ndim), + MiniArrayRef(strides_ptr, ndim), + self.device_type(), + self.device_idx()); +} + +template +inline T* get_data_ptr_wrapper(ArrayRefTensor& tensor) { + return tensor.data(); +} + +template +inline T* get_data_ptr_wrapper(const MiniArrayRef& arr) { + return arr.data(); +} + +template +inline const ArrayRefTensor& unwrap_raii_handle_if_needed( + const ArrayRefTensor& tensor) { + return tensor; +} + +template +inline ArrayRefTensor& unwrap_raii_handle_if_needed( + ArrayRefTensor& tensor) { + return tensor; +} + +template +inline const ArrayRefTensor& wrap_with_raii_handle_if_needed( + const ArrayRefTensor& tensor) { + return tensor; +} + +template +inline ArrayRefTensor& wrap_with_raii_handle_if_needed( + ArrayRefTensor& tensor) { + return tensor; +} + +template +inline ArrayRefTensor wrap_with_raii_handle_if_needed( + ArrayRefTensor&& tensor) { + return std::move(tensor); +} + +template +inline RAIIAtenTensorHandle expensive_copy_to_tensor_if_needed( + const ArrayRefTensor& tensor) { + return tensor.expensiveCopyToTensor(); +} + +inline AtenTensorHandle expensive_copy_to_tensor_if_needed( + AtenTensorHandle handle) { + return handle; +} + +template +const T& copy_arrayref_tensor_to_tensor(const T& t) { + return t; +} + +template +RAIIAtenTensorHandle copy_arrayref_tensor_to_tensor( + const ArrayRefTensor& art) { + return art.expensiveCopyToTensor(); +} + +template +const T& borrow_arrayref_tensor_as_tensor(const T& t) { + return t; +} + +template +RAIIAtenTensorHandle borrow_arrayref_tensor_as_tensor( + const ArrayRefTensor& art) { + return art.borrowAsTensor(); +} + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/arrayref_tensor_conversion.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/arrayref_tensor_conversion.h new file mode 100644 index 0000000000000000000000000000000000000000..fe9957ff1ef6a530a63f8ae865362f9ccee57d27 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/arrayref_tensor_conversion.h @@ -0,0 +1,90 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +// Zero-copy conversion utilities between ArrayRefTensor (C++ template) and +// AOTInductorArrayRefTensor (plain C struct). +// +// These helpers allow the host process to marshal ArrayRefTensor objects into +// the C-compatible AOTInductorArrayRefTensor descriptors before calling into a +// DSO, and to unmarshal the descriptors back after the call. Because only +// C types cross the DSO boundary, the host and DSO can be linked against +// different C++ standard libraries (e.g. libc++ vs libstdc++) without ABI +// conflicts. +// +// IMPORTANT: Both sides share the same underlying data buffers -- no copies +// are made. The caller must ensure the data remains valid for the lifetime +// of the descriptor. + +#include +#include + +#include +#include +#include +#include + +namespace torch::aot_inductor { + +inline void validate_arrayref_tensor_ndim(int32_t ndim) { + if (ndim < 0 || ndim > AOTI_ARRAYREF_TENSOR_MAX_DIMS) { + throw std::runtime_error( + "AOTInductorArrayRefTensor ndim exceeds AOTI_ARRAYREF_TENSOR_MAX_DIMS"); + } +} + +// ------------------------------------------------------------------------- +// ArrayRefTensor --> AOTInductorArrayRefTensor (zero-copy) +// ------------------------------------------------------------------------- +template +inline void arrayref_tensor_to_c( + const ArrayRefTensor& src, + AOTInductorArrayRefTensor& dst) { + const auto sizes = src.sizes(); + const auto strides = src.strides(); + dst.data = const_cast(static_cast(src.data())); + dst.numel = static_cast(src.numel()); + dst.ndim = static_cast(sizes.size()); + dst.dtype = aoti_torch_dtype>(); + dst.device_type = src.device_type(); + dst.device_idx = src.device_idx(); + + validate_arrayref_tensor_ndim(dst.ndim); + assert(dst.ndim <= AOTI_ARRAYREF_TENSOR_MAX_DIMS); + std::memcpy(dst.sizes, sizes.data(), dst.ndim * sizeof(int64_t)); + std::memcpy(dst.strides, strides.data(), dst.ndim * sizeof(int64_t)); + const int32_t remaining = AOTI_ARRAYREF_TENSOR_MAX_DIMS - dst.ndim; + std::memset(dst.sizes + dst.ndim, 0, remaining * sizeof(int64_t)); + std::memset(dst.strides + dst.ndim, 0, remaining * sizeof(int64_t)); + std::memset(dst.reserved, 0, sizeof(dst.reserved)); +} + +template +inline AOTInductorArrayRefTensor arrayref_tensor_to_c( + const ArrayRefTensor& src) { + AOTInductorArrayRefTensor dst; + arrayref_tensor_to_c(src, dst); + return dst; +} + +// ------------------------------------------------------------------------- +// AOTInductorArrayRefTensor --> ArrayRefTensor (zero-copy) +// ------------------------------------------------------------------------- +template +inline ArrayRefTensor c_to_arrayref_tensor( + const AOTInductorArrayRefTensor& src) { + validate_arrayref_tensor_ndim(src.ndim); + return ArrayRefTensor( + MiniArrayRef( + static_cast(const_cast(src.data)), + static_cast(src.numel)), + MiniArrayRef(src.sizes, static_cast(src.ndim)), + MiniArrayRef(src.strides, static_cast(src.ndim)), + src.device_type, + src.device_idx); +} + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/constant_type.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/constant_type.h new file mode 100644 index 0000000000000000000000000000000000000000..8666e0556acbebc2e798e02d05b725be57a167ea --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/constant_type.h @@ -0,0 +1,25 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +// WARNING: Be careful when adding new includes here. This header will be used +// in model.so, and should not refer to any aten/c10 headers except the stable +// C ABI defined in torch/csrc/inductor/aoti_torch/c/shim.h. The same rule +// applies to other files under torch/csrc/inductor/aoti_runtime/. + +namespace torch::aot_inductor { + +enum ConstantType : uint8_t { + Unknown = 0, + Parameter = 1, + Buffer = 2, + TensorConstant = 3, + FoldedConstant = 4, +}; + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/device_utils.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/device_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..1c57f319b594df4f4ad0135aab86eff3424244a9 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/device_utils.h @@ -0,0 +1,72 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +// WARNING: Be careful when adding new includes here. This header will be used +// in model.so, and should not refer to any aten/c10 headers except the stable +// C ABI defined in torch/csrc/inductor/aoti_torch/c/shim.h. The same rule +// applies to other files under torch/csrc/inductor/aoti_runtime/. + +#ifdef USE_CUDA + +// FIXME: Currently, CPU and CUDA backend are mutually exclusive. +// This is a temporary workaround. We need a better way to support +// multi devices. + +#include +#include + +#define AOTI_RUNTIME_CUDA_CHECK(EXPR) \ + do { \ + const cudaError_t code = EXPR; \ + const char* msg = cudaGetErrorString(code); \ + if (code != cudaSuccess) { \ + throw std::runtime_error( \ + std::string("CUDA error: ") + std::string(msg)); \ + } \ + } while (0) + +namespace torch::aot_inductor { + +using DeviceStreamType = cudaStream_t; + +} // namespace torch::aot_inductor + +#elif defined(USE_XPU) +#include +#include +#include +#define AOTI_RUNTIME_XPU_CHECK(EXPR) \ + do { \ + const ze_result_t status = EXPR; \ + if (status != ZE_RESULT_SUCCESS) { \ + std::stringstream ss; \ + ss << "L0 runtime error: " << std::hex << std::uppercase << status; \ + throw std::runtime_error(ss.str()); \ + } \ + } while (0) + +namespace torch::aot_inductor { + +using DeviceStreamType = sycl::queue*; + +} // namespace torch::aot_inductor + +#else + +#define AOTI_RUNTIME_CPU_CHECK(EXPR) \ + bool ok = EXPR; \ + if (!ok) { \ + throw std::runtime_error("CPU runtime error"); \ + } + +namespace torch::aot_inductor { + +using DeviceStreamType = void*; + +} // namespace torch::aot_inductor + +#endif // USE_CUDA + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/interface.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/interface.h new file mode 100644 index 0000000000000000000000000000000000000000..305261775da46f3225a59702dc2090f5fba40255 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/interface.h @@ -0,0 +1,340 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +// WARNING: Be careful when adding new includes here. This header will be used +// in model.so, and should not refer to any aten/c10 headers except the stable +// C ABI defined in torch/csrc/inductor/aoti_torch/c/shim.h. The same rule +// applies to other files under torch/csrc/inductor/aoti_runtime/. +#include + +#ifdef _WIN32 +/* +On Windows, we need to explicit declaration for export APIs. And because the +package loader call these API via GetProcAddress(ldsym on Linux), we can ignore +the import case. +*/ +#define AOTI_API __declspec(dllexport) +#else +#define AOTI_API __attribute__((__visibility__("default"))) +#endif + +extern "C" { +struct AOTInductorModelOpaque; +using AOTInductorModelHandle = AOTInductorModelOpaque*; + +struct AOTInductorModelContainerOpaque; +using AOTInductorModelContainerHandle = AOTInductorModelContainerOpaque*; + +struct AOTInductorStreamOpaque; +using AOTInductorStreamHandle = AOTInductorStreamOpaque*; + +struct AOTInductorConstantMap; +using AOTInductorConstantMapHandle = AOTInductorConstantMap*; + +struct AOTInductorConstantMapEntry { + const char* name; + AtenTensorHandle handle; +}; + +// --------------------------------------------------------------------------- +// C-compatible tensor descriptor for crossing the DSO boundary. +// +// This struct carries the same information as ArrayRefTensor but uses only +// C-compatible types so the host process and DSO can be built with different +// C++ standard libraries (e.g. libc++ vs libstdc++). All pointer fields +// reference memory owned by the caller; no copies are made. +// +// Maximum supported number of dimensions. 8 covers all practical AOTI +// models; tensors with more dims should fall back to the AtenTensorHandle +// interface. +// --------------------------------------------------------------------------- +#define AOTI_ARRAYREF_TENSOR_MAX_DIMS 8 + +struct AOTInductorArrayRefTensor { + // Pointer to the raw data buffer. Not owned. + void* data; + + // Number of elements in the data buffer (product of sizes for contiguous + // tensors). + int64_t numel; + + // Static-size arrays for shape metadata. Only the first `ndim` entries + // are meaningful. + int64_t sizes[AOTI_ARRAYREF_TENSOR_MAX_DIMS]; + int64_t strides[AOTI_ARRAYREF_TENSOR_MAX_DIMS]; + + // Number of dimensions (0 <= ndim <= AOTI_ARRAYREF_TENSOR_MAX_DIMS). + int32_t ndim; + + // Torch dtype encoded as int32_t (same encoding as aoti_torch_dtype_*()). + int32_t dtype; + + // Device information. + int32_t device_type; + int32_t device_idx; + + // Reserved for future extension. Zero-initialize and do not read — a + // newer reader must tolerate zeros, and an older reader must ignore them. + int64_t reserved[4]; +}; + +static_assert( + sizeof(AOTInductorArrayRefTensor) == 192, + "changing the size of AOTInductorArrayRefTensor breaks ABI compatibility!"); + +// TODO: Deprecate this API. This was kept for BC compatibility. +// Please use AOTInductorModelContainerCreateWithDevice instead. +AOTI_API AOTIRuntimeError AOTInductorModelContainerCreate( + AOTInductorModelContainerHandle* container_handle, + size_t num_models, + bool is_cpu, + const char* cubin_dir); + +// Creates an AOTInductor model container. The parameter num_models +// specifies the number of model instances that may be run concurrently for +// the same input model. +// `device_str` MUST NOT be nullptr. It must be a valid device string, e.g. +// "cpu", "cuda", "cuda:0", etc. If the device index is not specified for CUDA +// device, runtime will use the device index returned by +// "cudaGetDevice(&device_idx)" +AOTI_API AOTIRuntimeError AOTInductorModelContainerCreateWithDevice( + AOTInductorModelContainerHandle* container_handle, + size_t num_models, + const char* device_str, + const char* cubin_dir); + +// Deletes the AOTInductor model container. +AOTI_API AOTIRuntimeError AOTInductorModelContainerDelete( + AOTInductorModelContainerHandle container_handle); + +// Runs the inference. +AOTI_API AOTIRuntimeError AOTInductorModelContainerRun( + AOTInductorModelContainerHandle container_handle, + AtenTensorHandle* input_handles, // array of input AtenTensorHandle; handles + // are stolen; the array itself is borrowed + size_t num_inputs, + AtenTensorHandle* + output_handles, // array for writing output AtenTensorHandle; handles + // will be stolen by the caller; the array itself is + // borrowed + size_t num_outputs, + AOTInductorStreamHandle stream_handle, + AOTIProxyExecutorHandle proxy_executor_handle); + +// Single-threaded variant of previous. +AOTI_API AOTIRuntimeError AOTInductorModelContainerRunSingleThreaded( + AOTInductorModelContainerHandle container_handle, + AtenTensorHandle* input_handles, // array of input AtenTensorHandle; handles + // are stolen; the array itself is borrowed + size_t num_inputs, + AtenTensorHandle* + output_handles, // array for writing output AtenTensorHandle; handles + // will be stolen by the caller; the array itself is + // borrowed + size_t num_outputs, + AOTInductorStreamHandle stream_handle, + AOTIProxyExecutorHandle proxy_executor_handle); + +// Retrieves the number of constants for the model. +AOTI_API AOTIRuntimeError AOTInductorModelContainerGetNumConstants( + AOTInductorModelContainerHandle container_handle, + size_t* num_constants); + +// Retrieves a constant's name. +// idx is the index of the internal's constants. +// Need idx < num_constants from AOTInductorModelContainerGetNumConstants +AOTI_API AOTIRuntimeError AOTInductorModelContainerGetConstantName( + AOTInductorModelContainerHandle container_handle, + size_t idx, + const char** name); + +// Retrieves a constant's original FQN. +// idx is the index of the internal's constants. +// Need idx < num_constants from AOTInductorModelContainerGetNumConstants +AOTI_API AOTIRuntimeError AOTInductorModelContainerGetConstantOriginalFQN( + AOTInductorModelContainerHandle container_handle, + size_t idx, + const char** original_fqn); + +// Retrieves whether a constant is from folded. +// idx is the index of the internal's constants. +// Need idx < num_constants from AOTInductorModelContainerGetNumConstants +AOTI_API AOTIRuntimeError AOTInductorModelContainerGetConstantFromFolded( + AOTInductorModelContainerHandle container_handle, + size_t idx, + bool* from_folded); + +// Retrieves the inductor constant type. +// idx is the index of the internal's constants. +// Need idx < num_constants from AOTInductorModelContainerGetNumConstants +AOTI_API AOTIRuntimeError AOTInductorModelContainerGetConstantType( + AOTInductorModelContainerHandle container_handle, + size_t idx, + int32_t* type); + +// Retrieves a constant's dtype. +// idx is the index of the internal's constants. +// Need idx < num_constants from AOTInductorModelContainerGetNumConstants +AOTI_API AOTIRuntimeError AOTInductorModelContainerGetConstantDtype( + AOTInductorModelContainerHandle container_handle, + size_t idx, + int32_t* dtype); + +// Retrieves a constant's data size. +// idx is the index of the internal's constants. +// Need idx < num_constants from AOTInductorModelContainerGetNumConstants +AOTI_API AOTIRuntimeError AOTInductorModelContainerGetConstantDataSize( + AOTInductorModelContainerHandle container_handle, + size_t idx, + size_t* data_size); + +// Extract the constants that is being used in the container. +AOTI_API AOTIRuntimeError AOTInductorModelContainerExtractConstantsMap( + AOTInductorModelContainerHandle container_handle, + AOTInductorConstantMapHandle constant_map_handle, + bool use_inactive); + +// Setup the constant buffer in model container with provided ConstantMap. +// The ConstantMap is user managed, and the user would retain ownership. +AOTI_API AOTIRuntimeError +AOTInductorModelContainerUpdateUserManagedConstantBuffer( + AOTInductorModelContainerHandle container_handle, + AOTInductorConstantMapHandle constant_map_handle, + bool use_inactive, + bool validate_full_update); + +// Same as AOTInductorModelContainerUpdateUserManagedConstantBuffer, +// but no std::unordered_map crosses DLL boundaries for cross-compilation. +AOTI_API AOTIRuntimeError +AOTInductorModelContainerUpdateUserManagedConstantBufferPairs( + AOTInductorModelContainerHandle container_handle, + const AOTInductorConstantMapEntry* pairs, + size_t num_pairs, + bool use_inactive, + bool validate_full_update); + +// Setup the constant buffer in model container with provided ConstantMap +// use_inactive should be set as true if the inactive buffer is to be updated. +// validate_full_update checks if all constants are included in the ConstantMap +AOTI_API AOTIRuntimeError AOTInductorModelContainerUpdateConstantBuffer( + AOTInductorModelContainerHandle container_handle, + AOTInductorConstantMapHandle constant_map_handle, + bool use_inactive, + bool validate_full_update); + +// Setup the inactive constant buffer in model container with provided +// ConstantMap +AOTI_API AOTIRuntimeError AOTInductorModelContainerUpdateInactiveConstantBuffer( + AOTInductorModelContainerHandle container_handle, + AOTInductorConstantMapHandle constant_map_handle); + +// Free the inactive constant buffer in model container. +AOTI_API AOTIRuntimeError AOTInductorModelContainerFreeInactiveConstantBuffer( + AOTInductorModelContainerHandle container_handle); + +// Run constant folding on constant buffer. +AOTI_API AOTIRuntimeError AOTInductorModelContainerRunConstantFolding( + AOTInductorModelContainerHandle container_handle, + bool use_inactive, + AOTInductorStreamHandle stream_handle, + AOTIProxyExecutorHandle proxy_executor_handle); + +// Swap the constant buffer being used to the inactive one. +AOTI_API AOTIRuntimeError AOTInductorModelContainerSwapConstantBuffer( + AOTInductorModelContainerHandle container_handle); + +// Retrieves the number of inputs for the model. +AOTI_API AOTIRuntimeError AOTInductorModelContainerGetNumInputs( + AOTInductorModelContainerHandle container_handle, + size_t* ret_num_inputs); + +// Retrieves the input name at the given index. +AOTI_API AOTIRuntimeError AOTInductorModelContainerGetInputName( + AOTInductorModelContainerHandle container_handle, + size_t input_idx, + const char** ret_input_names); + +// Retrieves the number of outputs for the model. +AOTI_API AOTIRuntimeError AOTInductorModelContainerGetNumOutputs( + AOTInductorModelContainerHandle container_handle, + size_t* ret_num_outputs); + +// Retrieves the output name at the given index. +AOTI_API AOTIRuntimeError AOTInductorModelContainerGetOutputName( + AOTInductorModelContainerHandle container_handle, + size_t output_idx, + const char** ret_output_names); + +// Creates an AOTInductorModel instance. This is a thin and light wrapper +// around the compiled model; it doesn't handle concurrency, queueing, device +// management, etc. Use this if bare-metal performance is needed and you are +// willing to handle other "management" aspects yourself. +// +// constant_map_handle is an opaque type to satisfy the C ABI. It should be a +// std::unordered_map*. +AOTI_API AOTIRuntimeError AOTInductorModelCreate( + AOTInductorModelHandle* model_handle, + AOTInductorConstantMapHandle constant_map_handle); + +// Run an AOTInductorModel (see AOTInductorModelCreate for when one should use +// this function versus AOTInductorModelContainerRun). +AOTI_API AOTIRuntimeError AOTInductorModelRun( + AOTInductorModelHandle model_handle, + AtenTensorHandle* input_handles, + AtenTensorHandle* output_handles); + +// Replace AOTInductorModel's constant map. Note it doesn't handle concurrency +// so be sure to handle ordering if AOTInductorModelRun is ran concurrently. +AOTI_API AOTIRuntimeError AOTInductorModelUpdateConstantsMap( + AOTInductorModelHandle model_handle, + AOTInductorConstantMapHandle constant_map_handle); + +// Get the size of the constant blob +AOTI_API AOTIRuntimeError AOTInductorModelContainerGetConstantsBlobSize( + AOTInductorModelContainerHandle container_handle, + uint64_t* ret_size); + +// Load weights from a single blob in weight_blob_ptr +AOTI_API AOTIRuntimeError AOTInductorModelUpdateConstantsFromBlob( + AOTInductorModelContainerHandle container_handle, + const uint8_t* weight_blob_ptr); + +// Delete an AOTInductorModel created by AOTInductorModelCreate. +AOTI_API AOTIRuntimeError +AOTInductorModelDelete(AOTInductorModelHandle model_handle); + +AOTI_API AOTIRuntimeError AOTInductorModelGetNumOutputs( + AOTInductorModelHandle model_handle, + size_t* ret_num_outputs); + +AOTI_API AOTIRuntimeError AOTInductorModelContainerGetCallSpec( + AOTInductorModelContainerHandle container_handle, + const char** in_spec, + const char** out_spec); + +// --------------------------------------------------------------------------- +// C-ABI-safe variant of AOTInductorModelRunMinimalArrayrefInterface. +// +// Instead of passing std::tuple...>& (which encodes C++ +// standard library types into the ABI), this function accepts flat C arrays +// of AOTInductorArrayRefTensor descriptors. The descriptors reference the +// same underlying data buffers -- no copies are made. +// +// The host process marshals its ArrayRefTensor objects into +// AOTInductorArrayRefTensor descriptors, calls into the DSO through this +// pure-C interface, and then unmarshals the output descriptors back. +// Because only C types cross the DSO boundary, the host and DSO can be +// built with different C++ standard libraries (e.g. libc++ vs libstdc++). +// --------------------------------------------------------------------------- +AOTI_API AOTIRuntimeError AOTInductorModelRunMinimalArrayrefInterfaceV2( + AOTInductorModelHandle model_handle, + int32_t num_inputs, + const AOTInductorArrayRefTensor* inputs, + int32_t num_outputs, + AOTInductorArrayRefTensor* outputs); + +} // extern "C" + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/kernel_context_tls.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/kernel_context_tls.h new file mode 100644 index 0000000000000000000000000000000000000000..3bb92f6f84155ccb10fd19a18eb1af2a667e0c5c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/kernel_context_tls.h @@ -0,0 +1,149 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace torch::aot_inductor { + +struct KernelContext { + std::string kernel_name; + std::string python_stack; + std::string compressed_python_stack; + + KernelContext(std::string name, std::string stack) + : kernel_name(std::move(name)) { + python_stack = trim_stack(stack); + compressed_python_stack = compress_stack(python_stack); + } + + KernelContext(const KernelContext&) = default; + KernelContext& operator=(const KernelContext&) = default; + KernelContext(KernelContext&&) = default; + KernelContext& operator=(KernelContext&&) = default; + + private: + // Strip leading and trailing newlines from stack: + // - finds first and last non-newline characters + // - outputs substring between them (inclusive) + // - returns empty string if stack contains only newlines + static std::string trim_stack(const std::string& stack) { + std::string res_stack; + auto beg = stack.find_first_not_of('\n'); + if (beg == std::string::npos) { + return res_stack; + } + auto end = stack.find_last_not_of('\n'); + if (end == std::string::npos) { + res_stack = stack.substr(beg); + } else { + res_stack = stack.substr(beg, end - beg + 1); + } + return res_stack; + } + + // Compress stack into compact format: + // - blank lines are treated as stack separators + // - lines with 0 or 2 spaces of indentation are parsed as filename, fileline + // and function + // - lines with 4 spaces of indentation are parsed as the code snippet + // - outputs function[code], filename and fileline (at newline each) + // - returns empty string on any parse error + static std::string compress_stack(const std::string& stack) { + std::string res_stack; + namespace fs = std::filesystem; + char function[1025]; + char filename[1025]; + uint32_t fileline; + int ret, n, ws; + const char* p; + std::stringstream stream{stack}; + std::string line; + std::string fmt = "File \"%1024[^\"]\", line %u, in %1024[^\n]\n%n"; + while (std::getline(stream, line)) { + // check if new stack + if (line.empty()) { + res_stack += '\n'; + continue; + } + p = line.c_str(); + ws = 0; + while (*p == ' ') { + ++p; + ++ws; + } + // check if new file + if (ws != 0 && ws != 2) { + return {}; + } + ret = sscanf(p, fmt.c_str(), filename, &fileline, function, &n); + if (ret != 3) { + return {}; + } + if (!std::getline(stream, line)) { + return {}; + } + p = line.c_str(); + ws = 0; + while (*p == ' ') { + ++p; + ++ws; + } + // check if command + if (ws != 4) { + return {}; + } + res_stack += std::string{function} + '[' + std::string{p} + ']'; + res_stack += '\n'; + res_stack += fs::path{filename}.filename(); + res_stack += '\n'; + res_stack += std::to_string(fileline); + res_stack += '\n'; + } + return res_stack; + } +}; + +// Thread-local pointer +extern thread_local KernelContext* tls_kernel_context; + +inline KernelContext* current_kernel_context() { + return tls_kernel_context; +} + +inline void set_kernel_context(KernelContext* ctx) { + tls_kernel_context = ctx; +} + +inline void clear_kernel_context() { + tls_kernel_context = nullptr; +} + +struct KernelContextGuard { + KernelContextGuard(const std::string& name, const std::string& stack) + : owned_context_(name, stack) { + set_kernel_context(&owned_context_); + } + ~KernelContextGuard() { + clear_kernel_context(); + } + + // Delete copy constructor and copy assignment operator + KernelContextGuard(const KernelContextGuard&) = delete; + KernelContextGuard& operator=(const KernelContextGuard&) = delete; + + KernelContextGuard(KernelContextGuard&&) = default; + KernelContextGuard& operator=(KernelContextGuard&&) = delete; + + private: + KernelContext owned_context_; +}; + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/mini_array_ref.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/mini_array_ref.h new file mode 100644 index 0000000000000000000000000000000000000000..31cdf3063f928702619631d25997c1bd703e54db --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/mini_array_ref.h @@ -0,0 +1,165 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace torch::aot_inductor { + +// Can't use c10::ArrayRef because it's not truly header-only and +// pulls in other c10 headers. This is (sadly) copy-pasted and +// adapted. +template +class MiniArrayRef final { + public: + using iterator = T*; + using const_iterator = const T*; + using size_type = size_t; + using value_type = T; + + using reverse_iterator = std::reverse_iterator; + + private: + /// The start of the array, in an external buffer. + T* Data; + + /// The number of elements. + size_type Length; + + public: + /// @name Constructors + /// @{ + + /// Construct an empty MiniArrayRef. + /* implicit */ constexpr MiniArrayRef() : Data(nullptr), Length(0) {} + + /// Construct an MiniArrayRef from a single element. + // TODO Make this explicit + constexpr MiniArrayRef(const T& OneElt) : Data(&OneElt), Length(1) {} + + /// Construct an MiniArrayRef from a pointer and length. + constexpr MiniArrayRef(T* data, size_t length) : Data(data), Length(length) {} + + /// Construct an MiniArrayRef from a range. + constexpr MiniArrayRef(T* begin, T* end) : Data(begin), Length(end - begin) {} + + template < + typename Container, + typename = std::enable_if_t().data())>, + T*>>> + /* implicit */ MiniArrayRef(Container& container) + : Data(container.data()), Length(container.size()) {} + + /// Construct an MiniArrayRef from a std::vector. + // The enable_if stuff here makes sure that this isn't used for + // std::vector, because MiniArrayRef can't work on a std::vector + // bitfield. + template + /* implicit */ MiniArrayRef(const std::vector& Vec) + : Data(Vec.data()), Length(Vec.size()) { + static_assert( + !std::is_same_v, + "MiniArrayRef cannot be constructed from a std::vector bitfield."); + } + + /// Construct an MiniArrayRef from a std::array + template + /* implicit */ constexpr MiniArrayRef(std::array& Arr) + : Data(Arr.data()), Length(N) {} + + /// Construct an MiniArrayRef from a C array. + template + // NOLINTNEXTLINE(*c-array*) + /* implicit */ constexpr MiniArrayRef(T (&Arr)[N]) : Data(Arr), Length(N) {} + + // /// Construct an MiniArrayRef from an empty C array. + /* implicit */ constexpr MiniArrayRef(const volatile void* Arr) + : Data(nullptr), Length(0) {} + + /// Construct an MiniArrayRef from a std::initializer_list. + /* implicit */ constexpr MiniArrayRef(const std::initializer_list& Vec) + : Data( + std::begin(Vec) == std::end(Vec) ? static_cast(nullptr) + : std::begin(Vec)), + Length(Vec.size()) {} + + /// @} + /// @name Simple Operations + /// @{ + + constexpr iterator begin() const { + return Data; + } + constexpr iterator end() const { + return Data + Length; + } + + // These are actually the same as iterator, since MiniArrayRef only + // gives you const iterators. + constexpr const_iterator cbegin() const { + return Data; + } + constexpr const_iterator cend() const { + return Data + Length; + } + + constexpr reverse_iterator rbegin() const { + return reverse_iterator(end()); + } + constexpr reverse_iterator rend() const { + return reverse_iterator(begin()); + } + + /// empty - Check if the array is empty. + constexpr bool empty() const { + return Length == 0; + } + + constexpr T* data() const { + return Data; + } + + /// size - Get the array size. + constexpr size_t size() const { + return Length; + } + + /// equals - Check for element-wise equality. + constexpr bool equals(MiniArrayRef RHS) const { + return Length == RHS.Length && std::equal(begin(), end(), RHS.begin()); + } + + /// @} + /// @name Operator Overloads + /// @{ + constexpr const T& operator[](size_t Index) const { + return Data[Index]; + } + + /// Disallow accidental assignment from a temporary. + /// + /// The declaration here is extra complicated so that "arrayRef = {}" + /// continues to select the move assignment operator. + template + std::enable_if_t, MiniArrayRef>& operator=( + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + U&& Temporary) = delete; + + /// Disallow accidental assignment from a temporary. + /// + /// The declaration here is extra complicated so that "arrayRef = {}" + /// continues to select the move assignment operator. + template + std::enable_if_t, MiniArrayRef>& operator=( + std::initializer_list) = delete; +}; + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/model.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/model.h new file mode 100644 index 0000000000000000000000000000000000000000..eca53e62494e348a7c5f75684f650b71c45caa7f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/model.h @@ -0,0 +1,67 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +// WARNING: Be careful when adding new includes here. This header will be used +// in model.so, and should not refer to any aten/c10 headers except the stable +// C ABI defined in torch/csrc/inductor/aoti_torch/c/shim.h. The same rule +// applies to other files under torch/csrc/inductor/aoti_runtime/. +#include + +namespace torch::aot_inductor { + +class AOTInductorModel : public AOTInductorModelBase { + public: + AOTInductorModel( + std::shared_ptr constants_map, + std::shared_ptr> constants_array, + const std::string& device_str, + std::optional cubin_dir); + + std::unordered_map const_run_impl( + DeviceStreamType stream, + AOTIProxyExecutorHandle proxy_executor, + bool initialization = false); + + void _const_run_impl( + std::vector& output_handles, + DeviceStreamType stream, + AOTIProxyExecutorHandle proxy_executor); + + void run_impl( + AtenTensorHandle* + input_handles, // array of input AtenTensorHandle; handles + // are stolen; the array itself is borrowed + AtenTensorHandle* + output_handles, // array for writing output AtenTensorHandle; handles + // will be stolen by the caller; the array itself is + // borrowed + DeviceStreamType stream, + AOTIProxyExecutorHandle proxy_executor); + + template + Outputs run_impl_minimal_arrayref_interface( + const Inputs& inputs, + DeviceStreamType stream, + AOTIProxyExecutorHandle proxy_executor); + + static std::unique_ptr Create( + std::shared_ptr constants_map, + std::shared_ptr> constants_array, + const std::string& device_str, + std::optional cubin_dir) { + return std::make_unique( + std::move(constants_map), + std::move(constants_array), + device_str, + std::move(cubin_dir)); + } + + private: + std::unique_ptr kernels_; +}; + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/model_base.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/model_base.h new file mode 100644 index 0000000000000000000000000000000000000000..12fef809d7eac0f1479206fb1bef92989bc90473 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/model_base.h @@ -0,0 +1,1126 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#ifdef _WIN32 +#include +#include // std::function +#ifdef USE_MMAP_SELF +#include +#include +#include +#include + +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +#define PROT_EXEC 0x4 + +#define MAP_SHARED 0x01 +#define MAP_PRIVATE 0x02 +#define MAP_FAILED ((void*)-1) + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +struct Dl_info { + char dli_fname[MAX_PATH]; /**< Filename of defining object */ + void* dli_fbase; /**< Load address of that object */ + const char* dli_sname; /**< Name of nearest lower symbol */ + void* dli_saddr; /**< Exact value of nearest symbol */ +}; +typedef struct Dl_info Dl_info; + +int dladdr(const void* addr, Dl_info* info) { + // only returns filename, FWIW. + CHAR tpath[MAX_PATH]; + MEMORY_BASIC_INFORMATION mbi; + char* path; + char* tmp; + size_t length; + int ret = 0; + + if (!info) + return 0; + + HMODULE hModule; + if (!GetModuleHandleExA( + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (LPCSTR)addr, + &hModule) || + hModule == NULL) + return 0; + + ret = GetModuleFileNameA(hModule, (LPSTR)&tpath, MAX_PATH); + if (!ret) + return 0; + + path = tpath; + + length = strlen(path); + if (length >= MAX_PATH) { + length = MAX_PATH - 1; + path[MAX_PATH - 1] = '\0'; + } + + tmp = path; + while (*tmp) { + if (*tmp == '\\') + *tmp = '/'; + tmp++; + } + + memcpy(info->dli_fname, path, length + 1); + info->dli_fbase = hModule; + info->dli_sname = NULL; + info->dli_saddr = NULL; + return 1; +} + +static DWORD get_creation_disposition(int flags) { + if (flags & O_CREAT) { + if (flags & O_EXCL) + return CREATE_NEW; + if (flags & O_TRUNC) + return CREATE_ALWAYS; + return OPEN_ALWAYS; + } + if (flags & O_TRUNC) + return TRUNCATE_EXISTING; + return OPEN_EXISTING; +} + +#define O_ACCMODE 03 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 + +static DWORD get_access_mode(int flags) { + switch (flags & O_ACCMODE) { + case O_RDONLY: + return GENERIC_READ; + case O_WRONLY: + return GENERIC_WRITE; + case O_RDWR: + return GENERIC_READ | GENERIC_WRITE; + default: + return GENERIC_READ; + } +} +#ifndef O_DSYNC +#define O_DSYNC 00010000 /* used to be O_SYNC, see below */ +#endif + +#ifndef O_SYNC +#define __O_SYNC 04000000 +#define O_SYNC (__O_SYNC | O_DSYNC) +#endif + +int open(char* pathname, int flags) { + DWORD dwDesiredAccess = get_access_mode(flags); + DWORD dwCreationDisposition = get_creation_disposition(flags); + DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; + + if (flags & O_SYNC) { + dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH; + } + + if (flags & O_SEQUENTIAL) { + dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN; + } + + if (flags & O_RANDOM) { + dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; + } + + HANDLE hFile = CreateFileA( + pathname, + dwDesiredAccess, + dwShareMode, + NULL, + dwCreationDisposition, + dwFlagsAndAttributes, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) { + switch (GetLastError()) { + case ERROR_FILE_NOT_FOUND: + errno = ENOENT; + break; + case ERROR_PATH_NOT_FOUND: + errno = ENOTDIR; + break; + case ERROR_ACCESS_DENIED: + errno = EACCES; + break; + case ERROR_FILE_EXISTS: + errno = EEXIST; + break; + case ERROR_TOO_MANY_OPEN_FILES: + errno = EMFILE; + break; + default: + errno = EIO; + } + return -1; + } + + int fd = _open_osfhandle((intptr_t)hFile, flags); + if (fd == -1) { + CloseHandle(hFile); + errno = EMFILE; + return -1; + } + + if (flags & O_APPEND) { + lseek(fd, 0, SEEK_END); + } + + return fd; +} + +int close(int fd) { + return _close(fd); +} + +void* mmap( + void* addr, + size_t length, + int prot, + int flags, + int fd, + off_t offset) { + HANDLE hFile = (HANDLE)_get_osfhandle(fd); + if (hFile == INVALID_HANDLE_VALUE) { + errno = EBADF; + return MAP_FAILED; + } + + DWORD flProtect; + if (prot & PROT_WRITE) { + flProtect = PAGE_READWRITE; + } else if (prot & PROT_READ) { + flProtect = PAGE_READONLY; + } else { + flProtect = PAGE_NOACCESS; + } + + flProtect = PAGE_READONLY; + + DWORD dwDesiredAccess = 0; + if (prot & PROT_READ) + dwDesiredAccess |= FILE_MAP_READ; + if (prot & PROT_WRITE) + dwDesiredAccess |= FILE_MAP_WRITE; + if (prot & PROT_EXEC) + dwDesiredAccess |= FILE_MAP_EXECUTE; + + dwDesiredAccess = FILE_MAP_READ; + + SYSTEM_INFO SysInfo; + GetSystemInfo(&SysInfo); + DWORD dwSysGran = SysInfo.dwAllocationGranularity; + + DWORD dwFileMapStart = (offset / dwSysGran) * dwSysGran; + DWORD dwMapViewSize = (offset % dwSysGran) + length; + DWORD dwFileMapSize = offset + length; + int iViewDelta = offset - dwFileMapStart; + + HANDLE hMapping = + CreateFileMapping(hFile, NULL, flProtect, 0, dwFileMapSize, NULL); + + if (!hMapping) { + DWORD dwErrCode = GetLastError(); + errno = EACCES; + return MAP_FAILED; + } + + void* lpMapAddress = MapViewOfFileEx( + hMapping, dwDesiredAccess, 0, dwFileMapStart, dwMapViewSize, addr); + if (!lpMapAddress) { + DWORD dwErrCode = GetLastError(); + errno = EINVAL; + } + + void* pData = (char*)lpMapAddress + iViewDelta; + + CloseHandle(hMapping); + + if (!lpMapAddress) { + return MAP_FAILED; + } + + return pData; +} + +int munmap(void* addr, size_t length) { + if (!UnmapViewOfFile(addr)) { + errno = EINVAL; + return -1; + } + return 0; +} +#endif // USE_MMAP_SELF +#else // !_WIN32 +#include +#include +#include +#endif // _WIN32 + +#include +#include +#include +#include +#include +#include + +// WARNING: Be careful when adding new includes here. This header will be used +// in model.so, and should not refer to any aten/c10 headers except the stable +// C ABI defined in torch/csrc/inductor/aoti_torch/c/shim.h. The same rule +// applies to other files under torch/csrc/inductor/aoti_runtime/. +#include +#ifdef USE_MPS +#include +#endif // USE_MPS +#ifdef USE_XPU +#include +#else +#include +#endif // USE_XPU +#include + +#define AOTI_RUNTIME_CHECK(EXPR, MSG) \ + do { \ + bool ok = EXPR; \ + if (!ok) { \ + throw std::runtime_error(MSG); \ + } \ + } while (0) + +// At codegen time, we write out a binary file called constants.bin. +// We then turn the raw binary to an object file that exposes this +// symbol and link it into the final .so. +// For information on the binary format, see `man objcopy`, under +// the "binary-architecture" flag: +// https://man7.org/linux/man-pages/man1/objcopy.1.html +// todo: use #embed in C++ 23 once available +// The constants are NOT readonly because they may be mutated. +// NOLINTNEXTLINE(*array*) +extern uint8_t _binary_constants_bin_start[]; +// NOLINTNEXTLINE(*array*) +extern uint8_t _binary_constants_bin_end[]; + +#if defined(USE_CUDA) || defined(USE_XPU) +// Compute required blob size with 64-alignment if on GPU. +#define AOTI_CONST_ALIGNMENT 64 +#else +// Use 64-alignment (use something >=64)for better performance on CPU. +#define AOTI_CONST_ALIGNMENT 64 +#endif + +namespace { + +using RAIIDataPtr = std::unique_ptr>; + +#ifdef USE_CUDA + +// NOLINTNEXTLINE(clang-diagnostic-unneeded-internal-declaration) +RAIIDataPtr RAII_gpuMalloc(size_t num_bytes) { +#ifdef AOT_INDUCTOR_USE_CACHING_ALLOCATOR + // Use caching allocator for allocating GPU memory + void* data_ptr = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_cuda_caching_allocator_raw_alloc(num_bytes, &data_ptr)); + auto deleter = [](void* ptr) { + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_cuda_caching_allocator_raw_delete(ptr)); + }; + return RAIIDataPtr(data_ptr, deleter); +#else + // Use cudaMalloc directly for allocating GPU memory + void* data_ptr = nullptr; + AOTI_RUNTIME_CUDA_CHECK(cudaMalloc((void**)&data_ptr, num_bytes)); + auto deleter = [](void* ptr) { AOTI_RUNTIME_CUDA_CHECK(cudaFree(ptr)); }; + return RAIIDataPtr(data_ptr, deleter); +#endif +} + +#elif defined(USE_XPU) + +// NOLINTNEXTLINE(clang-diagnostic-unneeded-internal-declaration) +RAIIDataPtr RAII_gpuMalloc(size_t num_bytes) { + sycl::queue* queue_ptr = nullptr; + aoti_torch_get_current_sycl_queue((void**)&queue_ptr); + void* data_ptr = sycl::malloc_device(num_bytes, *queue_ptr); + auto deleter = [queue_ptr](void* ptr) { sycl::free(ptr, *queue_ptr); }; + return RAIIDataPtr(data_ptr, deleter); +} + +#elif defined(USE_MPS) + +RAIIDataPtr RAII_gpuMalloc(size_t num_bytes) { + void* data_ptr = nullptr; + aoti_torch_mps_malloc(&data_ptr, num_bytes); + auto deleter = [](void* ptr) { aoti_torch_mps_free(ptr); }; + return RAIIDataPtr(data_ptr, deleter); +} + +#endif // USE_CUDA + +// NOLINTNEXTLINE(clang-diagnostic-unneeded-internal-declaration) +RAIIDataPtr RAII_cpuMalloc(size_t num_bytes) { + void* data_ptr = std::malloc(num_bytes); + if (!data_ptr) { + throw std::bad_alloc(); + } + auto deleter = [](void* ptr) { std::free(ptr); }; + return RAIIDataPtr(data_ptr, deleter); +} +} // anonymous namespace + +namespace torch::aot_inductor { + +using ConstantMap = + std::unordered_map; + +// valid device strs are: cpu, cuda, cuda:0, cuda:1, ... +// Update the list here if more devices are supported in the future +inline void parse_device_str( + const std::string& device_str, + int32_t& device_type, + int32_t& device_idx) { + std::regex re("(cpu|cuda|xpu|mps)(:([0-9]+))?"); + std::smatch sm; + bool matched = std::regex_match(device_str, sm, re); + AOTI_RUNTIME_CHECK(matched, "Invalid device: " + device_str); + + if (sm[1].str() == "cpu") { + device_type = aoti_torch_device_type_cpu(); + } else if (sm[1].str() == "cuda") { + device_type = aoti_torch_device_type_cuda(); +#ifdef USE_XPU + } else if (sm[1].str() == "xpu") { + device_type = aoti_torch_device_type_xpu(); +#endif +#ifdef USE_MPS + } else if (sm[1].str() == "mps") { + device_type = aoti_torch_device_type_mps(); +#endif + } else { + AOTI_RUNTIME_CHECK(false, "Invalid device: " + device_str); + } + + if (sm[3].matched) { + device_idx = stoi(sm[3].str()); + } else { + device_idx = -1; + } +} + +// Defines the base class for AOTInductorModel, which is generated by the +// AOTInductor cpp codegen. Since we do not need dynamic dispatch, we rely +// on curiously recurring template pattern (CRTP) to save some runtime +// v-table overhead. The generated AOTInductorModel is specialized with +// methods such as run_impl. +template +class AOTInductorModelBase { + public: + AOTInductorModelBase( + size_t num_inputs, + size_t num_outputs, + size_t num_constants, + const std::string& device_str, + std::optional cubin_dir, + bool include_weights = true) + : inputs_info_(num_inputs), + outputs_info_(num_outputs), + constants_info_(num_constants), + cubin_dir_(std::move(cubin_dir)), + include_weights(include_weights) { + parse_device_str(device_str, device_type_, device_idx_); + +#ifdef USE_CUDA + if (device_idx_ == -1) { + AOTI_RUNTIME_CUDA_CHECK(cudaGetDevice(&device_idx_)); + } else { + // If device_idx_ is passed in, we need to set the current device to it + AOTI_RUNTIME_CUDA_CHECK(cudaSetDevice(device_idx_)); + } +#endif // USE_CUDA +#ifdef USE_XPU + if (device_idx_ == -1) { + aoti_torch_get_current_xpu_device(&device_idx_); + } else { + aoti_torch_set_current_xpu_device(device_idx_); + } +#endif // USE_XPU +#ifdef USE_MPS + if (device_idx_ == -1) { + device_idx_ = 0; + } +#endif // USE_MPS + } + + // NOLINTNEXTLINE(modernize-use-equals-default) + ~AOTInductorModelBase() { +#ifdef USE_CUDA + if (run_finished_) { + auto code = cudaEventDestroy(*run_finished_); + if (code != cudaSuccess) { + std::cerr << "Failed to destroy CUDA event in AOTInductor model: " + << cudaGetErrorString(code) << '\n'; + } + } +#endif // USE_CUDA +#ifdef USE_XPU + if (run_finished_) { + (*run_finished_)->wait_and_throw(); + delete *run_finished_; + } +#endif // USE_XPU + } + + AOTInductorModelBase(AOTInductorModelBase&&) = delete; + AOTInductorModelBase& operator=(AOTInductorModelBase&&) = delete; + AOTInductorModelBase(const AOTInductorModelBase&) = delete; + AOTInductorModelBase& operator=(const AOTInductorModelBase&) = delete; + + void run( + AtenTensorHandle* + input_handles, // array of input AtenTensorHandle; handles + // are stolen; the array itself is borrowed + AtenTensorHandle* + output_handles, // array for writing output AtenTensorHandle; handles + // will be stolen by the caller; the array itself is + // borrowed + DeviceStreamType stream, + AOTIProxyExecutorHandle proxy_executor) { +#ifdef USE_CUDA + if (!run_finished_) { + cudaEvent_t run_finished = nullptr; + AOTI_RUNTIME_CUDA_CHECK(cudaEventCreate(&run_finished)); + run_finished_.emplace(run_finished); + } +#elif defined(USE_XPU) + if (run_finished_) { + (*run_finished_)->wait_and_throw(); + delete *run_finished_; + run_finished_.reset(); + } + if (stream == nullptr) { + aoti_torch_get_current_xpu_stream(this->device_idx_, (void**)&stream); + } +#else // !USE_CUDA && !USE_XPU + run_finished_ = false; +#endif + + auto* model = static_cast(this); + model->run_impl(input_handles, output_handles, stream, proxy_executor); + +#ifdef USE_CUDA + AOTI_RUNTIME_CUDA_CHECK(cudaEventRecord(*run_finished_, stream)); +#elif defined(USE_XPU) + run_finished_ = std::make_optional(new sycl::event( + static_cast(stream)->ext_oneapi_submit_barrier())); +#else // !USE_CUDA && !USE_XPU + run_finished_ = true; +#endif // USE_CUDA + } + + // Non-thread-aware variant of run(). Obviously unsafe to use in a threaded + // environment :) + void run_single_threaded( + AtenTensorHandle* + input_handles, // array of input AtenTensorHandle; handles + // are stolen; the array itself is borrowed + AtenTensorHandle* + output_handles, // array for writing output AtenTensorHandle; handles + // will be stolen by the caller; the array itself is + // borrowed + DeviceStreamType stream, + AOTIProxyExecutorHandle proxy_executor) { + // don't bother with any of the run_finished stuff; this is unsafe to call + // in a threaded context + auto* model = static_cast(this); + model->run_impl(input_handles, output_handles, stream, proxy_executor); + } + + std::unordered_map run_const_fold( + DeviceStreamType stream, + AOTIProxyExecutorHandle proxy_executor, + bool initialization = false) { +#ifdef USE_CUDA + if (!run_finished_) { + cudaEvent_t run_finished = nullptr; + AOTI_RUNTIME_CUDA_CHECK(cudaEventCreate(&run_finished)); + run_finished_.emplace(run_finished); + } +#elif defined(USE_XPU) + if (run_finished_) { + (*run_finished_)->wait_and_throw(); + delete *run_finished_; + run_finished_.reset(); + } +#else // !USE_CUDA && !USE_XPU + run_finished_ = false; +#endif + + auto* model = static_cast(this); + auto folded_constants = + model->const_run_impl(stream, proxy_executor, initialization); + +#ifdef USE_CUDA + AOTI_RUNTIME_CUDA_CHECK(cudaEventRecord(*run_finished_, stream)); +#elif defined(USE_XPU) + // sycl::queue* queue_ptr = nullptr; + // aoti_torch_get_current_sycl_queue((void**)&queue_ptr); + run_finished_ = std::make_optional(new sycl::event( + static_cast(stream)->ext_oneapi_submit_barrier())); + +#else // !USE_CUDA && !USE_XPU + run_finished_ = true; +#endif // USE_CUDA + + return folded_constants; + } + + void update_constants_from_blob(const uint8_t* weight_blob_ptr) { +#if defined(USE_MMAP_EXTERNAL) + user_managed_mmap = const_cast(weight_blob_ptr); + load_constants(true); +#endif + } + + void load_constants(bool force = false) { + size_t num_constants = this->num_constants(); + size_t num_folded_constants = this->num_folded_constants(); + constants_map_->reserve(num_constants); + + // A CUDA model can still have constants on CPU, + // so we need a separate secondary blob for them. + std::vector constants_internal_offset( + num_constants - num_folded_constants); + std::vector secondary_cpu_constants_internal_offset( + num_constants - num_folded_constants); + size_t blob_size = 0; + size_t secondary_cpu_blob_size = 0; + compute_constant_blob( + blob_size, + constants_internal_offset, + secondary_cpu_blob_size, + secondary_cpu_constants_internal_offset); + + if (!force && !include_weights) { + return; + } + + // Allocate main blob + if (blob_size > 0) { +#if defined(USE_CUDA) || defined(USE_XPU) || defined(USE_MPS) + constant_blob_ = RAII_gpuMalloc(blob_size); +#else + constant_blob_ = RAII_cpuMalloc(blob_size); +#endif + } + + // Allocate secondary blob on CPU + if (secondary_cpu_blob_size > 0) { + secondary_cpu_constant_blob_ = RAII_cpuMalloc(secondary_cpu_blob_size); + } + + size_t bytes_read = 0; + size_t main_blob_idx = 0; + size_t secondary_cpu_blob_idx = 0; + + for (size_t i = 0; i < num_constants; i++) { + bool from_folded = this->constant_from_folded(i); + if (from_folded) { + continue; + } + std::string name = this->constant_name(i); + size_t data_size = this->constant_data_size(i); + int32_t const_device_type = this->constant_device_type(i); + bool device_type_matches = const_device_type == device_type_; + + // Mixed-device constants are only supported when the secondary device is + // CPU. If a constant was compiled for a non-CPU device but we're loading + // on a different device, we cannot safely create the tensor. + AOTI_RUNTIME_CHECK( + device_type_matches || + const_device_type == aoti_torch_device_type_cpu(), + "Mixed-device constants are only supported when the secondary " + "device is CPU. Constant '" + + name + + "' was compiled for a non-CPU device. " + "Hint: This can happen if you compiled on GPU but are loading " + "on CPU, which is not supported. In AOTI, you must compile and " + "load on the same device type."); + + uint8_t* internal_ptr = nullptr; + if (data_size != 0) { + if (device_type_matches) { + internal_ptr = constant_ptr( + constants_internal_offset[main_blob_idx], + bytes_read, + data_size, + /* skip_copy = */ false); + } else { + auto* secondary_cpu_constants_ptr = + static_cast(secondary_cpu_constant_blob_.get()); + internal_ptr = secondary_cpu_constants_ptr + + secondary_cpu_constants_internal_offset[secondary_cpu_blob_idx]; + memcpy(internal_ptr, _get_constants_start() + bytes_read, data_size); + } + } + + // Always increment blob indices to stay in sync with + // compute_constant_blob(), even for zero-size constants. + if (device_type_matches) { + main_blob_idx++; + } else { + secondary_cpu_blob_idx++; + } + + bytes_read += data_size; + + // Create at::Tensor from copied memory. + auto dtype = this->constant_dtype(i); + auto ndim = this->constant_ndim(i); + auto size = this->constant_shape(i); + auto stride = this->constant_stride(i); +#ifdef USE_MPS + auto offset = this->constant_offset(i) + + (constants_internal_offset[i] / aoti_torch_dtype_element_size(dtype)); +#else + auto offset = this->constant_offset(i); +#endif + auto layout = this->constant_layout(i); + auto opaque_metadata_ptr = this->opaque_metadata(i); + auto opaque_metadata_size = this->opaque_metadata_size(i); + + AtenTensorHandle tensor_handle = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_create_tensor_from_blob_v2( + internal_ptr, + ndim, + size, + stride, + offset, + dtype, + const_device_type, + device_type_matches ? device_idx_ : 0, + &tensor_handle, + layout, + opaque_metadata_ptr, + opaque_metadata_size)); + constants_map_->emplace(std::move(name), tensor_handle); + } + if (constants_map_) { + this->update_constants_array_from_map(); + } + } + + RAIIDataPtr&& release_constant_blob() { + return std::move(constant_blob_); + } + + std::shared_ptr> get_constants_array() { + return constants_; + } + + int32_t get_device_type() const { + return device_type_; + } + + int32_t get_device_idx() const { + return device_idx_; + } + + uint8_t* constant_ptr( + size_t constant_offset, + size_t bytes_read, + size_t data_size, + bool skip_copy) { + auto* constants_ptr = static_cast(constant_blob_.get()); + uint8_t* internal_ptr = constants_ptr + constant_offset; + // TODO: Handle shared storage case. + if (!skip_copy) { +#ifdef USE_XPU + sycl::queue* queue_ptr = nullptr; + aoti_torch_get_current_sycl_queue((void**)&queue_ptr); + queue_ptr + ->memcpy(internal_ptr, _get_constants_start() + bytes_read, data_size) + .wait(); +#elif USE_CUDA + AOTI_RUNTIME_CUDA_CHECK(cudaMemcpy( + internal_ptr, + _get_constants_start() + bytes_read, + data_size, + cudaMemcpyHostToDevice)); +#elif USE_MPS + aoti_torch_mps_memcpy( + constants_ptr, + constant_offset, + bytes_read, + data_size, + _get_constants_start()); + return constants_ptr; +#else + memcpy(internal_ptr, _get_constants_start() + bytes_read, data_size); +#endif + } + return internal_ptr; + } + + void compute_constant_blob( + size_t& blob_size, + std::vector& constants_internal_offset, + size_t& secondary_cpu_blob_size, + std::vector& secondary_cpu_constants_internal_offset) { + size_t num_constants = this->num_constants(); + blob_size = 0; + secondary_cpu_blob_size = 0; + size_t main_idx = 0; + size_t secondary_idx = 0; + + for (size_t i = 0; i < num_constants; i++) { + if (this->constant_from_folded(i)) { + continue; + } + + size_t data_size = this->constant_data_size(i); + // ok to use same AOTI_CONST_ALIGNMENT for both main and secondary blobs + if (data_size % AOTI_CONST_ALIGNMENT) { + data_size = AOTI_CONST_ALIGNMENT + + (data_size / AOTI_CONST_ALIGNMENT) * AOTI_CONST_ALIGNMENT; + } + + if (this->constant_device_type(i) == device_type_) { + constants_internal_offset[main_idx++] = blob_size; + blob_size += data_size; + } else { + secondary_cpu_constants_internal_offset[secondary_idx++] = + secondary_cpu_blob_size; + secondary_cpu_blob_size += data_size; + } + } + } + + size_t num_inputs() const { + return inputs_info_.size(); + } + + size_t num_outputs() const { + return outputs_info_.size(); + } + + size_t num_constants() const { + return constants_info_.size(); + } + + size_t num_folded_constants() const { + size_t total_consts = this->num_constants(); + size_t folded_consts = 0; + for (size_t i = 0; i < total_consts; i++) { + if (this->constant_from_folded(i)) { + folded_consts++; + } + } + return folded_consts; + } + + const char* input_name(int64_t idx) const { + return inputs_info_.at(idx).name; + } + + const char* output_name(int64_t idx) const { + return outputs_info_.at(idx).name; + } + + const char* constant_name(int64_t idx) const { + return constants_info_.at(idx).name; + } + + size_t constant_ndim(int64_t idx) { + return constants_info_.at(idx).shape.size(); + } + + const int64_t* constant_shape(int64_t idx) const { + return constants_info_.at(idx).shape.data(); + } + + const int64_t* constant_stride(int64_t idx) const { + return constants_info_.at(idx).stride.data(); + } + + int32_t constant_dtype(int64_t idx) const { + return constants_info_.at(idx).dtype; + } + + int32_t constant_layout(int64_t idx) const { + return constants_info_.at(idx).layout; + } + + size_t constant_offset(int64_t idx) const { + return constants_info_.at(idx).offset; + } + + size_t constant_data_size(int64_t idx) const { + return constants_info_.at(idx).data_size; + } + + const char* constant_original_fqn(int64_t idx) const { + return constants_info_.at(idx).original_fqn; + } + + const uint8_t* opaque_metadata(int64_t idx) const { + return constants_info_.at(idx).opaque_metadata.data(); + } + + size_t opaque_metadata_size(int64_t idx) { + return constants_info_.at(idx).opaque_metadata.size(); + } + + bool constant_from_folded(int64_t idx) const { + return constants_info_.at(idx).from_folded; + } + + int32_t constant_type(int64_t idx) const { + return constants_info_.at(idx).type; + } + + int32_t constant_device_type(int64_t idx) const { + return constants_info_.at(idx).device_type; + } + + const char* get_in_spec() const { + return in_spec_.c_str(); + } + + const char* get_out_spec() const { + return out_spec_.c_str(); + } + + uint64_t constant_blob_size() const { +#if defined(USE_MMAP_SELF) || defined(USE_MMAP_EXTERNAL) + const uint64_t weights_size = + reinterpret_cast(_binary_constants_bin_start)[0]; + return weights_size; +#else + throw std::runtime_error{ + "constant blob size is only available for mmap'd weights"}; +#endif + } + + void update_constants_array_from_map() { + if (!constants_map_) { + throw std::runtime_error{ + "constants_map_ was not ready when constants_ is trying to be constructed from it!"}; + } + if (!constants_) { + constants_ = + std::make_shared>(constants_info_.size()); + } else { + constants_->resize(constants_info_.size()); + } + int idx = 0; + for (const auto& info : constants_info_) { + const auto it = constants_map_->find(info.name); + if (it != constants_map_->end()) { + constants_->at(idx) = ConstantHandle(it->second); + } + idx++; + } + } + + void update_constants_map( + std::shared_ptr constants_map, + bool remap_constants_array = true) { + constants_map_ = std::move(constants_map); + if (remap_constants_array) { + update_constants_array_from_map(); + } + } + + // This function allows us to update the constants_ that is used to look up + // the corresponding constant tensor during runtime. + void update_constants_array( + std::shared_ptr> constants_array) { + constants_ = std::move(constants_array); + } + + /// Returns true if the model is complete. + bool is_finished() { +#ifdef USE_CUDA + if (!run_finished_) { + throw std::runtime_error{"Model CUDA event was not initialized"}; + } + + auto event_status = cudaEventQuery(*run_finished_); + if (event_status == cudaSuccess) { + return true; + } else if (event_status == cudaErrorNotReady) { + return false; + } + + throw std::runtime_error( + std::string("The model did not finish successfully. Error: ") + + cudaGetErrorString(cudaGetLastError())); +#elif defined(USE_XPU) + if (!run_finished_) { + throw std::runtime_error{"Model XPU event was not initialized"}; + } + using namespace sycl::info; + return (*run_finished_)->get_info() == + event_command_status::complete; + +#else // !USE_CUDA && !USE_XPU + return run_finished_; +#endif // USE_CUDA + } + + /// Synchronizes completion event. + void wait_for_completion() { +#ifdef USE_CUDA + if (!run_finished_) { + throw std::runtime_error{"Model event was not initialized"}; + } + + AOTI_RUNTIME_CUDA_CHECK(cudaEventSynchronize(*run_finished_)); +#endif // USE_CUDA +#ifdef USE_XPU + if (!run_finished_) { + throw std::runtime_error{"Model event was not initialized"}; + } + (*run_finished_)->wait_and_throw(); +#endif + } + + protected: + uint8_t* _get_constants_start() { +#if defined(USE_MMAP_EXTERNAL) + if (!user_managed_mmap) { + throw std::runtime_error{ + "Constants are not mmap'd. Use AOTInductorModelUpdateConstantsBlob to initialize the constants first."}; + } + // Mapped memory for weights + return user_managed_mmap; +#endif + +#ifndef USE_MMAP_SELF + // NOLINTNEXTLINE(*const-cast*) + return const_cast(_binary_constants_bin_start); +#else + if (self_mmap) { + return self_mmap; + } + Dl_info dl_info; + // get pointer to constant which are appended to the binary + AOTI_RUNTIME_CHECK( + dladdr(__func__, &dl_info), "Can't find shared library name"); + int fd = open(dl_info.dli_fname, O_RDONLY); + AOTI_RUNTIME_CHECK(fd >= 0, "Shared library file cannot be opened"); + auto fsize = lseek(fd, 0, SEEK_END); + auto weights_size = + reinterpret_cast(_binary_constants_bin_start)[0]; + auto magic_number = + reinterpret_cast(_binary_constants_bin_start)[1]; + auto weights_offset = fsize - weights_size; + AOTI_RUNTIME_CHECK( + (weights_offset & 0x3fff) == 0, + "weights_offset must be aligned to 16K boundary"); + auto ptr = mmap( + NULL, + weights_size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE, + fd, + weights_offset); + close(fd); + AOTI_RUNTIME_CHECK(ptr != MAP_FAILED, "mmap() failed"); + self_mmap = static_cast(ptr); + AOTI_RUNTIME_CHECK( + reinterpret_cast( + self_mmap + weights_size - sizeof(uint64_t))[0] == magic_number, + "Weights data seems corrupt"); + return self_mmap; +#endif + } + + struct ParamInfo { + const char* name = nullptr; + }; + + struct ConstInfo { + const char* name = nullptr; + std::vector shape; + std::vector stride; + int32_t dtype{}; + int32_t device_type{}; + int64_t offset{}; + size_t data_size{}; + int32_t layout{}; + std::vector opaque_metadata; + int64_t opaque_metadata_size{}; + const char* original_fqn = nullptr; + bool from_folded{}; + int32_t type{}; + }; + + std::vector inputs_info_; + std::vector outputs_info_; + std::vector constants_info_; + std::string in_spec_; + std::string out_spec_; + + std::shared_ptr constants_map_; + std::shared_ptr> constants_; + + // Holds the blob storage for constants' at::Tensor. + RAIIDataPtr constant_blob_; + // For mixed-device models, secondary_cpu_constant_blob_ holds CPU constants + RAIIDataPtr secondary_cpu_constant_blob_; + +#if defined(USE_MMAP_SELF) + // Mapped memory for weights + uint8_t* self_mmap = NULL; +#endif + +#if defined(USE_MMAP_EXTERNAL) + // Mapped memory for weights + uint8_t* user_managed_mmap = NULL; +#endif + + // A directory with CUDA binary files, e.g. compiled kernels, etc. + const std::optional cubin_dir_; + + // This is the flag that implies whether the weight is included in the model. + // If True, we would prepare the weight when loading the model, otherwise the + // model will be loaded without weights, and need to be provided by the user. + bool include_weights; + + // Record if the model finishes an inference run so that its owning + // AOTModelContainer can reuse this instance. +#ifdef USE_CUDA + std::optional run_finished_; +#elif defined(USE_XPU) + std::optional run_finished_; +#else // !USE_CUDA + bool run_finished_{}; +#endif + + // Generated model uses this device index to create CUDA guards. + int32_t device_type_{}; + int32_t device_idx_{}; +}; + +// Codegen-ed classes can derive from this to keep pointers to loaded kernels. +class AOTInductorModelKernelsBase { + public: + virtual ~AOTInductorModelKernelsBase() = default; +}; + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/model_container.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/model_container.h new file mode 100644 index 0000000000000000000000000000000000000000..742bc392fb313214e4689b096ce636f6f863df9d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/model_container.h @@ -0,0 +1,832 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +// WARNING: Be careful when adding new includes here. This header will be used +// in model.so, and should not refer to any aten/c10 headers except the stable +// C ABI defined in torch/csrc/inductor/aoti_torch/c/shim.h. The same rule +// applies to other files under torch/csrc/inductor/aoti_runtime/. +#include + +namespace torch::aot_inductor { +// The state transition is done by: +// (1) NONE state: The default state when created. This state should only exist +// when model_container is created and no constants are being loaded or updated. +// (2) INITIALIZED state: This state get set whenever we load the constants into +// the buffer. This could be done by load_constants or update_constants_buffer. +// (3) FOLDED state: This state should transition from INITIALIZED after +// const_fold is being invoked. +enum class ConstantState : uint8_t { NONE, INITIALIZED, FOLDED, UNKNOWN }; + +inline std::string toStringConstantState(ConstantState state) { + switch (state) { + case ConstantState::NONE: + return "ConstantState::NONE"; + case ConstantState::INITIALIZED: + return "ConstantState::INITIALIZED"; + case ConstantState::FOLDED: + return "ConstantState::FOLDED"; + case ConstantState::UNKNOWN: + return "ConstantState::UNKNOWN"; + default: + return "Unknown enum class state for ConstantState"; + } +} + +class AOTInductorModelContainer { + public: + AOTInductorModelContainer( + size_t num_models, + const std::string& device_str, + const std::optional& cubin_dir = std::nullopt) { + constants_map_ = std::make_shared(); + constants_array_ = std::make_shared>(); + + models_.reserve(num_models); + available_models_.reserve(num_models); + for (size_t i = 0; i < num_models; ++i) { + models_.push_back(AOTInductorModel::Create( + constants_map_, constants_array_, device_str, cubin_dir)); + available_models_.push_back(models_.back().get()); + } + + // Note that the all following fields (input_names_, output_names, + // etc) can be filled in by the AOT + // codegen. However, we choose to query such information from + // the owned AOTInductorModel for a couple of reasons: + // * simplify the codegen templates + // * reduce information fragmentation and duplication + // * the initialization process below is done only once when the container + // is constructed, so it would have little performance impact + auto* model = available_models_[0]; + size_t num_inputs = model->num_inputs(); + input_names_.reserve(num_inputs); + for (size_t i = 0; i < num_inputs; i++) { + input_names_.emplace_back(model->input_name(static_cast(i))); + } + + size_t num_outputs = model->num_outputs(); + output_names_.reserve(num_outputs); + for (size_t i = 0; i < num_outputs; i++) { + output_names_.emplace_back(model->output_name(static_cast(i))); + } + model->load_constants(); + constant_blob_ = model->release_constant_blob(); + constants_internal_offset_.resize( + model->num_constants() - model->num_folded_constants()); + secondary_cpu_constants_internal_offset_.resize( + model->num_constants() - model->num_folded_constants()); + model->compute_constant_blob( + blob_size_, + constants_internal_offset_, + secondary_cpu_blob_size_, + secondary_cpu_constants_internal_offset_); + constant_folded_ = ConstantState::INITIALIZED; + + for (auto& model : models_) { + model->update_constants_map(constants_map_); + } + + in_spec_ = model->get_in_spec(); + out_spec_ = model->get_out_spec(); + } + + void run( + AtenTensorHandle* + input_handles, // array of input AtenTensorHandle; handles + // are stolen; the array itself is borrowed + AtenTensorHandle* + output_handles, // array for writing output AtenTensorHandle; handles + // will be stolen by the caller; the array itself is + // borrowed + DeviceStreamType stream, + AOTIProxyExecutorHandle proxy_executor) { + std::shared_lock model_lk(model_exec_mutex_); + auto* model = get_available_model(); + + ConstantState& const_folded = + use_secondary_ ? constant_folded_secondary_ : constant_folded_; + if (const_folded == ConstantState::INITIALIZED) { + // At this point, constant is not ready yet. We need to call constant + // folding before we execute the model. We obtain a unique lock at this + // point to make sure constant is ready for all. + model_lk.unlock(); + std::unique_lock constants_folding_lk(model_exec_mutex_); + // Double locking to make sure constant folding is only ran once. + if (const_folded == ConstantState::INITIALIZED) { + auto folded_const_map = model->run_const_fold( + stream, proxy_executor, /* initialization = */ true); + update_constant_buffer( + std::move(folded_const_map), + /* use_inactive = */ false, + /* validate_full_update = */ false); + const_folded = ConstantState::FOLDED; + } + constants_folding_lk.unlock(); + model_lk.lock(); + } else if (const_folded != ConstantState::FOLDED) { + throw std::runtime_error( + "Unknown constant state: " + toStringConstantState(constant_folded_)); + } + + try { + model->run(input_handles, output_handles, stream, proxy_executor); + } catch (...) { + std::lock_guard lk(models_mutex_); + available_models_.push_back(model); + throw; + } + + { + std::lock_guard lk(models_mutex_); + pending_models_.push_back(model); + } + pending_models_available_.notify_one(); + } + + // Non-thread-aware variant of run(). Obviously unsafe to use in a threaded + // environment :) + void run_single_threaded( + AtenTensorHandle* + input_handles, // array of input AtenTensorHandle; handles + // are stolen; the array itself is borrowed + AtenTensorHandle* + output_handles, // array for writing output AtenTensorHandle; handles + // will be stolen by the caller; the array itself is + // borrowed + DeviceStreamType stream, + AOTIProxyExecutorHandle proxy_executor) { + auto* model = available_models_[0]; + + ConstantState& const_folded = + use_secondary_ ? constant_folded_secondary_ : constant_folded_; + if (const_folded == ConstantState::INITIALIZED) { + auto folded_const_map = model->run_const_fold( + stream, proxy_executor, /* initialization = */ true); + update_constant_buffer( + std::move(folded_const_map), + /* use_inactive = */ false, + /* validate_full_update = */ false); + const_folded = ConstantState::FOLDED; + } else if (const_folded != ConstantState::FOLDED) { + throw std::runtime_error( + "Unknown constant state: " + toStringConstantState(const_folded)); + } + + model->run_single_threaded( + input_handles, output_handles, stream, proxy_executor); + } + + const std::unordered_map extract_constants_map( + bool use_inactive) const { + size_t n_consts = this->num_constants(); + std::unordered_map ret; + ret.reserve(n_consts); + + std::shared_ptr extract_map = constants_map_; + // Essentially a XOR + if (use_inactive != use_secondary_) { + extract_map = constants_map_secondary_; + } + for (size_t idx = 0; idx < n_consts; idx++) { + if (this->constant_from_folded(idx)) { + continue; + } + + auto it = extract_map->find(this->constant_name(idx)); + if (it != extract_map->end()) { + ret.emplace(this->constant_original_fqn(idx), it->second); + continue; + } + } + + return ret; + } + + size_t num_constants() const { + if (this->num_models() == 0) { + throw std::runtime_error("No available models in container!"); + } + return models_[0]->num_constants(); + } + + // retrieve the constant name of constants_info_[idx] + const char* constant_name(size_t idx) const { + if (this->num_models() == 0) { + throw std::runtime_error("No available models in container!"); + } + return models_[0]->constant_name(static_cast(idx)); + } + + // retrieve original FQN of constants_info_[idx] + const char* constant_original_fqn(size_t idx) const { + if (this->num_models() == 0) { + throw std::runtime_error("No available models in container!"); + } + return models_[0]->constant_original_fqn(static_cast(idx)); + } + + // retrieve whether constant is from folded of constants_info_[idx] + bool constant_from_folded(size_t idx) const { + if (this->num_models() == 0) { + throw std::runtime_error("No available models in container!"); + } + return models_[0]->constant_from_folded(static_cast(idx)); + } + + size_t constant_data_size(size_t idx) const { + if (this->num_models() == 0) { + throw std::runtime_error("No available models in container!"); + } + return models_[0]->constant_data_size(static_cast(idx)); + } + + // retrieve type of constants_info_[idx] + int32_t constant_type(size_t idx) const { + if (this->num_models() == 0) { + throw std::runtime_error("No available models in container!"); + } + return models_[0]->constant_type(static_cast(idx)); + } + + // retrieve dtype of constants_info_[idx] + int32_t constant_dtype(size_t idx) const { + if (this->num_models() == 0) { + throw std::runtime_error("No available models in container!"); + } + return models_[0]->constant_dtype(static_cast(idx)); + } + + uint64_t constant_blob_size() const { + if (this->num_models() == 0) { + throw std::runtime_error("No available models in container!"); + } + return models_[0]->constant_blob_size(); + } + + void update_constants_from_blob(const uint8_t* weight_blob_ptr) { + if (this->num_models() == 0) { + throw std::runtime_error("No available models in container!"); + } + return models_[0]->update_constants_from_blob(weight_blob_ptr); + } + + void run_const_fold( + bool inactive_buffer, + DeviceStreamType stream, + AOTIProxyExecutorHandle proxy_executor) { + AOTInductorModel* model; + ConstantState& const_folded = inactive_buffer == use_secondary_ + ? constant_folded_ + : constant_folded_secondary_; + if (!inactive_buffer) { + // We would need to acquire a unique lock if we want to run constant + // folding on the active buffer. + std::unique_lock constants_folding_lk(model_exec_mutex_); + model = get_available_model(); + try { + auto folded_const_map = model->run_const_fold(stream, proxy_executor); + update_constant_buffer( + std::move(folded_const_map), + /* use_inactive = */ false, + /* validate_full_update = */ false); + const_folded = ConstantState::FOLDED; + } catch (...) { + std::lock_guard lk(models_mutex_); + available_models_.push_back(model); + throw; + } + } else { + std::shared_lock model_lk(model_exec_mutex_); + model = get_available_model(); + + // We swap the constant mapping to the inactive buffer in the model to run + // const run. + auto constants_map = get_constants_map(/* get_inactive= */ true); + auto constants_array = get_constants_array(/* get_inactive= */ true); + + try { + model->update_constants_map( + constants_map, /* remap_constants_array= */ false); + model->update_constants_array(constants_array); + + auto folded_const_map = model->run_const_fold(stream, proxy_executor); + update_constant_buffer( + std::move(folded_const_map), + /* use_inactive = */ true, + /* validate_full_update = */ false); + + // Swap back the model's constants mapping + constants_map = get_constants_map(/* get_inactive= */ false); + constants_array = get_constants_array(/* get_inactive= */ false); + model->update_constants_map( + constants_map, /* remap_constants_array= */ false); + model->update_constants_array(constants_array); + const_folded = ConstantState::FOLDED; + } catch (...) { + std::lock_guard lk(models_mutex_); + available_models_.push_back(model); + throw; + } + } + + { + std::lock_guard lk(models_mutex_); + pending_models_.push_back(model); + } + pending_models_available_.notify_one(); + } + + bool _is_tensor_constant_type(const size_t idx) const { + auto constant_type = models_[0]->constant_type(static_cast(idx)); + // We should skip constants + return constant_type == ConstantType::TensorConstant; + } + + bool _is_buffer_type(const size_t idx) const { + auto constant_type = models_[0]->constant_type(static_cast(idx)); + // Buffer can be optionally skipped, so if it not provided by upstream + // services, it is OK to relax the check. + return constant_type == ConstantType::Buffer; + } + + bool _is_empty_parameter_type(const size_t idx) const { + auto constant_type = models_[0]->constant_type(static_cast(idx)); + auto constant_data_size = + models_[0]->constant_data_size(static_cast(idx)); + // Empty parameters are skipped and not provided by the upstream services, + // it is OK to skip. + return constant_type == ConstantType::Parameter && constant_data_size == 0; + } + + bool _is_tensor_constant_or_buffer_type_or_empty_parameter( + const size_t idx) const { + return _is_tensor_constant_type(idx) || _is_buffer_type(idx) || + _is_empty_parameter_type(idx); + } + + void assert_all_constants( + const std::unordered_map& constants_map) { + auto num_constants = models_[0]->num_constants(); + for (size_t idx = 0; idx < num_constants; idx++) { + if (models_[0]->constant_from_folded(static_cast(idx))) { + continue; + } + + auto constant_name = + std::string(models_[0]->constant_name(static_cast(idx))); + auto it = constants_map.find(constant_name); + if (it == constants_map.end()) { + if (_is_tensor_constant_or_buffer_type_or_empty_parameter(idx)) { + // tracing sometimes creates tensors that are non-existent in + // original graph. We could skip those and do a direct copy. + std::cerr << "[WARNING] Found constant or module state buffer or " + << "empty module state parameter " << constant_name + << " in model, but not provided by user!\n"; + continue; + } + throw std::runtime_error( + std::string("Cannot find constants ") + constant_name + + std::string(" in constants_map!")); + } + } + } + + // We directly take ownership from AtenTensorHandle if constants are moved. + void update_constant_buffer( + std::unordered_map&& constants_map, + bool use_inactive, + bool validate_full_update) { + if (this->num_models() == 0) { + throw std::runtime_error("No model available in container!"); + } + if (validate_full_update) { + assert_all_constants(constants_map); + } + + ConstantState& const_folded = use_inactive == use_secondary_ + ? constant_folded_ + : constant_folded_secondary_; + const_folded = ConstantState::INITIALIZED; + + auto original_constants_map = get_constants_map(!use_inactive); + auto constants_map_to_update = get_constants_map(use_inactive); + + auto num_constants = models_[0]->num_constants(); + for (size_t idx = 0; idx < num_constants; idx++) { + auto constant_name = + std::string(models_[0]->constant_name(static_cast(idx))); + auto it = constants_map.find(constant_name); + if (it == constants_map.end() && + !(use_inactive && _is_tensor_constant_type(idx))) { + continue; + } + + AtenTensorHandle tensor; + if (it == constants_map.end()) { + aoti_torch_clone( + original_constants_map->find(constant_name)->second.get(), &tensor); + } else { + tensor = it->second; + } + + constants_map_to_update->insert_or_assign( + constant_name, RAIIAtenTensorHandle(tensor)); + } + // Update the inactive constant array. + update_array_from_map( + get_constants_array(use_inactive), constants_map_to_update); + } + + // This function updates the buffer for storing constants. + // It will update the buffer, the mapping and the array mapping. + void update_constant_buffer( + const std::unordered_map& constants_map, + bool use_inactive, + bool validate_full_update, + bool user_managed = false) { + if (this->num_models() == 0) { + throw std::runtime_error("No model available in container!"); + } + if (validate_full_update) { + assert_all_constants(constants_map); + } + + // update_constant_buffer does not support mixed CPU/CUDA constants + int32_t model_device_type = models_[0]->get_device_type(); + for (const auto& kv : constants_map) { + int32_t tensor_device_type = 0; + aoti_torch_get_device_type(kv.second, &tensor_device_type); + if (tensor_device_type != model_device_type) { + throw std::runtime_error( + "update_constant_buffer does not support mixed device constants. " + "Constant '" + + kv.first + "' has device type " + + std::to_string(tensor_device_type) + + " but model expects device type " + + std::to_string(model_device_type)); + } + } + + ConstantState& const_folded = use_inactive == use_secondary_ + ? constant_folded_ + : constant_folded_secondary_; + const_folded = ConstantState::INITIALIZED; + + auto original_constants_map = get_constants_map(!use_inactive); + auto constants_map_to_update = get_constants_map(use_inactive); + + auto num_constants = models_[0]->num_constants(); + for (size_t idx = 0; idx < num_constants; idx++) { + auto constant_name = + std::string(models_[0]->constant_name(static_cast(idx))); + auto it = constants_map.find(constant_name); + if (it == constants_map.end() && + !(use_inactive && + _is_tensor_constant_or_buffer_type_or_empty_parameter(idx))) { + continue; + } + + AtenTensorHandle tensor; + if (it == constants_map.end()) { + tensor = original_constants_map->find(constant_name)->second.get(); + } else { + tensor = it->second; + } + + if (user_managed) { + // If user managed, we pass in the pointer directly, and skip the + // copy. + constants_map_to_update->insert_or_assign( + constant_name, + MaybeOwningAtenTensorHandle(tensor, /* user_managed = */ true)); + continue; + } + + auto* constants_blob_ptr = + static_cast(get_constant_blob_ptr(use_inactive)); + + // Move the data to container handled blob. + uint8_t* internal_constants_ptr = + constants_blob_ptr + constants_internal_offset_[idx]; + void* user_constant_ptr; + int64_t constant_size; + int64_t* stride; + int64_t offset; + aoti_torch_get_data_ptr(tensor, &user_constant_ptr); + aoti_torch_get_storage_size(tensor, &constant_size); + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_strides(tensor, &stride)); + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_get_storage_offset(tensor, &offset)); + auto dtype = models_[0]->constant_dtype(idx); + +#ifdef USE_XPU + sycl::queue* queue_ptr = nullptr; + aoti_torch_get_current_sycl_queue((void**)&queue_ptr); + queue_ptr + ->memcpy(internal_constants_ptr, user_constant_ptr, constant_size) + .wait(); +#elif USE_MPS + internal_constants_ptr = constants_blob_ptr; + aoti_torch_mps_copy_buffer( + user_constant_ptr, + constants_blob_ptr, + constant_size, + offset, + constants_internal_offset_[idx]); + // For mps tensors, all constants are stored in one buffer, with the + // offset being where the constant starts. So we want to change the + // constant tensor's offset to point to constants_internal_offset_[idx] + offset = constants_internal_offset_[idx] / + aoti_torch_dtype_element_size(dtype); +#elif USE_CUDA + AOTI_RUNTIME_CUDA_CHECK(cudaMemcpy( + internal_constants_ptr, + user_constant_ptr, + constant_size, + cudaMemcpyDefault)); +#else + memcpy(internal_constants_ptr, user_constant_ptr, constant_size); +#endif + // Generate Tensor from container handled blob. + // We extract stride and offset from provided Tensor since we do not + // guarantee that the tensor is contiguous. + AtenTensorHandle tensor_handle; + int device_type = models_[0]->get_device_type(); + int device_idx = models_[0]->get_device_idx(); + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_create_tensor_from_blob( + internal_constants_ptr, + models_[0]->constant_ndim(idx), + models_[0]->constant_shape(idx), + stride, + offset, + dtype, + device_type, + device_idx, + &tensor_handle)); + + // Now place the tensor to constants_map. Note at this point the + // ownership of the tensor_handle will be taken over. + constants_map_to_update->insert_or_assign( + constant_name, RAIIAtenTensorHandle(tensor_handle)); + } + // Update the inactive constant array. + update_array_from_map( + get_constants_array(use_inactive), constants_map_to_update); + } + + void update_array_from_map( + const std::shared_ptr>& constants_array, + const std::shared_ptr& constants_map) { + auto num_constants = models_[0]->num_constants(); + for (size_t idx = 0; idx < num_constants; idx++) { + if (constants_map->find(models_[0]->constant_name( + static_cast(idx))) != constants_map->end()) { + constants_array->at(idx) = ConstantHandle( + constants_map + ->find(models_[0]->constant_name(static_cast(idx))) + ->second); + } + } + } + + void swap_constant_buffer() { + std::lock_guard unique_lk(model_exec_mutex_); + + auto constants_map = get_constants_map(/* get_inactive= */ true); + auto constants_array = get_constants_array(/* get_inactive= */ true); + + for (auto& model : models_) { + model->update_constants_map( + constants_map, /* remap_constants_array = */ false); + model->update_constants_array(constants_array); + } + + use_secondary_ = !use_secondary_; + } + + void free_inactive_constant_buffer() { + if (use_secondary_) { + constant_folded_ = ConstantState::NONE; + constant_blob_.reset(); + } else { + constant_folded_secondary_ = ConstantState::NONE; + constant_blob_secondary_.reset(); + } + // Free the internally held constants + int num_constants = static_cast(models_[0]->num_constants()); + std::shared_ptr to_free_map = + use_secondary_ ? constants_map_ : constants_map_secondary_; + + for (int i = 0; i < num_constants; i++) { + if (models_[0]->constant_from_folded(i)) { + auto it = to_free_map->find(models_[0]->constant_name(i)); + if (it != to_free_map->end()) { + it->second.reset(); + } + } + } + } + + size_t num_inputs() const { + return input_names_.size(); + } + + size_t num_outputs() const { + return output_names_.size(); + } + + const char* input_name(size_t idx) const { + return input_names_.at(idx).c_str(); + } + + const char* output_name(size_t idx) const { + return output_names_.at(idx).c_str(); + } + + size_t num_models() const { + return models_.size(); + } + + const char* get_in_spec() const { + return in_spec_; + } + + const char* get_out_spec() const { + return out_spec_; + } + + private: + std::vector input_names_; + std::vector output_names_; + const char* in_spec_; + const char* out_spec_; + + // Holds the blob storage for constants' at::Tensor within the container. + // This blob of memory will be managed by the container. + RAIIDataPtr constant_blob_; + RAIIDataPtr constant_blob_secondary_; + + size_t blob_size_; + std::vector constants_internal_offset_; + size_t secondary_cpu_blob_size_; + std::vector secondary_cpu_constants_internal_offset_; + + // Determine which constants is being used for the model. + // If true, + // constants_map_secondary/constant_blob_secondary/constants_array_secondary + // is being used. + bool use_secondary_{false}; + + // Determine whether we have ran constant folding + ConstantState constant_folded_{ConstantState::NONE}; + ConstantState constant_folded_secondary_{ConstantState::NONE}; + + // Holds the mapping of constants to at::Tensor. + // The underlying data of at::Tensor is in either constant_blob_ (for CUDA). + // or _binary_constants_bin_start (for CPU). + std::shared_ptr constants_map_; + std::shared_ptr constants_map_secondary_; + + // Holds the indexed array of constant for faster lookup during runtime. + std::shared_ptr> constants_array_; + std::shared_ptr> constants_array_secondary_; + + // Holds all the AOTInductorModel instances owned by this container. + std::vector> models_; + + // Holds the AOTInductorModel instances available for inference. + std::vector available_models_; + + // Holds the AOTInductorModel instances that have started running + // inference and can be placed onto available_models_ upon their + // completion. + std::deque pending_models_; + + // Protects available_models_ and pending_models_. + std::mutex models_mutex_; + + // Notified whenever a model is placed onto pending_models_. + std::condition_variable pending_models_available_; + + AOTInductorModel* get_available_model() { + std::unique_lock lk(models_mutex_); + if (available_models_.empty()) { + reclaim_finished_models(lk); + } + auto* result = available_models_.back(); + available_models_.pop_back(); + return result; + } + + // This mutex is used to protect execution of model. + // We acquire the mutex in shared mode if we allow concurrent execution. + // We acquire the mutex in unique mode when we want exclusive access of the + // model. One such case is when we want to do a weight swapping. We want to + // make sure no one is executing the model. + std::shared_mutex model_exec_mutex_; + + RAIIDataPtr allocate_constant_blob() { +#if defined(USE_CUDA) || defined(USE_XPU) || defined(USE_MPS) + return RAII_gpuMalloc(blob_size_); +#else + return RAII_cpuMalloc(blob_size_); +#endif // USE_CUDA + } + + void* get_constant_blob_ptr(bool get_inactive) { + if ((get_inactive && use_secondary_) || + (!get_inactive && !use_secondary_)) { + if (!constant_blob_) { + constant_blob_ = allocate_constant_blob(); + } + return constant_blob_.get(); + } else { + if (!constant_blob_secondary_) { + constant_blob_secondary_ = allocate_constant_blob(); + } + return constant_blob_secondary_.get(); + } + } + + std::shared_ptr get_constants_map(bool get_inactive) { + if ((get_inactive && use_secondary_) || + (!get_inactive && !use_secondary_)) { + return constants_map_; + } else { + if (!constants_map_secondary_) { + constants_map_secondary_ = std::make_shared(); + } + return constants_map_secondary_; + } + } + + std::shared_ptr> get_constants_array( + bool get_inactive) { + if ((get_inactive && use_secondary_) || + (!get_inactive && !use_secondary_)) { + return constants_array_; + } else { + if (!constants_array_secondary_) { + constants_array_secondary_ = + std::make_shared>( + models_[0]->num_constants()); + } + return constants_array_secondary_; + } + } + + void reclaim_finished_models(std::unique_lock& lk) { +#ifdef __aarch64__ + // push finished model instances to the end of pending_models_ + auto it = std::partition( + pending_models_.begin(), + pending_models_.end(), + [](AOTInductorModel* m) { return !m->is_finished(); }); +#else + // push finished model instances to the end of pending_models_ + auto it = std::stable_partition( + pending_models_.begin(), + pending_models_.end(), + [](AOTInductorModel* m) { return !m->is_finished(); }); +#endif + + if (it != pending_models_.end()) { + // We have finished model instances that can be pushed into + // available_models_ so that we don't have to be blocked on waiting + // the pending_models_available_ condition. + available_models_.insert( + available_models_.end(), it, pending_models_.end()); + pending_models_.erase(it, pending_models_.end()); + return; + } + + pending_models_available_.wait( + lk, [this]() { return !pending_models_.empty(); }); + // Let's make the schedule simple first. We always wait on the first + // pending_models_ to be complete. + auto* model = pending_models_.front(); + pending_models_.pop_front(); + lk.unlock(); + try { + model->wait_for_completion(); + } catch (...) { + lk.lock(); + available_models_.push_back(model); + throw; + } + lk.lock(); + available_models_.push_back(model); + } +}; + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/scalar_to_tensor.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/scalar_to_tensor.h new file mode 100644 index 0000000000000000000000000000000000000000..3ba22f3a286f0cb7725f2d013ed0bc4c447a7ffb --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/scalar_to_tensor.h @@ -0,0 +1,43 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::aot_inductor { + +template +inline RAIIAtenTensorHandle scalar_to_tensor_handle(T value) { + throw std::runtime_error("Unsupported scalar_to_tensor_handle"); +} + +// Specialize for supported C++ primitive types +#define AOTI_RUNTIME_SCALAR_TO_TENSOR(dtype, ctype) \ + template <> \ + inline RAIIAtenTensorHandle scalar_to_tensor_handle(ctype value) { \ + AtenTensorHandle tensor_handle; \ + AOTI_TORCH_ERROR_CODE_CHECK( \ + aoti_torch_scalar_to_tensor_##dtype(value, &tensor_handle)); \ + return RAIIAtenTensorHandle(tensor_handle); \ + } + +AOTI_RUNTIME_SCALAR_TO_TENSOR(float32, float) +AOTI_RUNTIME_SCALAR_TO_TENSOR(float64, double) +AOTI_RUNTIME_SCALAR_TO_TENSOR(uint8, uint8_t) +AOTI_RUNTIME_SCALAR_TO_TENSOR(uint16, uint16_t) +AOTI_RUNTIME_SCALAR_TO_TENSOR(uint32, uint32_t) +AOTI_RUNTIME_SCALAR_TO_TENSOR(uint64, uint64_t) +AOTI_RUNTIME_SCALAR_TO_TENSOR(int8, int8_t) +AOTI_RUNTIME_SCALAR_TO_TENSOR(int16, int16_t) +AOTI_RUNTIME_SCALAR_TO_TENSOR(int32, int32_t) +AOTI_RUNTIME_SCALAR_TO_TENSOR(int64, int64_t) +AOTI_RUNTIME_SCALAR_TO_TENSOR(bool, bool) +AOTI_RUNTIME_SCALAR_TO_TENSOR(complex64, c10::complex) +AOTI_RUNTIME_SCALAR_TO_TENSOR(complex128, c10::complex) +#undef AOTI_RUNTIME_SCALAR_TO_TENSOR + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/sycl_runtime_wrappers.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/sycl_runtime_wrappers.h new file mode 100644 index 0000000000000000000000000000000000000000..e9f9bdab9c5270e6fc9aababcd5587ad54bfee5c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/sycl_runtime_wrappers.h @@ -0,0 +1,183 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// NOLINT +#pragma once +#ifdef USE_XPU +#include +#include +#include +#include +#include +#include + +#define ZE_CHECK(status) \ + { \ + if (status != ZE_RESULT_SUCCESS) { \ + std::stringstream ss; \ + ss << "L0 runtime error: " << std::hex << std::uppercase << status; \ + throw std::runtime_error(ss.str()); \ + } \ + } + +static ze_module_handle_t _createModule( + const uint8_t* binaryPtr, + size_t binarySize, + bool isSpirv = false) { + sycl::device& syclDevice = + c10::xpu::get_raw_device(c10::xpu::current_device()); + auto& syclContext = c10::xpu::get_device_context(); + auto device = + sycl::get_native(syclDevice); + auto context = + sycl::get_native(syclContext); + + const char* buildFlags = ""; + const ze_module_format_t format = + isSpirv ? ZE_MODULE_FORMAT_IL_SPIRV : ZE_MODULE_FORMAT_NATIVE; + ze_module_desc_t moduleDescription = {}; + moduleDescription.stype = ZE_STRUCTURE_TYPE_MODULE_DESC; + moduleDescription.format = format; + moduleDescription.inputSize = binarySize; + moduleDescription.pInputModule = (uint8_t*)binaryPtr; + moduleDescription.pBuildFlags = buildFlags; + ze_module_build_log_handle_t buildLog = nullptr; + ze_module_handle_t module = nullptr; + auto error_no = ZE_RESULT_SUCCESS; + error_no = + zeModuleCreate(context, device, &moduleDescription, &module, &buildLog); + + if (error_no != ZE_RESULT_SUCCESS) { + size_t szLog = 0; + ZE_CHECK(zeModuleBuildLogGetString(buildLog, &szLog, nullptr)); + char* strLog = (char*)malloc(szLog); + ZE_CHECK(zeModuleBuildLogGetString(buildLog, &szLog, strLog)); + std::cerr << "L0 build module failed. Log: " << strLog << std::endl; + free(strLog); + } + if (buildLog) { + ZE_CHECK(zeModuleBuildLogDestroy(buildLog)); + } + ZE_CHECK(error_no); + return module; +} + +static std::unique_ptr _createKernel( + ze_module_handle_t module, + const char* kernelName) { + assert(module); + assert(kernelName); + ze_kernel_handle_t kernel = nullptr; + ze_kernel_desc_t kernelDescription = {}; + kernelDescription.stype = ZE_STRUCTURE_TYPE_KERNEL_DESC; + kernelDescription.pNext = nullptr; + kernelDescription.flags = ZE_KERNEL_FLAG_FORCE_RESIDENCY; + kernelDescription.pKernelName = kernelName; + ZE_CHECK(zeKernelCreate(module, &kernelDescription, &kernel)); + + auto& syclContext = c10::xpu::get_device_context(); + auto mod = sycl::make_kernel_bundle< + sycl::backend::ext_oneapi_level_zero, + sycl::bundle_state::executable>( + {module, sycl::ext::oneapi::level_zero::ownership::transfer}, + syclContext); + auto fun = sycl::make_kernel( + {mod, kernel, sycl::ext::oneapi::level_zero::ownership::transfer}, + syclContext); + return std::make_unique(fun); +} + +// GPU Cpp Wrapper API +[[maybe_unused]] static std::unique_ptr loadKernel( + std::string filePath, + const std::string& funcName, + uint32_t sharedMemBytes, + const std::optional& binDir = std::nullopt) { + if (binDir) { + std::filesystem::path p1{*binDir}; + std::filesystem::path p2{filePath}; + filePath = (p1 / p2.filename()).string(); + } + + std::ifstream IFS(filePath.c_str(), std::ios::binary); + std::ostringstream OSS; + OSS << IFS.rdbuf(); + std::string data(OSS.str()); + + bool isSpirv = filePath.size() >= 4 && + filePath.compare(filePath.size() - 4, 4, ".spv") == 0; + auto mod = _createModule( + reinterpret_cast(data.c_str()), data.size(), isSpirv); + + return _createKernel(mod, funcName.c_str()); +} + +// GPU Cpp Wrapper API +[[maybe_unused]] static std::unique_ptr loadKernel( + const void* start, + const void* end, + const std::string& funcName, + uint32_t sharedMemBytes, + bool isSpirv) { + size_t size = reinterpret_cast(end) - + reinterpret_cast(start); + + auto mod = + _createModule(reinterpret_cast(start), size, isSpirv); + + return _createKernel(mod, funcName.c_str()); +} + +// GPU Cpp Wrapper API +[[maybe_unused]] static void launchKernel( + std::unique_ptr& kernelPtr, + uint32_t gridX, + uint32_t gridY, + uint32_t gridZ, + uint32_t numWarps, + uint32_t sharedMemory, + void** params, + sycl::queue* queuePtr) { + uint32_t threadsPerWarp = kernelPtr->get_info< + sycl::info::kernel_device_specific::compile_sub_group_size>( + queuePtr->get_device()); + if (threadsPerWarp == 0) { + threadsPerWarp = 32; // default to 32 if not set + } + std::string kernelName = + kernelPtr->get_info(); + uint32_t numParams = kernelPtr->get_info(); + size_t globalRangeX = gridX * threadsPerWarp * numWarps; + size_t globalRangeY = gridY; + size_t globalRangeZ = gridZ; + size_t localRangeX = numWarps * threadsPerWarp; + size_t localRangeY = 1; + size_t localRangeZ = 1; + sycl::range<3> globalRange(globalRangeZ, globalRangeY, globalRangeX); + sycl::range<3> localRange(localRangeZ, localRangeY, localRangeX); + sycl::nd_range<3> parallelWorkSize(globalRange, localRange); + if (sharedMemory) { + // numParams from sycl info = user provided args + sharedMemoryBuffer + numParams -= 1; + } + // Submit the imported kernel. + auto cgf = [&](sycl::handler& cgh) { + for (uint32_t i = 0; i < numParams; ++i) { + cgh.set_arg(i, *(static_cast(params[i]))); + } + + if (sharedMemory > 0) { + constexpr int dimensions = 1; + using share_mem_t = sycl::local_accessor; + share_mem_t localBuffer = share_mem_t(sharedMemory, cgh); + cgh.set_arg(numParams, localBuffer); + cgh.parallel_for(parallelWorkSize, *kernelPtr); + } else { + cgh.parallel_for(parallelWorkSize, *kernelPtr); + } + }; + auto event = queuePtr->submit(cgf); +} +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/thread_local.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/thread_local.h new file mode 100644 index 0000000000000000000000000000000000000000..7aea78361dc5765eae78d748e3022cfbfa1ec63d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/thread_local.h @@ -0,0 +1,165 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::aot_inductor { + +template +struct ThreadLocalCachedOutputTensor; + +template <> +struct ThreadLocalCachedOutputTensor { + explicit ThreadLocalCachedOutputTensor(const RAIIAtenTensorHandle&) {} + void copy_data_from(const RAIIAtenTensorHandle& handle) { + throw std::runtime_error("can't happen"); + } + + AtenTensorHandle tensor() const { + throw std::runtime_error("can't happen"); + } +}; + +template <> +struct ThreadLocalCachedOutputTensor { + explicit ThreadLocalCachedOutputTensor(const AtenTensorHandle&) {} + void copy_data_from(const AtenTensorHandle& handle) { + throw std::runtime_error("can't happen"); + } + + AtenTensorHandle tensor() const { + throw std::runtime_error("can't happen"); + } +}; + +template <> +struct ThreadLocalCachedOutputTensor { + explicit ThreadLocalCachedOutputTensor(const ConstantHandle&) {} + void copy_data_from(const ConstantHandle& handle) { + throw std::runtime_error("can't happen"); + } + + AtenTensorHandle tensor() const { + throw std::runtime_error("can't happen"); + } +}; + +template +struct ThreadLocalCachedOutputTensor> { + explicit ThreadLocalCachedOutputTensor(const ArrayRefTensor& t) { + realloc(t); + } + + void copy_data_from(const ArrayRefTensor& t) { + if (t.numel() > capacity_) { + realloc(t); + } + std::copy(t.data(), t.data() + t.numel(), storage_.get()); + } + + AtenTensorHandle tensor() const { + return tensor_.get(); + } + + private: + void realloc(const ArrayRefTensor& t) { + capacity_ = t.numel(); + // NOLINTNEXTLINE(*arrays*) + storage_ = std::make_unique(t.numel()); + AtenTensorHandle handle = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_create_tensor_from_blob( + storage_.get(), + t.sizes().size(), + t.sizes().data(), + t.strides().data(), + 0, + aoti_torch_dtype>(), + t.device_type(), + t.device_idx(), + &handle)); + tensor_ = handle; + } + + // NOLINTNEXTLINE(*arrays*) + std::unique_ptr storage_; + int64_t capacity_ = 0; + RAIIAtenTensorHandle tensor_; +}; + +template +struct ThreadLocalCachedOutputArray; + +// Just needs to compile, doesn't need to do anything. +template <> +struct ThreadLocalCachedOutputArray { + explicit ThreadLocalCachedOutputArray(const RAIIAtenTensorHandle&) { + throw std::runtime_error("can't happen"); + } + + // Not supported yet! We would need to put contiguous() or + // expect_contiguous() into the ABI. + void copy_data_from(const RAIIAtenTensorHandle&) { + throw std::runtime_error("can't happen"); + } + + template + ArrayRefTensor arrayref_tensor() const { + throw std::runtime_error("can't happen"); + } +}; + +// Just needs to compile, doesn't need to do anything. +template <> +struct ThreadLocalCachedOutputArray { + explicit ThreadLocalCachedOutputArray(const ConstantHandle&) { + throw std::runtime_error("can't happen"); + } + + // Not supported yet! We would need to put contiguous() or + // expect_contiguous() into the ABI. + void copy_data_from(const ConstantHandle&) { + throw std::runtime_error("can't happen"); + } + + template + ArrayRefTensor arrayref_tensor() const { + throw std::runtime_error("can't happen"); + } +}; + +template +struct ThreadLocalCachedOutputArray> { + explicit ThreadLocalCachedOutputArray(const ArrayRefTensor& t) {} + + template < + typename U, + std::enable_if_t< + std::is_same_v, std::remove_const_t>, + bool> = true> + ArrayRefTensor arrayref_tensor() const { + return tensor_; + } + + void copy_data_from(const ArrayRefTensor& t) { + if (t.numel() > capacity_) { + capacity_ = t.numel(); + // NOLINTNEXTLINE(*arrays*) + storage_ = std::make_unique(capacity_); + } + std::copy(t.data(), t.data() + t.numel(), storage_.get()); + tensor_ = t; + tensor_.set_arrayref(MiniArrayRef(storage_.get(), t.numel())); + } + + private: + // NOLINTNEXTLINE(*arrays*) + std::unique_ptr storage_; + uint32_t capacity_ = 0; + ArrayRefTensor tensor_; +}; + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/utils.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/utils.h new file mode 100644 index 0000000000000000000000000000000000000000..1eb79da9f82d5bbb45f9e9452da1842cfacf7347 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/utils.h @@ -0,0 +1,484 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include + +// WARNING: Be careful when adding new includes here. This header will be used +// in model.so, and should not refer to any aten/c10 headers except the stable +// C ABI defined in torch/csrc/inductor/aoti_torch/c/shim.h. The same rule +// applies to other files under torch/csrc/inductor/aoti_runtime/. +#include +#include + +#if defined(__GNUC__) || defined(__clang__) +#define AOTI_NOINLINE __attribute__((noinline)) +#elif _MSC_VER +#define AOTI_NOINLINE __declspec(noinline) +#else +#define AOTI_NOINLINE +#endif + +#define AOTI_TORCH_ERROR_CODE_CHECK(call) \ + if ((call) != AOTI_TORCH_SUCCESS) { \ + torch::headeronly::detail::throw_exception(#call, __FILE__, __LINE__); \ + } + +using AOTIRuntimeError = int32_t; +#define AOTI_RUNTIME_SUCCESS 0 +#define AOTI_RUNTIME_FAILURE 1 + +#define AOTI_RUNTIME_ERROR_CODE_CHECK(call) \ + if ((call) != AOTI_RUNTIME_SUCCESS) { \ + torch::headeronly::detail::throw_exception(#call, __FILE__, __LINE__); \ + } + +namespace torch::aot_inductor { + +using DeleterFnPtr = void (*)(void*); + +inline void noop_deleter(void* /*unused*/) {} + +inline void delete_record_function_object(void* ptr) { + AOTI_TORCH_ERROR_CODE_CHECK(aoti_record_function_end( + reinterpret_cast(ptr))); +} + +inline void delete_tensor_object(void* ptr) { + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_delete_tensor_object(reinterpret_cast(ptr))); +} + +inline void delete_c10_value_object(void* ptr) { + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_delete_c10_value_object( + reinterpret_cast(ptr))); +} + +class RAIIAtenRecordFunctionHandle { + public: + RAIIAtenRecordFunctionHandle() : handle_(nullptr, noop_deleter) {} + RAIIAtenRecordFunctionHandle(const RAIIAtenRecordFunctionHandle& other) = + delete; + RAIIAtenRecordFunctionHandle& operator=( + const RAIIAtenRecordFunctionHandle& other) = delete; + + // Initiate an RAII RecordFunction without Inputs + RAIIAtenRecordFunctionHandle(const char* name, IValueMapHandle kwargs) + : handle_(nullptr, delete_record_function_object) { + AtenRecordFunctionHandle tmp_handle = nullptr; + aoti_record_function_start(name, kwargs, nullptr, 0, &tmp_handle); + handle_.reset(tmp_handle); + } + + // Initiate an RAII RecordFunction with Inputs + RAIIAtenRecordFunctionHandle( + const char* name, + IValueMapHandle kwargs, + std::vector inputs) + : handle_(nullptr, delete_record_function_object) { + AtenRecordFunctionHandle tmp_handle = nullptr; + aoti_record_function_start( + name, kwargs, inputs.data(), inputs.size(), &tmp_handle); + handle_.reset(tmp_handle); + } + + // Steal the ownership from another RAIIAtenRecordFunctionHandle using + // std::move + RAIIAtenRecordFunctionHandle(RAIIAtenRecordFunctionHandle&& other) = default; + RAIIAtenRecordFunctionHandle& operator=( + RAIIAtenRecordFunctionHandle&& other) = default; + + // Steal the ownership from raw AtenRecordFunctionHandle + RAIIAtenRecordFunctionHandle(AtenRecordFunctionHandle handle) + : handle_(handle, delete_record_function_object) {} + + ~RAIIAtenRecordFunctionHandle() { + handle_.reset(); + } + + // Return a raw AtenRecordFunctionHandle to be used by aoti_torch functions + // Note: this function does NOT transfer the ownership of the handle + operator AtenRecordFunctionHandle() const { + return handle_.get(); + } + + AtenRecordFunctionHandle release() { + return handle_.release(); + } + + AtenRecordFunctionHandle get() const { + return handle_.get(); + } + + void reset() { + handle_.reset(); + } + + private: + std::unique_ptr handle_; +}; + +// RAIIAtenTensorHandle steals the tensor objects created by the libtorch C ABI +class RAIIAtenTensorHandle { + public: + RAIIAtenTensorHandle() : handle_(nullptr, noop_deleter) {} + RAIIAtenTensorHandle(const RAIIAtenTensorHandle& other) = delete; + RAIIAtenTensorHandle& operator=(const RAIIAtenTensorHandle& other) = delete; + + // Steal the ownership from another RAIIAtenTensorHandle using std::move + RAIIAtenTensorHandle(RAIIAtenTensorHandle&& other) = default; + RAIIAtenTensorHandle& operator=(RAIIAtenTensorHandle&& other) = default; + + // Steal the ownership from raw AtenTensorHandle + RAIIAtenTensorHandle(AtenTensorHandle handle) + : handle_(handle, delete_tensor_object) {} + + ~RAIIAtenTensorHandle() { + handle_.reset(); + } + + // Return a raw AtenTensorHandle to be used by aoti_torch functions + // Note: this function does NOT transfer the ownership of the handle + operator AtenTensorHandle() const { + return handle_.get(); + } + + AtenTensorHandle release() { + return handle_.release(); + } + + AtenTensorHandle get() const { + return handle_.get(); + } + + void reset() { + handle_.reset(); + } + + int64_t size(int64_t d) { + int64_t size = 0; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_size(handle_.get(), d, &size)); + return size; + } + + int64_t stride(int64_t d) { + int64_t stride = 0; + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_get_stride(handle_.get(), d, &stride)); + return stride; + } + + int64_t storage_offset() { + int64_t storage_offset = 0; + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_get_storage_offset(handle_.get(), &storage_offset)); + return storage_offset; + } + + void* data_ptr() const { + void* result = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_get_data_ptr(handle_.get(), &result)); + return result; + } + + int64_t* sizes() const { + int64_t* result = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_sizes(handle_.get(), &result)); + return result; + } + + int64_t* strides() const { + int64_t* result = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_strides(handle_.get(), &result)); + return result; + } + + private: + std::unique_ptr handle_; +}; + +// RAIIC10IValueHandle steals the IValue objects created by the libtorch C ABI +class RAIIC10IValueHandle { + public: + RAIIC10IValueHandle() : handle_(nullptr, noop_deleter) {} + RAIIC10IValueHandle(const RAIIC10IValueHandle& other) = delete; + RAIIC10IValueHandle& operator=(const RAIIC10IValueHandle& other) = delete; + + // Steal the ownership from another RAIIC10IValueHandle using std::move + RAIIC10IValueHandle(RAIIC10IValueHandle&& other) = default; + RAIIC10IValueHandle& operator=(RAIIC10IValueHandle&& other) = default; + + // Steal the ownership from raw C10IValueHandle + RAIIC10IValueHandle(C10IValueHandle handle) + : handle_(handle, delete_c10_value_object) {} + + ~RAIIC10IValueHandle() { + handle_.reset(); + } + + // Return a raw C10IValueHandle to be used by aoti_torch functions + // Note: this function does NOT transfer the ownership of the handle + operator C10IValueHandle() const { + return handle_.get(); + } + + C10IValueHandle release() { + return handle_.release(); + } + + C10IValueHandle get() const { + return handle_.get(); + } + + void reset() { + handle_.reset(); + } + + private: + std::unique_ptr handle_; +}; + +class MaybeOwningAtenTensorHandle { + public: + MaybeOwningAtenTensorHandle() : handle_(nullptr) {} + // We skip copy constructor as MaybeOwningAtenTensorHandle might be RAII which + // makes it undefined. + MaybeOwningAtenTensorHandle(const MaybeOwningAtenTensorHandle& other) = + delete; + MaybeOwningAtenTensorHandle& operator=( + const MaybeOwningAtenTensorHandle& other) = delete; + + // Move constructor and move assignment operator + MaybeOwningAtenTensorHandle(MaybeOwningAtenTensorHandle&& other) = default; + MaybeOwningAtenTensorHandle& operator=(MaybeOwningAtenTensorHandle&& other) = + default; + + // Steal the ownership from another RAIIAtenTensorHandle using std::move + MaybeOwningAtenTensorHandle(RAIIAtenTensorHandle&& other) + : raii_handle_(std::move(other)) { + handle_ = raii_handle_.get(); + } + MaybeOwningAtenTensorHandle& operator=(RAIIAtenTensorHandle&& other) { + raii_handle_ = std::move(other); + handle_ = raii_handle_.get(); + return *this; + } + + // By default, steal the ownership from raw AtenTensorHandle + MaybeOwningAtenTensorHandle(AtenTensorHandle handle) : raii_handle_(handle) { + handle_ = raii_handle_.get(); + } + + // If user_managed is true, we do not steal the ownership. + MaybeOwningAtenTensorHandle(AtenTensorHandle handle, bool user_managed) { + if (user_managed) { + aoti_torch_new_tensor_handle(handle, &handle_); + } else { + raii_handle_ = RAIIAtenTensorHandle(handle); + handle_ = raii_handle_.get(); + } + } + + ~MaybeOwningAtenTensorHandle() { + // This is no-op if we don't hold raii_handle with the + // MaybeOwningAtenTensorHandle. + raii_handle_.reset(); + } + + // Return a raw AtenTensorHandle to be used by aoti_torch functions + // Note: this function does NOT transfer the ownership of the handle + operator AtenTensorHandle() const { + return handle_; + } + + AtenTensorHandle release() { + if (raii_handle_) { + return raii_handle_.release(); + } else { + AtenTensorHandle handle = handle_; + handle_ = nullptr; + return handle; + } + } + + AtenTensorHandle get() const { + return handle_; + } + + void reset() { + handle_ = nullptr; + raii_handle_.reset(); + } + + int64_t size(int64_t d) { + int64_t size = 0; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_size(handle_, d, &size)); + return size; + } + + int64_t stride(int64_t d) { + int64_t stride = 0; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_stride(handle_, d, &stride)); + return stride; + } + + int64_t storage_offset() { + int64_t storage_offset = 0; + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_get_storage_offset(handle_, &storage_offset)); + return storage_offset; + } + + void* data_ptr() const { + void* result = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_data_ptr(handle_, &result)); + return result; + } + + int64_t* sizes() const { + int64_t* result = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_sizes(handle_, &result)); + return result; + } + + int64_t* strides() const { + int64_t* result = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_strides(handle_, &result)); + return result; + } + + private: + // handle_ is the underlying AtenTensorHandle of raii_handle_ if raii_handle_ + // exists. Otherwise it would just be the AtenTensorHandle passed in by users. + AtenTensorHandle handle_; + RAIIAtenTensorHandle raii_handle_; +}; + +// Steal the ownership from raw AtenTensorHandle to RAIIAtenTensorHandle +inline std::vector steal_from_raw_handles_to_raii_handles( + AtenTensorHandle* handles, + size_t size) { + std::vector result; + result.reserve(size); + for (size_t i = 0; i < size; i++) { + result.emplace_back(handles[i]); + handles[i] = nullptr; + } + return result; +} + +inline AtenTensorHandle reinterpret_tensor_wrapper( + AtenTensorHandle self, + int64_t ndim, + const int64_t* sizes_ptr, + const int64_t* strides_ptr, + int64_t storage_offset) { + AtenTensorHandle result = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch__reinterpret_tensor( + self, ndim, sizes_ptr, strides_ptr, storage_offset, &result)); + return result; +} + +inline void* get_data_ptr_wrapper(AtenTensorHandle tensor) { + void* result = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_data_ptr(tensor, &result)); + return result; +} + +inline AtenTensorHandle unwrap_raii_handle_if_needed( + const RAIIAtenTensorHandle& handle) { + return handle.get(); +} + +inline RAIIAtenTensorHandle wrap_with_raii_handle_if_needed( + AtenTensorHandle handle) { + return RAIIAtenTensorHandle(handle); +} + +class ConstantHandle { + public: + ConstantHandle() = default; + + explicit ConstantHandle(AtenTensorHandle handle) : handle_(handle) { + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_data_ptr(handle_, &data_)); + } + + operator AtenTensorHandle() const { + return handle_; + } + + AtenTensorHandle tensor() const { + return handle_; + } + + AtenTensorHandle get() const { + return handle_; + } + + void* data_ptr() const { + return data_; + } + + int64_t* sizes() const { + int64_t* result = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_sizes(handle_, &result)); + return result; + } + + int64_t* strides() const { + int64_t* result = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_strides(handle_, &result)); + return result; + } + + private: + AtenTensorHandle handle_{}; + void* data_ = nullptr; +}; + +inline void* get_data_ptr_wrapper(const ConstantHandle& constant) { + return constant.data_ptr(); +} + +inline const ConstantHandle& unwrap_raii_handle_if_needed( + const ConstantHandle& handle) { + return handle; +} + +// Shouldn't be called. +inline AtenTensorHandle wrap_with_raii_handle_if_needed( + const ConstantHandle& handle) = delete; + +// DANGEROUS. Do not call unless you explicitly intend to get a reference to a +// temporary value, which will expire at the end of the current expression. +// This should only be called in cases where the C-shim API expects an optional +// input argument (passed by pointer), and a temporary needs to be passed to it. +template +T& temporary_reference(T&& t) { + return t; +} + +#define CACHE_TORCH_DTYPE(typename) \ + static auto cached_torch_dtype_##typename = aoti_torch_dtype_##typename() + +#define CACHE_TORCH_DEVICE(device) \ + static auto cached_torch_device_type_##device = \ + aoti_torch_device_type_##device() + +#define CACHE_TORCH_LAYOUT(layout) \ + static auto cached_torch_layout_##layout = aoti_torch_layout_##layout() + +#define CACHE_TORCH_MEMORY_FORMAT(format) \ + static auto cached_torch_memory_format_##format = \ + aoti_torch_memory_format_##format() + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/utils_cuda.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/utils_cuda.h new file mode 100644 index 0000000000000000000000000000000000000000..3dce90bd4059e185b68ead3729c2bb729cf7cbf7 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/utils_cuda.h @@ -0,0 +1,68 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef USE_CUDA +// WARNING: Be careful when adding new includes here. This header will be used +// in model.so, and should not refer to any aten/c10 headers except the stable +// C ABI defined in torch/csrc/inductor/aoti_torch/c/shim.h. The same rule +// applies to other files under torch/csrc/inductor/aoti_runtime/. +#include + +#include +#include +#ifndef USE_ROCM +#include +#include +#include +#endif + +namespace torch::aot_inductor { + +inline void delete_cuda_guard(void* ptr) { + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_delete_cuda_guard(reinterpret_cast(ptr))); +} + +inline void delete_cuda_stream_guard(void* ptr) { + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_delete_cuda_stream_guard( + reinterpret_cast(ptr))); +} + +class AOTICudaGuard { + public: + AOTICudaGuard(int32_t device_index) : guard_(nullptr, delete_cuda_guard) { + CUDAGuardHandle ptr = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_create_cuda_guard(device_index, &ptr)); + guard_.reset(ptr); + } + + void set_index(int32_t device_index) { + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_cuda_guard_set_index(guard_.get(), device_index)); + } + + private: + std::unique_ptr guard_; +}; + +class AOTICudaStreamGuard { + public: + AOTICudaStreamGuard(cudaStream_t stream, int32_t device_index) + : guard_(nullptr, delete_cuda_stream_guard) { + CUDAStreamGuardHandle ptr = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_create_cuda_stream_guard(stream, device_index, &ptr)); + guard_.reset(ptr); + } + + private: + std::unique_ptr guard_; +}; + +} // namespace torch::aot_inductor +#endif // USE_CUDA + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/utils_xpu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/utils_xpu.h new file mode 100644 index 0000000000000000000000000000000000000000..50149503b3117d912df41cabfe395af47bd7cbc5 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_runtime/utils_xpu.h @@ -0,0 +1,61 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef USE_XPU +// WARNING: Be careful when adding new includes here. This header will be used +// in model.so, and should not refer to any aten/c10 headers except the stable +// C ABI defined in torch/csrc/inductor/aoti_torch/c/shim.h. The same rule +// applies to other files under torch/csrc/inductor/aoti_runtime/. +#include +#include + +namespace torch::aot_inductor { + +inline void delete_xpu_guard(void* ptr) { + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_delete_xpu_guard(reinterpret_cast(ptr))); +} + +inline void delete_xpu_stream_guard(void* ptr) { + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_delete_xpu_stream_guard( + reinterpret_cast(ptr))); +} + +class AOTIXpuGuard { + public: + AOTIXpuGuard(int32_t device_index) : guard_(nullptr, delete_xpu_guard) { + XPUGuardHandle ptr = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_create_xpu_guard(device_index, &ptr)); + guard_.reset(ptr); + } + + void set_index(int32_t device_index) { + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_xpu_guard_set_index(guard_.get(), device_index)); + } + + private: + std::unique_ptr guard_; +}; + +class AOTIXpuStreamGuard { + public: + AOTIXpuStreamGuard(void* stream, int32_t device_index) + : guard_(nullptr, delete_xpu_stream_guard) { + XPUStreamGuardHandle ptr = nullptr; + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_create_xpu_stream_guard(stream, device_index, &ptr)); + guard_.reset(ptr); + } + + private: + std::unique_ptr guard_; +}; + +} // namespace torch::aot_inductor +#endif // USE_XPU + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/macros.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/macros.h new file mode 100644 index 0000000000000000000000000000000000000000..e49cd39deac0c8f2f0a5939c1503f515abed0d04 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/macros.h @@ -0,0 +1,66 @@ +#ifndef AOTI_TORCH_MACRO_H +#define AOTI_TORCH_MACRO_H + +#include +#include +#ifdef __GNUC__ +#define AOTI_TORCH_EXPORT __attribute__((__visibility__("default"))) +#else // !__GNUC__ +#ifdef _WIN32 +// PyTorch2 doesn't currently work on Windows. Exporting these APIs can lead +// to symbol clashes at link time if libtorch is included in a DLL and binary +// that depends on the DLL. As a short term fix, we don't export the symbols. +// In the long term, this will need to be addressed when Windows is supported. +#ifdef OVRSOURCE +// Do not export AOTI on Windows for internal builds +#define AOTI_TORCH_EXPORT +#else /* OVRSOURCE */ +#ifdef EXPORT_AOTI_FUNCTIONS +#define AOTI_TORCH_EXPORT __declspec(dllexport) +#else +#define AOTI_TORCH_EXPORT __declspec(dllimport) +#endif +#endif /* OVRSOURCE */ +#else // !_WIN32 +#define AOTI_TORCH_EXPORT +#endif // _WIN32 +#endif // __GNUC__ + +#ifdef __cplusplus +extern "C" { +#endif +// AtenTensorHandle represents an abstract notion of Tensor that can be passed +// between model.so and libtorch.so. The contents of the structure itself +// are private; model.so is not allowed to access any fields directly, it must +// go through functions defined in this ABI. Under the hood, this is +// represented as at::Tensor*, but we reserve the right to change this (and in +// fact, we probably should change it to at::TensorImpl* at least). +// +// An AtenTensorHandle can be owning (please check the API reference for exact +// ownership/borrow semantics). If you have an owning AtenTensorHandle +// in model.so, you are obligated to aoti_torch_delete_tensor_object when you +// are done. You can use the helper C++ class RAIIAtenTensorHandle +// (see aot_runtime/model.h) to ensure the deallocator is called in RAII style +// (note that RAIIAtenTensorHandle is private to model.so, and never crosses +// the ABI boundary.) +struct AtenTensorOpaque; +using AtenTensorHandle = AtenTensorOpaque*; + +struct AtenGeneratorOpaque; +using AtenGeneratorHandle = AtenGeneratorOpaque*; + +struct AOTIProxyExecutorOpaque; +using AOTIProxyExecutorHandle = AOTIProxyExecutorOpaque*; + +struct C10IValueOpaque; +using C10IValueHandle = C10IValueOpaque*; + +using AOTITorchError = int32_t; +#define AOTI_TORCH_SUCCESS 0 +#define AOTI_TORCH_FAILURE 1 + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // AOTI_TORCH_MACRO_H diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/shim.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/shim.h new file mode 100644 index 0000000000000000000000000000000000000000..f719828ba00d6c3e135267c6a42210483b9b1122 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/shim.h @@ -0,0 +1,697 @@ +#ifndef AOTI_TORCH_SHIM +#define AOTI_TORCH_SHIM + +#include +#include +#include + +// This header defines a stable C API for certain ATen functionality in +// libtorch. The AOTInductor compiled model.so will only refer to this header +// instead of other headers from aten/c10, which means it will NOT be able to +// directly use any data structures or call functions from libtorch. +// +// What problems are we trying to solve here? Direct use of aten/c10 APIs +// means use of C++ APIs on a library that doesn't have any ABI compatibility +// guarantees. However, we want model.so to remain usable across updates +// to the PyTorch C++ libraries, which requires a stable ABI. By introducing +// a C shim layer, we can minimize the surface that will cause breakage. The +// corresponding software stack can be illustrated as follows: +// +// |--------------------------------| +// | inference service code | +// |--------------------------------| +// | model.so | +// |--------------|-----------------| +// | | +// | libtorch.so | +// |--------------------------------| +// +// The general guidelines for the C API: +// +// - No exceptions, return an explicit error code to be checked at call site +// - Only pointers (AtenTensorHandle counts), integers and floats in headers +// +// If you want to make changes to this header, you MUST MAINTAIN ABI +// compatibility. Typically, this means you will have to add a _v2 version +// of a function that you, e.g., want to add a new function parameter to, and +// maintain the old and new versions of the APIs until all old model.so +// go out of use. + +// The following files are implemented in a header-only way and are guarded by +// test/cpp/aoti_abi_check +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Getter functions for retrieving various constants from the runtime, that +// can subsequently be passed to other aoti_* functions. By hiding these +// behind functions, the precise value of device/dtype is NOT part of the +// ABI contract. (In practice, aten/c10 is pretty good about not renumbering +// these, so we probably could later switch to having these in the ABI, if +// desired for perf reasons.) +AOTI_TORCH_EXPORT int32_t aoti_torch_device_type_cpu(); +AOTI_TORCH_EXPORT int32_t aoti_torch_device_type_cuda(); +AOTI_TORCH_EXPORT int32_t aoti_torch_device_type_meta(); +AOTI_TORCH_EXPORT int32_t aoti_torch_device_type_xpu(); +AOTI_TORCH_EXPORT int32_t aoti_torch_device_type_mps(); +AOTI_TORCH_EXPORT int32_t aoti_torch_device_type_privateuse1(); + +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_float8_e5m2(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_float8_e4m3fn(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_float8_e5m2fnuz(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_float8_e4m3fnuz(); +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_12_0 +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_float8_e8m0fnu(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_float4_e2m1fn_x2(); +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_12_0 +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_bfloat16(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_float16(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_float32(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_float64(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_uint8(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_uint16(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_uint32(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_uint64(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_int8(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_int16(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_int32(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_int64(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_bool(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_complex32(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_complex64(); +AOTI_TORCH_EXPORT int32_t aoti_torch_dtype_complex128(); +AOTI_TORCH_EXPORT size_t aoti_torch_dtype_element_size(int32_t dtype); + +AOTI_TORCH_EXPORT int32_t aoti_torch_layout_strided(); +AOTI_TORCH_EXPORT int32_t aoti_torch_layout_sparse_coo(); +AOTI_TORCH_EXPORT int32_t aoti_torch_layout_sparse_csr(); +AOTI_TORCH_EXPORT int32_t aoti_torch_layout_sparse_csc(); +AOTI_TORCH_EXPORT int32_t aoti_torch_layout_sparse_bsr(); +AOTI_TORCH_EXPORT int32_t aoti_torch_layout_sparse_bsc(); +AOTI_TORCH_EXPORT int32_t aoti_torch_layout__mkldnn(); +AOTI_TORCH_EXPORT int32_t aoti_torch_layout_jagged(); + +AOTI_TORCH_EXPORT int32_t aoti_torch_memory_format_contiguous_format(); +AOTI_TORCH_EXPORT int32_t aoti_torch_memory_format_channels_last(); +AOTI_TORCH_EXPORT int32_t aoti_torch_memory_format_channels_last_3d(); +AOTI_TORCH_EXPORT int32_t aoti_torch_memory_format_preserve_format(); + +// Get TORCH_ABI_VERSION of the built libtorch.so +AOTI_TORCH_EXPORT uint64_t aoti_torch_abi_version(); + +// Functions for converting a single-element tensor to a scalar value +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_item_float16(AtenTensorHandle tensor, c10::Half* ret_value); +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_item_float32(AtenTensorHandle tensor, float* ret_value); +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_item_float64(AtenTensorHandle tensor, double* ret_value); +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_item_uint8(AtenTensorHandle tensor, uint8_t* ret_value); +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_item_uint16(AtenTensorHandle tensor, uint16_t* ret_value); +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_item_uint32(AtenTensorHandle tensor, uint32_t* ret_value); +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_item_uint64(AtenTensorHandle tensor, uint64_t* ret_value); +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_item_int8(AtenTensorHandle tensor, int8_t* ret_value); +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_item_int16(AtenTensorHandle tensor, int16_t* ret_value); +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_item_int32(AtenTensorHandle tensor, int32_t* ret_value); +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_item_int64(AtenTensorHandle tensor, int64_t* ret_value); +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_item_bool(AtenTensorHandle tensor, bool* ret_value); +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_item_bfloat16(AtenTensorHandle tensor, c10::BFloat16* ret_value); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_item_complex64( + AtenTensorHandle tensor, + c10::complex* ret_value); + +// Functions for wrapping a scalar value to a single-element tensor +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_scalar_to_tensor_float32( + float value, + AtenTensorHandle* ret_new_tensor); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_scalar_to_tensor_float64( + double value, + AtenTensorHandle* ret_new_tensor); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_scalar_to_tensor_uint8( + uint8_t value, + AtenTensorHandle* ret_new_tensor); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_scalar_to_tensor_uint16( + uint16_t value, + AtenTensorHandle* ret_new_tensor); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_scalar_to_tensor_uint32( + uint32_t value, + AtenTensorHandle* ret_new_tensor); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_scalar_to_tensor_uint64( + uint64_t value, + AtenTensorHandle* ret_new_tensor); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_scalar_to_tensor_int8( + int8_t value, + AtenTensorHandle* ret_new_tensor); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_scalar_to_tensor_int16( + int16_t value, + AtenTensorHandle* ret_new_tensor); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_scalar_to_tensor_int32( + int32_t value, + AtenTensorHandle* ret_new_tensor); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_scalar_to_tensor_int64( + int64_t value, + AtenTensorHandle* ret_new_tensor); +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_scalar_to_tensor_bool(bool value, AtenTensorHandle* ret_new_tensor); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_scalar_to_tensor_complex64( + c10::complex value, + AtenTensorHandle* ret_new_tensor); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_scalar_to_tensor_complex128( + c10::complex value, + AtenTensorHandle* ret_new_tensor); + +AOTI_TORCH_EXPORT bool aoti_torch_grad_mode_is_enabled(); +AOTI_TORCH_EXPORT void aoti_torch_grad_mode_set_enabled(bool enabled); + +// Free the tensor object +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_delete_tensor_object(AtenTensorHandle tensor); + +// c10::IValue object conversion +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_int64_to_ivalue(int64_t val, C10IValueHandle* ivalue); + +// c10::IValue object conversions +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_strlist_to_ivalue( + const char** val, + int64_t len, + C10IValueHandle* ivalue); + +// c10::IValue object conversions +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_str_to_ivalue(const char* val, C10IValueHandle* ivalue); + +// c10::IValue object conversions +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_tensor_to_ivalue(AtenTensorHandle val, C10IValueHandle* ivalue); + +// Free the c10::IValue object +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_delete_c10_value_object(C10IValueHandle handle); + +// Get a pointer to the underlying storage data +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_get_data_ptr( + AtenTensorHandle tensor, + void** ret_data_ptr // returns borrowed reference +); + +// Get the nbytes of the underlying storage +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_get_storage_size(AtenTensorHandle tensor, int64_t* ret_size); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_get_dim(AtenTensorHandle tensor, int64_t* ret_dim); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_get_numel(AtenTensorHandle tensor, int64_t* ret_numel); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_get_storage_numel(AtenTensorHandle tensor, int64_t* ret_numel); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_get_sizes( + AtenTensorHandle tensor, + int64_t** ret_sizes // returns borrowed reference +); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_get_size(AtenTensorHandle tensor, int64_t d, int64_t* ret_size); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_get_strides( + AtenTensorHandle tensor, + int64_t** ret_strides // returns borrowed reference +); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_get_stride(AtenTensorHandle tensor, int64_t d, int64_t* ret_stride); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_get_dtype(AtenTensorHandle tensor, int32_t* ret_dtype); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_get_device_type(AtenTensorHandle tensor, int32_t* ret_device_type); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_get_device_index(AtenTensorHandle tensor, int32_t* ret_device_index); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_get_layout(AtenTensorHandle tensor, int32_t* ret_layout); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_get_storage_offset( + AtenTensorHandle tensor, + int64_t* ret_storage_offset); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_is_contiguous(AtenTensorHandle tensor, bool* ret_is_contiguous); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_is_defined(AtenTensorHandle tensor, bool* ret_is_defined); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_new_tensor_handle( + AtenTensorHandle orig_handle, + AtenTensorHandle* new_handle); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch__alloc_from_pool( + AtenTensorHandle self, + int64_t offset_bytes, + int32_t dtype, + int64_t ndim, + const int64_t* sizes_ptr, + const int64_t* strides_ptr, + AtenTensorHandle* ret_new_tensor); + +// This function will create a new tensor object and its pointer is returned +// through *out. The caller is responsible for wrapping the tensor pointer +// with RAIIAtenTensorHandle which will call aoti_torch_delete_tensor_object +// when going out of scope. +AOTI_TORCH_EXPORT AOTITorchError aoti_torch__reinterpret_tensor( + AtenTensorHandle self, + int64_t ndim, + const int64_t* sizes_ptr, + const int64_t* strides_ptr, + int64_t storage_offset, + AtenTensorHandle* ret_new_tensor // returns new reference +); + +// This function will create a new tensor object and its pointer is returned +// through *out. The caller is responsible for wrapping the tensor pointer +// with RAIIAtenTensorHandle which will call aoti_torch_delete_tensor_object +// when going out of scope. +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_empty_strided( + int64_t ndim, + const int64_t* sizes_ptr, + const int64_t* strides_ptr, + int32_t dtype, + int32_t device_type, + int32_t device_index, + AtenTensorHandle* ret_new_tensor // returns new reference +); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_empty_strided_pinned( + int64_t ndim, + const int64_t* sizes_ptr, + const int64_t* strides_ptr, + int32_t dtype, + int32_t device_type, + int32_t device_index, + AtenTensorHandle* ret_new_tensor // returns new reference +); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_as_strided( + AtenTensorHandle self, + const int64_t* sizes_ptr, + const int64_t* strides_ptr, + AtenTensorHandle* ret); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_create_tensor_from_blob( + void* data, + int64_t ndim, + const int64_t* sizes_ptr, + const int64_t* strides_ptr, + int64_t storage_offset, + int32_t dtype, + int32_t device_type, + int32_t device_index, + AtenTensorHandle* ret // returns new reference +); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_create_tensor_from_blob_v2( + void* data, + int64_t ndim, + const int64_t* sizes_ptr, + const int64_t* strides_ptr, + int64_t storage_offset, + int32_t dtype, + int32_t device_type, + int32_t device_index, + AtenTensorHandle* ret, // returns new reference + int32_t layout, + const uint8_t* opaque_metadata, + int64_t opaque_metadata_size); + +// This function will create a new uninitialized tensor object +// and its pointer is returned through *ret. +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_new_uninitialized_tensor(AtenTensorHandle* ret); + +// WARNING: This will be deprecated. Use aoti_torch_copy_ instead. +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_tensor_copy_(AtenTensorHandle src, AtenTensorHandle dst); + +// Make the tensor referred to by dst an alias for the tensor referred +// to by src. The two tensors must still be deleted with +// aoti_torch_delete_tensor separately (or not) as before the call. +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_assign_tensors(AtenTensorHandle src, AtenTensorHandle dst); + +// Make a shallow copy of the tensor referred to by src and assign +// it to the handle in the ret_dst. This is similar to the above +// aoti_torch_assign_tensors function, but creates and sets the +// ret_dst from within. +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_assign_tensors_out(AtenTensorHandle src, AtenTensorHandle* ret_dst); + +// This function will create a new tensor object and its pointer is returned +// through *ret. The caller is responsible for wrapping the tensor pointer +// with RAIIAtenTensorHandle which will call aoti_torch_delete_tensor_object +// when going out of scope. +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_clone(AtenTensorHandle self, AtenTensorHandle* ret); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_clone_preserve_strides(AtenTensorHandle self, AtenTensorHandle* ret); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_copy_( + AtenTensorHandle self, + AtenTensorHandle src, + int32_t non_blocking); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch__mm_plus_mm_out( + AtenTensorHandle out, + AtenTensorHandle a, + AtenTensorHandle b, + AtenTensorHandle c, + AtenTensorHandle d); + +// This will soon be deprecated after ao_quantization is complete. +// Please refrain from using this or increasing callsites. +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_cpu_wrapped_fbgemm_pack_gemm_matrix_fp16( + AtenTensorHandle weight, + AtenTensorHandle* out); + +// This will soon be deprecated after ao_quantization is complete. +// Please refrain from using this or increasing callsites. +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__wrapped_linear_prepack( + AtenTensorHandle weight, + AtenTensorHandle weight_scale, + AtenTensorHandle weight_zero_point, + AtenTensorHandle bias, + AtenTensorHandle* out); + +// This will soon be deprecated after ao_quantization is complete. +// Please refrain from using this or increasing callsites. +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_cpu_wrapped_fbgemm_linear_fp16_weight( + AtenTensorHandle input, + AtenTensorHandle weight, + AtenTensorHandle bias, // optional argument + int64_t out_channel, + AtenTensorHandle* out); + +// This will soon be deprecated after ao_quantization is complete. +// Please refrain from using this or increasing callsites. +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_cpu__wrapped_quantized_linear_prepacked( + AtenTensorHandle input, + AtenTensorHandle input_scale, + AtenTensorHandle input_zero_point, + AtenTensorHandle weight, + AtenTensorHandle out_scale, + AtenTensorHandle out_zeropoint, + int64_t out_channel, + AtenTensorHandle* out); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_zero_(AtenTensorHandle self); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_check_inf_and_nan(const char* tensor_name, AtenTensorHandle tensor); + +struct AtenRecordFunctionOpaque; +using AtenRecordFunctionHandle = AtenRecordFunctionOpaque*; + +struct IValueMapOpaque; +using IValueMapHandle = IValueMapOpaque*; + +AOTI_TORCH_EXPORT AOTITorchError aoti_record_function_start( + const char* name, + IValueMapHandle kwargs, + const C10IValueHandle* inputs, + const uint64_t n_inputs, + AtenRecordFunctionHandle* guard); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_record_function_end(AtenRecordFunctionHandle guard); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_scatter_out( + AtenTensorHandle out, + AtenTensorHandle self, + int64_t dim, + AtenTensorHandle index, + AtenTensorHandle src); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_scatter_reduce_out( + AtenTensorHandle out, + AtenTensorHandle self, + int64_t dim, + AtenTensorHandle index, + AtenTensorHandle src, + const char* reduce, + int32_t include_self); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_index_put_out( + AtenTensorHandle out, + AtenTensorHandle self, + const AtenTensorHandle* indices, + const uint32_t num_indices, + const AtenTensorHandle values, + bool accumulate); + +AOTI_TORCH_EXPORT void aoti_torch_print_tensor_handle( + AtenTensorHandle self, + const char* msg); + +// When AOTI debug printer option is enabled, this function will be invoked to +// torch pickle save the intermediate tensor for debugging purpose. +AOTI_TORCH_EXPORT void aoti_torch_save_tensor_handle( + AtenTensorHandle self, + const char* tensor_name, + const char* launch_prefix, + const char* kernel_name); + +// helpers for converting between StableIValue and actual IValues +using StableIValue = uint64_t; + +class TorchLibraryOpaque; +using TorchLibraryHandle = TorchLibraryOpaque*; + +// stable corollary to torch::Library constructor with Kind::IMPL +// will create a new torch::Library object on the heap +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_library_init_impl( + const char* ns, + const char* k, + const char* file, + uint32_t line, + TorchLibraryHandle* ret_new_torch_lib); + +// stable corollary to torch::Library constructor with Kind::DEF +// will create a new torch::Library object on the heap +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_library_init_def( + const char* ns, + const char* file, + uint32_t line, + TorchLibraryHandle* ret_new_torch_lib); + +// stable corollary to torch::Library constructor with Kind::FRAGMENT +// will create a new torch::Library object on the heap +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_library_init_fragment( + const char* ns, + const char* file, + uint32_t line, + TorchLibraryHandle* ret_new_torch_lib); + +// stable corollary to torch::Library method m.impl(), should be +// called from StableLibrary +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_library_impl( + TorchLibraryHandle self, + const char* name, + void (*fn)(StableIValue*, uint64_t, uint64_t)); + +// stable corollary to torch::Library method m.def(), should be +// called from StableLibrary +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_library_def(TorchLibraryHandle self, const char* schema); + +// the above stable constructors for torch::Library add Library objects +// to the heap. if you are calling those functions directly, please use +// this function to free the Library's memory. The more user friendly +// alternative is to use StableLibrary, which will free its handle upon +// destruction +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_delete_library_object(TorchLibraryHandle tlh); + +// calls the op overload defined by a given opName, overloadName, and a +// stack of StableIValues. This call will populate any return values of the +// op into the stack in their StableIValue form, with ret0 at index 0, ret1 +// at index 1, and so on. +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_call_dispatcher( + const char* opName, + const char* overloadName, + StableIValue* stack); + +// Device-generic guard for managing device context +struct DeviceGuardOpaque; +using DeviceGuardHandle = DeviceGuardOpaque*; + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_create_device_guard( + int32_t device_index, + DeviceGuardHandle* ret_guard // returns new reference +); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_delete_device_guard(DeviceGuardHandle guard); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_device_guard_set_index( + DeviceGuardHandle guard, + int32_t device_index); + +// Device-generic stream for managing stream objects +struct StreamOpaque; +using StreamHandle = StreamOpaque*; + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_delete_stream(StreamHandle stream); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_stream_id(StreamHandle stream, int64_t* ret_stream_id); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_get_current_stream( + int32_t device_index, + StreamHandle* ret_stream // returns new reference +); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_get_current_device_index(int32_t* ret_device_index); + +#ifdef USE_CUDA + +struct CUDAGuardOpaque; +using CUDAGuardHandle = CUDAGuardOpaque*; + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_create_cuda_guard( + int32_t device_index, + CUDAGuardHandle* ret_guard // returns new reference +); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_delete_cuda_guard(CUDAGuardHandle guard); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_cuda_guard_set_index(CUDAGuardHandle guard, int32_t device_index); + +struct CUDAStreamGuardOpaque; +using CUDAStreamGuardHandle = CUDAStreamGuardOpaque*; + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_create_cuda_stream_guard( + void* stream, + int32_t device_index, + CUDAStreamGuardHandle* ret_guard // returns new reference +); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_delete_cuda_stream_guard(CUDAStreamGuardHandle guard); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_get_current_cuda_stream(int32_t device_index, void** ret_stream); + +// CUDA memory allocation using CUDACachingAllocator +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_caching_allocator_raw_alloc( + uint64_t nbytes, + void** ret_ptr // returns raw GPU memory pointer +); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_cuda_caching_allocator_raw_delete(void* ptr); + +#endif // USE_CUDA + +// See `ProxyExecutor Design Note` in ir.py for more details +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_proxy_executor_call_function( + AOTIProxyExecutorHandle proxy_executor, + int extern_node_index, + int num_ints, + int64_t* flatten_int_args, + int num_tensors, + AtenTensorHandle* flatten_tensor_args); + +AOTI_TORCH_EXPORT void aoti_torch_check( + bool cond, + const char* func, + const char* file, + uint32_t line, + const char* msg); + +#ifdef STRIP_ERROR_MESSAGES +#define AOTI_TORCH_CHECK(cond, ...) \ + if (!(cond)) { \ + aoti_torch_check( \ + false, \ + __func__, \ + __FILE__, \ + static_cast(__LINE__), \ + STD_TORCH_CHECK_MSG(cond, "", __VA_ARGS__)); \ + } +#else +#define AOTI_TORCH_CHECK(cond, ...) \ + if (!(cond)) { \ + aoti_torch_check( \ + false, \ + __func__, \ + __FILE__, \ + static_cast(__LINE__), \ + STD_TORCH_CHECK_MSG(cond, "", ##__VA_ARGS__)); \ + } +#endif + +AOTI_TORCH_EXPORT void aoti_torch_warn( + const char* func, + const char* file, + uint32_t line, + const char* msg); + +#ifdef DISABLE_WARN +#define AOTI_TORCH_WARN(...) ((void)0); +#else +#define AOTI_TORCH_WARN(...) \ + aoti_torch_warn( \ + __func__, __FILE__, static_cast(__LINE__), #__VA_ARGS__); +#endif + +#ifdef __cplusplus +} // extern "C" + +template +int32_t aoti_torch_dtype() = delete; + +#define DEFINE_DTYPE_SPECIALIZATION(ctype, typename) \ + template <> \ + inline int32_t aoti_torch_dtype() { \ + return aoti_torch_dtype_##typename(); \ + } + +DEFINE_DTYPE_SPECIALIZATION(c10::BFloat16, bfloat16) +DEFINE_DTYPE_SPECIALIZATION(c10::Half, float16) +DEFINE_DTYPE_SPECIALIZATION(c10::complex, complex64) +DEFINE_DTYPE_SPECIALIZATION(float, float32) +DEFINE_DTYPE_SPECIALIZATION(double, float64) +DEFINE_DTYPE_SPECIALIZATION(uint8_t, uint8) +DEFINE_DTYPE_SPECIALIZATION(int8_t, int8) +DEFINE_DTYPE_SPECIALIZATION(int16_t, int16) +DEFINE_DTYPE_SPECIALIZATION(int32_t, int32) +DEFINE_DTYPE_SPECIALIZATION(int64_t, int64) +DEFINE_DTYPE_SPECIALIZATION(bool, bool) + +#endif +#endif // AOTI_TORCH_SHIM diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/shim_cpu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/shim_cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..5a10290decd1db529a924a89596e17c8e6829dcc --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/shim_cpu.h @@ -0,0 +1,267 @@ +#ifndef AOTI_TORCH_SHIM_CPU +#define AOTI_TORCH_SHIM_CPU + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if AT_MKLDNN_ENABLED() + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_cpu_mkldnn__convolution_pointwise_binary( + AtenTensorHandle X, + AtenTensorHandle other, + AtenTensorHandle W, + AtenTensorHandle* B, + const int64_t* padding, + int64_t padding_len_, + const int64_t* stride, + int64_t stride_len_, + const int64_t* dilation, + int64_t dilation_len_, + int64_t groups, + const char* binary_attr, + double* alpha, + const char** unary_attr, + const double** unary_scalars, + int64_t unary_scalars_len_, + const char** unary_algorithm, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_cpu_mkldnn__convolution_pointwise_binary_( + AtenTensorHandle other, + AtenTensorHandle X, + AtenTensorHandle W, + AtenTensorHandle* B, + const int64_t* padding, + int64_t padding_len_, + const int64_t* stride, + int64_t stride_len_, + const int64_t* dilation, + int64_t dilation_len_, + int64_t groups, + const char* binary_attr, + double* alpha, + const char** unary_attr, + const double** unary_scalars, + int64_t unary_scalars_len_, + const char** unary_algorithm, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_mkldnn__convolution_pointwise( + AtenTensorHandle X, + AtenTensorHandle W, + AtenTensorHandle* B, + const int64_t* padding, + int64_t padding_len_, + const int64_t* stride, + int64_t stride_len_, + const int64_t* dilation, + int64_t dilation_len_, + int64_t groups, + const char* attr, + const double** scalars, + int64_t scalars_len_, + const char** algorithm, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_cpu_mkldnn__convolution_transpose_pointwise( + AtenTensorHandle X, + AtenTensorHandle W, + AtenTensorHandle* B, + const int64_t* padding, + int64_t padding_len_, + const int64_t* output_padding, + int64_t output_padding_len_, + const int64_t* stride, + int64_t stride_len_, + const int64_t* dilation, + int64_t dilation_len_, + int64_t groups, + const char* attr, + const double** scalars, + int64_t scalars_len_, + const char** algorithm, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_mkldnn_rnn_layer( + AtenTensorHandle input, + AtenTensorHandle weight0, + AtenTensorHandle weight1, + AtenTensorHandle weight2, + AtenTensorHandle weight3, + AtenTensorHandle hx_, + AtenTensorHandle cx_, + int32_t reverse, + const int64_t* batch_sizes, + int64_t batch_sizes_len_, + int64_t mode, + int64_t hidden_size, + int64_t num_layers, + int32_t has_biases, + int32_t bidirectional, + int32_t batch_first, + int32_t train, + AtenTensorHandle* ret0, + AtenTensorHandle* ret1, + AtenTensorHandle* ret2, + AtenTensorHandle* ret3); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__linear_pointwise( + AtenTensorHandle X, + AtenTensorHandle W, + AtenTensorHandle* B, + const char* attr, + const double** scalars, + int64_t scalars_len_, + const char** algorithm, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__linear_pointwise_binary( + AtenTensorHandle X, + AtenTensorHandle other, + AtenTensorHandle W, + AtenTensorHandle* B, + const char* attr, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__qlinear_pointwise_tensor( + AtenTensorHandle X, + AtenTensorHandle act_scale, + AtenTensorHandle act_zero_point, + AtenTensorHandle onednn_weight, + AtenTensorHandle weight_scales, + AtenTensorHandle weight_zero_points, + AtenTensorHandle* B, + double output_scale, + int64_t output_zero_point, + const int32_t* output_dtype, + const char* post_op_name, + const double** post_op_args, + int64_t post_op_args_len_, + const char* post_op_algorithm, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_cpu__qlinear_pointwise_binary_tensor( + AtenTensorHandle X, + AtenTensorHandle act_scale, + AtenTensorHandle act_zero_point, + AtenTensorHandle onednn_weight, + AtenTensorHandle weight_scales, + AtenTensorHandle weight_zero_points, + AtenTensorHandle* other, + AtenTensorHandle* B, + double output_scale, + int64_t output_zero_point, + const int32_t* output_dtype, + double other_scale, + int64_t other_zero_point, + const char* binary_post_op, + double binary_alpha, + const char* unary_post_op, + const double** unary_post_op_args, + int64_t unary_post_op_args_len_, + const char* unary_post_op_algorithm, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__qconv_pointwise_tensor( + AtenTensorHandle X, + AtenTensorHandle act_scale, + AtenTensorHandle act_zero_point, + AtenTensorHandle onednn_weight, + AtenTensorHandle weight_scales, + AtenTensorHandle weight_zero_points, + AtenTensorHandle* B, + const int64_t* stride, + int64_t stride_len_, + const int64_t* padding, + int64_t padding_len_, + const int64_t* dilation, + int64_t dilation_len_, + int64_t groups, + double output_scale, + int64_t output_zero_point, + const int32_t* output_dtype, + const char* attr, + const double** post_op_args, + int64_t post_op_args_len_, + const char** algorithm, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_cpu__qconv2d_pointwise_binary_tensor( + AtenTensorHandle X, + AtenTensorHandle act_scale, + AtenTensorHandle act_zero_point, + AtenTensorHandle onednn_weight, + AtenTensorHandle weight_scales, + AtenTensorHandle weight_zero_points, + AtenTensorHandle accum, + AtenTensorHandle* B, + const int64_t* stride_args, + int64_t stride_len_, + const int64_t* padding_args, + int64_t padding_len_, + const int64_t* dilation_args, + int64_t dilation_len_, + int64_t groups, + double output_scale, + int64_t output_zero_point, + const int32_t* output_dtype, + double accum_scale, + int64_t accum_zero_point, + const char* binary_attr, + double* alpha, + const char** unary_attr, + const double** unary_scalars, + int64_t unary_scalars_len_, + const char** unary_algorithm, + AtenTensorHandle* ret0); + +#if AT_MKL_ENABLED() + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__mkl_linear( + AtenTensorHandle X, + AtenTensorHandle W, + AtenTensorHandle origin_W, + AtenTensorHandle* B, + int64_t prepack_batch_size, + AtenTensorHandle* ret0); + +#endif // AT_MKL_ENABLED + +#endif // AT_MKLDNN_ENABLED() + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__weight_int4pack_mm_cpu_tensor( + AtenTensorHandle X, + AtenTensorHandle w, + AtenTensorHandle qGroupSize, + AtenTensorHandle qScaleAndZeros, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__c10d_functional_all_reduce_( + AtenTensorHandle inp, + const char* reduce_op, + const char* group_name, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__c10d_functional_all_reduce( + AtenTensorHandle inp, + const char* reduce_op, + const char* group_name, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__c10d_functional_wait_tensor( + AtenTensorHandle inp, + AtenTensorHandle* ret0); + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // AOTI_TORCH_SHIM_CPU diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/shim_deprecated.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/shim_deprecated.h new file mode 100644 index 0000000000000000000000000000000000000000..964db6b0076c97bcbaac3bf5a831b6b87cec54c3 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/shim_deprecated.h @@ -0,0 +1,199 @@ +#ifndef AOTI_TORCH_SHIM_DEPRECATED +#define AOTI_TORCH_SHIM_DEPRECATED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +[[deprecated( + "aoti_torch__embedding_bag is deprecated and will be removed in future versions.")]] +AOTI_TORCH_EXPORT AOTITorchError aoti_torch__embedding_bag( + AtenTensorHandle weight, + AtenTensorHandle indices, + AtenTensorHandle offsets, + int32_t scale_grad_by_freq, + int32_t mode, + int32_t sparse, + AtenTensorHandle per_sample_weights, // optional argument + int32_t include_last_offset, + int32_t padding_idx, + AtenTensorHandle* ret0, // returns new reference + AtenTensorHandle* ret1, // returns new reference + AtenTensorHandle* ret2, // returns new reference + AtenTensorHandle* ret3 // returns new reference +); + +[[deprecated( + "aoti_torch__fft_c2c is deprecated and will be removed in future versions.")]] +AOTI_TORCH_EXPORT AOTITorchError aoti_torch__fft_c2c( + AtenTensorHandle self, + const int64_t* dim_ptr, + int64_t dim_size, + int64_t normalization, + int32_t forward, + AtenTensorHandle* ret // returns new reference +); + +[[deprecated( + "aoti_torch__scaled_mm is deprecated and will be removed in future versions.")]] +AOTI_TORCH_EXPORT AOTITorchError aoti_torch__scaled_mm( + AtenTensorHandle self, + AtenTensorHandle mat2, + AtenTensorHandle bias, + int32_t* out_dtype, + AtenTensorHandle scale_a, + AtenTensorHandle scale_b, + AtenTensorHandle scale_result, + int8_t use_fast_accum, + AtenTensorHandle* ret0, + AtenTensorHandle* ret1); + +[[deprecated( + "aoti_torch__scaled_mm_v2 is deprecated and will be removed in future versions.")]] +AOTI_TORCH_EXPORT AOTITorchError aoti_torch__scaled_mm_v2( + AtenTensorHandle self, + AtenTensorHandle mat2, + AtenTensorHandle scale_a, + AtenTensorHandle scale_b, + AtenTensorHandle bias, + AtenTensorHandle scale_result, + int32_t* out_dtype, + int8_t use_fast_accum, + AtenTensorHandle* ret0); + +[[deprecated( + "aoti_torch_addmm_out is deprecated and will be removed in future versions.")]] +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_addmm_out( + AtenTensorHandle out, + AtenTensorHandle self, + AtenTensorHandle mat1, + AtenTensorHandle mat2, + float beta, + float alpha); + +[[deprecated( + "aoti_torch_bmm is deprecated and will be removed in future versions.")]] +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_bmm_out( + AtenTensorHandle out, + AtenTensorHandle self, + AtenTensorHandle mat2); + +[[deprecated( + "aoti_torch_convolution is deprecated and will be removed in future versions.")]] +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_convolution( + AtenTensorHandle input, + AtenTensorHandle weight, + AtenTensorHandle bias, // optional argument + const int64_t* stride_ptr, + int64_t stride_size, + const int64_t* padding_ptr, + int64_t padding_size, + const int64_t* dilation_ptr, + int64_t dilation_size, + int transposed, + const int64_t* output_padding_ptr, + int64_t output_padding_size, + int64_t groups, + AtenTensorHandle* ret // returns new reference +); + +[[deprecated( + "aoti_torch_mm_out is deprecated and will be removed in future versions.")]] +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mm_out( + AtenTensorHandle out, + AtenTensorHandle self, + AtenTensorHandle mat2); + +[[deprecated( + "aoti_torch_nonzero is deprecated and will be removed in future versions.")]] +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_nonzero(AtenTensorHandle self, AtenTensorHandle* out); + +[[deprecated( + "aoti_torch_repeat_interleave_Tensor is deprecated and will be removed in future versions.")]] +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_repeat_interleave_Tensor( + AtenTensorHandle repeats, + int64_t* output_size, + AtenTensorHandle* out); + +[[deprecated( + "aoti_torch_view_as_real is deprecated and will be removed in future versions.")]] +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_view_as_real( + AtenTensorHandle self, + AtenTensorHandle* ret // returns new reference +); + +[[deprecated( + "aoti_torch_view_dtype is deprecated and will be removed in future versions.")]] +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_view_dtype( + AtenTensorHandle self, + int32_t dtype, + AtenTensorHandle* ret // returns new reference +); + +[[deprecated( + "aoti_torch__scaled_dot_product_flash_attention is deprecated and will be removed in future versions.")]] +AOTI_TORCH_EXPORT AOTITorchError aoti_torch__scaled_dot_product_flash_attention( + AtenTensorHandle query, + AtenTensorHandle key, + AtenTensorHandle value, + double dropout_p, + bool is_causal, + bool return_debug_mask, + double scale, + AtenTensorHandle* ret0, // returns new reference + AtenTensorHandle* ret1, // returns new reference + AtenTensorHandle* ret2, // returns new reference + AtenTensorHandle* ret3, // returns new reference + int64_t* ret4, + int64_t* ret5, + AtenTensorHandle* ret6, // returns new reference + AtenTensorHandle* ret7, // returns new reference + AtenTensorHandle* ret8 // returns new reference +); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch__scaled_dot_product_flash_attention_v2( + AtenTensorHandle query, + AtenTensorHandle key, + AtenTensorHandle value, + double dropout_p, + int is_causal, + int return_debug_mask, + double* scale, // optional argument + AtenTensorHandle* ret0, // returns new reference + AtenTensorHandle* ret1, // returns new reference + AtenTensorHandle* ret2, // returns new reference + AtenTensorHandle* ret3, // returns new reference + int64_t* ret4, + int64_t* ret5, + AtenTensorHandle* ret6, // returns new reference + AtenTensorHandle* ret7, // returns new reference + AtenTensorHandle* ret8 // returns new reference +); + +[[deprecated( + "aoti_torch__scaled_dot_product_efficient_attention is deprecated and will be removed in future versions.")]] +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch__scaled_dot_product_efficient_attention( + AtenTensorHandle query, + AtenTensorHandle key, + AtenTensorHandle value, + AtenTensorHandle attn_bias, // optional argument + int compute_log_sumexp, + double dropout_p, + int is_causal, + double* scale, // optional argument + AtenTensorHandle* ret0, // returns new reference + AtenTensorHandle* ret1, // returns new reference + AtenTensorHandle* ret2, // returns new reference + AtenTensorHandle* ret3 // returns new reference +); + +#ifdef __cplusplus +} // extern "C" + +#endif +#endif // AOTI_TORCH_SHIM_DEPRECATED diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/shim_mps.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/shim_mps.h new file mode 100644 index 0000000000000000000000000000000000000000..2ab0057805121c902c23e18386cb6121073ebe92 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/shim_mps.h @@ -0,0 +1,103 @@ +#ifndef AOTI_TORCH_SHIM_MPS +#define AOTI_TORCH_SHIM_MPS + +#include + +struct AOTIMetalKernelFunctionOpaque; +using AOTIMetalKernelFunctionHandle = AOTIMetalKernelFunctionOpaque*; + +struct AOTIMetalShaderLibraryOpaque; +using AOTIMetalShaderLibraryHandle = AOTIMetalShaderLibraryOpaque*; + +#ifdef __cplusplus +extern "C" { +#endif + +// MetalShaderLibrary functions +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_create_shader_library( + const char* metal_shader_source, + AOTIMetalShaderLibraryHandle* library_handle); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_delete_shader_library( + AOTIMetalShaderLibraryHandle library_handle); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_get_kernel_function( + AOTIMetalShaderLibraryHandle library_handle, + const char* kernel_name, + AOTIMetalKernelFunctionHandle* function_handle); + +// MetalKernelFunction functions +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_mps_start_encoding(AOTIMetalKernelFunctionHandle func); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_set_arg_tensor( + AOTIMetalKernelFunctionHandle func, + unsigned idx, + AtenTensorHandle tensor); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_set_arg_int( + AOTIMetalKernelFunctionHandle func, + unsigned idx, + int64_t val); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_dispatch_single( + AOTIMetalKernelFunctionHandle func, + uint64_t length); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_dispatch_single_with_group_size( + AOTIMetalKernelFunctionHandle func, + uint64_t length, + uint64_t group_size); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_dispatch_array( + AOTIMetalKernelFunctionHandle func, + const uint64_t* length, + size_t length_size); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_dispatch_array_with_group_size( + AOTIMetalKernelFunctionHandle func, + const uint64_t* length, + size_t length_size, + const uint64_t* group_size, + size_t group_size_size); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_mps_malloc(void** buffer, size_t num_bytes); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_free(void* ptr); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_memcpy( + void* buffer, + size_t constant_offset, + size_t bytes_read, + size_t data_size, + uint8_t* constants_start); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_copy_buffer( + void* src_buffer, + void* dst_buffer, + size_t data_size, + size_t src_offset, + size_t dst_offset); + +// C callback function type for command block execution +typedef void (*aoti_torch_mps_command_block_callback_t)( + AOTIMetalKernelFunctionHandle func, + void* user_data); + +// Shared callback function for std::function trampoline +AOTI_TORCH_EXPORT void aoti_torch_mps_shared_callback( + AOTIMetalKernelFunctionHandle func, + void* user_data); + +// Pure C version using function pointer and user data for trampoline pattern +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_run_command_block( + AOTIMetalKernelFunctionHandle func, + aoti_torch_mps_command_block_callback_t callback, + void* user_data); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // AOTI_TORCH_SHIM_MPS diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/shim_xpu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/shim_xpu.h new file mode 100644 index 0000000000000000000000000000000000000000..c25fe6443c9485c1c4b82760b3ccd4012fa03802 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/c/shim_xpu.h @@ -0,0 +1,210 @@ +#ifndef AOTI_TORCH_SHIM_XPU +#define AOTI_TORCH_SHIM_XPU + +#include +#include + +#ifdef USE_XPU +#ifdef __cplusplus +extern "C" { +#endif + +struct XPUGuardOpaque; +using XPUGuardHandle = XPUGuardOpaque*; + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_create_xpu_guard( + int32_t device_index, + XPUGuardHandle* ret_guard // returns new reference +); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_delete_xpu_guard(XPUGuardHandle guard); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_xpu_guard_set_index(XPUGuardHandle guard, int32_t device_index); + +struct XPUStreamGuardOpaque; +using XPUStreamGuardHandle = XPUStreamGuardOpaque*; + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_create_xpu_stream_guard( + void* stream, + int32_t device_index, + XPUStreamGuardHandle* ret_guard // returns new reference +); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_delete_xpu_stream_guard(XPUStreamGuardHandle guard); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_get_current_xpu_stream(int32_t device_index, void** ret_stream); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_get_current_xpu_device(int32_t* device_index); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_set_current_xpu_device(const int32_t& device_index); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_get_current_sycl_queue(void** ret); + +#if AT_MKLDNN_ENABLED() + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_xpu_mkldnn__convolution_pointwise_binary( + AtenTensorHandle X, + AtenTensorHandle other, + AtenTensorHandle W, + AtenTensorHandle* B, + const int64_t* padding, + int64_t padding_len_, + const int64_t* stride, + int64_t stride_len_, + const int64_t* dilation, + int64_t dilation_len_, + int64_t groups, + const char* binary_attr, + double* alpha, + const char** unary_attr, + const double** unary_scalars, + int64_t unary_scalars_len_, + const char** unary_algorithm, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_mkldnn__convolution_pointwise( + AtenTensorHandle X, + AtenTensorHandle W, + AtenTensorHandle* B, + const int64_t* padding, + int64_t padding_len_, + const int64_t* stride, + int64_t stride_len_, + const int64_t* dilation, + int64_t dilation_len_, + int64_t groups, + const char* attr, + const double** scalars, + int64_t scalars_len_, + const char** algorithm, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_xpu_mkldnn__convolution_pointwise_binary_( + AtenTensorHandle other, + AtenTensorHandle X, + AtenTensorHandle W, + AtenTensorHandle* B, + const int64_t* padding, + int64_t padding_len_, + const int64_t* stride, + int64_t stride_len_, + const int64_t* dilation, + int64_t dilation_len_, + int64_t groups, + const char* binary_attr, + double* alpha, + const char** unary_attr, + const double** unary_scalars, + int64_t unary_scalars_len_, + const char** unary_algorithm, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__qlinear_pointwise_tensor( + AtenTensorHandle X, + AtenTensorHandle act_scale, + AtenTensorHandle act_zero_point, + AtenTensorHandle onednn_weight, + AtenTensorHandle weight_scales, + AtenTensorHandle weight_zero_points, + AtenTensorHandle* B, + double output_scale, + int64_t output_zero_point, + const int32_t* output_dtype, + const char* post_op_name, + const double** post_op_args, + int64_t post_op_args_len_, + const char* post_op_algorithm, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_xpu__qlinear_pointwise_binary_tensor( + AtenTensorHandle X, + AtenTensorHandle act_scale, + AtenTensorHandle act_zero_point, + AtenTensorHandle onednn_weight, + AtenTensorHandle weight_scales, + AtenTensorHandle weight_zero_points, + AtenTensorHandle* other, + AtenTensorHandle* B, + double output_scale, + int64_t output_zero_point, + const int32_t* output_dtype, + double other_scale, + int64_t other_zero_point, + const char* binary_post_op, + double binary_alpha, + const char* unary_post_op, + const double** unary_post_op_args, + int64_t unary_post_op_args_len_, + const char* unary_post_op_algorithm, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__qconv_pointwise_tensor( + AtenTensorHandle X, + AtenTensorHandle act_scale, + AtenTensorHandle act_zero_point, + AtenTensorHandle onednn_weight, + AtenTensorHandle weight_scales, + AtenTensorHandle weight_zero_points, + AtenTensorHandle* B, + const int64_t* stride, + int64_t stride_len_, + const int64_t* padding, + int64_t padding_len_, + const int64_t* dilation, + int64_t dilation_len_, + int64_t groups, + double output_scale, + int64_t output_zero_point, + const int32_t* output_dtype, + const char* attr, + const double** post_op_args, + int64_t post_op_args_len_, + const char** algorithm, + AtenTensorHandle* ret0); + +AOTI_TORCH_EXPORT AOTITorchError +aoti_torch_xpu__qconv2d_pointwise_binary_tensor( + AtenTensorHandle X, + AtenTensorHandle act_scale, + AtenTensorHandle act_zero_point, + AtenTensorHandle onednn_weight, + AtenTensorHandle weight_scales, + AtenTensorHandle weight_zero_points, + AtenTensorHandle accum, + AtenTensorHandle* B, + const int64_t* stride_args, + int64_t stride_len_, + const int64_t* padding_args, + int64_t padding_len_, + const int64_t* dilation_args, + int64_t dilation_len_, + int64_t groups, + double output_scale, + int64_t output_zero_point, + const int32_t* output_dtype, + double accum_scale, + int64_t accum_zero_point, + const char* binary_attr, + double* alpha, + const char** unary_attr, + const double** unary_scalars, + int64_t unary_scalars_len_, + const char** unary_algorithm, + AtenTensorHandle* ret0); + +#endif // AT_MKLDNN_ENABLED() +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // USE_XPU +#endif // AOTI_TORCH_SHIM_XPU diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated/c_shim_aten.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated/c_shim_aten.h new file mode 100644 index 0000000000000000000000000000000000000000..96348d6a129be1c1be09b3e716edd6133315d840 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated/c_shim_aten.h @@ -0,0 +1,28 @@ + + +// WARNING: THIS FILE IS AUTOGENERATED BY torchgen. DO NOT MODIFY BY HAND. +// See https://github.com/pytorch/pytorch/blob/7e86a7c0155295539996e0cf422883571126073e/torchgen/gen.py#L2424-L2436 for details + +// This file corresponds to the aten_shimified_ops list in torchgen/aoti/fallback_ops.py + + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_aten_amax(AtenTensorHandle self, const int64_t* dim, int64_t dim_len_, int32_t keepdim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_aten_fill__Scalar(AtenTensorHandle self, double value); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_aten_full(const int64_t* size, int64_t size_len_, double fill_value, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_aten_narrow(AtenTensorHandle self, int64_t dim, int64_t start, int64_t length, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_aten_new_empty(AtenTensorHandle self, const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_aten_new_zeros(AtenTensorHandle self, const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_aten_pad(AtenTensorHandle self, const int64_t* pad, int64_t pad_len_, const char* mode, double* value, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_aten_subtract_Tensor(AtenTensorHandle self, AtenTensorHandle other, double alpha, AtenTensorHandle* ret0); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated/c_shim_cpu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated/c_shim_cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..21ee7438165dc170d6c91de2f50080d82b33d62f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated/c_shim_cpu.h @@ -0,0 +1,168 @@ + + +// WARNING: THIS FILE IS AUTOGENERATED BY torchgen. DO NOT MODIFY BY HAND. +// See https://github.com/pytorch/pytorch/blob/7e86a7c0155295539996e0cf422883571126073e/torchgen/gen.py#L2424-L2436 for details + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__adaptive_avg_pool2d(AtenTensorHandle self, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__adaptive_avg_pool2d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__adaptive_avg_pool3d(AtenTensorHandle self, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__adaptive_avg_pool3d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__addmm_activation(AtenTensorHandle self, AtenTensorHandle mat1, AtenTensorHandle mat2, double beta, double alpha, int32_t use_gelu, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__cdist_backward(AtenTensorHandle grad, AtenTensorHandle x1, AtenTensorHandle x2, double p, AtenTensorHandle cdist, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__cdist_forward(AtenTensorHandle x1, AtenTensorHandle x2, double p, int64_t* compute_mode, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__dyn_quant_matmul_4bit(AtenTensorHandle inp, AtenTensorHandle packed_weights, int64_t block_size, int64_t in_features, int64_t out_features, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__dyn_quant_pack_4bit_weight(AtenTensorHandle weights, AtenTensorHandle scales_zeros, AtenTensorHandle* bias, int64_t block_size, int64_t in_features, int64_t out_features, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__efficientzerotensor(const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__embedding_bag(AtenTensorHandle weight, AtenTensorHandle indices, AtenTensorHandle offsets, int32_t scale_grad_by_freq, int64_t mode, int32_t sparse, AtenTensorHandle* per_sample_weights, int32_t include_last_offset, int64_t padding_idx, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__embedding_bag_dense_backward(AtenTensorHandle grad, AtenTensorHandle indices, AtenTensorHandle offset2bag, AtenTensorHandle bag_size, AtenTensorHandle maximum_indices, int64_t num_weights, int32_t scale_grad_by_freq, int64_t mode, AtenTensorHandle* per_sample_weights, int64_t padding_idx, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__embedding_bag_forward_only(AtenTensorHandle weight, AtenTensorHandle indices, AtenTensorHandle offsets, int32_t scale_grad_by_freq, int64_t mode, int32_t sparse, AtenTensorHandle* per_sample_weights, int32_t include_last_offset, int64_t padding_idx, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__embedding_bag_per_sample_weights_backward(AtenTensorHandle grad, AtenTensorHandle weight, AtenTensorHandle indices, AtenTensorHandle offsets, AtenTensorHandle offset2bag, int64_t mode, int64_t padding_idx, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__fft_c2c(AtenTensorHandle self, const int64_t* dim, int64_t dim_len_, int64_t normalization, int32_t forward, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__fft_r2c(AtenTensorHandle self, const int64_t* dim, int64_t dim_len_, int64_t normalization, int32_t onesided, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__fused_moving_avg_obs_fq_helper(AtenTensorHandle self, AtenTensorHandle observer_on, AtenTensorHandle fake_quant_on, AtenTensorHandle running_min, AtenTensorHandle running_max, AtenTensorHandle scale, AtenTensorHandle zero_point, double averaging_const, int64_t quant_min, int64_t quant_max, int64_t ch_axis, int32_t per_row_fake_quant, int32_t symmetric_quant, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__fused_moving_avg_obs_fq_helper_functional(AtenTensorHandle self, AtenTensorHandle observer_on, AtenTensorHandle fake_quant_on, AtenTensorHandle running_min, AtenTensorHandle running_max, AtenTensorHandle scale, AtenTensorHandle zero_point, double averaging_const, int64_t quant_min, int64_t quant_max, int64_t ch_axis, int32_t per_row_fake_quant, int32_t symmetric_quant, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, AtenTensorHandle* ret4, AtenTensorHandle* ret5); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__fused_rms_norm(AtenTensorHandle input, const int64_t* normalized_shape, int64_t normalized_shape_len_, AtenTensorHandle* weight, double* eps, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__grouped_mm(AtenTensorHandle self, AtenTensorHandle mat2, AtenTensorHandle* offs, AtenTensorHandle* bias, int32_t* out_dtype, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__histogramdd_from_bin_cts(AtenTensorHandle self, const int64_t* bins, int64_t bins_len_, const double** range, int64_t range_len_, AtenTensorHandle* weight, int32_t density, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__int_mm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__pdist_backward(AtenTensorHandle grad, AtenTensorHandle self, double p, AtenTensorHandle pdist, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__pdist_forward(AtenTensorHandle self, double p, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__scaled_dot_product_flash_attention_for_cpu(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, double dropout_p, int32_t is_causal, AtenTensorHandle* attn_mask, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__scaled_dot_product_flash_attention_for_cpu_backward(AtenTensorHandle grad_out, AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle out, AtenTensorHandle logsumexp, double dropout_p, int32_t is_causal, AtenTensorHandle* attn_mask, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__scaled_dot_product_fused_attention_overrideable(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* attn_bias, double dropout_p, int32_t is_causal, int32_t return_debug_mask, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, int64_t* ret4, int64_t* ret5, AtenTensorHandle* ret6, AtenTensorHandle* ret7, AtenTensorHandle* ret8); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__scaled_dot_product_fused_attention_overrideable_backward(AtenTensorHandle grad_out, AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle attn_bias, const int32_t* grad_input_mask, int64_t grad_input_mask_len_, AtenTensorHandle out, AtenTensorHandle logsumexp, AtenTensorHandle cum_seq_q, AtenTensorHandle cum_seq_k, int64_t max_q, int64_t max_k, double dropout_p, int32_t is_causal, AtenTensorHandle philox_seed, AtenTensorHandle philox_offset, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__scaled_mm(AtenTensorHandle self, AtenTensorHandle mat2, AtenTensorHandle scale_a, AtenTensorHandle scale_b, AtenTensorHandle* bias, AtenTensorHandle* scale_result, int32_t* out_dtype, int32_t use_fast_accum, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__scaled_mm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2, AtenTensorHandle scale_a, AtenTensorHandle scale_b, AtenTensorHandle* bias, AtenTensorHandle* scale_result, int32_t* out_dtype, int32_t use_fast_accum); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__segment_reduce_backward(AtenTensorHandle grad, AtenTensorHandle output, AtenTensorHandle data, const char* reduce, AtenTensorHandle* lengths, AtenTensorHandle* offsets, int64_t axis, double* initial, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__to_sparse(AtenTensorHandle self, int32_t* layout, const int64_t** blocksize, int64_t blocksize_len_, int64_t* dense_dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__trilinear(AtenTensorHandle i1, AtenTensorHandle i2, AtenTensorHandle i3, const int64_t* expand1, int64_t expand1_len_, const int64_t* expand2, int64_t expand2_len_, const int64_t* expand3, int64_t expand3_len_, const int64_t* sumdim, int64_t sumdim_len_, int64_t unroll_dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu__weight_int8pack_mm(AtenTensorHandle self, AtenTensorHandle mat2, AtenTensorHandle scales, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_abs(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_adaptive_max_pool2d(AtenTensorHandle self, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_adaptive_max_pool2d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, AtenTensorHandle indices, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_adaptive_max_pool3d(AtenTensorHandle self, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_adaptive_max_pool3d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, AtenTensorHandle indices, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_add_Scalar(AtenTensorHandle self, double other, double alpha, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_add_Tensor(AtenTensorHandle self, AtenTensorHandle other, double alpha, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_addbmm(AtenTensorHandle self, AtenTensorHandle batch1, AtenTensorHandle batch2, double beta, double alpha, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_addmm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat1, AtenTensorHandle mat2, double beta, double alpha); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_addmv(AtenTensorHandle self, AtenTensorHandle mat, AtenTensorHandle vec, double beta, double alpha, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_angle(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_avg_pool2d(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, int32_t ceil_mode, int32_t count_include_pad, int64_t* divisor_override, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_avg_pool2d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, int32_t ceil_mode, int32_t count_include_pad, int64_t* divisor_override, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_avg_pool3d(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, int32_t ceil_mode, int32_t count_include_pad, int64_t* divisor_override, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_avg_pool3d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, int32_t ceil_mode, int32_t count_include_pad, int64_t* divisor_override, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_baddbmm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle batch1, AtenTensorHandle batch2, double beta, double alpha); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_bernoulli__Tensor(AtenTensorHandle self, AtenTensorHandle p, AtenGeneratorHandle* generator); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_bernoulli__float(AtenTensorHandle self, double p, AtenGeneratorHandle* generator); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_bmm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_bucketize_Tensor(AtenTensorHandle self, AtenTensorHandle boundaries, int32_t out_int32, int32_t right, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_cat(const AtenTensorHandle* tensors, int64_t tensors_len_, int64_t dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_cholesky_inverse(AtenTensorHandle self, int32_t upper, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_cholesky_solve(AtenTensorHandle self, AtenTensorHandle input2, int32_t upper, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_convolution(AtenTensorHandle input, AtenTensorHandle weight, AtenTensorHandle* bias, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t transposed, const int64_t* output_padding, int64_t output_padding_len_, int64_t groups, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_convolution_backward(AtenTensorHandle grad_output, AtenTensorHandle input, AtenTensorHandle weight, const int64_t** bias_sizes, int64_t bias_sizes_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t transposed, const int64_t* output_padding, int64_t output_padding_len_, int64_t groups, const int32_t* output_mask, int64_t output_mask_len_, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_cummax(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_cummin(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_cumprod(AtenTensorHandle self, int64_t dim, int32_t* dtype, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_cumsum(AtenTensorHandle self, int64_t dim, int32_t* dtype, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_exponential(AtenTensorHandle self, double lambd, AtenGeneratorHandle* generator, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_fill__Scalar(AtenTensorHandle self, double value); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_fractional_max_pool2d(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle random_samples, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_fractional_max_pool2d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle indices, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_fractional_max_pool3d(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle random_samples, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_fractional_max_pool3d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle indices, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_gcd(AtenTensorHandle self, AtenTensorHandle other, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_geqrf(AtenTensorHandle self, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_grid_sampler_2d_backward(AtenTensorHandle grad_output, AtenTensorHandle input, AtenTensorHandle grid, int64_t interpolation_mode, int64_t padding_mode, int32_t align_corners, const int32_t* output_mask, int64_t output_mask_len_, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_hann_window(int64_t window_length, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_histc(AtenTensorHandle self, int64_t bins, double min, double max, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_histogram_bin_ct(AtenTensorHandle self, int64_t bins, const double** range, int64_t range_len_, AtenTensorHandle* weight, int32_t density, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_index_Tensor(AtenTensorHandle self, const AtenTensorHandle** indices, int64_t indices_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_index_put(AtenTensorHandle self, const AtenTensorHandle** indices, int64_t indices_len_, AtenTensorHandle values, int32_t accumulate, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_index_reduce(AtenTensorHandle self, int64_t dim, AtenTensorHandle index, AtenTensorHandle source, const char* reduce, int32_t include_self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_kthvalue(AtenTensorHandle self, int64_t k, int64_t dim, int32_t keepdim, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_logcumsumexp(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_lu_unpack(AtenTensorHandle LU_data, AtenTensorHandle LU_pivots, int32_t unpack_data, int32_t unpack_pivots, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_masked_scatter(AtenTensorHandle self, AtenTensorHandle mask, AtenTensorHandle source, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_masked_scatter_backward(AtenTensorHandle grad_output, AtenTensorHandle mask, const int64_t* sizes, int64_t sizes_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_masked_select(AtenTensorHandle self, AtenTensorHandle mask, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_max_pool2d_with_indices(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t ceil_mode, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_max_pool2d_with_indices_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t ceil_mode, AtenTensorHandle indices, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_max_pool3d_with_indices(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t ceil_mode, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_max_pool3d_with_indices_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t ceil_mode, AtenTensorHandle indices, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_max_unpool2d(AtenTensorHandle self, AtenTensorHandle indices, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_max_unpool3d(AtenTensorHandle self, AtenTensorHandle indices, const int64_t* output_size, int64_t output_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_median(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_mm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_mode(AtenTensorHandle self, int64_t dim, int32_t keepdim, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_mul_Scalar(AtenTensorHandle self, double other, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_mul_Tensor(AtenTensorHandle self, AtenTensorHandle other, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_nanmedian(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_narrow(AtenTensorHandle self, int64_t dim, int64_t start, int64_t length, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_native_dropout(AtenTensorHandle input, double p, int32_t* train, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_nonzero(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_nonzero_static(AtenTensorHandle self, int64_t size, int64_t fill_value, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_normal_functional(AtenTensorHandle self, double mean, double std, AtenGeneratorHandle* generator, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_ormqr(AtenTensorHandle self, AtenTensorHandle input2, AtenTensorHandle input3, int32_t left, int32_t transpose, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_pad(AtenTensorHandle self, const int64_t* pad, int64_t pad_len_, const char* mode, double* value, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_permute(AtenTensorHandle self, const int64_t* dims, int64_t dims_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_polar(AtenTensorHandle abs, AtenTensorHandle angle, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_pow_Scalar(double self, AtenTensorHandle exponent, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_pow_Tensor_Scalar(AtenTensorHandle self, double exponent, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_pow_Tensor_Tensor(AtenTensorHandle self, AtenTensorHandle exponent, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_rand(const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_rand_generator(const int64_t* size, int64_t size_len_, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_rand_like(AtenTensorHandle self, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_rand_like_generator(AtenTensorHandle self, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_randint(int64_t high, const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_randint_generator(int64_t high, const int64_t* size, int64_t size_len_, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_randint_low(int64_t low, int64_t high, const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_randint_low_out(AtenTensorHandle out, int64_t low, int64_t high, const int64_t* size, int64_t size_len_); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_randint_like(AtenTensorHandle self, int64_t high, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_randint_like_low_dtype(AtenTensorHandle self, int64_t low, int64_t high, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_randn(const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_randn_generator(const int64_t* size, int64_t size_len_, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_randn_like(AtenTensorHandle self, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_randn_like_generator(AtenTensorHandle self, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_randperm(int64_t n, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_repeat_interleave_Tensor(AtenTensorHandle repeats, int64_t* output_size, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_replication_pad1d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* padding, int64_t padding_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_replication_pad2d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* padding, int64_t padding_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_reshape(AtenTensorHandle self, const int64_t* shape, int64_t shape_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_resize_(AtenTensorHandle self, const int64_t* size, int64_t size_len_, int32_t* memory_format); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_resize_as_(AtenTensorHandle self, AtenTensorHandle the_template, int32_t* memory_format); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_scatter_src_out(AtenTensorHandle out, AtenTensorHandle self, int64_t dim, AtenTensorHandle index, AtenTensorHandle src); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_scatter_value_out(AtenTensorHandle out, AtenTensorHandle self, int64_t dim, AtenTensorHandle index, double value); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_scatter_reduce_two_out(AtenTensorHandle out, AtenTensorHandle self, int64_t dim, AtenTensorHandle index, AtenTensorHandle src, const char* reduce, int32_t include_self); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_searchsorted_Scalar(AtenTensorHandle sorted_sequence, double self, int32_t out_int32, int32_t right, const char** side, AtenTensorHandle* sorter, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_searchsorted_Tensor(AtenTensorHandle sorted_sequence, AtenTensorHandle self, int32_t out_int32, int32_t right, const char** side, AtenTensorHandle* sorter, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_segment_reduce(AtenTensorHandle data, const char* reduce, AtenTensorHandle* lengths, AtenTensorHandle* indices, AtenTensorHandle* offsets, int64_t axis, int32_t unsafe, double* initial, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_set__source_Tensor(AtenTensorHandle self, AtenTensorHandle source); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_slice_Tensor(AtenTensorHandle self, int64_t dim, int64_t* start, int64_t* end, int64_t step, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_soft_margin_loss_backward(AtenTensorHandle grad_output, AtenTensorHandle self, AtenTensorHandle target, int64_t reduction, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_sort(AtenTensorHandle self, int64_t dim, int32_t descending, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_sort_stable(AtenTensorHandle self, int32_t* stable, int64_t dim, int32_t descending, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_squeeze_dim(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_to_sparse(AtenTensorHandle self, int32_t* layout, const int64_t** blocksize, int64_t blocksize_len_, int64_t* dense_dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_topk(AtenTensorHandle self, int64_t k, int64_t dim, int32_t largest, int32_t sorted, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_triangular_solve(AtenTensorHandle self, AtenTensorHandle A, int32_t upper, int32_t transpose, int32_t unitriangular, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_uniform(AtenTensorHandle self, double from, double to, AtenGeneratorHandle* generator, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_upsample_bicubic2d_backward(AtenTensorHandle grad_output, const int64_t* output_size, int64_t output_size_len_, const int64_t* input_size, int64_t input_size_len_, int32_t align_corners, double* scales_h, double* scales_w, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_upsample_linear1d_backward(AtenTensorHandle grad_output, const int64_t* output_size, int64_t output_size_len_, const int64_t* input_size, int64_t input_size_len_, int32_t align_corners, double* scales, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_upsample_trilinear3d_backward(AtenTensorHandle grad_output, const int64_t* output_size, int64_t output_size_len_, const int64_t* input_size, int64_t input_size_len_, int32_t align_corners, double* scales_d, double* scales_h, double* scales_w, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_view_dtype(AtenTensorHandle self, int32_t dtype, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_view_as_complex(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cpu_view_as_real(AtenTensorHandle self, AtenTensorHandle* ret0); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated/c_shim_cuda.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated/c_shim_cuda.h new file mode 100644 index 0000000000000000000000000000000000000000..413a393f6fa7de6abbdca892666ee04f11c4e455 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated/c_shim_cuda.h @@ -0,0 +1,182 @@ + + +// WARNING: THIS FILE IS AUTOGENERATED BY torchgen. DO NOT MODIFY BY HAND. +// See https://github.com/pytorch/pytorch/blob/7e86a7c0155295539996e0cf422883571126073e/torchgen/gen.py#L2424-L2436 for details + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__adaptive_avg_pool2d(AtenTensorHandle self, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__adaptive_avg_pool2d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__adaptive_avg_pool3d(AtenTensorHandle self, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__adaptive_avg_pool3d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__addmm_activation(AtenTensorHandle self, AtenTensorHandle mat1, AtenTensorHandle mat2, double beta, double alpha, int32_t use_gelu, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__cdist_backward(AtenTensorHandle grad, AtenTensorHandle x1, AtenTensorHandle x2, double p, AtenTensorHandle cdist, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__cdist_forward(AtenTensorHandle x1, AtenTensorHandle x2, double p, int64_t* compute_mode, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__cudnn_rnn(AtenTensorHandle input, const AtenTensorHandle* weight, int64_t weight_len_, int64_t weight_stride0, AtenTensorHandle* weight_buf, AtenTensorHandle hx, AtenTensorHandle* cx, int64_t mode, int64_t hidden_size, int64_t proj_size, int64_t num_layers, int32_t batch_first, double dropout, int32_t train, int32_t bidirectional, const int64_t* batch_sizes, int64_t batch_sizes_len_, AtenTensorHandle* dropout_state, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, AtenTensorHandle* ret4); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__efficient_attention_backward(AtenTensorHandle grad_out_, AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* bias, AtenTensorHandle out, AtenTensorHandle* cu_seqlens_q, AtenTensorHandle* cu_seqlens_k, int64_t max_seqlen_q, int64_t max_seqlen_k, AtenTensorHandle logsumexp, double dropout_p, AtenTensorHandle philox_seed, AtenTensorHandle philox_offset, int64_t custom_mask_type, int32_t bias_requires_grad, double* scale, int64_t* num_splits_key, int64_t* window_size, int32_t shared_storage_dqdkdv, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__efficient_attention_forward(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* bias, AtenTensorHandle* cu_seqlens_q, AtenTensorHandle* cu_seqlens_k, int64_t* max_seqlen_q, int64_t* max_seqlen_k, double dropout_p, int64_t custom_mask_type, int32_t compute_log_sumexp, double* scale, AtenTensorHandle* seqlen_k, int64_t* window_size, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, int64_t* ret4, int64_t* ret5); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__efficientzerotensor(const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__embedding_bag(AtenTensorHandle weight, AtenTensorHandle indices, AtenTensorHandle offsets, int32_t scale_grad_by_freq, int64_t mode, int32_t sparse, AtenTensorHandle* per_sample_weights, int32_t include_last_offset, int64_t padding_idx, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__embedding_bag_dense_backward(AtenTensorHandle grad, AtenTensorHandle indices, AtenTensorHandle offset2bag, AtenTensorHandle bag_size, AtenTensorHandle maximum_indices, int64_t num_weights, int32_t scale_grad_by_freq, int64_t mode, AtenTensorHandle* per_sample_weights, int64_t padding_idx, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__embedding_bag_forward_only(AtenTensorHandle weight, AtenTensorHandle indices, AtenTensorHandle offsets, int32_t scale_grad_by_freq, int64_t mode, int32_t sparse, AtenTensorHandle* per_sample_weights, int32_t include_last_offset, int64_t padding_idx, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__embedding_bag_per_sample_weights_backward(AtenTensorHandle grad, AtenTensorHandle weight, AtenTensorHandle indices, AtenTensorHandle offsets, AtenTensorHandle offset2bag, int64_t mode, int64_t padding_idx, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__fft_c2c(AtenTensorHandle self, const int64_t* dim, int64_t dim_len_, int64_t normalization, int32_t forward, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__fft_r2c(AtenTensorHandle self, const int64_t* dim, int64_t dim_len_, int64_t normalization, int32_t onesided, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__flash_attention_backward(AtenTensorHandle grad_out, AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle out, AtenTensorHandle logsumexp, AtenTensorHandle cum_seq_q, AtenTensorHandle cum_seq_k, int64_t max_q, int64_t max_k, double dropout_p, int32_t is_causal, AtenTensorHandle rng_state, AtenTensorHandle unused, double* scale, int64_t* window_size_left, int64_t* window_size_right, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__flash_attention_forward_v2(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* cum_seq_q, AtenTensorHandle* cum_seq_k, int64_t max_q, int64_t max_k, double dropout_p, int32_t is_causal, int32_t return_debug_mask, double* scale, int64_t* window_size_left, int64_t* window_size_right, AtenTensorHandle* seqused_k, AtenTensorHandle* alibi_slopes, AtenTensorHandle* block_table, int64_t* num_splits, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, AtenTensorHandle* ret4); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__flash_attention_forward(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* cum_seq_q, AtenTensorHandle* cum_seq_k, int64_t max_q, int64_t max_k, double dropout_p, int32_t is_causal, int32_t return_debug_mask, double* scale, int64_t* window_size_left, int64_t* window_size_right, AtenTensorHandle* seqused_k, AtenTensorHandle* alibi_slopes, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, AtenTensorHandle* ret4); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__flash_attention_forward_quantized(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* cum_seq_q, AtenTensorHandle* cum_seq_k, int64_t max_q, int64_t max_k, double dropout_p, int32_t is_causal, int32_t return_debug_mask, AtenTensorHandle* q_descale, AtenTensorHandle* k_descale, AtenTensorHandle* v_descale, double* scale, int64_t* window_size_left, int64_t* window_size_right, AtenTensorHandle* seqused_k, AtenTensorHandle* alibi_slopes, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, AtenTensorHandle* ret4); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__flash_attention_forward_no_dropout_inplace_v2(AtenTensorHandle out, AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* cum_seq_q, AtenTensorHandle* cum_seq_k, int64_t max_q, int64_t max_k, double dropout_p, int32_t is_causal, int32_t return_debug_mask, double* scale, int64_t* window_size_left, int64_t* window_size_right, AtenTensorHandle* seqused_k, AtenTensorHandle* alibi_slopes, AtenTensorHandle* block_table, int64_t* num_splits, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__flash_attention_forward_no_dropout_inplace(AtenTensorHandle out, AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* cum_seq_q, AtenTensorHandle* cum_seq_k, int64_t max_q, int64_t max_k, double dropout_p, int32_t is_causal, int32_t return_debug_mask, double* scale, int64_t* window_size_left, int64_t* window_size_right, AtenTensorHandle* seqused_k, AtenTensorHandle* alibi_slopes, AtenTensorHandle* block_table, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__fused_moving_avg_obs_fq_helper(AtenTensorHandle self, AtenTensorHandle observer_on, AtenTensorHandle fake_quant_on, AtenTensorHandle running_min, AtenTensorHandle running_max, AtenTensorHandle scale, AtenTensorHandle zero_point, double averaging_const, int64_t quant_min, int64_t quant_max, int64_t ch_axis, int32_t per_row_fake_quant, int32_t symmetric_quant, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__fused_moving_avg_obs_fq_helper_functional(AtenTensorHandle self, AtenTensorHandle observer_on, AtenTensorHandle fake_quant_on, AtenTensorHandle running_min, AtenTensorHandle running_max, AtenTensorHandle scale, AtenTensorHandle zero_point, double averaging_const, int64_t quant_min, int64_t quant_max, int64_t ch_axis, int32_t per_row_fake_quant, int32_t symmetric_quant, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, AtenTensorHandle* ret4, AtenTensorHandle* ret5); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__fused_rms_norm(AtenTensorHandle input, const int64_t* normalized_shape, int64_t normalized_shape_len_, AtenTensorHandle* weight, double* eps, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__grouped_mm(AtenTensorHandle self, AtenTensorHandle mat2, AtenTensorHandle* offs, AtenTensorHandle* bias, int32_t* out_dtype, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__int_mm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__pdist_backward(AtenTensorHandle grad, AtenTensorHandle self, double p, AtenTensorHandle pdist, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__pdist_forward(AtenTensorHandle self, double p, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__scaled_dot_product_cudnn_attention(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* attn_bias, int32_t compute_log_sumexp, double dropout_p, int32_t is_causal, int32_t return_debug_mask, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, int64_t* ret4, int64_t* ret5, AtenTensorHandle* ret6, AtenTensorHandle* ret7, AtenTensorHandle* ret8); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__scaled_dot_product_cudnn_attention_backward(AtenTensorHandle grad_out, AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle out, AtenTensorHandle logsumexp, AtenTensorHandle philox_seed, AtenTensorHandle philox_offset, AtenTensorHandle attn_bias, AtenTensorHandle cum_seq_q, AtenTensorHandle cum_seq_k, int64_t max_q, int64_t max_k, double dropout_p, int32_t is_causal, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__scaled_dot_product_efficient_attention(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* attn_bias, int32_t compute_log_sumexp, double dropout_p, int32_t is_causal, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__scaled_dot_product_efficient_attention_backward(AtenTensorHandle grad_out_, AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle attn_bias, AtenTensorHandle out, AtenTensorHandle logsumexp, AtenTensorHandle philox_seed, AtenTensorHandle philox_offset, double dropout_p, const int32_t* grad_input_mask, int64_t grad_input_mask_len_, int32_t is_causal, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__scaled_dot_product_flash_attention(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, double dropout_p, int32_t is_causal, int32_t return_debug_mask, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, int64_t* ret4, int64_t* ret5, AtenTensorHandle* ret6, AtenTensorHandle* ret7, AtenTensorHandle* ret8); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__scaled_dot_product_flash_attention_quantized(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* q_descale, AtenTensorHandle* k_descale, AtenTensorHandle* v_descale, double dropout_p, int32_t is_causal, int32_t return_debug_mask, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, int64_t* ret4, int64_t* ret5, AtenTensorHandle* ret6, AtenTensorHandle* ret7, AtenTensorHandle* ret8); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__scaled_dot_product_flash_attention_backward(AtenTensorHandle grad_out, AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle out, AtenTensorHandle logsumexp, AtenTensorHandle cum_seq_q, AtenTensorHandle cum_seq_k, int64_t max_q, int64_t max_k, double dropout_p, int32_t is_causal, AtenTensorHandle philox_seed, AtenTensorHandle philox_offset, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__scaled_dot_product_fused_attention_overrideable(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* attn_bias, double dropout_p, int32_t is_causal, int32_t return_debug_mask, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, int64_t* ret4, int64_t* ret5, AtenTensorHandle* ret6, AtenTensorHandle* ret7, AtenTensorHandle* ret8); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__scaled_dot_product_fused_attention_overrideable_backward(AtenTensorHandle grad_out, AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle attn_bias, const int32_t* grad_input_mask, int64_t grad_input_mask_len_, AtenTensorHandle out, AtenTensorHandle logsumexp, AtenTensorHandle cum_seq_q, AtenTensorHandle cum_seq_k, int64_t max_q, int64_t max_k, double dropout_p, int32_t is_causal, AtenTensorHandle philox_seed, AtenTensorHandle philox_offset, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__scaled_grouped_mm(AtenTensorHandle self, AtenTensorHandle mat2, AtenTensorHandle scale_a, AtenTensorHandle scale_b, AtenTensorHandle* offs, AtenTensorHandle* bias, AtenTensorHandle* scale_result, int32_t* out_dtype, int32_t use_fast_accum, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__scaled_mm(AtenTensorHandle self, AtenTensorHandle mat2, AtenTensorHandle scale_a, AtenTensorHandle scale_b, AtenTensorHandle* bias, AtenTensorHandle* scale_result, int32_t* out_dtype, int32_t use_fast_accum, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__scaled_mm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2, AtenTensorHandle scale_a, AtenTensorHandle scale_b, AtenTensorHandle* bias, AtenTensorHandle* scale_result, int32_t* out_dtype, int32_t use_fast_accum); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__segment_reduce_backward(AtenTensorHandle grad, AtenTensorHandle output, AtenTensorHandle data, const char* reduce, AtenTensorHandle* lengths, AtenTensorHandle* offsets, int64_t axis, double* initial, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__thnn_fused_lstm_cell(AtenTensorHandle input_gates, AtenTensorHandle hidden_gates, AtenTensorHandle cx, AtenTensorHandle* input_bias, AtenTensorHandle* hidden_bias, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__to_sparse(AtenTensorHandle self, int32_t* layout, const int64_t** blocksize, int64_t blocksize_len_, int64_t* dense_dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__trilinear(AtenTensorHandle i1, AtenTensorHandle i2, AtenTensorHandle i3, const int64_t* expand1, int64_t expand1_len_, const int64_t* expand2, int64_t expand2_len_, const int64_t* expand3, int64_t expand3_len_, const int64_t* sumdim, int64_t sumdim_len_, int64_t unroll_dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__weight_int4pack_mm(AtenTensorHandle self, AtenTensorHandle mat2, int64_t qGroupSize, AtenTensorHandle qScaleAndZeros, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda__weight_int8pack_mm(AtenTensorHandle self, AtenTensorHandle mat2, AtenTensorHandle scales, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_abs(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_adaptive_max_pool2d(AtenTensorHandle self, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_adaptive_max_pool2d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, AtenTensorHandle indices, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_adaptive_max_pool3d(AtenTensorHandle self, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_adaptive_max_pool3d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, AtenTensorHandle indices, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_add_Scalar(AtenTensorHandle self, double other, double alpha, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_add_Tensor(AtenTensorHandle self, AtenTensorHandle other, double alpha, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_addbmm(AtenTensorHandle self, AtenTensorHandle batch1, AtenTensorHandle batch2, double beta, double alpha, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_addmm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat1, AtenTensorHandle mat2, double beta, double alpha); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_addmv(AtenTensorHandle self, AtenTensorHandle mat, AtenTensorHandle vec, double beta, double alpha, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_angle(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_avg_pool2d(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, int32_t ceil_mode, int32_t count_include_pad, int64_t* divisor_override, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_avg_pool2d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, int32_t ceil_mode, int32_t count_include_pad, int64_t* divisor_override, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_avg_pool3d(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, int32_t ceil_mode, int32_t count_include_pad, int64_t* divisor_override, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_avg_pool3d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, int32_t ceil_mode, int32_t count_include_pad, int64_t* divisor_override, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_baddbmm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle batch1, AtenTensorHandle batch2, double beta, double alpha); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_bernoulli__Tensor(AtenTensorHandle self, AtenTensorHandle p, AtenGeneratorHandle* generator); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_bernoulli__float(AtenTensorHandle self, double p, AtenGeneratorHandle* generator); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_bmm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_bucketize_Tensor(AtenTensorHandle self, AtenTensorHandle boundaries, int32_t out_int32, int32_t right, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_cat(const AtenTensorHandle* tensors, int64_t tensors_len_, int64_t dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_cholesky_inverse(AtenTensorHandle self, int32_t upper, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_cholesky_solve(AtenTensorHandle self, AtenTensorHandle input2, int32_t upper, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_convolution(AtenTensorHandle input, AtenTensorHandle weight, AtenTensorHandle* bias, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t transposed, const int64_t* output_padding, int64_t output_padding_len_, int64_t groups, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_convolution_backward(AtenTensorHandle grad_output, AtenTensorHandle input, AtenTensorHandle weight, const int64_t** bias_sizes, int64_t bias_sizes_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t transposed, const int64_t* output_padding, int64_t output_padding_len_, int64_t groups, const int32_t* output_mask, int64_t output_mask_len_, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_cummax(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_cummin(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_cumprod(AtenTensorHandle self, int64_t dim, int32_t* dtype, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_cumsum(AtenTensorHandle self, int64_t dim, int32_t* dtype, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_exponential(AtenTensorHandle self, double lambd, AtenGeneratorHandle* generator, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_fill__Scalar(AtenTensorHandle self, double value); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_fractional_max_pool2d(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle random_samples, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_fractional_max_pool2d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle indices, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_fractional_max_pool3d(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle random_samples, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_fractional_max_pool3d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle indices, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_gcd(AtenTensorHandle self, AtenTensorHandle other, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_geqrf(AtenTensorHandle self, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_grid_sampler_2d_backward(AtenTensorHandle grad_output, AtenTensorHandle input, AtenTensorHandle grid, int64_t interpolation_mode, int64_t padding_mode, int32_t align_corners, const int32_t* output_mask, int64_t output_mask_len_, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_hann_window(int64_t window_length, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_histc(AtenTensorHandle self, int64_t bins, double min, double max, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_index_Tensor(AtenTensorHandle self, const AtenTensorHandle** indices, int64_t indices_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_index_put(AtenTensorHandle self, const AtenTensorHandle** indices, int64_t indices_len_, AtenTensorHandle values, int32_t accumulate, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_index_reduce(AtenTensorHandle self, int64_t dim, AtenTensorHandle index, AtenTensorHandle source, const char* reduce, int32_t include_self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_kthvalue(AtenTensorHandle self, int64_t k, int64_t dim, int32_t keepdim, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_logcumsumexp(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_lu_unpack(AtenTensorHandle LU_data, AtenTensorHandle LU_pivots, int32_t unpack_data, int32_t unpack_pivots, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_masked_scatter(AtenTensorHandle self, AtenTensorHandle mask, AtenTensorHandle source, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_masked_scatter_backward(AtenTensorHandle grad_output, AtenTensorHandle mask, const int64_t* sizes, int64_t sizes_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_masked_select(AtenTensorHandle self, AtenTensorHandle mask, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_max_pool2d_with_indices(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t ceil_mode, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_max_pool2d_with_indices_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t ceil_mode, AtenTensorHandle indices, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_max_pool3d_with_indices(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t ceil_mode, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_max_pool3d_with_indices_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t ceil_mode, AtenTensorHandle indices, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_max_unpool2d(AtenTensorHandle self, AtenTensorHandle indices, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_max_unpool3d(AtenTensorHandle self, AtenTensorHandle indices, const int64_t* output_size, int64_t output_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_median(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_mm_dtype_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2, int32_t out_dtype); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_mm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_mode(AtenTensorHandle self, int64_t dim, int32_t keepdim, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_mul_Scalar(AtenTensorHandle self, double other, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_mul_Tensor(AtenTensorHandle self, AtenTensorHandle other, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_nanmedian(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_narrow(AtenTensorHandle self, int64_t dim, int64_t start, int64_t length, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_native_dropout(AtenTensorHandle input, double p, int32_t* train, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_nonzero(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_nonzero_static(AtenTensorHandle self, int64_t size, int64_t fill_value, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_normal_functional(AtenTensorHandle self, double mean, double std, AtenGeneratorHandle* generator, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_ormqr(AtenTensorHandle self, AtenTensorHandle input2, AtenTensorHandle input3, int32_t left, int32_t transpose, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_pad(AtenTensorHandle self, const int64_t* pad, int64_t pad_len_, const char* mode, double* value, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_permute(AtenTensorHandle self, const int64_t* dims, int64_t dims_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_polar(AtenTensorHandle abs, AtenTensorHandle angle, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_pow_Scalar(double self, AtenTensorHandle exponent, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_pow_Tensor_Scalar(AtenTensorHandle self, double exponent, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_pow_Tensor_Tensor(AtenTensorHandle self, AtenTensorHandle exponent, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_rand(const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_rand_generator(const int64_t* size, int64_t size_len_, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_rand_like(AtenTensorHandle self, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_rand_like_generator(AtenTensorHandle self, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_randint(int64_t high, const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_randint_generator(int64_t high, const int64_t* size, int64_t size_len_, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_randint_low(int64_t low, int64_t high, const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_randint_low_out(AtenTensorHandle out, int64_t low, int64_t high, const int64_t* size, int64_t size_len_); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_randint_like(AtenTensorHandle self, int64_t high, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_randint_like_low_dtype(AtenTensorHandle self, int64_t low, int64_t high, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_randn(const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_randn_generator(const int64_t* size, int64_t size_len_, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_randn_like(AtenTensorHandle self, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_randn_like_generator(AtenTensorHandle self, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_randperm(int64_t n, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_repeat_interleave_Tensor(AtenTensorHandle repeats, int64_t* output_size, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_replication_pad1d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* padding, int64_t padding_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_replication_pad2d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* padding, int64_t padding_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_reshape(AtenTensorHandle self, const int64_t* shape, int64_t shape_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_resize_(AtenTensorHandle self, const int64_t* size, int64_t size_len_, int32_t* memory_format); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_resize_as_(AtenTensorHandle self, AtenTensorHandle the_template, int32_t* memory_format); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_scatter_src_out(AtenTensorHandle out, AtenTensorHandle self, int64_t dim, AtenTensorHandle index, AtenTensorHandle src); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_scatter_value_out(AtenTensorHandle out, AtenTensorHandle self, int64_t dim, AtenTensorHandle index, double value); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_scatter_reduce_two_out(AtenTensorHandle out, AtenTensorHandle self, int64_t dim, AtenTensorHandle index, AtenTensorHandle src, const char* reduce, int32_t include_self); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_searchsorted_Scalar(AtenTensorHandle sorted_sequence, double self, int32_t out_int32, int32_t right, const char** side, AtenTensorHandle* sorter, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_searchsorted_Tensor(AtenTensorHandle sorted_sequence, AtenTensorHandle self, int32_t out_int32, int32_t right, const char** side, AtenTensorHandle* sorter, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_segment_reduce(AtenTensorHandle data, const char* reduce, AtenTensorHandle* lengths, AtenTensorHandle* indices, AtenTensorHandle* offsets, int64_t axis, int32_t unsafe, double* initial, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_set__source_Tensor(AtenTensorHandle self, AtenTensorHandle source); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_slice_Tensor(AtenTensorHandle self, int64_t dim, int64_t* start, int64_t* end, int64_t step, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_soft_margin_loss_backward(AtenTensorHandle grad_output, AtenTensorHandle self, AtenTensorHandle target, int64_t reduction, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_sort(AtenTensorHandle self, int64_t dim, int32_t descending, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_sort_stable(AtenTensorHandle self, int32_t* stable, int64_t dim, int32_t descending, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_squeeze_dim(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_to_sparse(AtenTensorHandle self, int32_t* layout, const int64_t** blocksize, int64_t blocksize_len_, int64_t* dense_dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_topk(AtenTensorHandle self, int64_t k, int64_t dim, int32_t largest, int32_t sorted, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_triangular_solve(AtenTensorHandle self, AtenTensorHandle A, int32_t upper, int32_t transpose, int32_t unitriangular, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_uniform(AtenTensorHandle self, double from, double to, AtenGeneratorHandle* generator, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_upsample_bicubic2d_backward(AtenTensorHandle grad_output, const int64_t* output_size, int64_t output_size_len_, const int64_t* input_size, int64_t input_size_len_, int32_t align_corners, double* scales_h, double* scales_w, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_upsample_linear1d_backward(AtenTensorHandle grad_output, const int64_t* output_size, int64_t output_size_len_, const int64_t* input_size, int64_t input_size_len_, int32_t align_corners, double* scales, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_upsample_trilinear3d_backward(AtenTensorHandle grad_output, const int64_t* output_size, int64_t output_size_len_, const int64_t* input_size, int64_t input_size_len_, int32_t align_corners, double* scales_d, double* scales_h, double* scales_w, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_view_dtype(AtenTensorHandle self, int32_t dtype, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_view_as_complex(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_cuda_view_as_real(AtenTensorHandle self, AtenTensorHandle* ret0); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated/c_shim_mps.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated/c_shim_mps.h new file mode 100644 index 0000000000000000000000000000000000000000..f5fe2cb852d4f9ace1afd32ffa5b424c9854bf39 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated/c_shim_mps.h @@ -0,0 +1,145 @@ + + +// WARNING: THIS FILE IS AUTOGENERATED BY torchgen. DO NOT MODIFY BY HAND. +// See https://github.com/pytorch/pytorch/blob/7e86a7c0155295539996e0cf422883571126073e/torchgen/gen.py#L2424-L2436 for details + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__adaptive_avg_pool2d(AtenTensorHandle self, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__adaptive_avg_pool2d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__cdist_forward(AtenTensorHandle x1, AtenTensorHandle x2, double p, int64_t* compute_mode, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__efficientzerotensor(const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__embedding_bag(AtenTensorHandle weight, AtenTensorHandle indices, AtenTensorHandle offsets, int32_t scale_grad_by_freq, int64_t mode, int32_t sparse, AtenTensorHandle* per_sample_weights, int32_t include_last_offset, int64_t padding_idx, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__embedding_bag_dense_backward(AtenTensorHandle grad, AtenTensorHandle indices, AtenTensorHandle offset2bag, AtenTensorHandle bag_size, AtenTensorHandle maximum_indices, int64_t num_weights, int32_t scale_grad_by_freq, int64_t mode, AtenTensorHandle* per_sample_weights, int64_t padding_idx, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__embedding_bag_forward_only(AtenTensorHandle weight, AtenTensorHandle indices, AtenTensorHandle offsets, int32_t scale_grad_by_freq, int64_t mode, int32_t sparse, AtenTensorHandle* per_sample_weights, int32_t include_last_offset, int64_t padding_idx, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__embedding_bag_per_sample_weights_backward(AtenTensorHandle grad, AtenTensorHandle weight, AtenTensorHandle indices, AtenTensorHandle offsets, AtenTensorHandle offset2bag, int64_t mode, int64_t padding_idx, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__fft_c2c(AtenTensorHandle self, const int64_t* dim, int64_t dim_len_, int64_t normalization, int32_t forward, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__fft_r2c(AtenTensorHandle self, const int64_t* dim, int64_t dim_len_, int64_t normalization, int32_t onesided, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__fused_moving_avg_obs_fq_helper_functional(AtenTensorHandle self, AtenTensorHandle observer_on, AtenTensorHandle fake_quant_on, AtenTensorHandle running_min, AtenTensorHandle running_max, AtenTensorHandle scale, AtenTensorHandle zero_point, double averaging_const, int64_t quant_min, int64_t quant_max, int64_t ch_axis, int32_t per_row_fake_quant, int32_t symmetric_quant, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, AtenTensorHandle* ret4, AtenTensorHandle* ret5); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__fused_rms_norm(AtenTensorHandle input, const int64_t* normalized_shape, int64_t normalized_shape_len_, AtenTensorHandle* weight, double* eps, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__grouped_mm(AtenTensorHandle self, AtenTensorHandle mat2, AtenTensorHandle* offs, AtenTensorHandle* bias, int32_t* out_dtype, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__histogramdd_from_bin_cts(AtenTensorHandle self, const int64_t* bins, int64_t bins_len_, const double** range, int64_t range_len_, AtenTensorHandle* weight, int32_t density, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__scaled_dot_product_attention_math_for_mps_v2(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* attn_mask, double dropout_p, int32_t is_causal, AtenTensorHandle* dropout_mask, double* scale, int32_t enable_gqa, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__scaled_dot_product_attention_math_for_mps(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* attn_mask, double dropout_p, int32_t is_causal, AtenTensorHandle* dropout_mask, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__scaled_dot_product_fused_attention_overrideable(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* attn_bias, double dropout_p, int32_t is_causal, int32_t return_debug_mask, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, int64_t* ret4, int64_t* ret5, AtenTensorHandle* ret6, AtenTensorHandle* ret7, AtenTensorHandle* ret8); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__scaled_dot_product_fused_attention_overrideable_backward(AtenTensorHandle grad_out, AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle attn_bias, const int32_t* grad_input_mask, int64_t grad_input_mask_len_, AtenTensorHandle out, AtenTensorHandle logsumexp, AtenTensorHandle cum_seq_q, AtenTensorHandle cum_seq_k, int64_t max_q, int64_t max_k, double dropout_p, int32_t is_causal, AtenTensorHandle philox_seed, AtenTensorHandle philox_offset, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__to_sparse(AtenTensorHandle self, int32_t* layout, const int64_t** blocksize, int64_t blocksize_len_, int64_t* dense_dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__trilinear(AtenTensorHandle i1, AtenTensorHandle i2, AtenTensorHandle i3, const int64_t* expand1, int64_t expand1_len_, const int64_t* expand2, int64_t expand2_len_, const int64_t* expand3, int64_t expand3_len_, const int64_t* sumdim, int64_t sumdim_len_, int64_t unroll_dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__weight_int4pack_mm(AtenTensorHandle self, AtenTensorHandle mat2, int64_t qGroupSize, AtenTensorHandle qScaleAndZeros, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps__weight_int8pack_mm(AtenTensorHandle self, AtenTensorHandle mat2, AtenTensorHandle scales, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_abs(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_adaptive_max_pool2d(AtenTensorHandle self, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_adaptive_max_pool2d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, AtenTensorHandle indices, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_add_Scalar(AtenTensorHandle self, double other, double alpha, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_add_Tensor(AtenTensorHandle self, AtenTensorHandle other, double alpha, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_addbmm(AtenTensorHandle self, AtenTensorHandle batch1, AtenTensorHandle batch2, double beta, double alpha, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_addmm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat1, AtenTensorHandle mat2, double beta, double alpha); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_addmv(AtenTensorHandle self, AtenTensorHandle mat, AtenTensorHandle vec, double beta, double alpha, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_angle(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_avg_pool2d(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, int32_t ceil_mode, int32_t count_include_pad, int64_t* divisor_override, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_avg_pool2d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, int32_t ceil_mode, int32_t count_include_pad, int64_t* divisor_override, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_avg_pool3d(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, int32_t ceil_mode, int32_t count_include_pad, int64_t* divisor_override, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_avg_pool3d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, int32_t ceil_mode, int32_t count_include_pad, int64_t* divisor_override, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_baddbmm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle batch1, AtenTensorHandle batch2, double beta, double alpha); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_bernoulli__Tensor(AtenTensorHandle self, AtenTensorHandle p, AtenGeneratorHandle* generator); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_bernoulli__float(AtenTensorHandle self, double p, AtenGeneratorHandle* generator); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_bmm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_bucketize_Tensor(AtenTensorHandle self, AtenTensorHandle boundaries, int32_t out_int32, int32_t right, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_cat(const AtenTensorHandle* tensors, int64_t tensors_len_, int64_t dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_cholesky_inverse(AtenTensorHandle self, int32_t upper, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_cholesky_solve(AtenTensorHandle self, AtenTensorHandle input2, int32_t upper, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_convolution(AtenTensorHandle input, AtenTensorHandle weight, AtenTensorHandle* bias, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t transposed, const int64_t* output_padding, int64_t output_padding_len_, int64_t groups, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_convolution_backward(AtenTensorHandle grad_output, AtenTensorHandle input, AtenTensorHandle weight, const int64_t** bias_sizes, int64_t bias_sizes_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t transposed, const int64_t* output_padding, int64_t output_padding_len_, int64_t groups, const int32_t* output_mask, int64_t output_mask_len_, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_cummax(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_cummin(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_cumprod(AtenTensorHandle self, int64_t dim, int32_t* dtype, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_cumsum(AtenTensorHandle self, int64_t dim, int32_t* dtype, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_exponential(AtenTensorHandle self, double lambd, AtenGeneratorHandle* generator, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_fill__Scalar(AtenTensorHandle self, double value); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_gcd(AtenTensorHandle self, AtenTensorHandle other, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_hann_window(int64_t window_length, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_histc(AtenTensorHandle self, int64_t bins, double min, double max, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_histogram_bin_ct(AtenTensorHandle self, int64_t bins, const double** range, int64_t range_len_, AtenTensorHandle* weight, int32_t density, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_index_Tensor(AtenTensorHandle self, const AtenTensorHandle** indices, int64_t indices_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_index_put(AtenTensorHandle self, const AtenTensorHandle** indices, int64_t indices_len_, AtenTensorHandle values, int32_t accumulate, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_index_reduce(AtenTensorHandle self, int64_t dim, AtenTensorHandle index, AtenTensorHandle source, const char* reduce, int32_t include_self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_kthvalue(AtenTensorHandle self, int64_t k, int64_t dim, int32_t keepdim, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_logcumsumexp(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_lu_unpack(AtenTensorHandle LU_data, AtenTensorHandle LU_pivots, int32_t unpack_data, int32_t unpack_pivots, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_masked_scatter(AtenTensorHandle self, AtenTensorHandle mask, AtenTensorHandle source, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_masked_scatter_backward(AtenTensorHandle grad_output, AtenTensorHandle mask, const int64_t* sizes, int64_t sizes_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_masked_select(AtenTensorHandle self, AtenTensorHandle mask, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_max_pool2d_with_indices(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t ceil_mode, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_max_pool2d_with_indices_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t ceil_mode, AtenTensorHandle indices, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_max_pool3d_with_indices(AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t ceil_mode, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_max_pool3d_with_indices_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* kernel_size, int64_t kernel_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t ceil_mode, AtenTensorHandle indices, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_max_unpool2d(AtenTensorHandle self, AtenTensorHandle indices, const int64_t* output_size, int64_t output_size_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_max_unpool3d(AtenTensorHandle self, AtenTensorHandle indices, const int64_t* output_size, int64_t output_size_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_median(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_mm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_mul_Scalar(AtenTensorHandle self, double other, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_mul_Tensor(AtenTensorHandle self, AtenTensorHandle other, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_nanmedian(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_narrow(AtenTensorHandle self, int64_t dim, int64_t start, int64_t length, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_native_dropout(AtenTensorHandle input, double p, int32_t* train, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_nonzero(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_nonzero_static(AtenTensorHandle self, int64_t size, int64_t fill_value, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_normal_functional(AtenTensorHandle self, double mean, double std, AtenGeneratorHandle* generator, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_pad(AtenTensorHandle self, const int64_t* pad, int64_t pad_len_, const char* mode, double* value, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_permute(AtenTensorHandle self, const int64_t* dims, int64_t dims_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_polar(AtenTensorHandle abs, AtenTensorHandle angle, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_pow_Scalar(double self, AtenTensorHandle exponent, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_pow_Tensor_Scalar(AtenTensorHandle self, double exponent, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_pow_Tensor_Tensor(AtenTensorHandle self, AtenTensorHandle exponent, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_rand(const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_rand_generator(const int64_t* size, int64_t size_len_, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_rand_like(AtenTensorHandle self, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_rand_like_generator(AtenTensorHandle self, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_randint(int64_t high, const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_randint_generator(int64_t high, const int64_t* size, int64_t size_len_, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_randint_low(int64_t low, int64_t high, const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_randint_low_out(AtenTensorHandle out, int64_t low, int64_t high, const int64_t* size, int64_t size_len_); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_randint_like(AtenTensorHandle self, int64_t high, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_randint_like_low_dtype(AtenTensorHandle self, int64_t low, int64_t high, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_randn(const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_randn_generator(const int64_t* size, int64_t size_len_, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_randn_like(AtenTensorHandle self, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_randn_like_generator(AtenTensorHandle self, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_randperm(int64_t n, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_repeat_interleave_Tensor(AtenTensorHandle repeats, int64_t* output_size, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_replication_pad1d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* padding, int64_t padding_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_replication_pad2d_backward(AtenTensorHandle grad_output, AtenTensorHandle self, const int64_t* padding, int64_t padding_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_reshape(AtenTensorHandle self, const int64_t* shape, int64_t shape_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_resize_(AtenTensorHandle self, const int64_t* size, int64_t size_len_, int32_t* memory_format); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_resize_as_(AtenTensorHandle self, AtenTensorHandle the_template, int32_t* memory_format); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_scatter_src_out(AtenTensorHandle out, AtenTensorHandle self, int64_t dim, AtenTensorHandle index, AtenTensorHandle src); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_scatter_value_out(AtenTensorHandle out, AtenTensorHandle self, int64_t dim, AtenTensorHandle index, double value); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_scatter_reduce_two_out(AtenTensorHandle out, AtenTensorHandle self, int64_t dim, AtenTensorHandle index, AtenTensorHandle src, const char* reduce, int32_t include_self); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_searchsorted_Scalar(AtenTensorHandle sorted_sequence, double self, int32_t out_int32, int32_t right, const char** side, AtenTensorHandle* sorter, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_searchsorted_Tensor(AtenTensorHandle sorted_sequence, AtenTensorHandle self, int32_t out_int32, int32_t right, const char** side, AtenTensorHandle* sorter, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_set__source_Tensor(AtenTensorHandle self, AtenTensorHandle source); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_slice_Tensor(AtenTensorHandle self, int64_t dim, int64_t* start, int64_t* end, int64_t step, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_soft_margin_loss_backward(AtenTensorHandle grad_output, AtenTensorHandle self, AtenTensorHandle target, int64_t reduction, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_sort(AtenTensorHandle self, int64_t dim, int32_t descending, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_sort_stable(AtenTensorHandle self, int32_t* stable, int64_t dim, int32_t descending, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_squeeze_dim(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_to_sparse(AtenTensorHandle self, int32_t* layout, const int64_t** blocksize, int64_t blocksize_len_, int64_t* dense_dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_topk(AtenTensorHandle self, int64_t k, int64_t dim, int32_t largest, int32_t sorted, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_triangular_solve(AtenTensorHandle self, AtenTensorHandle A, int32_t upper, int32_t transpose, int32_t unitriangular, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_uniform(AtenTensorHandle self, double from, double to, AtenGeneratorHandle* generator, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_upsample_bicubic2d_backward(AtenTensorHandle grad_output, const int64_t* output_size, int64_t output_size_len_, const int64_t* input_size, int64_t input_size_len_, int32_t align_corners, double* scales_h, double* scales_w, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_upsample_linear1d_backward(AtenTensorHandle grad_output, const int64_t* output_size, int64_t output_size_len_, const int64_t* input_size, int64_t input_size_len_, int32_t align_corners, double* scales, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_upsample_trilinear3d_backward(AtenTensorHandle grad_output, const int64_t* output_size, int64_t output_size_len_, const int64_t* input_size, int64_t input_size_len_, int32_t align_corners, double* scales_d, double* scales_h, double* scales_w, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_view_dtype(AtenTensorHandle self, int32_t dtype, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_view_as_complex(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_mps_view_as_real(AtenTensorHandle self, AtenTensorHandle* ret0); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated/c_shim_xpu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated/c_shim_xpu.h new file mode 100644 index 0000000000000000000000000000000000000000..ea0cbfdc5659d4489db74954c46c772a9abff471 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated/c_shim_xpu.h @@ -0,0 +1,82 @@ + + +// WARNING: THIS FILE IS AUTOGENERATED BY torchgen. DO NOT MODIFY BY HAND. +// See https://github.com/pytorch/pytorch/blob/7e86a7c0155295539996e0cf422883571126073e/torchgen/gen.py#L2424-L2436 for details + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__addmm_activation(AtenTensorHandle self, AtenTensorHandle mat1, AtenTensorHandle mat2, double beta, double alpha, int32_t use_gelu, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__fused_moving_avg_obs_fq_helper_functional(AtenTensorHandle self, AtenTensorHandle observer_on, AtenTensorHandle fake_quant_on, AtenTensorHandle running_min, AtenTensorHandle running_max, AtenTensorHandle scale, AtenTensorHandle zero_point, double averaging_const, int64_t quant_min, int64_t quant_max, int64_t ch_axis, int32_t per_row_fake_quant, int32_t symmetric_quant, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, AtenTensorHandle* ret4, AtenTensorHandle* ret5); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__fused_rms_norm(AtenTensorHandle input, const int64_t* normalized_shape, int64_t normalized_shape_len_, AtenTensorHandle* weight, double* eps, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__grouped_mm(AtenTensorHandle self, AtenTensorHandle mat2, AtenTensorHandle* offs, AtenTensorHandle* bias, int32_t* out_dtype, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__int_mm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__scaled_dot_product_flash_attention(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, double dropout_p, int32_t is_causal, int32_t return_debug_mask, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, int64_t* ret4, int64_t* ret5, AtenTensorHandle* ret6, AtenTensorHandle* ret7, AtenTensorHandle* ret8); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__scaled_dot_product_flash_attention_backward(AtenTensorHandle grad_out, AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle out, AtenTensorHandle logsumexp, AtenTensorHandle cum_seq_q, AtenTensorHandle cum_seq_k, int64_t max_q, int64_t max_k, double dropout_p, int32_t is_causal, AtenTensorHandle philox_seed, AtenTensorHandle philox_offset, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__scaled_dot_product_fused_attention_overrideable(AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle* attn_bias, double dropout_p, int32_t is_causal, int32_t return_debug_mask, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3, int64_t* ret4, int64_t* ret5, AtenTensorHandle* ret6, AtenTensorHandle* ret7, AtenTensorHandle* ret8); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__scaled_dot_product_fused_attention_overrideable_backward(AtenTensorHandle grad_out, AtenTensorHandle query, AtenTensorHandle key, AtenTensorHandle value, AtenTensorHandle attn_bias, const int32_t* grad_input_mask, int64_t grad_input_mask_len_, AtenTensorHandle out, AtenTensorHandle logsumexp, AtenTensorHandle cum_seq_q, AtenTensorHandle cum_seq_k, int64_t max_q, int64_t max_k, double dropout_p, int32_t is_causal, AtenTensorHandle philox_seed, AtenTensorHandle philox_offset, double* scale, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2, AtenTensorHandle* ret3); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__scaled_mm(AtenTensorHandle self, AtenTensorHandle mat2, AtenTensorHandle scale_a, AtenTensorHandle scale_b, AtenTensorHandle* bias, AtenTensorHandle* scale_result, int32_t* out_dtype, int32_t use_fast_accum, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__scaled_mm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2, AtenTensorHandle scale_a, AtenTensorHandle scale_b, AtenTensorHandle* bias, AtenTensorHandle* scale_result, int32_t* out_dtype, int32_t use_fast_accum); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__trilinear(AtenTensorHandle i1, AtenTensorHandle i2, AtenTensorHandle i3, const int64_t* expand1, int64_t expand1_len_, const int64_t* expand2, int64_t expand2_len_, const int64_t* expand3, int64_t expand3_len_, const int64_t* sumdim, int64_t sumdim_len_, int64_t unroll_dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__weight_int4pack_mm_with_scales_and_zeros(AtenTensorHandle self, AtenTensorHandle mat2, int64_t qGroupSize, AtenTensorHandle qScale, AtenTensorHandle qZeros, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu__weight_int8pack_mm(AtenTensorHandle self, AtenTensorHandle mat2, AtenTensorHandle scales, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_abs(AtenTensorHandle self, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_add_Scalar(AtenTensorHandle self, double other, double alpha, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_addbmm(AtenTensorHandle self, AtenTensorHandle batch1, AtenTensorHandle batch2, double beta, double alpha, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_addmm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat1, AtenTensorHandle mat2, double beta, double alpha); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_addmv(AtenTensorHandle self, AtenTensorHandle mat, AtenTensorHandle vec, double beta, double alpha, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_baddbmm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle batch1, AtenTensorHandle batch2, double beta, double alpha); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_bmm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_cholesky_solve(AtenTensorHandle self, AtenTensorHandle input2, int32_t upper, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_convolution(AtenTensorHandle input, AtenTensorHandle weight, AtenTensorHandle* bias, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t transposed, const int64_t* output_padding, int64_t output_padding_len_, int64_t groups, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_convolution_backward(AtenTensorHandle grad_output, AtenTensorHandle input, AtenTensorHandle weight, const int64_t** bias_sizes, int64_t bias_sizes_len_, const int64_t* stride, int64_t stride_len_, const int64_t* padding, int64_t padding_len_, const int64_t* dilation, int64_t dilation_len_, int32_t transposed, const int64_t* output_padding, int64_t output_padding_len_, int64_t groups, const int32_t* output_mask, int64_t output_mask_len_, AtenTensorHandle* ret0, AtenTensorHandle* ret1, AtenTensorHandle* ret2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_cummax(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_cummin(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_exponential(AtenTensorHandle self, double lambd, AtenGeneratorHandle* generator, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_hann_window(int64_t window_length, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_index_put(AtenTensorHandle self, const AtenTensorHandle** indices, int64_t indices_len_, AtenTensorHandle values, int32_t accumulate, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_kthvalue(AtenTensorHandle self, int64_t k, int64_t dim, int32_t keepdim, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_logcumsumexp(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_masked_scatter(AtenTensorHandle self, AtenTensorHandle mask, AtenTensorHandle source, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_masked_scatter_backward(AtenTensorHandle grad_output, AtenTensorHandle mask, const int64_t* sizes, int64_t sizes_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_mm_dtype_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2, int32_t out_dtype); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_mm_out(AtenTensorHandle out, AtenTensorHandle self, AtenTensorHandle mat2); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_mul_Scalar(AtenTensorHandle self, double other, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_narrow(AtenTensorHandle self, int64_t dim, int64_t start, int64_t length, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_normal_functional(AtenTensorHandle self, double mean, double std, AtenGeneratorHandle* generator, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_pad(AtenTensorHandle self, const int64_t* pad, int64_t pad_len_, const char* mode, double* value, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_permute(AtenTensorHandle self, const int64_t* dims, int64_t dims_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_polar(AtenTensorHandle abs, AtenTensorHandle angle, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_rand(const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_rand_generator(const int64_t* size, int64_t size_len_, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_rand_like(AtenTensorHandle self, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_rand_like_generator(AtenTensorHandle self, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_randint(int64_t high, const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_randint_generator(int64_t high, const int64_t* size, int64_t size_len_, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_randint_low(int64_t low, int64_t high, const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_randint_low_out(AtenTensorHandle out, int64_t low, int64_t high, const int64_t* size, int64_t size_len_); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_randint_like(AtenTensorHandle self, int64_t high, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_randint_like_low_dtype(AtenTensorHandle self, int64_t low, int64_t high, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_randn(const int64_t* size, int64_t size_len_, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_randn_generator(const int64_t* size, int64_t size_len_, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_randn_like(AtenTensorHandle self, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_randn_like_generator(AtenTensorHandle self, AtenGeneratorHandle* generator, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, int32_t* memory_format, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_randperm(int64_t n, int32_t* dtype, int32_t* layout, int32_t* device, int32_t device_index_, int32_t* pin_memory, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_reshape(AtenTensorHandle self, const int64_t* shape, int64_t shape_len_, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_resize_as_(AtenTensorHandle self, AtenTensorHandle the_template, int32_t* memory_format); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_slice_Tensor(AtenTensorHandle self, int64_t dim, int64_t* start, int64_t* end, int64_t step, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_soft_margin_loss_backward(AtenTensorHandle grad_output, AtenTensorHandle self, AtenTensorHandle target, int64_t reduction, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_sort(AtenTensorHandle self, int64_t dim, int32_t descending, AtenTensorHandle* ret0, AtenTensorHandle* ret1); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_squeeze_dim(AtenTensorHandle self, int64_t dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_to_sparse(AtenTensorHandle self, int32_t* layout, const int64_t** blocksize, int64_t blocksize_len_, int64_t* dense_dim, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_uniform(AtenTensorHandle self, double from, double to, AtenGeneratorHandle* generator, AtenTensorHandle* ret0); +AOTI_TORCH_EXPORT AOTITorchError aoti_torch_xpu_view_dtype(AtenTensorHandle self, int32_t dtype, AtenTensorHandle* ret0); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated_enum_converters.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated_enum_converters.h new file mode 100644 index 0000000000000000000000000000000000000000..fa5e8a180ac3e3d00e2750f7db110c1e92f67cf8 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/generated_enum_converters.h @@ -0,0 +1,128 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// @generated by update_schema.py +// clang-format off + +#pragma once + +#include +#include +#include +#include + +// Converter functions from serialized enum values (torch._export.serde.schema) +// to c10 enums. The serialized format has different enum values than c10. + +namespace torch::aot_inductor { + +inline c10::ScalarType convertSerializedScalarType(int serialized_value) { + constexpr int kInvalid = -1; + constexpr int kScalarTypeMap[] = { + kInvalid, // 0 + static_cast(c10::ScalarType::Byte), // 1 + static_cast(c10::ScalarType::Char), // 2 + static_cast(c10::ScalarType::Short), // 3 + static_cast(c10::ScalarType::Int), // 4 + static_cast(c10::ScalarType::Long), // 5 + static_cast(c10::ScalarType::Half), // 6 + static_cast(c10::ScalarType::Float), // 7 + static_cast(c10::ScalarType::Double), // 8 + static_cast(c10::ScalarType::ComplexHalf), // 9 + static_cast(c10::ScalarType::ComplexFloat), // 10 + static_cast(c10::ScalarType::ComplexDouble), // 11 + static_cast(c10::ScalarType::Bool), // 12 + static_cast(c10::ScalarType::BFloat16), // 13 + kInvalid, // 14 + kInvalid, // 15 + kInvalid, // 16 + kInvalid, // 17 + kInvalid, // 18 + kInvalid, // 19 + kInvalid, // 20 + kInvalid, // 21 + kInvalid, // 22 + kInvalid, // 23 + kInvalid, // 24 + kInvalid, // 25 + kInvalid, // 26 + kInvalid, // 27 + static_cast(c10::ScalarType::UInt16), // 28 + static_cast(c10::ScalarType::Float8_e4m3fn), // 29 + static_cast(c10::ScalarType::Float8_e5m2), // 30 + static_cast(c10::ScalarType::Float8_e4m3fnuz), // 31 + static_cast(c10::ScalarType::Float8_e5m2fnuz), // 32 + static_cast(c10::ScalarType::Float8_e8m0fnu), // 33 + static_cast(c10::ScalarType::UInt32), // 34 + static_cast(c10::ScalarType::UInt64), // 35 + }; + constexpr int kMapSize = sizeof(kScalarTypeMap) / sizeof(kScalarTypeMap[0]); + + TORCH_CHECK( + serialized_value >= 0 && serialized_value < kMapSize, + "Serialized ScalarType value out of range: ", + serialized_value); + int result = kScalarTypeMap[serialized_value]; + TORCH_CHECK( + result != kInvalid, + "Invalid serialized ScalarType value: ", + serialized_value); + return static_cast(result); +} + + +inline c10::Layout convertSerializedLayout(int serialized_value) { + constexpr int kInvalid = -1; + constexpr int kLayoutMap[] = { + kInvalid, // 0 + static_cast(c10::Layout::Sparse), // 1 + static_cast(c10::Layout::SparseCsr), // 2 + static_cast(c10::Layout::SparseCsc), // 3 + static_cast(c10::Layout::SparseBsr), // 4 + static_cast(c10::Layout::SparseBsc), // 5 + static_cast(c10::Layout::Mkldnn), // 6 + static_cast(c10::Layout::Strided), // 7 + }; + constexpr int kMapSize = sizeof(kLayoutMap) / sizeof(kLayoutMap[0]); + + TORCH_CHECK( + serialized_value >= 0 && serialized_value < kMapSize, + "Serialized Layout value out of range: ", + serialized_value); + int result = kLayoutMap[serialized_value]; + TORCH_CHECK( + result != kInvalid, + "Invalid serialized Layout value: ", + serialized_value); + return static_cast(result); +} + + +inline c10::MemoryFormat convertSerializedMemoryFormat(int serialized_value) { + constexpr int kInvalid = -1; + constexpr int kMemoryFormatMap[] = { + kInvalid, // 0 + static_cast(c10::MemoryFormat::Contiguous), // 1 + static_cast(c10::MemoryFormat::ChannelsLast), // 2 + static_cast(c10::MemoryFormat::ChannelsLast3d), // 3 + static_cast(c10::MemoryFormat::Preserve), // 4 + }; + constexpr int kMapSize = sizeof(kMemoryFormatMap) / sizeof(kMemoryFormatMap[0]); + + TORCH_CHECK( + serialized_value >= 0 && serialized_value < kMapSize, + "Serialized MemoryFormat value out of range: ", + serialized_value); + int result = kMemoryFormatMap[serialized_value]; + TORCH_CHECK( + result != kInvalid, + "Invalid serialized MemoryFormat value: ", + serialized_value); + return static_cast(result); +} + +} // namespace torch::aot_inductor + +// clang-format on + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/mkldnn_tensor.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/mkldnn_tensor.h new file mode 100644 index 0000000000000000000000000000000000000000..57aa0645fb79e83c94f30a120fc6898062e89bce --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/mkldnn_tensor.h @@ -0,0 +1,22 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::aot_inductor { + +void* data_ptr_from_mkldnn(at::Tensor* mkldnn_tensor); + +at::Tensor mkldnn_tensor_from_data_ptr( + void* data_ptr, + at::IntArrayRef dims, + at::ScalarType dtype, + at::Device device, + const uint8_t* opaque_metadata, + int64_t opaque_metadata_size); + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/oss_proxy_executor.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/oss_proxy_executor.h new file mode 100644 index 0000000000000000000000000000000000000000..61428e2cef64ceb3c600d8a8dd03ac63e018c4b1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/oss_proxy_executor.h @@ -0,0 +1,158 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include // @manual +#include +#include + +namespace torch::aot_inductor { + +inline std::ostream& operator<<(std::ostream& os, DynamicArgType arg_type) { + os << static_cast(arg_type); + return os; +} + +struct OSSDynamicArg { + OSSDynamicArg( + int arg_index, + DynamicArgType arg_type, + int length, + std::optional> list_item_types = std::nullopt) + : arg_index(arg_index), + arg_type(arg_type), + length(length), + list_item_types(std::move(list_item_types)) {} + int arg_index; + DynamicArgType arg_type; + int length; + std::optional> + list_item_types; // only used for parsing list of optional tensors +}; + +struct OSSTorchBindArg { + OSSTorchBindArg(int arg_index, std::string arg_name) + : arg_index(arg_index), arg_name(std::move(arg_name)) {} + int arg_index; + // arg_name is used to find the corresponding IValue in customObjs_ + std::string arg_name; +}; + +struct OSSOpKernel { + explicit OSSOpKernel(std::string target) : target_(std::move(target)) {} + // Explicitly declare copy and move constructors + OSSOpKernel(const OSSOpKernel&) = default; + OSSOpKernel(OSSOpKernel&&) = default; + // Explicitly declare copy and move assignment operators + OSSOpKernel& operator=(const OSSOpKernel&) = default; + OSSOpKernel& operator=(OSSOpKernel&&) = default; + + std::string target_; + std::vector dynamic_args_; + std::vector torchbind_args_; + std::vector outputs_; + std::vector stack_; + + int num_output_tensors() const { + int num_output_tensors = 0; + for (const auto& output : outputs_) { + if (isTensorType(output.arg_type)) { + num_output_tensors += output.length; + } + } + return num_output_tensors; + } + + int num_output_ints() const { + int num_output_ints = 0; + for (const auto& output : outputs_) { + if (output.arg_type == DynamicArgType::IntType) { + num_output_ints += output.length; + } + } + return num_output_ints; + } + + virtual void run(std::vector& stack) = 0; + virtual c10::FunctionSchema schema() const = 0; + virtual ~OSSOpKernel() = default; +}; + +struct OSSOpKernelOperator : public OSSOpKernel { + OSSOpKernelOperator(std::string target, c10::OperatorHandle op_handle) + : OSSOpKernel(std::move(target)), op_handle_(std::move(op_handle)) {} + + c10::OperatorHandle op_handle_; + void run(std::vector& stack) override { + op_handle_.callBoxed(stack); + } + + c10::FunctionSchema schema() const override { + return op_handle_.schema(); + } +}; + +struct OSSCallTorchBindKernel : public OSSOpKernel { + OSSCallTorchBindKernel(std::string target, torch::jit::Function* method) + : OSSOpKernel(std::move(target)), method_(method) {} + torch::jit::Function* method_; + void run(std::vector& stack) override { + method_->run(stack); + } + + c10::FunctionSchema schema() const override { + return method_->getSchema(); + } +}; + +class OSSProxyExecutor : public ProxyExecutor { + public: + explicit OSSProxyExecutor( + const std::string& json_path, + bool is_cpu, + std::optional> custom_objs = + std::nullopt); + + void call_function( + int extern_node_index, + int num_ints, + int64_t* flatten_int_args, + int num_tensors, + AtenTensorHandle* flatten_tensor_args) override; + + private: + void prefill_stack_with_static_arguments( + size_t index, + const at::TypePtr& schema_arg_type, + const nlohmann::json& serialized_arg, + OSSOpKernel* op_kernel, + const std::string& torchbind_arg_name); + + void get_input_info_from_serialized( + const std::vector& schema_args, + const nlohmann::json& serialized_node, + OSSOpKernel& op_kernel); + + void get_output_info_from_serialized( + const std::vector& schema_returns, + const nlohmann::json& serialized_node, + OSSOpKernel& op_kernel); + + std::unique_ptr get_call_torch_bind_kernel( + const nlohmann::json& serialized_node); + + std::vector> op_kernels_; + std::unique_ptr device_; + std::unordered_map custom_objs_; +}; + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/proxy_executor.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/proxy_executor.h new file mode 100644 index 0000000000000000000000000000000000000000..b25a7e396c8c349810c56d59a20e800fa68d0882 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/proxy_executor.h @@ -0,0 +1,42 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace torch::aot_inductor { + +enum class DynamicArgType : int { + TensorType = 0, + ListTensorType = 1, + ListOptionalTensorType = 2, + IntType = 3, + ListIntType = 4, + NoneType = 5, +}; + +inline bool isTensorType(DynamicArgType arg_type) { + return arg_type == DynamicArgType::TensorType || + arg_type == DynamicArgType::ListTensorType || + arg_type == DynamicArgType::ListOptionalTensorType; +} + +class ProxyExecutor { + public: + ProxyExecutor() = default; + virtual ~ProxyExecutor() = default; + + virtual void call_function( + int extern_node_index, + int num_ints, + int64_t* flatten_int_args, + int num_tensors, + AtenTensorHandle* flatten_tensor_args) = 0; +}; + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/tensor_converter.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/tensor_converter.h new file mode 100644 index 0000000000000000000000000000000000000000..4461d682ad3a5f70ae83161c6590cab63bf6a675 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/tensor_converter.h @@ -0,0 +1,31 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::aot_inductor { + +// Functions declared here are not meant to be called from the AOTInductor +// generated model.so + +// unsafe_alloc_new_handles_from_tensors is used for allocating new aten +// tensor objects and return them as a vector of AtenTensorHandle (raw +// pointers), and those pointers will be stolen by model.so. +TORCH_API std::vector unsafe_alloc_new_handles_from_tensors( + const std::vector& tensors); + +// alloc_tensors_by_stealing_from_handles is used for creating a vector of aten +// tensors by stealing from an array of handles. Only the handles are stolen, +// and the array itself is borrowed. +// +// WARNING: Can NOT be called in model.so +TORCH_API std::vector alloc_tensors_by_stealing_from_handles( + AtenTensorHandle* handles, + size_t length); + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/utils.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/utils.h new file mode 100644 index 0000000000000000000000000000000000000000..0e71766b3f0a24a6129eac1e08fec84fefbbabbf --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/aoti_torch/utils.h @@ -0,0 +1,240 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AOTI_TORCH_CONVERT_EXCEPTION_TO_ERROR_CODE(...) \ + try { \ + __VA_ARGS__ \ + } catch (const std::exception& e) { \ + LOG(ERROR) << "Exception in aoti_torch: " << e.what(); \ + return AOTI_TORCH_FAILURE; \ + } catch (...) { \ + LOG(ERROR) << "Exception in aoti_torch: UNKNOWN"; \ + return AOTI_TORCH_FAILURE; \ + } \ + return AOTI_TORCH_SUCCESS; + +namespace torch::aot_inductor { + +inline at::Tensor* tensor_handle_to_tensor_pointer(AtenTensorHandle handle) { + return reinterpret_cast(handle); +} + +inline AtenTensorHandle tensor_pointer_to_tensor_handle(at::Tensor* tensor) { + return reinterpret_cast(tensor); +} + +inline at::Tensor resolve_tensor_dispatch_flags(AtenTensorHandle handle) { + at::Tensor* tensor{tensor_handle_to_tensor_pointer(handle)}; + if (tensor->is_conj() || tensor->is_neg()) { + // If the conjugation or negation dispatch flags are set, runtime dispatch + // handles them by cloning the tensor before passing them to the native ATen + // function. Since the C-shim calls the native function directly, we have + // to handle the flags ourselves, or results will be silently incorrect. + return tensor->clone(); + } + return *tensor; +} + +inline std::optional resolve_tensor_dispatch_flags( + const AtenTensorHandle* handle) { + return handle ? std::make_optional(resolve_tensor_dispatch_flags(*handle)) + : std::nullopt; +} + +inline std::vector resolve_tensor_list_dispatch_flags( + const AtenTensorHandle* handle, + int64_t len) { + std::vector ret{}; + ret.reserve(len); + for (int64_t i{0}; i < len; ++i) { + ret.emplace_back(resolve_tensor_dispatch_flags(handle[i])); + } + return ret; +} + +inline std::vector> resolve_tensor_list_dispatch_flags( + const AtenTensorHandle** handle, + int64_t len) { + std::vector> ret{}; + ret.reserve(len); + for (int64_t i{0}; i < len; ++i) { + ret.emplace_back(resolve_tensor_dispatch_flags(handle[i])); + } + return ret; +} + +inline at::Generator* generator_handle_to_generator_pointer( + AtenGeneratorHandle handle) { + return reinterpret_cast(handle); +} + +inline AtenGeneratorHandle generator_pointer_to_generator_handle( + at::Generator* generator) { + return reinterpret_cast(generator); +} + +inline AtenTensorHandle new_tensor_handle(at::Tensor&& tensor) { + at::Tensor* new_tensor = new at::Tensor(std::move(tensor)); + return tensor_pointer_to_tensor_handle(new_tensor); +} + +inline void assert_inf_and_nan( + const std::string& tensor_name, + at::Tensor& check_tensor) { + auto isnan_tensor = check_tensor.isnan(); + if (isnan_tensor.any().item()) { + throw std::runtime_error("At least one NaN in " + tensor_name); + } + auto isinf_tensor = check_tensor.isinf(); + if (isinf_tensor.any().item()) { + throw std::runtime_error("At least one INF in " + tensor_name); + } +} + +// utility functions to convert a pointer to an optional value +template +inline std::optional pointer_to_optional(T* ptr) { + return ptr ? std::make_optional(*ptr) : std::nullopt; +} + +template >> +inline std::optional pointer_to_optional(U* ptr) { + return ptr ? std::make_optional(T(*ptr)) : std::nullopt; +} + +template <> +inline std::optional pointer_to_optional(AtenTensorHandle* ptr) { + return ptr ? std::make_optional(*tensor_handle_to_tensor_pointer(*ptr)) + : std::nullopt; +} + +template <> +inline std::optional pointer_to_optional( + const AtenTensorHandle* ptr) { + return ptr ? std::make_optional(*tensor_handle_to_tensor_pointer(*ptr)) + : std::nullopt; +} + +template <> +inline std::optional pointer_to_optional( + AtenGeneratorHandle* ptr) { + return ptr ? std::make_optional(*generator_handle_to_generator_pointer(*ptr)) + : std::nullopt; +} + +inline std::optional pointer_to_optional_device( + int32_t* device_type, + int32_t device_index) { + return device_type ? std::make_optional(c10::Device( + static_cast(*device_type), + static_cast(device_index))) + : std::nullopt; +} + +// utility functions to convert a pointer to a list +template +struct is_optional : std::false_type {}; +template +struct is_optional> : std::true_type {}; + +template +inline c10::ArrayRef pointer_to_list(T* ptr, int64_t len) { + return c10::ArrayRef(ptr, len); +} + +template < + class T, + class U, + typename = std::enable_if_t>, + typename = std::enable_if_t::value>> +inline std::vector pointer_to_list(U* ptr, int64_t len) { + // std::vector will be implicitly converted to c10::ArrayRef at the call + // site + std::vector result; + result.reserve(len); + for (int64_t i = 0; i < len; i++) { + result.emplace_back(T(ptr[i])); + } + return result; +} + +template ::value>> +inline std::vector pointer_to_list(U** ptr, int64_t len) { + // Here U** denotes a list of optional arguments + // std::vector will be implicitly converted to c10::ArrayRef at the call + // site + std::vector result; + result.reserve(len); + for (int64_t i = 0; i < len; i++) { + result.emplace_back(pointer_to_optional(ptr[i])); + } + return result; +} + +template <> +inline std::vector pointer_to_list( + const AtenTensorHandle* ptr, + int64_t len) { + std::vector result; + result.reserve(len); + for (int64_t i = 0; i < len; i++) { + result.emplace_back(*tensor_handle_to_tensor_pointer(ptr[i])); + } + return result; +} + +template <> +inline std::vector> pointer_to_list( + const AtenTensorHandle** ptr, + int64_t len) { + std::vector> result; + result.reserve(len); + for (int64_t i = 0; i < len; i++) { + result.emplace_back(pointer_to_optional(ptr[i])); + } + return result; +} + +template +inline std::array pointer_to_list(const int32_t* ptr) { + std::array result; + std::copy(ptr, ptr + N, result.begin()); + return result; +} + +// Utility function to convert a pointer to an optional list of values +template +inline std::optional> pointer_to_optional_list( + U** ptr, + int64_t len) { + return ptr + ? std::make_optional>(pointer_to_list(*ptr, len)) + : std::nullopt; +} + +template +static c10::List convert_to_c10_List(const T* scalars, const int64_t len) { + c10::List scalars_list; + scalars_list.reserve(len); + for (int64_t i = 0; i < len; i++) { + scalars_list.emplace_back(scalars[i]); + } + return scalars_list; +} + +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/array_ref_impl.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/array_ref_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..6c732af17029ec3d90fff1b667b0609d3731848a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/array_ref_impl.h @@ -0,0 +1,93 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace torch::aot_inductor { +template +void convert_output_to_handle( + const ArrayRefTensor& output, + AtenTensorHandle& handle) { + handle = output.expensiveCopyToTensor(); +} + +template +void convert_outputs_to_handles_helper( + const std::tuple...>& outputs, + AtenTensorHandle* output_handles, + std::index_sequence) { + (convert_output_to_handle(std::get(outputs), output_handles[Is]), ...); +} +template +void convert_outputs_to_handles( + const std::tuple...>& outputs, + AtenTensorHandle* output_handles) { + convert_outputs_to_handles_helper( + outputs, output_handles, std::make_index_sequence()); +} + +template +void convert_handle_to_arrayref_tensor( + AtenTensorHandle handle, + ArrayRefTensor& input) { + void* data_ptr; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_data_ptr(handle, &data_ptr)); + int64_t dim; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_dim(handle, &dim)); + int64_t numel; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_numel(handle, &numel)); + int64_t* sizes; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_sizes(handle, &sizes)); + int64_t* strides; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_strides(handle, &strides)); + int32_t dtype; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_dtype(handle, &dtype)); + int32_t device_type; + AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_device_type(handle, &device_type)); + int32_t device_index; + AOTI_TORCH_ERROR_CODE_CHECK( + aoti_torch_get_device_index(handle, &device_index)); + + input = ArrayRefTensor( + MiniArrayRef(reinterpret_cast(data_ptr), numel), + MiniArrayRef(sizes, dim), + MiniArrayRef(strides, dim), + device_type, + device_index); +} + +template +void convert_handles_to_inputs_helper( + AtenTensorHandle* input_handles, + std::tuple...>& inputs, + std::index_sequence) { + (convert_handle_to_arrayref_tensor(input_handles[Is], std::get(inputs)), + ...); +} + +template +void convert_handles_to_inputs( + AtenTensorHandle* input_handles, + std::tuple...>& inputs) { + convert_handles_to_inputs_helper( + input_handles, inputs, std::make_index_sequence()); +} + +template +void assert_numel(const ArrayRefTensor& tensor, uint64_t numel) { + TORCH_CHECK( + tensor.numel() == numel, + "incorrect numel for input tensor. expected ", + numel, + ", got ", + tensor.numel()); +} +} // namespace torch::aot_inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_prefix.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_prefix.h new file mode 100644 index 0000000000000000000000000000000000000000..5d867caf8b49364f006675c01cc03ee89c21a851 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_prefix.h @@ -0,0 +1,1328 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// WARNING: be extra careful when including more ATen/c10 header files here! +// Because AOTInductor generated code will copy-paste this cpp_prefix.h for +// the CPU backend, we have to make sure the used headers are implemented +// in a header-only way, i.e. all the function and class definitions are +// in .h files instead of .cpp files, to avoid ABI backward-compatibility +// breakage. + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CPU_CAPABILITY_AVX512) || defined(CPU_CAPABILITY_AVX2) || \ + defined(CPU_CAPABILITY_ZVECTOR) || defined(CPU_CAPABILITY_NEON) || \ + defined(CPU_CAPABILITY_VSX) || defined(CPU_CAPABILITY_SVE256) +#define INDUCTOR_USE_VECTOR_TYPES() 1 +#else +#define INDUCTOR_USE_VECTOR_TYPES() 0 +#endif + +#if INDUCTOR_USE_VECTOR_TYPES() +#include +#include +#else +// For calc_erfinv +#include +#endif + +template +struct Welford { + T mean = T(0); + T m2 = T(0); + // Use weight for tail cases since the index of each element in the vec may be + // different. A single index can not express masked welford reduction. + T weight = T(0); + uint64_t index = 0; +}; + +template +struct IsVecType : std::false_type {}; + +template +struct IsVecMaskType : std::false_type {}; + +#if INDUCTOR_USE_VECTOR_TYPES() +template +struct IsVecType> : std::true_type {}; +template +struct IsVecType> : std::true_type {}; + +template +struct IsVecMaskType> : std::true_type {}; +#endif + +template +struct GetScalarType { + using type = T; +}; + +#if INDUCTOR_USE_VECTOR_TYPES() +template +struct GetScalarType> { + using type = T; +}; +template +struct GetScalarType> { + using type = T; +}; +#endif + +template +struct CascadeSumHelper { + // A data struct to help cascade summation: + std::vector sum_stk{}; + uint64_t depth{0}; // depth of sum_stk. + uint64_t num_chunks{0}; // number of chunks stored in sum_stk. + uint64_t index{0}; // index of the current data. + CascadeSumHelper() = default; + CascadeSumHelper(uint64_t N) { + uint64_t m = (N + kChunkSize - 1) / kChunkSize; // div up + depth = m > 0 + ? static_cast(ceil(log2(static_cast(m)))) + : 0; + if constexpr (IsVecType::value) { + sum_stk.assign( + std::max(depth, static_cast(1)), + T(typename T::value_type(0))); + } else { + sum_stk.assign(std::max(depth, static_cast(1)), T(0)); + } + } +}; + +template +inline T cascade_sum_combine(T& data, CascadeSumHelper* c) { + // Note: In order to be consistent with other reductions in inductor, + // the returned value may be wrong and cascade_sum_final must be executed to + // get the final correct result. Inductor uses the reduction suffix to ensure + // that cascade_sum_final is called in the end. + c->sum_stk[0] = c->sum_stk[0] + data; + // Use cascade summation to improve numerical stability. + // https://en.wikipedia.org/wiki/Pairwise_summation + if (c->depth > 0) { + c->index++; + if (c->index == kChunkSize) { + c->num_chunks += 1; + c->index = 0; + uint64_t mask = c->num_chunks; + uint64_t j = 1; + for (; j < c->depth && (mask & 1) == 0; ++j) { + c->sum_stk[j] = c->sum_stk[j] + c->sum_stk[j - 1]; + c->sum_stk[j - 1] = T(0); + mask >>= 1; + } + return c->sum_stk[j - 1]; + } + } + return c->sum_stk[0]; +} + +template +inline T cascade_sum_final(CascadeSumHelper* c) { + T result = c->sum_stk[0]; + for (const auto i : c10::irange(1, c->depth)) { + result = result + c->sum_stk[i]; + } + return result; +} + +template +struct WelfordHelper { + // A data struct to help welford reduction: + // 1. Save the reciprocal of weights to avoid redundant divisions. + // 2. Save the welford stack, which is used to combine welford reduction + // with cascade summation to improve numerical stability. + static std::vector::type> weight_recps; + std::vector> welford_stk{}; + uint64_t depth{0}; // depth of welford_stk. + uint64_t num_chunks{0}; // number of chunks stored in welford_stk. + WelfordHelper() = default; + WelfordHelper(uint64_t N) { + uint64_t m = (N + kChunkSize - 1) / kChunkSize; // div up + depth = m > 0 + ? static_cast(ceil(log2(static_cast(m)))) + : 0; + welford_stk.assign(depth, Welford()); + } +}; + +template +std::vector::type> + WelfordHelper::weight_recps = []() { + using scalar_t = typename GetScalarType::type; + std::vector temp(kChunkSize); + for (const auto i : c10::irange(kChunkSize)) { + temp[i] = scalar_t(static_cast(1) / static_cast(i + 1)); + } + return temp; + }(); + +template +Welford welford_combine( + const Welford& a, + const Welford& b, + bool use_index = false) { + if (a.index == 0) { + return b; + } + if (b.index == 0) { + return a; + } + auto delta = b.mean - a.mean; + auto a_weight = use_index ? T(a.index) : a.weight; + auto b_weight = use_index ? T(b.index) : b.weight; + auto new_weight = a_weight + b_weight; + auto new_index = a.index + b.index; + auto wb_over_w = b_weight / new_weight; + if constexpr (IsVecType::value) { + // Guard against division by zero + wb_over_w = T::blendv(wb_over_w, T(0), new_weight == T(0)); + } + auto result = Welford{ + a.mean + delta * wb_over_w, + a.m2 + b.m2 + delta * delta * a_weight * wb_over_w, + new_weight, + new_index}; + return result; +} + +template +Welford welford_combine( + Welford& acc, + T& data, + WelfordHelper* w = nullptr) { + // Combine welford reduction with cascade summation to improve numerical + // stability. + // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance + // https://en.wikipedia.org/wiki/Pairwise_summation + if (w != nullptr && w->depth > 0 && acc.index == kChunkSize) { + w->welford_stk[0] = welford_combine(w->welford_stk[0], acc); + w->num_chunks += 1; + acc.mean = T(0); + acc.m2 = T(0); + acc.weight = T(0); + acc.index = 0; + uint64_t mask = w->num_chunks; + for (uint64_t j = 1; j < w->depth && (mask & 1) == 0; ++j) { + w->welford_stk[j] = + welford_combine(w->welford_stk[j], w->welford_stk[j - 1]); + w->welford_stk[j - 1] = Welford(); + mask >>= 1; + } + } + // Add a single data point + uint64_t new_index = acc.index + 1; + auto new_weight = acc.weight + T(1); + auto delta = data - acc.mean; + T new_mean; + // use new_index to fecth 1 / new_weight to avoid divisions + new_mean = acc.mean + + ((w == nullptr || acc.index >= w->weight_recps.size()) + ? delta / new_weight + : delta * T(w->weight_recps[acc.index])); + auto new_delta = data - new_mean; + auto result = + Welford{new_mean, acc.m2 + delta * new_delta, new_weight, new_index}; + return result; +} + +template +Welford welford_combine(Welford& acc, WelfordHelper* w) { + for (const auto i : c10::irange(w->depth)) { + acc = welford_combine(acc, w->welford_stk[i]); + } + return acc; +} + +template +struct IndexValue { + int64_t index{}; + T value; + IndexValue(int64_t idx, T val) : index(idx), value(val) {} + IndexValue() = default; +}; + +#if INDUCTOR_USE_VECTOR_TYPES() +template +Welford welford_combine( + Welford& acc, + T& data, + int64_t tail_size, + WelfordHelper* w = nullptr) { + auto out = welford_combine(acc, data, w); + return Welford{ + T::set(acc.mean, out.mean, tail_size), + T::set(acc.m2, out.m2, tail_size), + T::set(acc.weight, out.weight, tail_size), + out.index}; +} + +template +inline T cascade_sum_combine( + T& data, + int64_t tail_size, + CascadeSumHelper* c) { + auto out = c->sum_stk[0] + data; + c->sum_stk[0] = T::set(c->sum_stk[0], out, tail_size); + if (c->depth > 0) { + c->index++; + if (c->index == kChunkSize) { + c->num_chunks += 1; + c->index = 0; + uint64_t mask = c->num_chunks; + uint64_t j = 1; + for (; j < c->depth && (mask & 1) == 0; ++j) { + c->sum_stk[j] = c->sum_stk[j] + c->sum_stk[j - 1]; + c->sum_stk[j - 1] = T(0); + mask >>= 1; + } + return c->sum_stk[j - 1]; + } + } + return c->sum_stk[0]; +} + +template +inline T max_masked_reduce(const T& a, const T& b, const int64_t tail_size) { + auto out = at::vec::maximum(a, b); + return T::set(a, out, tail_size); +} + +template <> +inline at::vec::VecMask max_masked_reduce( + const at::vec::VecMask& a, + const at::vec::VecMask& b, + const int64_t tail_size) { + auto out = a | b; + return at::vec::VecMask::set(a, out, tail_size); +} + +template +inline T min_masked_reduce(const T& a, const T& b, const int64_t tail_size) { + auto out = at::vec::minimum(a, b); + return T::set(a, out, tail_size); +} + +template <> +inline at::vec::VecMask min_masked_reduce( + const at::vec::VecMask& a, + const at::vec::VecMask& b, + const int64_t tail_size) { + auto out = a & b; + return at::vec::VecMask::set(a, out, tail_size); +} + +template +inline T sum_masked_reduce(const T& a, const T& b, const int64_t tail_size) { + auto out = a + b; + return T::set(a, out, tail_size); +} + +template <> +inline at::vec::VecMask sum_masked_reduce( + const at::vec::VecMask& a, + const at::vec::VecMask& b, + const int64_t tail_size) { + auto out = a | b; + return at::vec::VecMask::set(a, out, tail_size); +} + +template +T prod_masked_reduce(const T& a, const T& b, const int64_t tail_size) { + auto out = a * b; + return T::set(a, out, tail_size); +} + +template +T xor_sum_masked_reduce(const T& a, const T& b, const int64_t tail_size) { + auto out = a ^ b; + return T::set(a, out, tail_size); +} + +template +T any_masked_reduce(const T& a, const T& b, const int64_t tail_size) { + auto out = a | b; + return T::set(a, out, tail_size); +} +#endif + +// Refer to +// https://github.com/pytorch/pytorch/blob/b5b36cf0c4e1958f1ff25120f5d4beeef3288187/ +// aten/src/ATen/native/SharedReduceOps.h#L419-L445 +template +inline bool greater_or_nan( + scalar_t a, + scalar_t b, + int64_t idx_a, + int64_t idx_b) { + // If (a == b), then choose the one with lower idx, else max(a, b) + if (at::_isnan(a)) { + if (at::_isnan(b)) { + return idx_a < idx_b; + } + return true; + } + return (a == b) ? idx_a < idx_b : (a > b); +} + +template +inline bool less_or_nan(scalar_t a, scalar_t b, int64_t idx_a, int64_t idx_b) { + // If (a == b), then choose the one with lower idx, else min(a, b) + if (at::_isnan(a)) { + if (at::_isnan(b)) { + return idx_a < idx_b; + } + return true; + } + return (a == b) ? idx_a < idx_b : (a < b); +} + +template +inline IndexValue& argmin_combine( + IndexValue& a, + T next_value, + int64_t next_index) { + if (!(less_or_nan(a.value, next_value, a.index, next_index))) { + a.value = next_value; + a.index = next_index; + } + return a; +} +template +inline IndexValue& argmax_combine( + IndexValue& a, + T next_value, + int64_t next_index) { + if (!(greater_or_nan(a.value, next_value, a.index, next_index))) { + a.value = next_value; + a.index = next_index; + } + return a; +} +template +inline IndexValue& argmin_combine( + IndexValue& a, + const IndexValue& next) { + return argmin_combine(a, next.value, next.index); +} +template +inline IndexValue& argmax_combine( + IndexValue& a, + const IndexValue& next) { + return argmax_combine(a, next.value, next.index); +} + +#if INDUCTOR_USE_VECTOR_TYPES() + +template +inline at::vec::Vectorized div_floor_floating_vec( + const at::vec::Vectorized& a, + const at::vec::Vectorized& b) { + using vec_t = at::vec::Vectorized; + const auto basic_div = a / b; + vec_t inf(std::numeric_limits::infinity()); + auto mod = a.fmod(b); + // Fixup for a case that isn't properly handled by Sleef_fmod + auto floor = + vec_t::blendv(a - mod, a, (basic_div.abs() == inf) & (a.abs() != inf)); + auto div = floor / b; + const auto zero = vec_t(0); + auto mask = (mod != zero) & ((b < zero) ^ (mod < zero)); + const auto one = vec_t(1); + div = vec_t::blendv(div, div - one, mask); + auto floordiv = div.floor(); + mask = (div - floordiv) > vec_t(0.5); + floordiv = vec_t::blendv(floordiv, floordiv + one, mask); + floordiv = vec_t::blendv(floordiv, zero.copysign(basic_div), div == zero); + floordiv = vec_t::blendv(floordiv, basic_div, b == zero); + return floordiv; +}; + +template +inline at::vec::VectorizedN div_floor_floating_vec( + const at::vec::VectorizedN& a, + const at::vec::VectorizedN& b) { + at::vec::VectorizedN result; +#ifndef _MSC_VER +#pragma unroll +#endif + for (int i = 0; i < N; ++i) { + result[i] = div_floor_floating_vec(a[i], b[i]); + } + return result; +} + +template +struct IndexValueVec { + at::vec::VectorizedN value; + at::vec::VectorizedN index; + + IndexValueVec(const T _value) { + value = at::vec::VectorizedN(_value); + index = at::vec::VectorizedN(0); + }; + + IndexValueVec() {}; +}; + +template < + typename T, + int NV, + int NI, + typename std::enable_if_t, int> = 0> +at::vec::VecMask inline get_mask_for_argmin_argmax( + const at::vec::VecMask& vmask, + const IndexValueVec& a, + const at::vec::VectorizedN& value, + const at::vec::VectorizedN& index) { + /* + vec impl for less_or_nan and greater_or_nan + example for argmin: + a.value = [NaN, NaN, 0, 2, 1, 0] + value = [NaN, 0, 0, 1, 2, NaN] + vmask = [false, false, false, false, true, false] + all_nan_or_equal = [true, false, true, false, false, false] + imask = [a.index[0] < index[0], ..., a.index[-1] < index[-1]] + iv_mask = blendv (vmask, imask, all_nan_or_equal) + [a.index[0] < index[0], false, a.index[2] < index[2], false, true, + false] a_nan_b_not: [false, false, false, false, false, true] mask = iv_mask | + a_nan_b_not [a.index[0] < index[0], false, a.index[2] < index[2], false, true, + true] + */ + using v_t = at::vec::VecMask; + using i_t = at::vec::VecMask; + i_t vmask_itype = vmask.template cast(); + // use itype here since there is vec impl for operator~ for itype + // while there may not vec impl for vtype + v_t isnan_a = a.value.isnan(); + i_t isnan_a_itype = isnan_a.template cast(); + v_t isnan_b = value.isnan(); + i_t isnan_b_type = isnan_b.template cast(); + i_t all_nan_mask = isnan_a_itype & isnan_b_type; + v_t equal_mask = (a.value == value); + i_t equal_mask_itype = equal_mask.template cast(); + i_t all_nan_or_equal = all_nan_mask | equal_mask_itype; + i_t imask(a.index < index); + i_t iv_mask = i_t::blendv(vmask_itype, imask, all_nan_or_equal); + i_t isnan_a_notnan_b = isnan_a_itype & (~isnan_b_type); + return iv_mask | isnan_a_notnan_b; +} + +template < + typename T, + int NV, + int NI, + typename std::enable_if_t, int> = 0> +at::vec::VecMask inline get_mask_for_argmin_argmax( + const at::vec::VecMask& vmask, + const IndexValueVec& a, + const at::vec::VectorizedN& value, + const at::vec::VectorizedN& index) { + using v_t = at::vec::VecMask; + using i_t = at::vec::VecMask; + i_t vmask_itype = vmask.template cast(); + v_t equal_mask = (a.value == value); + i_t equal_mask_itype = equal_mask.template cast(); + i_t imask(a.index < index); + return i_t::blendv(vmask_itype, imask, equal_mask_itype); +} + +template +inline IndexValueVec& argmin_vec_impl( + IndexValueVec& a, + at::vec::VectorizedN value, + at::vec::VectorizedN index, + std::optional tail_size) { + at::vec::VecMask vmask(a.value < value); + at::vec::VecMask final_mask = + get_mask_for_argmin_argmax(vmask, a, value, index); + if (tail_size.has_value()) { + a.value = at::vec::VectorizedN::set( + a.value, at::vec::minimum(a.value, value), tail_size.value()); + a.index = at::vec::VectorizedN::set( + a.index, + at::vec::VecMask::blendv(index, a.index, final_mask), + tail_size.value()); + } else { + a.value = at::vec::minimum(a.value, value); + a.index = at::vec::VecMask::blendv(index, a.index, final_mask); + } + return a; +} + +template +inline IndexValueVec& argmax_vec_impl( + IndexValueVec& a, + at::vec::VectorizedN value, + at::vec::VectorizedN index, + std::optional tail_size) { + at::vec::VecMask vmask(a.value > value); + at::vec::VecMask final_mask = + get_mask_for_argmin_argmax(vmask, a, value, index); + if (tail_size.has_value()) { + a.value = at::vec::VectorizedN::set( + a.value, at::vec::maximum(a.value, value), tail_size.value()); + a.index = at::vec::VectorizedN::set( + a.index, + at::vec::VecMask::blendv(index, a.index, final_mask), + tail_size.value()); + } else { + a.value = at::vec::maximum(a.value, value); + a.index = at::vec::VecMask::blendv(index, a.index, final_mask); + } + return a; +} + +template +inline at::vec::VectorizedN create_index(int64_t next_index) { + at::vec::VectorizedN next_idx; + if constexpr (horizontal) { + next_idx = at::vec::VectorizedN::arange(next_index, 1); + } else { + next_idx = at::vec::VectorizedN(next_index); + } + return next_idx; +} + +template +inline IndexValueVec& argmin_combine_vec( + IndexValueVec& a, + at::vec::VectorizedN next_value, + int64_t next_index, + std::optional tail_size = std::nullopt) { + auto next_idx = create_index(next_index); + return argmin_vec_impl(a, next_value, next_idx, tail_size); +} + +template +inline IndexValueVec& argmax_combine_vec( + IndexValueVec& a, + at::vec::VectorizedN next_value, + int64_t next_index, + std::optional tail_size = std::nullopt) { + auto next_idx = create_index(next_index); + return argmax_vec_impl(a, next_value, next_idx, tail_size); +} + +template +inline IndexValue argmin_vec_reduce_all( + const IndexValueVec& vec) { + constexpr int len = at::vec::VectorizedN::size(); + __at_align__ T tmpval[len]; + __at_align__ int64_t tmpidx[len]; + vec.value.store(tmpval); + vec.index.store(tmpidx); + IndexValue res = IndexValue(tmpidx[0], tmpval[0]); + for (int i = 1; i < len; i++) { + res = argmin_combine(res, tmpval[i], tmpidx[i]); + } + return res; +} + +template +inline IndexValue argmax_vec_reduce_all( + const IndexValueVec& vec) { + constexpr int len = at::vec::VectorizedN::size(); + __at_align__ T tmpval[len]; + __at_align__ int64_t tmpidx[len]; + vec.value.store(tmpval); + vec.index.store(tmpidx); + IndexValue res = IndexValue(tmpidx[0], tmpval[0]); + for (int i = 1; i < len; i++) { + res = argmax_combine(res, tmpval[i], tmpidx[i]); + } + return res; +} + +template +inline IndexValueVec& argmin_combine_vec( + IndexValueVec& vec_a, + const IndexValueVec& vec_b, + std::optional tail_size = std::nullopt) { + return argmin_vec_impl(vec_a, vec_b.value, vec_b.index, tail_size); +} + +template +inline IndexValueVec& argmax_combine_vec( + IndexValueVec& vec_a, + const IndexValueVec& vec_b, + std::optional tail_size = std::nullopt) { + return argmax_vec_impl(vec_a, vec_b.value, vec_b.index, tail_size); +} + +template +inline at::vec::Vectorized vec_shuffle_down( + at::vec::Vectorized x, + size_t n) { + using Vec = at::vec::Vectorized; + alignas(alignof(Vec)) scalar_t array[Vec::size()]; + x.store(array); + for (size_t i = 0; i + n < Vec::size(); i += 2 * n) { + array[i] = array[i + n]; + } + return Vec::loadu(array); +} + +#ifdef CPU_CAPABILITY_AVX2 +inline at::vec::Vectorized vec_shuffle_down( + at::vec::Vectorized x, + size_t n) { + using vec_t = at::vec::Vectorized; +#define SHUFFLE_MASK(z, y, x, w) ((z << 6) | (y << 4) | (x << 2) | w) + switch (n) { + case 1: + return vec_t(_mm256_permute_ps(x, SHUFFLE_MASK(1, 1, 3, 3))); + case 2: + return vec_t(_mm256_permute_ps(x, SHUFFLE_MASK(2, 2, 2, 2))); + case 4: + return vec_t(_mm256_permute2f128_ps(x, x, SHUFFLE_MASK(1, 1, 1, 1))); + } + + TORCH_CHECK(false, "Unhandled vec_shuffle_down value ", n); +} +#endif + +#ifdef CPU_CAPABILITY_AVX512 +inline at::vec::Vectorized vec_shuffle_down( + at::vec::Vectorized x, + size_t n) { + using vec_t = at::vec::Vectorized; +#define SHUFFLE_MASK(z, y, x, w) ((z << 6) | (y << 4) | (x << 2) | w) + switch (n) { + case 1: + return vec_t(_mm512_permute_ps(x, SHUFFLE_MASK(1, 1, 3, 3))); + case 2: + return vec_t(_mm512_permute_ps(x, SHUFFLE_MASK(2, 2, 2, 2))); + case 4: + return vec_t(_mm512_permutexvar_ps( + _mm512_set_epi32( + 12, 12, 12, 12, 12, 12, 12, 12, 4, 4, 4, 4, 4, 4, 4, 4), + x)); + case 8: + return vec_t(_mm512_permutexvar_ps( + _mm512_set_epi32(8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8), x)); + } + + TORCH_CHECK(false, "Unhandled vec_shuffle_down value ", n); +} +#endif + +template +Welford welford_vec_reduce_all( + Welford> acc) { + using Vec = at::vec::Vectorized; + Welford result; + if (acc.index == 0) { + return result; + } + // if all values of acc.weight are same as index, + // use index to reduce to save the overhead of vec_shuffle_down for acc.weight + bool use_index = (acc.weight - Vec(acc.index)).zero_mask() == + static_cast((1 << Vec::size()) - 1); + for (size_t n = 1; n < Vec::size(); n *= 2) { + auto shuffled = Welford{ + vec_shuffle_down(acc.mean, n), + vec_shuffle_down(acc.m2, n), + use_index ? Vec(0) : vec_shuffle_down(acc.weight, n), + acc.index}; + acc = welford_combine(acc, shuffled, use_index); + } + + alignas(alignof(Vec)) scalar_t array[Vec::size()]; + acc.mean.store(array); + result.mean = array[0]; + + acc.m2.store(array); + result.m2 = array[0]; + + acc.weight.store(array); + result.weight = array[0]; + result.index = result.weight; + + return result; +} + +template +Welford welford_vec_reduce_all( + Welford> acc) { + auto Welford0 = Welford>{ + acc.mean[0], acc.m2[0], acc.weight[0], acc.index}; + auto Welford1 = Welford>{ + acc.mean[1], acc.m2[1], acc.weight[1], acc.index}; + return welford_vec_reduce_all(welford_combine(Welford0, Welford1)); +} +#endif + +template +inline typename std::common_type_t mod(T a, U b) { + return a % b; +} +template <> +inline float mod(float a, float b) { + return std::fmod(a, b); +} +template <> +inline double mod(double a, double b) { + return std::fmod(a, b); +} + +template +inline scalar_t max_propagate_nan(scalar_t a, scalar_t b) { + if (at::_isnan(a)) { + return a; + } + return a > b ? a : b; +} + +template +inline scalar_t min_propagate_nan(scalar_t a, scalar_t b) { + if (at::_isnan(a)) { + return a; + } + return a < b ? a : b; +} + +constexpr float uint32_to_uniform_float(uint32_t value) { + // maximum value such that `MAX_INT * scale < 1.0` (with float rounding) + constexpr float scale = 4.6566127342e-10; + return static_cast(value & 0x7FFFFFFF) * scale; +} + +inline float normalized_rand_cpu(uint32_t seed, uint32_t offset) { + return uint32_to_uniform_float(at::Philox4_32(seed, 0, offset)()); +} + +inline float randn_cpu(uint32_t seed, uint32_t offset) { + at::Philox4_32 engine(seed, 0, offset); + return engine.randn(10); +} + +inline int64_t randint64_cpu( + uint32_t seed, + uint32_t offset, + int64_t low, + int64_t high) { + auto gen = at::Philox4_32(seed, 0, offset); + uint64_t r0 = gen(); + uint64_t r1 = gen(); + uint64_t result = r0 | (r1 << 32); + return static_cast(result % (high - low)) + low; +} + +template +struct AsIntegerType { + typedef T type; +}; +template <> +struct AsIntegerType { + typedef uint32_t type; +}; +template <> +struct AsIntegerType { + typedef uint64_t type; +}; +template <> +struct AsIntegerType { + typedef uint16_t type; +}; + +template +typename std::enable_if_t< + !c10::is_reduced_floating_point_v, + T> inline fetch_value(volatile T* addr) { + return *addr; +} + +template +typename std::enable_if_t< + c10::is_reduced_floating_point_v, + T> inline fetch_value(volatile T* addr) { + return T(addr->x, T::from_bits()); +} + +template +typename std::enable_if_t> atomic_add( + volatile T* addr, + T offset) { + typedef typename AsIntegerType::type alt_type; + + static_assert( + sizeof(std::atomic) == sizeof(T), "std::atomic issue"); + + alt_type expected; + + alt_type desired; + + std::atomic* atomic_addr = (std::atomic*)addr; + do { + T val = fetch_value(addr); + reinterpret_cast(&expected)[0] = val; + reinterpret_cast(&desired)[0] = val + offset; + } while (!atomic_addr->compare_exchange_weak( + expected, desired, std::memory_order_relaxed)); +} + +// Since C++20 float is supported by fetch_add, but the performance may not +// better than compare_exchange_weak, which can be checked by microbenchmark +// inductor_cpu_atomic.py +template +typename std::enable_if_t> atomic_add( + volatile T* addr, + T offset) { + static_assert(sizeof(std::atomic) == sizeof(T), "std::atomic issue"); + std::atomic* atomic_addr = (std::atomic*)addr; + atomic_addr->fetch_add(offset, std::memory_order_relaxed); +} + +#if INDUCTOR_USE_VECTOR_TYPES() +template +void atomic_add_vec( + T* addr, + at::vec::VectorizedN index, + at::vec::VectorizedN offset, + std::optional tail_size = std::nullopt) { + constexpr int len = at::vec::VectorizedN::size(); + static_assert(len <= at::vec::VectorizedN::size()); + __at_align__ std::array tmpbuf; + __at_align__ std::array tmpidx; + offset.store(tmpbuf.data(), len); + index.store(tmpidx.data(), len); + int size = tail_size.has_value() ? tail_size.value() : len; + for (int i = 0; i < size; i++) { + atomic_add(addr + tmpidx[i], tmpbuf[i]); + } +} + +template +struct transpose_mxn_helper; + +template +struct transpose_mxn_helper { + static void call( + const T* src, + int64_t ld_src, + T* dst, + int64_t ld_dst, + int M, + int N) { + for (int i = 0; i < M; i++) { + for (int j = 0; j < N; j++) { + atomic_add(&dst[j * ld_dst + i], src[i * ld_src + j]); + } + } + } +}; + +template +struct transpose_mxn_helper { + static void call( + const T* src, + int64_t ld_src, + T* dst, + int64_t ld_dst, + int M, + int N) { + at::vec::transpose_mxn(src, ld_src, dst, ld_dst, M, N); + } +}; + +template +inline void transpose_mxn( + const T* src, + int64_t ld_src, + T* dst, + int64_t ld_dst, + int M, + int N) { + transpose_mxn_helper::call(src, ld_src, dst, ld_dst, M, N); +} + +template +inline void transpose_mxn( + const T* src, + int64_t ld_src, + T* dst, + int64_t ld_dst) { + transpose_mxn(src, ld_src, dst, ld_dst, M, N); +} +#endif + +// NOLINTBEGIN(*-avoid-c-arrays) +inline std::tuple, int> _get_factors( + int64_t number) { + int count = 0; + for (auto i = static_cast(std::sqrt(number)); i > 0; --i) { + if (number % i == 0) { + count += 2; + } + } + auto factors = std::shared_ptr(new int64_t[count]); + int index = 0; + for (auto i = static_cast(std::sqrt(number)); i > 0; --i) { + if (number % i == 0) { + factors[index++] = number / i; + factors[index++] = i; + } + } + return std::make_tuple(factors, count); +} + +inline std::tuple, int> get_factors(int64_t number) { + thread_local std::map, int>> + cache; + auto it = cache.find(number); + if (it != cache.end()) { + return it->second; + } else { + auto factors = _get_factors(number); + cache[number] = factors; + return factors; + } +} +// NOLINTEND(*-avoid-c-arrays) + +inline void _mm_get_thread_blocking( + int num_threads, + int max_k_slices, + int64_t M, + int64_t N, + int64_t K, + int64_t Mr, + int64_t Nr, + int64_t Kr, + int64_t& Mt, + int64_t& Nt, + int64_t& Kt) { + // see NOTE [Thread blocking in Cpp GEMM] for heuristics + Mt = Nt = Kt = 0; + + auto get_blocking = [](int64_t m_factor, + int64_t n_factor, + int64_t k_factor, + int64_t m_blocks, + int64_t n_blocks, + int64_t k_blocks) { + int64_t thread_block_k = (k_blocks + k_factor - 1) / k_factor; + int64_t thread_block_n = (n_blocks + n_factor - 1) / n_factor; + int64_t thread_block_m = (m_blocks + m_factor - 1) / m_factor; + return std::make_tuple(thread_block_m, thread_block_n, thread_block_k); + }; + + auto is_better_blocking = [=](int64_t Mt_, + int64_t Nt_, + int64_t Kt_, + int64_t Mt, + int64_t Nt, + int64_t Kt) { + return Mt == 0 || Kt_ < Kt || Mt_ * Mr + Nt_ * Nr < Mt * Mr + Nt * Nr; + }; + + int64_t m_blocks = (M + Mr - 1) / Mr; + int64_t n_blocks = (N + Nr - 1) / Nr; + int64_t k_blocks = (K + Kr - 1) / Kr; + + auto [factors, count] = get_factors(num_threads); + assert(count > 0); + + for (int i = 0; i < count; ++i) { + int64_t n_factor = factors[i]; + int64_t m_factor = num_threads / n_factor; + if (n_blocks >= n_factor && m_blocks >= m_factor) { + auto [Mt_, Nt_, Kt_] = + get_blocking(m_factor, n_factor, 1, m_blocks, n_blocks, k_blocks); + if (is_better_blocking(Mt_, Nt_, Kt_, Mt, Nt, Kt)) { + std::tie(Mt, Nt, Kt) = std::make_tuple(Mt_, Nt_, Kt_); + } + } + } + + if (Mt != 0) { + return; + } + + for (int i = 0; i < count; ++i) { + int64_t k_factor = factors[i]; + if (k_blocks >= k_factor && + (max_k_slices == 0 || k_factor <= max_k_slices)) { + auto [mxn_factors, mxn_count] = get_factors(num_threads / k_factor); + for (int j = 0; j < mxn_count; ++j) { + int64_t n_factor = mxn_factors[j]; + int64_t m_factor = num_threads / (k_factor * n_factor); + if (n_blocks >= n_factor && m_blocks >= m_factor) { + auto [Mt_, Nt_, Kt_] = get_blocking( + m_factor, n_factor, k_factor, m_blocks, n_blocks, k_blocks); + if (is_better_blocking(Mt_, Nt_, Kt_, Mt, Nt, Kt)) { + std::tie(Mt, Nt, Kt) = std::make_tuple(Mt_, Nt_, Kt_); + } + } + } + } + } + + if (Mt != 0) { + return; + } + + for (int i = 0; i < count; ++i) { + int64_t n_factor = factors[i]; + int64_t m_factor = num_threads / n_factor; + if (n_blocks >= n_factor || m_blocks >= m_factor) { + auto [Mt_, Nt_, Kt_] = + get_blocking(m_factor, n_factor, 1, m_blocks, n_blocks, k_blocks); + if (is_better_blocking(Mt_, Nt_, Kt_, Mt, Nt, Kt)) { + std::tie(Mt, Nt, Kt) = std::make_tuple(Mt_, Nt_, Kt_); + } + } + } + + assert(Mt != 0); +} + +inline void mm_get_thread_blocking( + int num_threads, + int max_k_slices, + int64_t M, + int64_t N, + int64_t K, + int64_t Mr, + int64_t Nr, + int64_t Kr, + int64_t& Mt, + int64_t& Nt, + int64_t& Kt) { + thread_local std::map< + std:: + tuple, + std::tuple> + cache; + auto key = std::make_tuple(num_threads, max_k_slices, M, N, K, Mr, Nr, Kr); + auto it = cache.find(key); + if (it != cache.end()) { + std::tie(Mt, Nt, Kt) = it->second; + return; + } else { + _mm_get_thread_blocking( + num_threads, max_k_slices, M, N, K, Mr, Nr, Kr, Mt, Nt, Kt); + cache[key] = std::make_tuple(Mt, Nt, Kt); + } +} + +// NOLINTBEGIN(*-narrowing-conversions) +template +void _mm_get_cache_blocking( + int num_threads, + int64_t M, + int64_t N, + int64_t K, + int64_t Mr, + int64_t Nr, + int64_t Kr, + int64_t Mt_blocks, + int64_t Nt_blocks, + int64_t Kt_blocks, + int64_t& Mc_blocks, + int64_t& Nc_blocks, + int64_t& Kc_blocks, + uint32_t L1_cache_size, + uint32_t L2_cache_size) { + // See NOTE [CPP GEMM Cache Blocking Algorithm] for the cache blocking + // algorithm. + // TODO(jgong5): cache cache blocking results + // TODO: tune the factor here + float L1_limit_factor = 0.8; + float L2_limit_factor = 0.5; + + auto L1 = L1_cache_size * L1_limit_factor; + auto L2 = L2_cache_size * L2_limit_factor; + + constexpr size_t num_byte_A = sizeof(X_t); + constexpr size_t num_byte_B = sizeof(W_t); + + int64_t size_cache_B = Kr * Kt_blocks * Nr * num_byte_B; + Kc_blocks = Kt_blocks; + if (size_cache_B > L1) { + Kc_blocks = (int64_t)std::floor(L1 / (Kr * Nr * num_byte_B)); + } + + float min_Mc_ratio = 2; + int64_t min_Mc_blocks = std::ceil(min_Mc_ratio * Mr / Nr); + auto Kt_bytes = Kt_blocks * Kr * num_byte_A; + if (min_Mc_blocks * Mr * Kt_bytes < L2) { + Mc_blocks = std::min(Mt_blocks, (int64_t)std::floor(L2 / (Mr * Kt_bytes))); + Nc_blocks = 1; + } else { + Mc_blocks = Mt_blocks; + Nc_blocks = + std::min((int64_t)std::ceil((float)Mc_blocks * Mr / Nr), Nt_blocks); + auto Nc_bytes = Nc_blocks * Nr * 4; + auto Kc_bytes = Kc_blocks * Kr * num_byte_A; + if (Mc_blocks * Mr * (Kc_bytes + Nc_bytes) > L2) { + auto M_max = (std::sqrt(Kc_bytes * Kc_bytes + 16 * L2) - Kc_bytes) / 8; + if (M_max < Mc_blocks * Mr) { + Mc_blocks = (int64_t)std::floor(M_max / Mr); + Nc_blocks = + std::min((int64_t)std::ceil((float)Mc_blocks * Mr / Nr), Nt_blocks); + } + } + } +} +// NOLINTEND(*-narrowing-conversions) + +template +void mm_get_cache_blocking( + int num_threads, + int64_t M, + int64_t N, + int64_t K, + int64_t Mr, + int64_t Nr, + int64_t Kr, + int64_t Mt_blocks, + int64_t Nt_blocks, + int64_t Kt_blocks, + int64_t& Mc_blocks, + int64_t& Nc_blocks, + int64_t& Kc_blocks, + uint32_t L1_cache_size, + uint32_t L2_cache_size) { + thread_local std::map< + std::tuple< + int, + int64_t, + int64_t, + int64_t, + int64_t, + int64_t, + int64_t, + int64_t, + int64_t, + int64_t, + int64_t, + int64_t>, + std::tuple> + cache; + auto key = std::make_tuple( + num_threads, + M, + N, + K, + Mr, + Nr, + Kr, + Mt_blocks, + Nt_blocks, + Kt_blocks, + L1_cache_size, + L2_cache_size); + auto it = cache.find(key); + if (it != cache.end()) { + std::tie(Mc_blocks, Nc_blocks, Kc_blocks) = it->second; + return; + } else { + _mm_get_cache_blocking( + num_threads, + M, + N, + K, + Mr, + Nr, + Kr, + Mt_blocks, + Nt_blocks, + Kt_blocks, + Mc_blocks, + Nc_blocks, + Kc_blocks, + L1_cache_size, + L2_cache_size); + cache[key] = std::make_tuple(Mc_blocks, Nc_blocks, Kc_blocks); + } +} + +struct amx_tilecfg { + uint8_t palette_id{0}; + uint8_t start_row{0}; + std::array reserved_0{}; + std::array colsb{}; + std::array rows{}; +}; + +class AMXState { + private: + amx_tilecfg tilecfg_{}; + uint8_t rows_{0}; + uint16_t colsb_{0}; + uint8_t num_tile_rows_{0}; + uint8_t num_tile_columns_{0}; + + public: + AMXState() = default; + + inline void configure( + uint8_t rows, + uint16_t colsb, + uint8_t num_tile_rows, + uint8_t num_tile_columns, + void (*loadconfig)(const amx_tilecfg&)) { + if (tilecfg_.palette_id == 1 && rows_ == rows && colsb_ == colsb && + num_tile_rows_ == num_tile_rows && + num_tile_columns_ == num_tile_columns) { + return; + } + tilecfg_.palette_id = 1; + rows_ = rows; + colsb_ = colsb; + num_tile_rows_ = num_tile_rows; + num_tile_columns_ = num_tile_columns; + const auto num_c_tiles = num_tile_rows * num_tile_columns; + // For C + for (int i = 0; i < num_c_tiles; i++) { + tilecfg_.rows[i] = rows; + tilecfg_.colsb[i] = 64; + } + // For A + for (int i = 0; i < num_tile_rows; i++) { + tilecfg_.rows[i + num_c_tiles] = rows; + tilecfg_.colsb[i + num_c_tiles] = colsb; + } + // For B + for (int i = 0; i < num_tile_columns; i++) { + tilecfg_.rows[i + num_c_tiles + num_tile_rows] = colsb / 4; + tilecfg_.colsb[i + num_c_tiles + num_tile_rows] = 64; + } + loadconfig(tilecfg_); + } + + inline void release(void (*tile_release)()) { + tilecfg_.palette_id = 0; + tile_release(); + } +}; + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/array_ref.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/array_ref.h new file mode 100644 index 0000000000000000000000000000000000000000..3ff757120d49fa01155e8e20626bff05d9a0c9fe --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/array_ref.h @@ -0,0 +1,12 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/common.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/common.h new file mode 100644 index 0000000000000000000000000000000000000000..d8c5697757770bde1bf1cce3c0d166c6f3a0f17a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/common.h @@ -0,0 +1,95 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include +#if __has_include() +#include +#else +// pybind11 < 3.0: gil_simple.h does not exist yet. +#define PYBIND11_SIMPLE_GIL_MANAGEMENT +#include +// Provide the _simple aliases so generated code works with either version. +namespace pybind11 { +using gil_scoped_acquire_simple = gil_scoped_acquire; +using gil_scoped_release_simple = gil_scoped_release; +} // namespace pybind11 +#endif + +// Required for custom op dispatch via the stable ABI +#include + +#ifdef TORCH_INDUCTOR_PRECOMPILE_HEADERS +// Include some often-used cpp_wrapper headers, for precompiling. +#include +#include +#include +#include +#include +#endif + +namespace py = pybind11; // NOLINT(misc-unused-alias-decls) + +class RAIIPyObject { + public: + RAIIPyObject() = default; + // steals a reference to a PyObject + RAIIPyObject(PyObject* obj) : obj_{obj} {} + RAIIPyObject(const RAIIPyObject& other) : obj_{other.obj_} { + Py_XINCREF(obj_); + } + RAIIPyObject(RAIIPyObject&& other) noexcept { + // refcount doesn't change, and obj_ is currently nullptr + std::swap(obj_, other.obj_); + } + ~RAIIPyObject() { + Py_XDECREF(obj_); + } + RAIIPyObject& operator=(const RAIIPyObject& other) { + if (this != &other) { + Py_XDECREF(obj_); + obj_ = other.obj_; + Py_XINCREF(obj_); + } + return *this; + } + RAIIPyObject& operator=(RAIIPyObject&& other) noexcept { + // refcount to the current object decreases, but refcount to other.obj_ is + // the same + Py_XDECREF(obj_); + obj_ = std::exchange(other.obj_, nullptr); + return *this; + } + operator bool() const noexcept { + return obj_; + } + operator PyObject*() { + return obj_; + } + PyObject* get() { + return obj_; + } + + private: + PyObject* obj_{nullptr}; +}; + +#include +#include +using namespace torch::aot_inductor; + +#include +#include + +// Round up to the nearest multiple of 64 +[[maybe_unused]] inline int64_t align(int64_t nbytes) { + return (nbytes + 64 - 1) & -64; +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/cpu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..e98e987de358efd0ad1c810d837cae8205bbb33c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/cpu.h @@ -0,0 +1,9 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/cuda.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/cuda.h new file mode 100644 index 0000000000000000000000000000000000000000..209d9b49c4f1dbcd60764858ba2a1d4be7f394be --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/cuda.h @@ -0,0 +1,15 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include + +#ifdef TORCH_INDUCTOR_PRECOMPILE_HEADERS +#include +#include +#include +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/device_internal/cpu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/device_internal/cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..98fd14fb45fc6138446fcc80b9148b3471d4ebde --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/device_internal/cpu.h @@ -0,0 +1,8 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/device_internal/cuda.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/device_internal/cuda.h new file mode 100644 index 0000000000000000000000000000000000000000..2f9e7104c1b2a16f8d4a0dbd920e6a2816f059a2 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/device_internal/cuda.h @@ -0,0 +1,9 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/device_internal/mps.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/device_internal/mps.h new file mode 100644 index 0000000000000000000000000000000000000000..7711a5e019966c970818c5e7082a5b99f22856e1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/device_internal/mps.h @@ -0,0 +1,9 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/device_internal/xpu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/device_internal/xpu.h new file mode 100644 index 0000000000000000000000000000000000000000..eda98fd2052767ac360e31245fa94a9e350cbdaf --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/device_internal/xpu.h @@ -0,0 +1,10 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/lazy_triton_compile.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/lazy_triton_compile.h new file mode 100644 index 0000000000000000000000000000000000000000..a3bb04b421d2b02d5533fedf9b11f5bb95a96453 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/lazy_triton_compile.h @@ -0,0 +1,206 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include +#include +#if defined(USE_XPU) +#include +#else +#include +#endif + +struct LazyKernelCompileResult { + std::string cubin_path; + std::string mangled_name; + int num_warps; + int shared_mem; + int xblock; + int yblock; + int zblock; + int r0block; + int rsplit; + int rsplit_size; + int config_index; + int global_scratch; + int profile_scratch; +}; + +static PyObject* (*_THPVariable_Wrap)(const at::TensorBase&) = nullptr; +static int32_t (*_THPUtils_unpackInt)(PyObject*) = nullptr; + +// Cached module and function references +static PyObject* triton_lazy_compile_module = nullptr; +static PyObject* start_kernel_compile = nullptr; +static PyObject* run_triton_kernel_with_autotune = nullptr; + +// Per-module dict for pending kernel compile results (avoids global state +// collisions when multiple compiled modules produce kernels with the same +// name). +static PyObject* _module_pending_kernels = nullptr; + +static inline void loadLazyCompileFuncs() { + if (triton_lazy_compile_module == nullptr) { + triton_lazy_compile_module = + PyImport_ImportModule("torch._inductor.runtime.triton_lazy_compile"); + AOTI_TORCH_CHECK( + triton_lazy_compile_module, "Failed to import triton_lazy_compile"); + + start_kernel_compile = PyObject_GetAttrString( + triton_lazy_compile_module, "start_kernel_compile"); + AOTI_TORCH_CHECK( + start_kernel_compile, "Failed to get start_kernel_compile"); + + run_triton_kernel_with_autotune = PyObject_GetAttrString( + triton_lazy_compile_module, "run_triton_kernel_with_autotune"); + AOTI_TORCH_CHECK( + run_triton_kernel_with_autotune, + "Failed to get run_triton_kernel_with_autotune"); + + RAIIPyObject guards_mod = PyImport_ImportModule("torch._C._dynamo.guards"); + AOTI_TORCH_CHECK(guards_mod, "Failed to import torch._C._dynamo.guards"); + + RAIIPyObject wrap_addr = + PyObject_GetAttrString(guards_mod, "_torchinductor_thp_variable_wrap"); + AOTI_TORCH_CHECK( + wrap_addr, "Failed to get _torchinductor_thp_variable_wrap"); + _THPVariable_Wrap = reinterpret_cast( + PyLong_AsVoidPtr(wrap_addr)); + AOTI_TORCH_CHECK(_THPVariable_Wrap, "THPVariable_Wrap not resolved"); + + RAIIPyObject unpack_addr = PyObject_GetAttrString( + guards_mod, "_torchinductor_thputils_unpack_int"); + AOTI_TORCH_CHECK( + unpack_addr, "Failed to get _torchinductor_thputils_unpack_int"); + _THPUtils_unpackInt = reinterpret_cast( + PyLong_AsVoidPtr(unpack_addr)); + AOTI_TORCH_CHECK(_THPUtils_unpackInt, "THPUtils_unpackInt not resolved"); + } +} + +static inline std::string getStringAttr(PyObject* obj, const char* attr) { + RAIIPyObject val = PyObject_GetAttrString(obj, attr); + AOTI_TORCH_CHECK(val, "Failed to get attribute"); + return PyUnicode_AsUTF8(val); +} + +static inline int getIntAttr(PyObject* obj, const char* attr) { + RAIIPyObject val = PyObject_GetAttrString(obj, attr); + AOTI_TORCH_CHECK(val, "Failed to get attribute"); + return _THPUtils_unpackInt(val); +} + +static inline int getOptionalIntAttr( + PyObject* obj, + const char* attr, + int sentinel = -1) { + RAIIPyObject val = PyObject_GetAttrString(obj, attr); + AOTI_TORCH_CHECK(val, "Failed to get attribute"); + return (val.get() != Py_None) ? _THPUtils_unpackInt(val) : sentinel; +} + +static inline LazyKernelCompileResult extractCompileResult(PyObject* result) { + LazyKernelCompileResult compile_result; + compile_result.cubin_path = getStringAttr(result, "cubin_path"); + compile_result.mangled_name = getStringAttr(result, "mangled_name"); + compile_result.num_warps = getIntAttr(result, "num_warps"); + compile_result.shared_mem = getIntAttr(result, "shared_mem"); + compile_result.xblock = getIntAttr(result, "xblock"); + compile_result.yblock = getIntAttr(result, "yblock"); + compile_result.zblock = getIntAttr(result, "zblock"); + compile_result.r0block = getIntAttr(result, "r0block"); + compile_result.rsplit = getIntAttr(result, "rsplit"); + compile_result.rsplit_size = getIntAttr(result, "rsplit_size"); + compile_result.config_index = getOptionalIntAttr(result, "config_index"); + compile_result.global_scratch = getOptionalIntAttr(result, "global_scratch"); + compile_result.profile_scratch = + getOptionalIntAttr(result, "profile_scratch"); + return compile_result; +} + +template +static inline PyObject* convertArgToPython(const T& arg) { + using DecayedT = std::decay_t; + if constexpr (std::is_same_v) { + at::Tensor* tensor_ptr = + torch::aot_inductor::tensor_handle_to_tensor_pointer(arg); + return _THPVariable_Wrap(*tensor_ptr); + } else if constexpr (std::is_same_v< + DecayedT, + torch::aot_inductor::RAIIAtenTensorHandle>) { + at::Tensor* tensor_ptr = + torch::aot_inductor::tensor_handle_to_tensor_pointer(arg.get()); + return _THPVariable_Wrap(*tensor_ptr); + } else if constexpr (std::is_same_v) { + PyObject* py_arg = arg ? Py_True : Py_False; + Py_INCREF(py_arg); + return py_arg; + } else if constexpr (std::is_integral_v) { + return PyLong_FromLongLong(static_cast(arg)); + } else if constexpr (std::is_floating_point_v) { + return PyFloat_FromDouble(static_cast(arg)); + } else { + AOTI_TORCH_CHECK(false, "Invalid input type to convertArgToPython"); + } +} + +template +static inline LazyKernelCompileResult runTritonKernelWithAutotune( + PyObject* pending_kernels, + const std::string& kernel_name, + void* stream, + const Args&... kernel_args) { + py::gil_scoped_acquire_simple acquire; + + constexpr size_t num_args = sizeof...(Args); + RAIIPyObject py_args_list = PyList_New(num_args); + AOTI_TORCH_CHECK(py_args_list, "Failed to create args list"); + + size_t idx = 0; + auto add_arg = [&py_args_list, &idx](PyObject* py_arg) { + AOTI_TORCH_CHECK(py_arg, "Failed to convert argument"); + PyList_SetItem(py_args_list, idx++, py_arg); + }; + // Use array pack-expansion instead of a fold expression to avoid + // hitting the compiler's expression-nesting limit when there are + // hundreds of kernel arguments (e.g. combo kernels). + int dummy[] = {0, (add_arg(convertArgToPython(kernel_args)), 0)...}; + (void)dummy; + + RAIIPyObject call_args = PyTuple_Pack( + 4, + pending_kernels, + PyUnicode_FromString(kernel_name.c_str()), + PyLong_FromVoidPtr(stream), + py_args_list.get()); + AOTI_TORCH_CHECK(call_args, "Failed to create call args"); + + RAIIPyObject result = + PyObject_CallObject(run_triton_kernel_with_autotune, call_args); + AOTI_TORCH_CHECK(result, "Failed to run kernel with autotuning"); + + return extractCompileResult(result); +} + +static inline void startKernelCompile( + PyObject* pending_kernels, + const std::string& kernel_name, + const std::string& kernel_source) { + py::gil_scoped_acquire_simple acquire; + + RAIIPyObject py_name = PyUnicode_FromString(kernel_name.c_str()); + RAIIPyObject py_source = PyUnicode_FromString(kernel_source.c_str()); + AOTI_TORCH_CHECK(py_name && py_source, "Failed to create Python args"); + + RAIIPyObject call_args = + PyTuple_Pack(3, pending_kernels, py_name.get(), py_source.get()); + AOTI_TORCH_CHECK(call_args, "Failed to create call args"); + + RAIIPyObject result = PyObject_CallObject(start_kernel_compile, call_args); + AOTI_TORCH_CHECK(result, "Failed to start kernel compilation"); +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/mps.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/mps.h new file mode 100644 index 0000000000000000000000000000000000000000..00d4464071f64f8c46df042813e6bd56222a304e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/mps.h @@ -0,0 +1,9 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/xpu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/xpu.h new file mode 100644 index 0000000000000000000000000000000000000000..705efd22032156ac5125638d286741568d0c25bd --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/cpp_wrapper/xpu.h @@ -0,0 +1,10 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/inductor_ops.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/inductor_ops.h new file mode 100644 index 0000000000000000000000000000000000000000..77eef6c69f5eb4725fcf08489bf57e27dd97ae30 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/inductor_ops.h @@ -0,0 +1,44 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::inductor { + +TORCH_API at::Tensor _mm_plus_mm_out( + at::Tensor& out, + const at::Tensor& a, + const at::Tensor& b, + const at::Tensor& c, + const at::Tensor& d); + +// After adding _mm_plus_mm_out, this should not be exposed and called by model +// code. Keeping it around for backward compatibility. Will be deprecated later. +TORCH_API at::Tensor _mm_plus_mm( + const at::Tensor& a, + const at::Tensor& b, + const at::Tensor& c, + const at::Tensor& d, + at::Tensor& out); + +TORCH_API at::Tensor _alloc_from_pool( + const at::Tensor& self, + int64_t offset_bytes, + at::ScalarType dtype, + at::IntArrayRef size, + at::IntArrayRef stride); + +// Similar to as_strided with the following differences +// - offset is added to the existing offset (rather than replacing it) +// - view tracking is disabled similar to unsafe_view +TORCH_API at::Tensor _reinterpret_tensor( + const at::Tensor& self, + at::IntArrayRef size, + at::IntArrayRef stride, + int64_t offset_increment = 0); + +} // namespace torch::inductor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/static_launcher/cuda.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/static_launcher/cuda.h new file mode 100644 index 0000000000000000000000000000000000000000..4015bd2d535659c1e6b2cad92a71cd04af2117ac --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/static_launcher/cuda.h @@ -0,0 +1,12 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#if defined(USE_CUDA) +#include +#include + +bool StaticCudaLauncher_init(PyObject* module); +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/static_launcher/xpu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/static_launcher/xpu.h new file mode 100644 index 0000000000000000000000000000000000000000..91fc6de742003b33c79b3ebdb2083e37533c1b6a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/inductor/static_launcher/xpu.h @@ -0,0 +1,11 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#if defined(USE_XPU) +#include + +bool StaticXpuLauncher_init(PyObject* module); +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/instruction_counter/Module.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/instruction_counter/Module.h new file mode 100644 index 0000000000000000000000000000000000000000..b7fbac85c979734a709aef89819ae609e54b6686 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/instruction_counter/Module.h @@ -0,0 +1,13 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include + +namespace torch::instruction_counter { + +void initModule(PyObject* module); + +} // namespace torch::instruction_counter + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/itt.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/itt.h new file mode 100644 index 0000000000000000000000000000000000000000..64d9824c3b551da4ee761a2ab213bb8f7ce143b6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/itt.h @@ -0,0 +1,13 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#ifndef ITT_H +#define ITT_H +#include + +namespace torch::profiler { +void initIttBindings(PyObject* module); // namespace torch::profiler +} +#endif // ITT_H + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/itt_wrapper.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/itt_wrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..3a556190443fc84b9eb72fb5f6f251149425b318 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/itt_wrapper.h @@ -0,0 +1,17 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#ifndef PROFILER_ITT_H +#define PROFILER_ITT_H +#include + +namespace torch::profiler { +TORCH_API bool itt_is_available(); +TORCH_API void itt_range_push(const char* msg); +TORCH_API void itt_range_pop(); +TORCH_API void itt_mark(const char* msg); +} // namespace torch::profiler + +#endif // PROFILER_ITT_H + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/api/compilation_unit.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/api/compilation_unit.h new file mode 100644 index 0000000000000000000000000000000000000000..e6264f6f992a61123df6647a90176397261bc47f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/api/compilation_unit.h @@ -0,0 +1,356 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace torch::jit { + +struct Def; +struct Property; +struct ClassDef; +struct SugaredValue; +struct Resolver; + +using ResolverPtr = std::shared_ptr; +struct Self { + virtual ~Self() = default; + virtual std::shared_ptr makeSugared(Value* v) const = 0; + virtual ClassTypePtr getClassType() const = 0; +}; + +// A CompilationUnit is a list of named Functions +// with helper methods to iterate the list or invoke the function. +// Classes have a CompilationUnit holding the class methods, +// and Modules have a CompilationUnit holding the Functions that +// are used to implement their Methods + +struct TORCH_API CompilationUnit { + enum class FunctionType { Method, Hook, PreHook }; + // constructor that takes a set of functions to compile using the native + // resolver + explicit CompilationUnit(const std::string& source); + CompilationUnit() = default; + + CompilationUnit& operator=(CompilationUnit&&) = default; + CompilationUnit(CompilationUnit&&) = default; + CompilationUnit& operator=(const CompilationUnit&) = delete; + CompilationUnit(const CompilationUnit&) = delete; + + Function* find_function(const c10::QualifiedName& name) const { + auto it = dict_.find(name); + if (it == dict_.end()) { + return nullptr; + } + return functions_[it->second].get(); + } + + Function& get_function(const c10::QualifiedName& name) const { + if (auto r = find_function(name)) { + return *r; + } + TORCH_CHECK(false, "attempted to get undefined function ", name.name()); + } + + void set_optimized(bool o) { + TORCH_WARN( + "CompilationUnit::set_optimized() is deprecated and has no effect. " + "Please use setGraphExecutorOptimize()"); + } + + bool is_optimized() const { + TORCH_WARN( + "CompilationUnit::is_optimized() is deprecated and always returns true. " + "Please use getGraphExecutorOptimize()"); + return true; + } + + // for historic reasons, these are defined in ir_emitter.cpp + // Returns the list of Functions just defined. + std::vector define( + const std::optional& prefix, + const std::vector& properties, + const std::vector& propResolvers, + const std::vector& definitions, + const std::vector& + defResolvers, /* determines how we handle free + variables in each definition*/ + // if non-null, the first argument to each def, is bound to this value + const Self* self, + // see [name mangling] + bool shouldMangle = false, + std::optional operator_set_version = std::nullopt); + + void define_hooks( + const std::optional& prefix, + const std::vector& hookDefs, + const std::vector& hookResolvers, + const std::vector& preHookDefs, + const std::vector& preHookResolvers, + const Self* self, + bool shouldMangle = false); + + // same as above but parse the definitions from source + // Returns the list of Functions just defined. + std::vector define( + // prefix namespace to put all the defined functions into + const std::optional& prefix, + const std::string& source, + const ResolverPtr& resolver, + const Self* self); + + void define_interface( + const c10::QualifiedName& qualifiedName, + const ClassDef& classDef, + ResolverPtr rcb, + bool is_module = false); + + Function* create_function( + c10::QualifiedName name, + std::shared_ptr graph, + bool shouldMangle = false) { + if (shouldMangle) { + name = mangle(name); + } + auto fn = std::make_unique( + std::move(name), std::move(graph), nullptr); + auto ret = fn.get(); + register_function(std::move(fn)); + return ret; + } + + std::vector get_functions() const { + return fmap(functions_, [](const std::unique_ptr& fn) { + return fn.get(); + }); + } + + /// Run a method from this compilation. + /// + /// For example: + /// @code + /// IValue output = module->run("relu_script", a, b); + /// @endcode + /// + /// To get a compile a module from a source string, see torch::jit::compile + /// + /// @param method_name The name of the method to run + /// @param args Arguments to be passed to the method + /// @return An IValue containing the return value (or values if it is a tuple) + /// from the method + template + IValue run_method(const c10::QualifiedName& method_name, Types&&... args) { + return get_function(method_name)({IValue(std::forward(args))...}); + } + + void drop_all_functions() { + dict_.clear(); + functions_.clear(); + } + + /** + * Register a class as being owned by this compilation unit. + */ + void register_type(c10::NamedTypePtr namedType) { + // TODO: class types cannot be redefined because we have no way right now + // of invalidating their methods. NamedTuples are fine though, since they + // don't have methods. + TORCH_CHECK( + 0 == classDict_.count(*namedType->name()), + "class '", + namedType->name()->qualifiedName(), + "' already defined."); + classes_.push_back(std::move(namedType)); + classDict_[*classes_.back()->name()] = classes_.size() - 1; + } + + c10::ClassTypePtr get_class(const c10::QualifiedName& name) const { + auto type = get_type(name); + if (!type) { + return nullptr; + } + return type->cast(); + } + + c10::InterfaceTypePtr get_interface(const c10::QualifiedName& name) const { + auto type = get_type(name); + if (!type) { + return nullptr; + } + return type->cast(); + } + + c10::TupleTypePtr get_named_tuple(const c10::QualifiedName& name) const { + for (const auto& cls : classes_) { + if (cls->name()->qualifiedName() == name.qualifiedName()) { + return cls->expect(); + } + } + return nullptr; + } + + c10::NamedTypePtr get_type(const c10::QualifiedName& name) const { + auto it = classDict_.find(name); + if (it == classDict_.end()) { + return nullptr; + } + return classes_[it->second]; + } + + // For testing: clear all Python-defined classes to ensure that unit tests + // have isolation. + void _clear_python_cu() { + // Delete all the associated class methods + for (const auto& type : classes_) { + if (auto cls = type->cast()) { + for (auto method : cls->methods()) { + // Tombstone the method in the compilation unit. + // Don't erase because the dict_ + auto it = dict_.find(method->qualname()); + if (it != dict_.end()) { + functions_[it->second] = nullptr; + // Erase in our big lookup table + dict_.erase(it); + } + } + // Classes can have multiple pointers to the same hook, + // need to make sure to not delete it twice + std::unordered_set hooks_to_delete; + for (const auto& hook : cls->getForwardHooks()) { + hooks_to_delete.insert(hook); + } + for (const auto& pre_hook : cls->getForwardPreHooks()) { + hooks_to_delete.insert(pre_hook); + } + for (const auto& hook : hooks_to_delete) { + // Tombstone the hook in the compilation unit. + auto it = dict_.find(hook->qualname()); + if (it != dict_.end()) { + functions_[it->second] = nullptr; + // Erase in our big lookup table + dict_.erase(it); + } + } + } + } + classes_.clear(); + classDict_.clear(); + } + + // [Internal Only] Remove method. + // Note Used for freezing. + void unsafeRemoveMethod(const c10::QualifiedName& method_name) { + auto it = dict_.find(method_name); + TORCH_CHECK( + it != dict_.end(), + "method '", + method_name.qualifiedName(), + "' does not exist."); + functions_[it->second] = nullptr; + dict_.erase(it); + } + + // [name mangling] All code objects must have a unique qualified name in a + // CompilationUnit. In Python, sometimes functions won't have unique qualified + // name (for example, nested functions). So we mangle Python functions to + // ensure that they are uniquely named. + // + // We also use mangling to distinguish different Module instances. Since each + // Module is a singleton class instance, different instances of the same + // Python Module will have different types but the same qualified name. + c10::QualifiedName mangle(const c10::QualifiedName& name) const { + auto mangled = name; + while (get_type(mangled) || find_function(mangled)) { + mangled = mangler_.mangle(mangled); + } + return mangled; + } + + private: + std::unique_ptr define( + const std::optional& prefix, + const Def& def, + const ResolverPtr& resolver, + const Self* self, + const std::unordered_map& function_table, + bool shouldMangle = false, + FunctionType type = FunctionType::Method, + std::optional version = std::nullopt) const; + + // Define a property on \p self. + struct PropertyPair; + PropertyPair define_property( + const std::optional& prefix, + const Property& prop, + const ResolverPtr& resolver, + const Self* self, + const std::unordered_map& function_table, + bool shouldMangle = false) const; + + Function& register_function(std::unique_ptr fn) { + TORCH_CHECK( + 0 == dict_.count(fn->qualname().qualifiedName()), + "method '", + fn->qualname().qualifiedName(), + "' already defined."); + functions_.emplace_back(std::move(fn)); + dict_[functions_.back()->qualname()] = functions_.size() - 1; + return *functions_.back(); + } + std::vector> functions_; + // for fast lookup + std::unordered_map dict_; + std::unordered_map classDict_; + + // [class ownership] Right now there are two relationships between classes + // and compilation units: + // 1. Classes have compilation units internally that hold their methods. + // 2. On load, the TypePtrs of any imported classes are owned by the main + // module's compilation unit. + std::vector classes_; + + mutable NameMangler mangler_; +}; + +// An owning pointer to a Function. Just a pair of a raw Function ptr and it's +// owning CU. We need this because pybind requires a ref-counted way to refer to +// Functions. +struct StrongFunctionPtr { + StrongFunctionPtr(std::shared_ptr cu, Function* function) + : cu_(std::move(cu)), function_(function) { + TORCH_INTERNAL_ASSERT(cu_); + TORCH_INTERNAL_ASSERT(function_); + } + std::shared_ptr cu_; + Function* function_; +}; + +namespace script { +// We once had a `script::` namespace that was deleted. This is for backcompat +// of the public API; new code should not use this type alias. +using CompilationUnit = ::torch::jit::CompilationUnit; +} // namespace script +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/api/function_impl.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/api/function_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..e311563890e13e39c5382b582953433131ab62cd --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/api/function_impl.h @@ -0,0 +1,185 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace torch::jit { + +struct TORCH_API GraphFunction : public Function { + GraphFunction( + c10::QualifiedName name, + std::shared_ptr graph, + std::function function_creator, + std::optional executor_execution_mode = + std::nullopt) + : name_(std::move(name)), + graph_(std::move(graph)), + executor_execution_mode_(executor_execution_mode), + function_creator_(std::move(function_creator)) {} + + bool isGraphFunction() const override { + return true; + } + + void run(Stack& stack) override; + + std::function function_creator() const { + return function_creator_; + } + + c10::intrusive_ptr runAsync( + Stack& stack, + TaskLauncher taskLauncher = at::launch) override; + + std::shared_ptr graph() const { + return graph_; + } + + std::shared_ptr optimized_graph() const; + + const c10::QualifiedName& qualname() const override { + return name_; + } + + // private/unstable api. sets the initial execution mode + // will not affect executor if there is an existing executor + // created for this function + void _set_initial_executor_execution_mode(ExecutorExecutionMode mode) { + executor_execution_mode_ = mode; + } + // private/unstable api. sets flag of whether or not to ignore amp. + // will not affect executor if there is an existing executor + // created for this function + void _set_ignore_amp(bool ignore_amp) { + force_no_amp_ = ignore_amp; + } + + // if this isn't yet defined, run its method_creator function + void ensure_defined() override; + + size_t num_inputs() const override { + return graph()->inputs().size(); + } + + Function& setSchema(FunctionSchema schema) override { + schema_ = std::make_unique(std::move(schema)); + return *this; + } + + const FunctionSchema& getSchema() const override; + + GraphExecutorState getDebugState() { + return get_executor().getDebugState(); + } + + bool is_optimized() const { + TORCH_WARN( + "GraphFunction::is_optimized() is deprecated and always returns true. " + "Please use getGraphExecutorOptimize()"); + return true; + } + + void check_single_output() { + TORCH_CHECK( + graph()->outputs().size() == 1, + "Method (but not graphs in general) require a single output. Use None/Tuple for 0 or 2+ outputs"); + } + + GraphExecutor& get_executor() { + ensure_defined(); + std::lock_guard lock(compile_mutex); + auto& executor = executors_[currentSpecialization()]; + if (executor) { + return *executor; + } + check_single_output(); + const std::string& name = name_.name(); + std::shared_ptr opt_graph = optimized_graph(); + if (!executor_execution_mode_) { + executor = GraphExecutor(opt_graph, name); + } else { + executor = GraphExecutor(opt_graph, name, *executor_execution_mode_); + } + return *executor; + } + + using Function::call; + bool call( + Stack& stack, + std::optional bailOut, + c10::function_ref f) override { + f(get_executor().getPlanFor(stack, bailOut).code); + return true; + } + + void clear_optimized_graphs() { + optimized_graphs_.fill(nullptr); + } + + private: + enum SpecializationKey { + AutocastOff, + CpuAutocastOn, + GpuAutocastOn, + CpuGpuAutocastOn, + + // This provides the number of specializations + // (Must be last entry) + TotalCount + }; + + SpecializationKey currentSpecialization() const; + + private: + c10::QualifiedName name_; + // The original, non-optimized graph + std::shared_ptr graph_; // for debugging and for inlining + + // allows users to specify Simple/Profiling Executor for function + // TODO: add more executors + mutable std::optional executor_execution_mode_; + + // if invoked on a graph that has already traced through amp + // don't invoke amp pass + mutable bool force_no_amp_ = false; + // Optimized graph, computed lazily. Used for inlining. + mutable std::array, SpecializationKey::TotalCount> + optimized_graphs_; + + // GraphFunctions are invocable from multiple threads, so this lock needs to + // be held when we're initializing graph executor for the first time or + // computing the optimized graph. We're using reentrant mutex so that we don't + // need to worry about causing a deadlock by calling one method from another + // (e.g. optimized_graph() from get_executor()). + mutable std::recursive_mutex compile_mutex; + + // executor_[0] - autocast off + // executor_[1] - autocast cpu on + // executor_[2] - autocast gpu on + // executor_[3] - autocast cpu & gpu on + std::array, SpecializationKey::TotalCount> + executors_; + + // an optional function that actually creates the method when + // ensure_defined() is called. This is used by the compiler so + // that it can construct methods out of order + std::function function_creator_; + + // if absent, then we generate a default schema based on the graph + // mutable because getSchema caches the default schema if one is requested + // before a call to setSchema + mutable std::unique_ptr schema_; +}; + +// Short hands for dynamic_cast. +TORCH_API GraphFunction* tryToGraphFunction(Function& /*function*/) noexcept; +TORCH_API GraphFunction& toGraphFunction(Function& /*function*/); +TORCH_API const GraphFunction& toGraphFunction(const Function& /*function*/); +} // namespace torch::jit +C10_DECLARE_bool(torch_jit_do_not_store_optimized_graph); + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/api/method.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/api/method.h new file mode 100644 index 0000000000000000000000000000000000000000..d138f8f847d2d0074f0b1669022fa0f4b3e811f6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/api/method.h @@ -0,0 +1,91 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace torch::jit { + +using ObjectPtr = c10::intrusive_ptr; + +// A method in a module, e.g. f in: +// +// class M(ScriptModule): +// @script_method +// def f(self, x): +// ... +// Note: because Method/Module are exposed to python these +// classes use python method naming conventions +struct TORCH_API Method : public torch::IMethod { + Method(ObjectPtr owner, Function* function); + + // the module that contains this method. + Module owner() const; + // the raw objectptr that owns this method, for when the method is owned by a + // torchbind object. + ObjectPtr raw_owner() const; + void run(Stack& stack); + void run(Stack&& stack) { + run(stack); + } + + c10::IValue operator()( + std::vector stack, + const Kwargs& kwargs = Kwargs()) const override; + + // Run method async. Invocation on this function would invokes a JIT + // interpreter that executes ops inline, one by one, on caller's thread. A + // model can utilize async op, i.e. `fork`, to launch an asynchronous task + // which will be launched on provided `taskLauncher`. + c10::intrusive_ptr run_async( + std::vector stack, + const Kwargs& kwargs = Kwargs(), + TaskLauncher taskLauncher = at::launch); + + std::shared_ptr graph() const { + return toGraphFunction(*function_).graph(); + } + + const std::string& name() const override { + return function_->name(); + } + + size_t num_inputs() const { + return function_->num_inputs(); + } + + GraphExecutor& get_executor() { + return toGraphFunction(*function_).get_executor(); + } + + Function& function() const { + return *function_; + } + + private: + void setArgumentNames( + std::vector& /*argumentNames*/ /*argumentNamesOut*/) + const override; + + // Methods are uniqued owned by a single module. This raw pointer allows + // looking up the module. + ObjectPtr owner_; + + // Underlying unbound function + Function* function_; +}; + +namespace script { +// We once had a `script::` namespace that was deleted. This is for backcompat +// of the public API; new code should not use this type alias. +using Method = ::torch::jit::Method; +} // namespace script + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/api/module.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/api/module.h new file mode 100644 index 0000000000000000000000000000000000000000..385c1ec489fc9d43caee073b604b4d5c777c286e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/api/module.h @@ -0,0 +1,690 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// This file contains classes which assist in desugaring Python style +// modules and their methods into flattened graphs which don't have any +// function calls. + +namespace torch::jit { + +using ::c10::Argument; +using ::c10::FunctionSchema; +using ::c10::QualifiedName; +// Map which stores filename to content. +using ExtraFilesMap = std::unordered_map; + +using ModulePtr = c10::intrusive_ptr; + +struct Module; + +template +struct slot_list_impl; + +template +struct Named { + std::string name; + T value; +}; + +using NameModule = Named; +using NameValue = Named; +using NameTensor = Named; + +namespace detail { +struct TORCH_API ModulePolicy; +struct TORCH_API ParameterPolicy; +struct TORCH_API AttributePolicy; +struct TORCH_API BufferPolicy; +template +struct NamedPolicy; +} // namespace detail + +using module_list = slot_list_impl; +using named_module_list = + slot_list_impl>; + +using parameter_list = slot_list_impl; +using named_parameter_list = + slot_list_impl>; + +using attribute_list = slot_list_impl; +using named_attribute_list = + slot_list_impl>; + +using buffer_list = slot_list_impl; +using named_buffer_list = + slot_list_impl>; + +using ModuleLookup = std::function&)>; + +struct TORCH_API Module : public Object { + explicit Module(c10::QualifiedName class_name); + Module(std::shared_ptr cu, const c10::ClassTypePtr& type); + Module() = default; + Module(const Module&) = default; + Module& operator=(const Module&) = default; + Module(Module&&) noexcept = default; + Module& operator=(Module&&) noexcept = default; + Module( + c10::QualifiedName /*class_name*/, + std::shared_ptr cu, + bool shouldMangle = false); + Module(ModulePtr module_value) : Object(std::move(module_value)) {} + ~Module() = default; + + void set_optimized(bool o) { + TORCH_WARN( + "Module::set_optimized() is deprecated and has no effect. " + "Please use setGraphExecutorOptimize()"); + } + + bool is_optimized() const { + TORCH_WARN( + "Module::is_optimized() is deprecated and always returns true. " + "Please use getGraphExecutorOptimize()"); + return true; + } + + IValue forward(std::vector inputs, const Kwargs& kwargs = Kwargs()) { + return get_method("forward")(std::move(inputs), kwargs); + } + + // In script modules, buffers are Tensors attribute that are _not_ registered + // as parameters. This is different than in nn.Module where there is a special + // register_buffer method. With this simplification, we only need to track + // whether a slot is a parameter to be able to classify it. + void register_buffer(const std::string& name, at::Tensor v) { + bool is_param = false; + bool is_buffer = true; + std::lock_guard lock(*register_mutex_); + type()->addOrCheckAttribute(name, TensorType::get(), is_param, is_buffer); + _ivalue()->setAttr(name, std::move(v)); + } + + void register_parameter( + const std::string& name, + at::Tensor v, + bool is_buffer) { + std::lock_guard lock(*register_mutex_); + type()->addOrCheckAttribute(name, TensorType::get(), !is_buffer, is_buffer); + _ivalue()->setAttr(name, std::move(v)); + } + + void register_attribute( + const std::string& name, + const TypePtr& t, + IValue v, + bool is_param = false, + bool is_buffer = false) { + type()->addOrCheckAttribute(name, t, is_param, is_buffer); + _ivalue()->setAttr(name, std::move(v)); + } + + void register_module(const std::string& name, const Module& module) { + type()->addOrCheckAttribute(name, module.type()); + _ivalue()->setAttr(name, module._ivalue()); + } + + void apply(const std::function& fn); + + buffer_list buffers(bool recurse = true) const; + named_buffer_list named_buffers(bool recurse = true) const; + + module_list children() const; // direct modules + named_module_list named_children() const; + module_list modules() const; // all modules, including this one, recursively + named_module_list named_modules() const; + + // all tensors involved in gradient optimization + parameter_list parameters(bool recurse = true) const; + named_parameter_list named_parameters(bool recurse = true) const; + + // all members of the object, similar to iterating over dir(obj) in python + attribute_list attributes(bool recurse = true) const; + named_attribute_list named_attributes(bool recurse = true) const; + + void dump( + bool print_method_bodies, + bool print_attr_values, + bool print_param_values) const; + + std::string dump_to_str( + bool print_method_bodies, + bool print_attr_values, + bool print_param_values) const; + + /// Enables "training" mode. + void train(bool on = true); + /// Calls train(false) to enable "eval" mode. + /// Do not override this method, override `train()` instead. + void eval() { + train(/*on=*/false); + } + /// True if the module is in training mode. + bool is_training() const { + return attr("training", true).toBool(); + } + + /// Recursively casts all parameters to the given `dtype` and `device`. + /// + /// If `non_blocking` is true and the source is in pinned memory and + /// destination is on the GPU or vice versa, the copy is performed + /// asynchronously with respect to the host. Otherwise, the argument has no + /// effect. + void to(at::Device device, at::ScalarType dtype, bool non_blocking = false); + + /// Recursively casts all parameters to the given dtype. + /// + /// If `non_blocking` is true and the source is in pinned memory and + /// destination is on the GPU or vice versa, the copy is performed + /// asynchronously with respect to the host. Otherwise, the argument has no + /// effect. + void to(at::ScalarType dtype, bool non_blocking = false); + + /// Recursively moves all parameters to the given device. + /// + /// If `non_blocking` is true and the source is in pinned memory and + /// destination is on the GPU or vice versa, the copy is performed + /// asynchronously with respect to the host. Otherwise, the argument has no + /// effect. + void to(at::Device device, bool non_blocking = false); + + void save( + std::ostream& out, + const ExtraFilesMap& extra_files = ExtraFilesMap()) const; + + void save( + const std::string& filename, + const ExtraFilesMap& extra_files = ExtraFilesMap()) const; + + void _save_for_mobile( + std::ostream& out, + const ExtraFilesMap& extra_files = ExtraFilesMap(), + bool save_mobile_debug_info = false, + bool use_flatbuffer = false) const; + + void _save_for_mobile( + const std::string& filename, + const ExtraFilesMap& extra_files = ExtraFilesMap(), + bool save_mobile_debug_info = false, + bool use_flatbuffer = false) const; + + Module copy() const; + + Module deepcopy(std::optional device = std::nullopt) const; + + // Clones both the underlying `ClassType` and the module instance(data), this + // function creates a new `ClassType` and returns a new instance that has the + // same data as the current instance but with the new type, shared ClassType + // will be preserved as well + Module clone(bool inplace = false) const; + + // Clones both the underlying `ClassType` and the module instance(data), this + // function creates a new `ClassType` and returns a new instance that has the + // same data as the current instance but with the new type, shared ClassType + // will be preserved as well. Also allows the caller to specify a set of + // method and attribute names to not clone. + Module clone( + bool inplace, + const std::unordered_set& ignored_method, + const std::unordered_set& ignored_attributes) const; + + void clone_method(const Module& orig, const std::string& name); + + IValue operator()(std::vector inputs); + + template + IValue create_class(const c10::QualifiedName& name, Types&&... args) const { + return create_class(name, {IValue(std::forward(args))...}); + } + + IValue create_class(const c10::QualifiedName& name, Stack stack) const; + + inline bool operator==(const Module& y) const noexcept { + return _ivalue() == y._ivalue(); + } + + void set_delete_memory(std::shared_ptr delete_mem) { + mem_to_delete_ = std::move(delete_mem); + } + + // A set of functions to maintain input shapes through torch.jit.save and + // torch.jit.load. It only works on tensors and lists/dicts of tensors + // because tracing is only supported by these types. + void store_traced_inputs( + const std::string& func_name, + std::vector inputs) { + if (inputs.empty()) { + return; + } + auto c10_inputs = c10::impl::GenericList(AnyType::get()); + for (IValue& value : inputs) { + // Not checking whether this is traceable type as that is already checked + // higher up in the stack and changing that would require a larger + // restructuring. + c10_inputs.emplace_back(std::move(value)); + } + traced_inputs_.insert_or_assign(func_name, c10_inputs); + } + + c10::Dict retrieve_traced_inputs() + const { + return traced_inputs_; + } + + private: + Module clone_impl( + std::unordered_map& type_remap, + bool inplace, + IValue::HashIdentityIValueMap memo, + const std::unordered_set& ignored_methods, + const std::unordered_set& ignored_attributes) const; + + void clone_method( + const Module& orig, + const Function& method, + const std::unordered_map& type_remap); + + c10::QualifiedName getNameForMethod(std::string basename) const { + return QualifiedName(*type()->name(), std::move(basename)); + } + + void to_impl( + const std::optional& device, + const std::optional& dtype, + bool non_blocking); + + // Extra handle for the module to delete when itself is deleted + std::shared_ptr mem_to_delete_; + + // Map of function names to the traced inputs that they have been traced with + c10::Dict traced_inputs_; + + // Mutex to keep registering buffer or parameter thread safe. + std::shared_ptr register_mutex_ = std::make_shared(); +}; + +// C++ equivalent api of `torch.jit.freeze`. See documentation there for +// details. +TORCH_API Module freeze( + const Module& module, + const std::optional>& preserved_attrs = + std::nullopt, + bool optimize_numerics = true); + +// C++ equivalent api of `torch.jit.optimize_for_inference`. See documentation +// there for details. +TORCH_API Module optimize_for_inference( + Module& module, + const std::vector& other_methods = {}); + +enum class FusionBehavior { STATIC, DYNAMIC }; + +using FusionStrategy = std::vector>; +// clang-format off +/* +Sets the type and number of specializations that can occur during fusion. + +Usage: provide a list of pairs (type, depth) where type is one of STATIC or DYNAMIC +and depth is an integer. + +Behavior - static vs dynamic: + In STATIC fusion, fused ops are compiled to have fixed input shapes. The shape is determined + based on some initial profiling runs. + In DYNAMIC fusion, fused ops are compiled to have variable input shapes, so that multiple + shapes are possible. + +In both cases, we also recompile on new striding behavior, device, or dtype. + +Behavior - fallback functions & depth: + When an input doesn't match the format required by the specialized compiled op, it will run + a fallback function. Fallback functions are recursively be compiled and specialized based + on the observed tensor shapes. Since compilation can be slow, the "depth" parameter is provided to + limit the number of specializations that can be compiled, before giving up on recompiling and + falling back to a completely un-fused, un-specialized implementation. + +The list of (type, depth) pairs controls the type of specializations and the number of +specializations. For example: [(STATIC, 2), (DYNAMIC, 2)] indicates that the first +two specializations will use static fusions, the following two specializations will use +dynamic fusion, and any inputs that satisfy none of the 4 options will run an +unfused implementation. + +NB: in the future, if more as more fusion backends are added there may be more granular +apis for specific fusers. +*/ +// clang-format on +TORCH_API FusionStrategy getFusionStrategy(); +// returns previous strategy +TORCH_API FusionStrategy setFusionStrategy(FusionStrategy& fusion_strategy); + +namespace detail { + +struct TORCH_API SlotCursor { + Module module_; + int64_t i_; // slot offset, -1 indicates the module itself +}; + +} // namespace detail + +// This iterator allows the (optionally recursive) enumeration of +// the members of a Module. It performs a depth-first pre-order +// traversal of the module. The Policy template parameter determines +// which slots of the object should be included. For instance, +// when iterating parameters, we return the parameter tensors, +// but skip modules, buffers, and other attributes. +// See ModulePolicy for comments about Policy object's API. +template +struct slot_iterator_impl { + using SlotCursor = detail::SlotCursor; + using value_type = typename Policy::value_type; + slot_iterator_impl( + Module root, + bool recurse, // if true, do a depth-first search, otherwise, just look at + // slots of root + bool return_module) // if true include root itself as the first thing + // visited (used in modules()) + : cursors_({SlotCursor{std::move(root), return_module ? -1 : 0}}), + recurse_(recurse) { + // advance iterator to first valid element (or the end, if empty) + while_not_valid_next(); + } + // empty cursors_, represents end of iteration + slot_iterator_impl() : recurse_(false) {} + value_type operator*() const { + return Policy::create(cursors_, cur()); + } + value_type operator->() const { + return **this; + } + slot_iterator_impl& operator++() { + next_valid(); + return *this; + } + slot_iterator_impl operator++(int) { + // this is really expensive, should we delete it so people don't use it + // instead of prefix? + slot_iterator_impl old = *this; + ++(*this); + return old; + } + + private: + // return_module() is a corner case where instead of returning a submodule + // of root, we are returning root itself, because we are iterating modules(), + // which contains the root module itself. + // It is represented with a single SlotCursor whose index is -1. + bool return_module() const { + return top().i_ == -1; + } + const SlotCursor& top() const { + return cursors_.back(); + } + SlotCursor& top() { + return cursors_.back(); + } + IValue cur() const { + return return_module() ? top().module_._ivalue() + : top().module_._ivalue()->getSlot(top().i_); + } + + // advance to the next slot in a depth first pre-order traversal of the + // modules slots. This function does not guarantee the next slot is a + // valid element of the iteration. That is done by valid(). + // invariant: !cursors_.empty() + void next() { + // we just returned the module itself, advance i_ to 0 so we are now + // at the first slot of the module. + if (return_module()) { + ++top().i_; + return; + } + // the last traversal action advanced beyond the number of slots in the + // module so continue the iteration in the parent. + if (top().i_ >= int64_t(top().module_._ivalue()->type()->numAttributes())) { + cursors_.pop_back(); + if (!cursors_.empty()) { + ++top().i_; + } + return; + } + // if the current thing is a module, we have to scan it for recursive + // traversals. We do this by adding a new SlotCursor to track the traversal. + if (recurse_ && + top().module_._ivalue()->type()->getAttribute(top().i_)->is_module()) { + cursors_.emplace_back(SlotCursor{cur().toModule(), 0}); + return; + } + // common case: advance to the next slot. + ++top().i_; + } + // is the current position of the iterator a valid one? + // otherwise, we have to continue advancing. + bool valid() const { + return top().i_ < + int64_t(top().module_._ivalue()->type()->numAttributes()) && + Policy::valid( + top().module_._ivalue()->type(), + top().i_, + top().module_._ivalue()->getSlot(top().i_)); + } + void while_not_valid_next() { + // advance iteration until we are either at the end (cursors_.empty()) + // or in a valid state. return_module() is a special case, + // and is always considered valid, regardless of Policy, because it is + // it is only true when we are iterating modules. + while (!cursors_.empty() && !return_module() && !valid()) { + next(); + } + } + void next_valid() { + // avoid crashing if this is empty + if (cursors_.empty()) { + return; + } + // advance to next element, which is maybe not valid + next(); + while_not_valid_next(); + } + + std::vector cursors_; + bool recurse_; + + friend inline bool operator!=( + const slot_iterator_impl& a, + const slot_iterator_impl& b) { + // we are finished iteration when we have no more iteration SlotCursors. + // end is always an empty iterator with no cursors. + return (a.cursors_.empty() != b.cursors_.empty()); + } +}; + +// This type represents lists of parameters, attributes, and +// submodules contained in the module. It is abstract because +// they are not stored directly in std::vectors but inside the +// module's IValue object itself. +template +struct slot_list_impl { + using iterator = slot_iterator_impl; + using const_iterator = slot_iterator_impl; + using value_type = typename iterator::value_type; + slot_iterator_impl begin() const { + return slot_iterator_impl(module_, recurse_, return_module_); + } + slot_iterator_impl end() const { + return slot_iterator_impl(); + } + size_t size() const { + if (!size_) { + size_ = size_t(0); + for ([[maybe_unused]] const value_type& _ : *(this)) { + ++*size_; + } + } + return *size_; + } + + slot_list_impl(Module module, bool recurse, bool return_module) + : module_(std::move(module)), + recurse_(recurse), + return_module_(return_module), + size_(std::nullopt) { + if (!recurse && !return_module && Policy::all_slots) { + size_ = module_.num_slots(); + } + } + + private: + Module module_; + bool recurse_; + bool return_module_; + // size of this list, cached on first request + // when we need to filter the slot list + mutable std::optional size_; + friend struct Module; +}; + +namespace detail { + +// slot_iterator_impl always iterate over all the slots in a module, +// the Policy template argument determines slots should be returned and their +// types +struct TORCH_API ModulePolicy { + // the type of the value being returned + using value_type = Module; + + // the logic for creating the type being returned, given the raw IValue + // of that object. + static value_type create( + const std::vector& cursors, + IValue v) { + return Module(std::move(v).toObject()); + } + // is slot i in typ something that this iterator should return, otherwise, + // we skip it. + static bool valid(const ClassTypePtr& typ, size_t i, const IValue& v) { + return typ->getAttribute(i)->is_module(); + } + // are we going to return everything? If so, we can optimize the calculate + // of the size of the list. + static constexpr bool all_slots = false; +}; + +struct TORCH_API ParameterPolicy { + using value_type = at::Tensor; + static value_type create( + const std::vector& cursors, + IValue v) { + return std::move(v).toTensor(); + } + static bool valid(const ClassTypePtr& typ, size_t i, const IValue& v) { + return typ->is_parameter(i) && v.isTensor(); + } + static constexpr bool all_slots = false; +}; + +struct TORCH_API BufferPolicy { + using value_type = at::Tensor; + static value_type create( + const std::vector& cursors, + IValue v) { + return std::move(v).toTensor(); + } + static bool valid(const ClassTypePtr& typ, size_t i, const IValue& v) { + return typ->getAttribute(i)->isSubtypeOf(*TensorType::get()) && + typ->is_buffer(i); + } + static constexpr bool all_slots = false; +}; + +struct TORCH_API AttributePolicy { + using value_type = IValue; + static value_type create( + const std::vector& cursors, + IValue v) { + return v; + } + static bool valid(const ClassTypePtr& typ, size_t i, const IValue& v) { + return true; + } + static constexpr bool all_slots = true; +}; + +// take a Policy object, and make a version of it that returns the slot. +// along with the fully qualified name of that slot. This is used for the named_ +// variants like named_parameters(). +template +struct NamedPolicy { + using value_type = Named; + static value_type create( + const std::vector& cursors, + IValue v) { + std::string name; + if (cursors.size() == 1) { + name = (cursors.back().i_ == -1) ? "" : nameFragment(cursors.back()); + } else { + std::ostringstream ss; + for (const auto i : c10::irange(cursors.size())) { + if (i > 0) { + ss << '.'; + } + ss << nameFragment(cursors[i]); + } + name = ss.str(); + } + return value_type{std::move(name), Policy::create(cursors, std::move(v))}; + } + static bool valid(const ClassTypePtr& t, size_t i, const IValue& v) { + return Policy::valid(t, i, v); + } + static constexpr bool all_slots = Policy::all_slots; + + private: + static std::string nameFragment(const detail::SlotCursor& f) { + return f.module_.type()->getAttributeName(f.i_); + } +}; + +} // namespace detail + +TORCH_API bool& getInlineEverythingMode(); + +namespace script { +// We once had a `script::` namespace that was deleted. This is for backcompat +// of the public API; new code should not use this type alias. +using Module = ::torch::jit::Module; +using ExtraFilesMap = ::torch::jit::ExtraFilesMap; +} // namespace script + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/api/object.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/api/object.h new file mode 100644 index 0000000000000000000000000000000000000000..f25e599974b138172c593fe2c3f9f9fac2e26397 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/api/object.h @@ -0,0 +1,205 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include + +namespace torch::jit { + +struct Resolver; +using ResolverPtr = std::shared_ptr; + +using ObjectPtr = c10::intrusive_ptr; + +// Throw this in C++ land if `attr` fails. This will be converted to a Python +// AttributeError by the Python binding code +class ObjectAttributeError : public std::runtime_error { + public: + ObjectAttributeError(const std::string& what) : std::runtime_error(what) {} +}; + +struct TORCH_API Object { + Object() = default; + Object(const Object&) = default; + Object& operator=(const Object&) = default; + Object(Object&&) noexcept = default; + Object& operator=(Object&&) noexcept = default; + Object(ObjectPtr _ivalue) : _ivalue_(std::move(_ivalue)) {} + Object(std::shared_ptr cu, const c10::ClassTypePtr& type); + Object( + c10::QualifiedName, + std::shared_ptr cu, + bool shouldMangle = false); + + ObjectPtr _ivalue() const { + TORCH_INTERNAL_ASSERT(_ivalue_); + return _ivalue_; + } + + c10::ClassTypePtr type() const { + return _ivalue()->type(); + } + + struct Property { + std::string name; + Method getter_func; + std::optional setter_func; + }; + + void setattr(const std::string& name, c10::IValue v) { + if (_ivalue()->type()->hasConstant(name)) { + TORCH_CHECK( + false, + "Can't set constant '", + name, + "' which has value:", + _ivalue()->type()->getConstant(name)); + } else if (auto slot = _ivalue()->type()->findAttributeSlot(name)) { + const c10::TypePtr& expected = _ivalue()->type()->getAttribute(*slot); + TORCH_CHECK( + v.type()->isSubtypeOf(*expected), + "Expected a value of type '", + expected->repr_str(), + "' for field '", + name, + "', but found '", + v.type()->repr_str(), + "'"); + _ivalue()->setSlot(*slot, std::move(v)); + } else { + TORCH_CHECK(false, "Module has no attribute '", name, "'"); + } + } + + c10::IValue attr(const std::string& name) const { + if (auto r = _ivalue()->type()->findAttributeSlot(name)) { + return _ivalue()->getSlot(*r); + } + if (auto r = _ivalue()->type()->findConstantSlot(name)) { + return _ivalue()->type()->getConstant(*r); + } + std::stringstream err; + err << _ivalue()->type()->repr_str() << " does not have a field with name '" + << name.c_str() << "'"; + throw ObjectAttributeError(err.str()); + } + + c10::IValue attr(const std::string& name, c10::IValue or_else) const { + if (auto r = _ivalue()->type()->findAttributeSlot(name)) { + return _ivalue()->getSlot(*r); + } + if (auto r = _ivalue()->type()->findConstantSlot(name)) { + return _ivalue()->type()->getConstant(*r); + } + return or_else; + } + + bool hasattr(const std::string& name) const { + return _ivalue()->type()->hasAttribute(name) || + _ivalue()->type()->hasConstant(name); + } + + // each object owns its methods. The reference returned here + // is guaranteed to stay valid until this module has been destroyed + Method get_method(const std::string& name) const { + if (auto method = find_method(name)) { + return *method; + } + TORCH_CHECK(false, "Method '", name, "' is not defined."); + } + + const std::vector get_methods() const { + return c10::fmap(type()->methods(), [&](Function* func) { + return Method(_ivalue(), func); + }); + } + + bool has_property(const std::string& name) const { + for (const auto& prop : type()->properties()) { + if (prop.name == name) { + return true; + } + } + return false; + } + + const Property get_property(const std::string& name) const { + for (const auto& prop : type()->properties()) { + if (prop.name == name) { + std::optional setter = std::nullopt; + if (prop.setter) { + setter = Method(_ivalue(), prop.setter); + } + return Property{ + prop.name, Method(_ivalue(), prop.getter), std::move(setter)}; + } + } + TORCH_CHECK(false, "Property '", name, "' is not defined."); + } + + const std::vector get_properties() const { + return c10::fmap(type()->properties(), [&](ClassType::Property prop) { + std::optional setter = std::nullopt; + if (prop.setter) { + setter = Method(_ivalue(), prop.setter); + } + return Property{ + std::move(prop.name), + Method(_ivalue(), prop.getter), + std::move(setter)}; + }); + } + + std::optional find_method(const std::string& basename) const; + + /// Run a method from this module. + /// + /// For example: + /// @code + /// IValue output = module->run("relu_script", a, b); + /// @endcode + /// + /// To get a compile a module from a source string, see torch::jit::compile + /// + /// @param method_name The name of the method to run + /// @param args Arguments to be passed to the method + /// @return An IValue containing the return value (or values if it is a tuple) + /// from the method + template + IValue run_method(const std::string& method_name, Types&&... args) { + return get_method(method_name)({IValue(std::forward(args))...}); + } + + // so that C++ users can easily add methods + void define(const std::string& src, const ResolverPtr& resolver = nullptr); + + size_t num_slots() const { + return _ivalue()->slots().size(); + } + + // shallow copy the object + Object copy() const; + + // Copies all the attributes of the object recursively without creating new + // `ClassType`, including deepcopy of Tensors + Object deepcopy() const; + + private: + // mutable be we lazily initialize in module_object. + mutable ObjectPtr _ivalue_; +}; + +namespace script { +// We once had a `script::` namespace that was deleted. This is for backcompat +// of the public API; new code should not use this type alias. +using Object = ::torch::jit::Object; +} // namespace script +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend.h new file mode 100644 index 0000000000000000000000000000000000000000..cea04920023b6876ac4c8123c4b887b88d457fbd --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend.h @@ -0,0 +1,119 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +namespace torch::jit { +namespace { +inline c10::FunctionSchema getIsAvailableSchema() { + c10::Argument self("self", c10::AnyType::get()); + c10::Argument available("available", c10::BoolType::get()); + c10::FunctionSchema preprocessor_schema( + "is_available", + /*overload_name=*/"", + /*arguments=*/{self}, + /*returns=*/{available}); + return preprocessor_schema; +} + +constexpr static auto kBackendsNamespace = "__backends__"; + +inline c10::FunctionSchema getCompileSchema() { + c10::Argument self("self", c10::AnyType::get()); + c10::Argument mod("processed", c10::AnyType::get()); + auto any_dict_ty = + c10::DictType::create(c10::StringType::get(), c10::AnyType::get()); + c10::Argument method_compile_spec("method_compile_spec", any_dict_ty); + c10::Argument handles("handles", any_dict_ty); + + c10::FunctionSchema compile_schema( + "compile", + /*overload_name=*/"", + /*arguments=*/{self, mod, method_compile_spec}, + /*returns=*/{handles}); + return compile_schema; +} + +inline c10::FunctionSchema getExecuteSchema() { + auto any_list_ty = c10::ListType::create(c10::AnyType::get()); + c10::Argument self("self", c10::AnyType::get()); + c10::Argument handle("handle", c10::AnyType::get()); + c10::Argument input("input", any_list_ty); + c10::Argument output("output", any_list_ty); + return c10::FunctionSchema( + "execute", + /*overload_name=*/"", + /*arguments=*/{self, handle, input}, + /*returns=*/{output}); +} + +template +std::function getIsAvailableFunc() { + return [](Stack& stack) { + auto self = pop(stack).toCustomClass(); + auto ret = self->is_available(); + push(stack, ret); + }; +} + +template +std::function getCompileFunc() { + return [](Stack& stack) { + auto method_compile_spec = pop(stack).toGenericDict(); + auto processed = pop(stack); + auto self = pop(stack).toCustomClass(); + auto ret = self->compile(processed, method_compile_spec); + push(stack, ret); + }; +} + +template +std::function getExecuteFunc() { + return [](Stack& stack) { + auto args = pop(stack); + auto handle = pop(stack); + auto self = pop(stack); + auto backend = self.toCustomClass(); + auto res = backend->execute(handle, args.toList()); + push(stack, res); + }; +} +} // namespace + +// Static registration API for backends. +template +class backend { + static_assert( + std::is_base_of_v, + "torch::jit::backend requires T to inherit from PyTorchBackendInterface"); + std::string backend_name_; + + public: + // Registers a new backend with /p name, and the given /p preprocess + // function. + backend(const std::string& name) : backend_name_(name) { + static auto cls = torch::class_(kBackendsNamespace, name) + .def(torch::init<>()) + ._def_unboxed( + "is_available", + getIsAvailableFunc(), + getIsAvailableSchema()) + ._def_unboxed( + "compile", + getCompileFunc(), + getCompileSchema()) + ._def_unboxed( + "execute", + getExecuteFunc(), + getExecuteSchema()); + } +}; + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_debug_handler.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_debug_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..ec124d0cf8ae0cbee9a38a575c49c22e2712164d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_debug_handler.h @@ -0,0 +1,143 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include + +#include +#include +#include + +#include + +namespace torch::jit { + +/* + * BackendDebugHandleManager is responsible for issuing debug handles to + * backends. Debug handles are associated with nodes of a graph. + * BackendDebugHandleManager also maintains a map + * [debug-handle, DebugInfoTuple = {source range, inlined callstack ptr]} that + * will help generate a callstack for exception raised using debug handles. + * Effectively debug handles are something that is given to backend and later + * when an exception occurs in the backend, backend can tell, using debug + * handle, that an exception occurred here. Then the runtime can generate + * callstack corresponding to the exception. + * There are two parts to BackendDebugHandleManager: + * 1. static std::atomic debug_handle + * 2. Map of [debug-handle, DebugInfoTuple] + * + * About 1: + * Why do they have to be unique. The reason is that by ensuring + * uniqueness of debug handles, we remove the burden of another layer of + * mapping where we need to say this set of debug handles were generated for + * this lowered module or this bytecode function. This simplifies the API for + * serialization since debug handles can uniquely identify DebugInfoTuple. + * Thus simplifies the runtime API for throwing exception. Exception throwing + * only needs to know debug_handle and not which module or method threw it. + * There are 2 issues to keep in mind, though,for static std::atomic + * debug_handle: A. Performance implications of using atomic variable. However + * this is only used for compilation so we assume to absorb some of that + * penalty. Plus if there is no contention then we should have less to worry + * about. B. If repeated compilation is part of a long running process then we + * may overflow int64_t. We may detect and fail on this. For now this is not + * done. + * + * Now about 2: + * There are two usecases for [debug-handle, DebugInfoTuple] + * A. During bytecode generation the DebugInfoTuple corresponding to the nodes + * of the inlined graph being serialized, are stored in this object and a + * unique debug handle is returned. This unique debug handle is stored in + * mobile_debug info for pytorch lite models. It will be used for raising + * exceptions as well as profiling. B. During backend lowering, each backend's + * preprocess/compile method can compile method's graph and serialize those + * methods. Once the method is lowered to backend, graph is essentially lost. + * Without access to graph it is hard to generate model level debug info. Thus + * the debug handles provide a way to map nodes of the graph to the model level + * debug info. + * + * During byte-code model serialization, [debug-handle, DebugInfoTuple] is + * serialized. Now we know a. debug handles and b. how to map debug handles to + * model source code. Thus we can either do eager symbolication by converting + * debug handles to corresponding source code at runtime, or do lazy + * symbolicattion offline. + * + * Note that it is not necessary to serialize [debug-handle, DebugInfoTuple] + * corresponding to lowered backend if the lowering process, that is + * preprocess/compile, and execution happens in the same session, then eager + * symbolication can be employed. + * + * Now how does BackendDebugHandleManager capture all of the above? + * By providing two API. + * 1. getNextDebugHandle which given a Node* returns a unique debug handle, + * that will uniquely identify DebugInfoTuple. + * and + * 2. getCallStackPtrMap which returns the map + * [debug-handle, DebugInfoTuple] + * + * 1 provides debug handles to backends and 2 provides runtime a way to map + * debug handles to source level debug info. + * + * So why does debug handle map to DebugInfoTuple = {source range and inlined + * cs}? {debug_handle, source_range_tag, serialized_callstack} Take this + * example: class L(nn.Module): def __init__(self) -> None: + * ... + * def forward(self, x): + * return x * 5 + * class M(nn.Module): + * def __init__(self) -> None: + * ... + * def forward(self, x): + * return x - 2 + * class N(nn.Module): + * def __init__(self) -> None: + * self.m = M() + * def forward(self, x): + * return self.m(x) + 3 + * m = torch.jit.script(N()) + * Once you inline m's forward method, m.forward.graph will look something + * like this + * graph(%self...): + * %x = aten::mul(..) + * %x = aten::sub(x, ..) + * %y = aten::add(x, ..) + * .. + * Inlined callstack ptr for these two nodes will look like: + * aten::mul's inlined CS (callstack): [N.forward, source range] -> [M.forward, + * source range] aten::sub's inlined CS (callstack): [N.forward, source range] + * aten::add's inlined CS: null + * mul node's inlined CS contains only information about the callsites' source + * range The information about mul node's source range ('return x * 5') is not + * available in its inlined CS. It is rather part of node's source range + * instead of inlined CS. Thus to get full stack: [N.forward, source range] -> + * [M.forward, source range] -> [aten::mul's source range] We need to track + * mul's source range and inlined CS both. + */ + +using BackendDebugInfoMapType = + std::unordered_map; + +/* + * This class is used to generate debug info map. + * backend's preprocess will call generate_debug_handles (see + * backend_detail.cpp), which uses debug_handle_manager to generate debug + * handles. When lowering process finishes, calling stopRecording will + * return debug info map from debug_handle_manager + */ +class TORCH_API BackendDebugInfoRecorder { + public: + BackendDebugInfoRecorder() = default; + int64_t getNextDebugHandle(const Node* node); + // Reason this is not done as RAII is that work done in stopRecording + // can throw, and throwing with dtor will call terminate and thus voids any + // exception catching at a higher level. + BackendDebugInfoMapType stopRecording(); + NodeToDebugHandle generate_debug_handles(const std::shared_ptr& graph); + + private: + static std::atomic unique_debug_handle_; + BackendDebugInfoMapType handles_to_inlined_callstack_ptrs_; +}; + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_debug_info.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_debug_info.h new file mode 100644 index 0000000000000000000000000000000000000000..b2ff9a3fe801206fba4bf40538e5770a3ae493e4 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_debug_info.h @@ -0,0 +1,68 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifndef BUILD_LITE_INTERPRETER +#include +#endif +#include + +namespace torch::jit { + +constexpr static auto kBackendUtilsNamespace = "backendutils"; +constexpr static auto kBackendDebugInfoClass = "BackendDebugInfo"; + +#ifndef BUILD_LITE_INTERPRETER +/* + * Custom class for holding debug information in lowered modules, intended + * purely for keeping this information to be later serialized outside of the + * lowered module itself. + * Its usage pattern is: + * 1. LoweredModule declares an instance of this class in __backend_debug_info + * 2. During serialization, __backend_debug_info is used to obtain the debug + * information. + * 3. The contents of LoweredModule.__backend_debug_info are not serialized + * within the LoweredModule itself. + */ +class TORCH_API PyTorchBackendDebugInfo : public torch::CustomClassHolder { + public: + PyTorchBackendDebugInfo() = default; + + std::optional& getDebugInfoMap() { + return debug_info_map_; + } + + void setDebugInfoMap(BackendDebugInfoMapType&& debug_info_map) { + debug_info_map_ = std::move(debug_info_map); + } + + private: + std::optional debug_info_map_; +}; + +#else + +/* + * Dummy instance exists for the following reason: + * __backend_debug_info is of type BackendDebugInfo which is a torchbind' + * class backed by cpp class PyTorchBackendDebugInfo. + * PyTorchBackendDebugInfo, depends on ir.h., scope.h, source_range etc. + * We dont include this on lite interpreter side. Thus on lite interpreter side + * we cannot have valid definition of PyTorchBackendDebugInfo. However we do not + * need valid instance of __backend_debug_info in lite interpreter anyway as we + * dont serialize this info as part of LowerdModule as mentioned ealrier. + * However since LoweredModule has registered attribute of __backend_debug_info + * we still need to make sure that BackendDebugInfo is registered with + * TorchScript. However in this instance it does not have to be backed by + * PyTorchBackendDebugInfo, so we create a dummy PyTorchBackendDebugInfoDummy + * just for this purpose. + */ +class PyTorchBackendDebugInfoDummy : public torch::CustomClassHolder { + public: + PyTorchBackendDebugInfoDummy() = default; +}; +#endif +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_detail.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_detail.h new file mode 100644 index 0000000000000000000000000000000000000000..cca52f2866881927fa9db1b8f35cb20be87a5183 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_detail.h @@ -0,0 +1,44 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include + +#include + +namespace torch::jit { + +using DebugHandleType = int64_t; + +using NodeToDebugHandle = std::unordered_map; + +using BackendDebugHandleGenerator = + std::function&)>; + +namespace detail { + +using BackendPreprocessFunction = std::function&, + const BackendDebugHandleGenerator& generate_debug_handles)>; + +TORCH_API void registerBackendPreprocessFunction( + const std::string& name, + const BackendPreprocessFunction& preprocess); + +bool hasBackendPreprocessFunction(const std::string& name); + +BackendPreprocessFunction getBackendPreprocessFunction(const std::string& name); + +TORCH_API Module codegen_backend_module( + const std::string& backend_name, + const Module& orig_module, + const c10::Dict& method_compile_spec, + const c10::DictTypePtr& any_dict_ty); +} // namespace detail +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_exception.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_exception.h new file mode 100644 index 0000000000000000000000000000000000000000..caec46ee4666f0c8867a0326ad9ed9ccb1567599 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_exception.h @@ -0,0 +1,62 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// @allow-raw-throw +#pragma once +#include + +#include + +namespace c10 { +class TORCH_API BackendRuntimeException : public c10::Error { + public: + // Use debug_handle to throw exception + BackendRuntimeException( + SourceLocation loc, + std::string msg, + int64_t debug_handle) + : c10::Error(loc, std::move(msg)) { + debug_handles.push_back(debug_handle); + } + // If rethrowing, can push another debug_handle + // This is useful in couple of scenarios. + // 1. A submodule is lowered and lite interpreter has CallMethod + // to lowered module's method. In this case lowered module will throw with + // a handle, plus there will be another debug handle corresponding + // to the CallMethod node in lite interpreter. Both together give complete + // trace. This function allows lite interpreter to rethrow with debug + // handle it has for CallMethod. + // 2. Another scenarios is when lite interpreter can make function calls or + // the lowered backend also has function call ability. Thus we have + // multiple function frames. Now we need a stack of handles to symbolicate + // entire stack trace. + void pushDebugHandle(int64_t debug_handle) { + debug_handles.push_back(debug_handle); + } + const std::vector& getDebugHandles() { + return debug_handles; + } + + private: + // Stores stack of debug handles. + std::vector debug_handles; +}; + +} // namespace c10 +#define TORCH_DELEGATED_BACKEND_THROW(cond, msg, debug_handle) \ + if (C10_UNLIKELY_OR_CONST(!(cond))) { \ + throw ::c10::BackendRuntimeException( \ + {__func__, __FILE__, static_cast(__LINE__)}, \ + msg, \ + debug_handle); \ + } + +#define TORCH_DELEGATED_BACKEND_RETHROW(e, debug_handle) \ + do { \ + e.pushDebugHandle(debug_handle); \ + throw; \ + } while (false) + +#define DEBUG_HANDLE_UNKNOWN -1 + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_init.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_init.h new file mode 100644 index 0000000000000000000000000000000000000000..bc490802ff882f7c10b304af7803b80d1c511b9e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_init.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::jit { +// Initialize Python bindings for JIT to_ functions. +void initJitBackendBindings(PyObject* module); +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_interface.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..5f7056a86d0628c1a861465c1cc30d46fc2d1db7 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_interface.h @@ -0,0 +1,37 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit { + +// Interface for a JIT backend. +class TORCH_API PyTorchBackendInterface : public torch::CustomClassHolder { + public: + PyTorchBackendInterface() noexcept; + ~PyTorchBackendInterface() override; + + // Returns true if the backend is available to process delegation calls. + virtual bool is_available() = 0; + + // Compile the module contained in \p processed using the details provided in + // \p method_compile_spec for each module method that should be compiled for + // the backend. \p method_compile_spec should be of type Dict. + // \returns a dictionary of type Dict that contains a backend + // handle each method that can run on the backend (i.e. each key in \p + // method_compile_spec). + virtual c10::impl::GenericDict compile( + c10::IValue processed, + c10::impl::GenericDict method_compile_spec) = 0; + + // Execute the method specified by \p handle using \p inputs. \returns the + // outputs as a tuple. + virtual c10::impl::GenericList execute( + c10::IValue handle, + c10::impl::GenericList inputs) = 0; +}; +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_preprocess.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_preprocess.h new file mode 100644 index 0000000000000000000000000000000000000000..f0241ec96ef63b32e94b6116f8fcc31df5da9f51 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_preprocess.h @@ -0,0 +1,21 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +namespace torch::jit { +class backend_preprocess_register { + std::string backend_name_; + + public: + backend_preprocess_register( + const std::string& name, + const detail::BackendPreprocessFunction& preprocess) + : backend_name_(name) { + detail::registerBackendPreprocessFunction(name, preprocess); + } +}; +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_resolver.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_resolver.h new file mode 100644 index 0000000000000000000000000000000000000000..aee7fac6ddfb3fe942a82ad33074e672a3422821 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/backend_resolver.h @@ -0,0 +1,13 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit { +// Create a Resolver for use in generating LoweredModules for specific backends. +TORCH_API std::shared_ptr loweredModuleResolver(); +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/cpp/context.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/cpp/context.h new file mode 100644 index 0000000000000000000000000000000000000000..6ac2655639b3b0dc4a087056e90a7f75a593f226 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/cpp/context.h @@ -0,0 +1,27 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#ifndef PTM_COREML_Context_h +#define PTM_COREML_Context_h + +#include + +namespace torch::jit::mobile::coreml { + +struct ContextInterface { + virtual ~ContextInterface() = default; + virtual void setModelCacheDirectory(std::string path) = 0; +}; + +class BackendRegistrar { + public: + explicit BackendRegistrar(ContextInterface* ctx); +}; + +void setModelCacheDirectory(std::string path); + +} // namespace torch::jit::mobile::coreml + +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/objc/PTMCoreMLCompiler.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/objc/PTMCoreMLCompiler.h new file mode 100644 index 0000000000000000000000000000000000000000..1b040c52c64f22364741a4c926686ec3579edd3b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/objc/PTMCoreMLCompiler.h @@ -0,0 +1,27 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#import + +#include + +NS_ASSUME_NONNULL_BEGIN + +@interface PTMCoreMLCompiler : NSObject + ++ (void)setCacheDirectory:(const std::string&)dir; + ++ (NSString*)cacheDirectory; + ++ (BOOL)compileModel:(const std::string&)modelSpecs modelID:(const std::string&)modelID; + ++ (nullable MLModel*)loadModel:(const std::string)modelID + backend:(const std::string)backend + allowLowPrecision:(BOOL)allowLowPrecision + error:(NSError**)error; + +@end + +NS_ASSUME_NONNULL_END + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/objc/PTMCoreMLExecutor.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/objc/PTMCoreMLExecutor.h new file mode 100644 index 0000000000000000000000000000000000000000..5a79337260dcc3099d395a1639f39420796ab6b0 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/objc/PTMCoreMLExecutor.h @@ -0,0 +1,24 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface PTMCoreMLExecutor : NSObject + +@property(atomic, strong) MLModel* model; + +- (instancetype)initWithFeatureNames:(NSArray*)featureNames; + +- (void)setInputs:(c10::impl::GenericList)inputs; + +- (id)forward:(NSError**)error; + +@end + +NS_ASSUME_NONNULL_END + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/objc/PTMCoreMLFeatureProvider.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/objc/PTMCoreMLFeatureProvider.h new file mode 100644 index 0000000000000000000000000000000000000000..c0e536370b6ee5209dc88ae869539bad7a423260 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/objc/PTMCoreMLFeatureProvider.h @@ -0,0 +1,21 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface PTMCoreMLFeatureProvider : NSObject + +- (instancetype)initWithFeatureNames:(NSSet*)featureNames; + +- (void)clearInputTensors; + +- (void)setInputTensor:(const at::Tensor&)tensor forFeatureName:(NSString*)name; + +@end + +NS_ASSUME_NONNULL_END + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/objc/PTMCoreMLModelWrapper.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/objc/PTMCoreMLModelWrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..5ee77404da4e52f35be363da00dbf4779b75af89 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/objc/PTMCoreMLModelWrapper.h @@ -0,0 +1,46 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include +#include +#include + +namespace torch { +namespace jit { +namespace mobile { +namespace coreml { + +class MLModelWrapper : public CustomClassHolder { + public: + PTMCoreMLExecutor* executor; + std::vector outputs; + + MLModelWrapper() = delete; + + MLModelWrapper(PTMCoreMLExecutor* executor) : executor(executor) { + [executor retain]; + } + + MLModelWrapper(const MLModelWrapper& oldObject) { + executor = oldObject.executor; + outputs = oldObject.outputs; + [executor retain]; + } + + MLModelWrapper(MLModelWrapper&& oldObject) { + executor = oldObject.executor; + outputs = oldObject.outputs; + [executor retain]; + } + + ~MLModelWrapper() { + [executor release]; + } +}; + +} // namespace coreml +} // namespace mobile +} // namespace jit +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/objc/PTMCoreMLTensorSpec.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/objc/PTMCoreMLTensorSpec.h new file mode 100644 index 0000000000000000000000000000000000000000..7537f743d938199c4d13c8f8aca01c6e5b0c231b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/coreml/objc/PTMCoreMLTensorSpec.h @@ -0,0 +1,31 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include +#import + +#include + +namespace torch::jit::mobile::coreml { + +struct TensorSpec { + std::string name; + c10::ScalarType dtype = c10::ScalarType::Float; +}; + +static inline c10::ScalarType scalar_type(const std::string& type_string) { + if (type_string == "0") { + return c10::ScalarType::Float; + } else if (type_string == "1") { + return c10::ScalarType::Double; + } else if (type_string == "2") { + return c10::ScalarType::Int; + } else if (type_string == "3") { + return c10::ScalarType::Long; + } + return c10::ScalarType::Undefined; +} + +} // namespace torch::jit::mobile::coreml + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/xnnpack/compiler/xnn_compiler.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/xnnpack/compiler/xnn_compiler.h new file mode 100644 index 0000000000000000000000000000000000000000..61bd88c05345fc626ef96149efa97d5235afa52b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/xnnpack/compiler/xnn_compiler.h @@ -0,0 +1,29 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// Copyright (c) Meta Platforms, Inc. and affiliates. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#include +#include +#include +#include + +namespace torch::jit::xnnpack::delegate { + +class XNNCompiler { + public: + // Takes Flatbuffer Serialized XNNPack Model and rebuilds the xnn-subgraph + // returns an executor object that holds the xnn runtime object which we + // can then use to set inputs and run inference using the xnn graph. + static void compileModel( + const void* buffer_pointer, + size_t num_bytes, + XNNExecutor* executor); +}; + +} // namespace torch::jit::xnnpack::delegate + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/xnnpack/executor/xnn_executor.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/xnnpack/executor/xnn_executor.h new file mode 100644 index 0000000000000000000000000000000000000000..376de821a60acabd138d32b375e1c833bd077886 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/xnnpack/executor/xnn_executor.h @@ -0,0 +1,73 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// Copyright (c) Meta Platforms, Inc. and affiliates. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once +#include +#include +#include + +namespace torch::jit::xnnpack::delegate { + +class XNNExecutor { + private: + std::unique_ptr runtime_{ + nullptr, + &xnn_delete_runtime}; + std::vector input_ids_; + std::vector output_ids_; + std::vector externals_; + + public: + XNNExecutor() = default; + + template + bool set_inputs(std::vector& inputs, std::vector& outputs) { + externals_.clear(); + + if (inputs.size() != input_ids_.size()) { + return false; + } + + for (int i = 0; i < inputs.size(); i++) { + externals_.emplace_back(xnn_external_value{input_ids_[i], inputs[i]}); + } + + if (outputs.size() != output_ids_.size()) { + return false; + } + + for (int i = 0; i < outputs.size(); i++) { + externals_.emplace_back(xnn_external_value{output_ids_[i], outputs[i]}); + } + + return true; + } + + bool forward() { + xnn_status status = + xnn_setup_runtime(runtime_.get(), externals_.size(), externals_.data()); + + if (status != xnn_status_success) { + return false; + } + + status = xnn_invoke_runtime(runtime_.get()); + + if (status != xnn_status_success) { + return false; + } + + return true; + } + + friend class XNNCompiler; +}; + +} // namespace torch::jit::xnnpack::delegate + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/xnnpack/serialization/serializer.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/xnnpack/serialization/serializer.h new file mode 100644 index 0000000000000000000000000000000000000000..1ca44842bad03c04d60d83a20a67ae8f845a1213 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/xnnpack/serialization/serializer.h @@ -0,0 +1,94 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// Copyright (c) Meta Platforms, Inc. and affiliates. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#include +#include +#include +#include +#include + +namespace torch { +namespace jit { +namespace xnnpack { +namespace delegate { + +using namespace fb_xnnpack; // Specified in the schema + +class XNNSerializer { + public: + // Constructors + // initial buffersize of 1024 which will grow + // automatically, constant buffer and buffer sizes initialized with dummy + // values as 0 index is reserved for non-constant tensors + XNNSerializer() : XNNSerializer(1024) {} + + explicit XNNSerializer(size_t bufferSize) + : _builder(bufferSize), + _nodes(), + _values(), + _constantBuffer({CreateBuffer( + _builder, + {})}), // index 0 is reserved for non-const data + _bufferSizes({0}) {} + + // Serializing Nodes + + // Serialize add node, we are serializing the argument needed to call + // xnn_define_add2. Serializing these values, and at run time we build + // the graph by re running xnn_define_add2 + void serializeAddNode( + uint32_t input1_id, + uint32_t input2_id, + uint32_t output_id, + uint32_t flags); + + // Serializing Values + void serializeTensorValue( + uint32_t xnn_datatype, + size_t num_dims, + std::vector dims, + size_t buffer_data_idx, + uint32_t external_id, + uint32_t flags, + uint32_t id_out); + + // finish and serialize xnngraph returning serialized data + std::string finishAndSerialize( + std::vector input_ids, + std::vector output_ids, + size_t num_extern_ids); + + // decoupled data serialization with tensor values. This way constant tensor + // data can be referenced by multiple intermediate tensors. This call + // serializes the num_bytes of the data_ptr and returns the index it was + // placed in. + size_t serializeData(const uint8_t* data_ptr, size_t num_bytes); + + private: + // xnnpack version we are serializing + const char* _version_sha1 = "ae108ef49aa5623b896fc93d4298c49d1750d9ba"; + + // flatbuffer objects we will create and serialize together to create xnngraph + flatbuffers_fbsource::FlatBufferBuilder _builder; + + // Vector of the serialized xnnpack nodes + std::vector> _nodes; + + // Vector of the serialized xnnpack values + std::vector> _values; + + std::vector> _constantBuffer; + std::vector _bufferSizes; +}; + +} // namespace delegate +} // namespace xnnpack +} // namespace jit +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/xnnpack/xnnpack_graph_builder.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/xnnpack/xnnpack_graph_builder.h new file mode 100644 index 0000000000000000000000000000000000000000..369d56f8d9a33971d3047c5c499fe014a4dea7c9 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/backends/xnnpack/xnnpack_graph_builder.h @@ -0,0 +1,102 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// Copyright (c) Meta Platforms, Inc. and affiliates. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#include +#include +#include +#include +#include +#include + +#include + +namespace torch { +namespace jit { +namespace xnnpack { +namespace delegate { + +class XNNGraph { + private: + const float output_min = -std::numeric_limits::infinity(); + const float output_max = std::numeric_limits::infinity(); + + // serializer class + XNNSerializer _serializer; + // xnn subgraph + xnn_subgraph_t _subgraph_ptr; + // Set of all the tensor values throughout the jit graph + std::unordered_set _intermediate_tensors; + // Set of all the tensor values mapped to the xnnpack ids + std::unordered_map _val_to_ids; + // Vector containing the torch valued inputs/outputs, + // must be ordered to preserve the order of input/outputs + std::vector _inputs; + std::vector _outputs; + + // Graph passes for optimizing and tracing torchscript graph + // Essentially massaging the graph into a digestiable format for + // xnnpack graph lowering. + std::shared_ptr optimizeAndTraceGraph( + std::shared_ptr graph, + std::vector& example_inputs); + + // Gather all the intermediate tensor values within a graph. This + // skips through all prim constants. The purpose of this is for defining + // the tensor values beforehand for the xnnpack subgraph. + void gatherTensorValues(std::shared_ptr& graph); + + // Gathers the tensor values in a give node + void gatherNodeInputs(torch::jit::Node& node); + + // Helper function to determine if a jit value is a graph input + bool isGraphInput(torch::jit::Value* val); + + // Helper function to determine if a jit value is a graph output + bool isGraphOutput(torch::jit::Value* val); + + // Defines all xnnpack nodes for the nodes in the graph + void defineAllNodes(std::shared_ptr& graph); + + // Defines all xnn tensor values used throughout the graph + void defineAllTensorValues(); + + // Makes a pass through the graph and throws if any ops are unsupported + void checkOpsToDelegate(std::shared_ptr& graph); + + public: + XNNGraph() : _serializer(), _subgraph_ptr(nullptr) { + xnn_status status = xnn_initialize(/*allocator =*/nullptr); + TORCH_CHECK(xnn_status_success == status, "Failed to initialize xnnpack"); + } + + ~XNNGraph() { + xnn_deinitialize(); + if (_subgraph_ptr != nullptr) { + xnn_delete_subgraph(_subgraph_ptr); + } + } + + void buildXNNGraph( + std::shared_ptr& graph, + std::vector example_inputs); + + void runGraphOnInputs( + std::vector tensor_inputs, + std::vector tensor_outputs); + + std::string serializedXNNGraph(); + + std::vector> getGraphOutputShapes(); +}; + +} // namespace delegate +} // namespace xnnpack +} // namespace jit +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/cuda/interface.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/cuda/interface.h new file mode 100644 index 0000000000000000000000000000000000000000..211a2fe3a749f934e4c9347b46fb0c6eb111e7f6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/cuda/interface.h @@ -0,0 +1,57 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +/* + * This file contains APIs for cuda fuser; + * + * We use an empty static struct to hold the function pointers, which are + * registered separately. This is to support cpu-only compilation. + * Registration is done in torch/csrc/jit/codegen/cuda/register_interface.cpp + */ + +namespace torch::jit::fuser::cuda { + +TORCH_API std::atomic& getCudaFusionGuardMode(); + +TORCH_API bool getSingletonFusion(); +TORCH_API bool setSingletonFusion(bool value); +TORCH_API bool getHorizontalFusion(); +TORCH_API bool setHorizontalFusion(bool value); + +// dummy struct to allow API registration +struct CudaFuserInterface { + void (*fn_compile_n)(Node*) = nullptr; + void (*fn_run_n_s)(const Node*, Stack&) = nullptr; + void (*fn_fuse_graph)(std::shared_ptr&) = nullptr; + bool (*fn_can_fuse_n)(const Node*) = nullptr; + void (*fn_insert_profile_inodes)(ProfilingRecord* pr) = nullptr; + bool (*fn_profile_n)(const Node*) = nullptr; + bool (*fn_skip_n)(const std::string&, bool flip) = nullptr; +}; + +// Get interface, this is used by registration and user facing API internally +TORCH_API CudaFuserInterface* getFuserInterface(); + +TORCH_API void compileFusionGroup(Node* fusion_node); +TORCH_API void runFusionGroup(const Node* fusion_node, Stack& stack); +TORCH_API void fuseGraph(std::shared_ptr& /*graph*/); +TORCH_API bool canFuseNode(const Node* node); +TORCH_API void InsertProfileNodesForCUDAFuser(ProfilingRecord* pr); +TORCH_API bool profileNode(const Node* node); + +TORCH_API bool skipNode(const std::string& symbol_str, bool flip = true); + +TORCH_API bool isEnabled(); +TORCH_API bool setEnabled(bool is_enabled); +TORCH_API bool canBeEnabled(); + +} // namespace torch::jit::fuser::cuda + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/arg_spec.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/arg_spec.h new file mode 100644 index 0000000000000000000000000000000000000000..3621030aed0ee08ccf973d0d64ebe2592118a851 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/arg_spec.h @@ -0,0 +1,60 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include // fmap +#include +#include +#include + +#include +#include + +namespace torch::jit::fuser { + +// Describes the (runtime) arguments to a kernel. +// ArgSpecs are also used as keys to lookup instantiated kernels, so +// they are hashable. +// Note: the device to run on is included in the arg spec because kernels +// are compiled per-device. +struct TORCH_API ArgSpec { + ArgSpec(at::TensorList inputs, const int _device) + : descs_{c10::fmap(inputs)}, + hash_code_{c10::get_hash(_device, inputs.size(), descs_)}, + device_{_device} {} + + // (Common) hash function + static size_t hash(const ArgSpec& spec) { + return spec.hash_code_; + } + + // Comparators + bool operator==(const ArgSpec& other) const { + return (descs_ == other.descs_ && device_ == other.device_); + } + + bool operator!=(const ArgSpec& spec) const { + return !(*this == spec); + } + + // Getters + size_t hashCode() const { + return hash_code_; + } + const std::vector& descs() const { + return descs_; + } + int device() const { + return device_; + } + + private: + std::vector descs_; + size_t hash_code_; + int device_; +}; + +} // namespace torch::jit::fuser + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/codegen.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/codegen.h new file mode 100644 index 0000000000000000000000000000000000000000..1cc359481bf7cb9eb5b1bf72b1f7043bf0612309 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/codegen.h @@ -0,0 +1,29 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +namespace torch::jit::fuser { + +// Creates a CPU or CUDA kernel for the given graph. +// Returns the C++ or CUDA string implementing the kernel. +TORCH_API std::string generateKernel( + const std::string& name, + const Graph& graph, + const std::vector>>& + inputs, + const std::vector>& outputs, + const bool use_cuda); + +} // namespace torch::jit::fuser + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/compiler.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/compiler.h new file mode 100644 index 0000000000000000000000000000000000000000..e76959805a5cdee9d94582b09f76d3750e0ecdc4 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/compiler.h @@ -0,0 +1,61 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace torch::jit::fuser { + +// Performs device-independent "upfront" compilation of the given fusion_group, +// if it has not been registered already. +// Returns a key that can be used to run the fusion later +TORCH_API int64_t registerFusion(const Node* fusion_group); + +// Performs device-specific "runtime" compilation of the given kernel +// with the runtime arguments specified in ArgSpec. +// Outputs are allocated using map_size on the specified device. +TORCH_API std::shared_ptr compileKernel( + const KernelSpec& spec, + const ArgSpec& arg_spec, + const std::vector& map_size, + const at::Device& device); + +TORCH_API size_t nCompiledKernels(); + +TORCH_API int debugFuser(); + +using FusedKernelConstructor = std::function( + int16_t device, + std::string name, + std::string code, + std::vector input_desc, + std::vector output_desc, + std::vector chunk_desc, + std::vector concat_desc, + bool has_random)>; + +TORCH_API void registerFusionBackend( + at::Device::Type backend_type, + FusedKernelConstructor ctor); +TORCH_API bool hasFusionBackend(at::Device::Type backend_type); +struct TORCH_API RegisterFusionBackend{RegisterFusionBackend( + at::Device::Type backend_type, + FusedKernelConstructor ctor){ + registerFusionBackend(backend_type, std::move(ctor)); +} // namespace torch::jit::fuser +} +; + +} // namespace torch::jit::fuser + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/cpu/fused_kernel.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/cpu/fused_kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..13e37fe47a442853f902b18967222dfd930cec2c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/cpu/fused_kernel.h @@ -0,0 +1,44 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +namespace torch::jit::fuser::cpu { + +// Represents a compiled CPU kernel and the metadata necessary to run it +struct TORCH_API FusedKernelCPU : public FusedKernel { + FusedKernelCPU( + std::string name, + std::string code, + std::vector input_desc, + std::vector output_desc, + std::vector chunk_desc, + std::vector concat_desc, + bool has_random); + + at::Backend backend() const override { + return at::Backend::CPU; + } + + void launch_raw(const uint32_t numel, std::vector& arguments) + const override { + kernel(numel, arguments.data()); + } + + private: + std::unique_ptr so_lib; + void (*kernel)(uint32_t, void**) = nullptr; +}; + +} // namespace torch::jit::fuser::cpu + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/cpu/resource_strings.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/cpu/resource_strings.h new file mode 100644 index 0000000000000000000000000000000000000000..62c3008b31ff5ecacfca5541068ced287dcb84cc --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/cpu/resource_strings.h @@ -0,0 +1,106 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit::fuser::cpu { + +/*with type_as not checking type of its input, a fusion group can have non-fp32 +tensor as input. Correct code for this case is generated, however, nvrtc does +not know how to handle int*_t integer types, so typedefs help it handle those +cases*/ + +static auto type_declarations_template = at::jit::CodeTemplate(R"( + +#define POS_INFINITY INFINITY +#define NEG_INFINITY -INFINITY + +typedef ${IndexType} IndexType; +template +struct TensorInfo { + T* data; + IndexType sizes[N]; + IndexType strides[N]; +}; +template +struct TensorInfo { + T * data; +}; +)"); + +static auto cpu_compilation_unit_template = at::jit::CodeTemplate(R"( +#include +#include +#include + +double rsqrt(double x) { + return 1.0/sqrt(x); +} + +float rsqrtf(float x) { + return 1.0f/sqrtf(x); +} + +double frac(double x) { + return x - trunc(x); +} + +float fracf(float x) { + return x - truncf(x); +} + +${type_declarations} + +#ifdef _MSC_VER +template struct int_of_size; + +#define DEFINE_INT_OF_SIZE(int_t) \ +template<> struct int_of_size { using type = int_t; } + +DEFINE_INT_OF_SIZE(int64_t); +DEFINE_INT_OF_SIZE(int32_t); +DEFINE_INT_OF_SIZE(int16_t); +DEFINE_INT_OF_SIZE(int8_t); + +#undef DEFINE_INT_OF_SIZE + +template +using int_same_size_t = typename int_of_size::type; + +#define IndexTypeLoop int_same_size_t +#define ToIndexTypeLoop(x) static_cast(x) +#else +#define IndexTypeLoop IndexType +#define ToIndexTypeLoop(x) x +#endif + +#define OMP_THRESHOLD 100000 +static void ${kernelName}_kernel(IndexType totalElements, ${formals}) { + #pragma omp parallel for if(totalElements > OMP_THRESHOLD) + for (IndexTypeLoop linearIndex = 0; + linearIndex < ToIndexTypeLoop(totalElements); + linearIndex += 1) { + // Convert `linearIndex` into an offset of tensor: + ${tensorOffsets} + // calculate the results + ${kernelBody} + } +} + +#ifdef _WIN32 +#define JIT_API __declspec(dllexport) +#else +#define JIT_API +#endif + +extern "C" +JIT_API void ${kernelName}(IndexType totalElements, void ** args) { + ${kernelName}_kernel(totalElements ${,argument_loads}); +} +)"); + +} // namespace torch::jit::fuser::cpu + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/cpu/temp_file.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/cpu/temp_file.h new file mode 100644 index 0000000000000000000000000000000000000000..726ca1e7cc63e1fa32a04b9ca9995aad365ff778 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/cpu/temp_file.h @@ -0,0 +1,140 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#endif + +#include +#include + +namespace torch::jit::fuser::cpu { + +#ifdef _MSC_VER +inline int wmkstemps(wchar_t* tmpl, int suffix_len) { + int len; + wchar_t* name; + int fd = -1; + int save_errno = errno; + + len = wcslen(tmpl); + if (len < 6 + suffix_len || + wcsncmp(&tmpl[len - 6 - suffix_len], L"XXXXXX", 6)) { + return -1; + } + + name = &tmpl[len - 6 - suffix_len]; + + std::random_device rd; + do { + for (unsigned i = 0; i < 6; ++i) { + name[i] = "abcdefghijklmnopqrstuvwxyz0123456789"[rd() % 36]; + } + + fd = _wopen(tmpl, _O_RDWR | _O_CREAT | _O_EXCL, _S_IWRITE | _S_IREAD); + } while (errno == EEXIST); + + if (fd >= 0) { + errno = save_errno; + return fd; + } else { + return -1; + } +} +#endif + +struct TempFile { + AT_DISALLOW_COPY_AND_ASSIGN(TempFile); + + TempFile(const std::string& t, int suffix) { +#ifdef _MSC_VER + auto wt = c10::u8u16(t); + std::vector tt(wt.c_str(), wt.c_str() + wt.size() + 1); + int fd = wmkstemps(tt.data(), suffix); + AT_ASSERT(fd != -1); + file_ = _wfdopen(fd, L"r+"); + auto wname = std::wstring(tt.begin(), tt.end() - 1); + name_ = c10::u16u8(wname); +#else + // mkstemps edits its first argument in places + // so we make a copy of the string here, including null terminator + std::vector tt(t.c_str(), t.c_str() + t.size() + 1); + int fd = mkstemps(tt.data(), suffix); + AT_ASSERT(fd != -1); + file_ = fdopen(fd, "r+"); + // - 1 because tt.size() includes the null terminator, + // but std::string does not expect one + name_ = std::string(tt.begin(), tt.end() - 1); +#endif + } + + const std::string& name() const { + return name_; + } + + void sync() { + fflush(file_); + } + + void write(const std::string& str) { + size_t result = fwrite(str.c_str(), 1, str.size(), file_); + AT_ASSERT(str.size() == result); + } + +#ifdef _MSC_VER + void close() { + if (file_ != nullptr) { + fclose(file_); + } + file_ = nullptr; + } +#endif + + FILE* file() { + return file_; + } + + ~TempFile() { +#ifdef _MSC_VER + if (file_ != nullptr) { + fclose(file_); + } + auto wname = c10::u8u16(name_); + if (!wname.empty() && _waccess(wname.c_str(), 0) != -1) { + _wunlink(wname.c_str()); + } +#else + if (file_ != nullptr) { + // unlink first to ensure another mkstemps doesn't + // race between close and unlink + unlink(name_.c_str()); + fclose(file_); + } +#endif + } + + private: + FILE* file_ = nullptr; + std::string name_; +}; + +} // namespace torch::jit::fuser::cpu + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/cuda/fused_kernel.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/cuda/fused_kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..85c23b394ab73e4cce98eb632a4979059f2429d3 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/cuda/fused_kernel.h @@ -0,0 +1,64 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace torch::jit::fuser::cuda { + +// query codegen output arch and target +TORCH_CUDA_CU_API void codegenOutputQuery( + const cudaDeviceProp* const prop, + int& major, + int& minor, + bool& compile_to_sass); + +// A class holding metadata for an actual CUDA function. +// Note: CUDA functions are per device. +struct TORCH_CUDA_CU_API FusedKernelCUDA + : public ::torch::jit::fuser::FusedKernel { + FusedKernelCUDA( + at::DeviceIndex device, + std::string name, + std::string code, + std::vector input_desc, + std::vector output_desc, + std::vector chunk_desc, + std::vector concat_desc, + bool has_random); + + ~FusedKernelCUDA() override; + + void launch_raw(const uint32_t numel, std::vector& arguments) + const override; + + at::Backend backend() const override { + return at::Backend::CUDA; + } + + private: + static constexpr auto kBlockSize = 128; + + // Note: per device to store device properties and compute launch heuristics + // Acquiring these values at launch time would be too slow + at::DeviceIndex device_; + int maxBlocks_{}; + cudaDeviceProp* prop_{}; + std::vector ptx_; + CUmodule module_{}; + CUfunction function_{}; +}; + +} // namespace torch::jit::fuser::cuda + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/cuda/resource_strings.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/cuda/resource_strings.h new file mode 100644 index 0000000000000000000000000000000000000000..b495251ad391d9d9a86ab1c8867e84dfd1f07f07 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/cuda/resource_strings.h @@ -0,0 +1,417 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::jit::fuser::cuda { + +/*with type_as not checking type of its input, a fusion group can have non-fp32 +tensor as input. Correct code for this case is generated, however, nvrtc does +not know how to handle int*_t integer types, so typedefs help it handle those +cases*/ + +static constexpr auto bfloat16_type_string = "__nv_bfloat16"; + +#if defined(USE_ROCM) && ROCM_VERSION < 70000 +static auto type_declarations_template = at::jit::CodeTemplate(R"( +${HalfHeader} +${BFloat16Header} +${RandHeader} + +#define NAN __int_as_float(0x7fffffff) +#define POS_INFINITY __int_as_float(0x7f800000) +#define NEG_INFINITY __int_as_float(0xff800000) + +typedef ${IndexType} IndexType; +template +struct TensorInfo { + T* data; + IndexType sizes[N]; + IndexType strides[N]; +}; +template +struct TensorInfo { + T * data; +}; +)"); +#else +static auto type_declarations_template = at::jit::CodeTemplate(R"( +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef short int int16_t; +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +${HalfHeader} +${BFloat16Header} +${RandHeader} + +#define NAN __int_as_float(0x7fffffff) +#define POS_INFINITY __int_as_float(0x7f800000) +#define NEG_INFINITY __int_as_float(0xff800000) + +typedef ${IndexType} IndexType; +template +struct TensorInfo { + T* data; + IndexType sizes[N]; + IndexType strides[N]; +}; +template +struct TensorInfo { + T * data; +}; +)"); +#endif + +// We rewrite the code for philox RNG from curand as nvrtc couldn't resolve the +// curand header correctly. +constexpr auto rand_support_literal = R"( + + class Philox { + public: + __device__ inline Philox(unsigned long long seed, + unsigned long long subsequence, + unsigned long long offset) { + key.x = (unsigned int)seed; + key.y = (unsigned int)(seed >> 32); + counter = make_uint4(0, 0, 0, 0); + counter.z = (unsigned int)(subsequence); + counter.w = (unsigned int)(subsequence >> 32); + STATE = 0; + incr_n(offset / 4); + } + + __device__ inline unsigned long operator()() { + if(STATE == 0) { + uint4 counter_ = counter; + uint2 key_ = key; + for(int i = 0; i < 9; i++) { + counter_ = single_round(counter_, key_); + key_.x += (kPhilox10A); key_.y += (kPhilox10B); + } + output = single_round(counter_, key_); + incr(); + } + unsigned long ret; + switch(STATE) { + case 0: ret = output.x; break; + case 1: ret = output.y; break; + case 2: ret = output.z; break; + case 3: ret = output.w; break; + } + STATE = (STATE + 1) % 4; + return ret; + } + + private: + uint4 counter; + uint4 output; + uint2 key; + unsigned int STATE; + __device__ inline void incr_n(unsigned long long n) { + unsigned int nlo = (unsigned int)(n); + unsigned int nhi = (unsigned int)(n >> 32); + counter.x += nlo; + if (counter.x < nlo) + nhi++; + counter.y += nhi; + if (nhi <= counter.y) + return; + if (++counter.z) + return; + ++counter.w; + } + __device__ inline void incr() { + if (++counter.x) + return; + if (++counter.y) + return; + if (++counter.z) + return; + ++counter.w; + } + __device__ unsigned int mulhilo32(unsigned int a, unsigned int b, + unsigned int *result_high) { + *result_high = __umulhi(a, b); + return a*b; + } + + __device__ inline uint4 single_round(uint4 ctr, uint2 key) { + unsigned int hi0; + unsigned int hi1; + unsigned int lo0 = mulhilo32(kPhiloxSA, ctr.x, &hi0); + unsigned int lo1 = mulhilo32(kPhiloxSB, ctr.z, &hi1); + + uint4 ret = {hi1 ^ ctr.y ^ key.x, lo1, hi0 ^ ctr.w ^ key.y, lo0}; + return ret; + } + + static const unsigned long kPhilox10A = 0x9E3779B9; + static const unsigned long kPhilox10B = 0xBB67AE85; + static const unsigned long kPhiloxSA = 0xD2511F53; + static const unsigned long kPhiloxSB = 0xCD9E8D57; + }; + + // Inverse of 2^32. + #define M_RAN_INVM32 2.3283064e-10f + __device__ __inline__ float uniform(unsigned int x) { + return x * M_RAN_INVM32; + } +)"; + +constexpr auto rand_param = + ",unsigned long long seed, unsigned long long offset"; + +constexpr auto rand_init = R"( + int idx = blockIdx.x*blockDim.x + threadIdx.x; + Philox rnd(seed, idx, offset); +)"; + +static auto cuda_compilation_unit_template = at::jit::CodeTemplate(R"( +${type_declarations} + +extern "C" __global__ +void ${kernelName}(IndexType totalElements, ${formals} ${RandParam}) { + ${RandInit} + // check whether do vectorized load/store and allocate buffer + bool flag_vec4 = true; + ${tensorChecks} + if (flag_vec4) { + for (IndexType linearIndex = 4 * (blockIdx.x * blockDim.x + threadIdx.x); + linearIndex < totalElements; + linearIndex += 4 * gridDim.x * blockDim.x) { + // Convert `linearIndex` into an offset of tensor as it is: + ${tensorOffsets} + // load 4 at a time + ${kernelLoad} + #pragma unroll 4 + for (int i=0; i<4; i++) { + // calculate the results + ${kernelBody_vec4} + } + // store 4 at a time + ${kernelStore} + } + } else { + for (IndexType linearIndex = blockIdx.x * blockDim.x + threadIdx.x; + linearIndex < totalElements; + linearIndex += gridDim.x * blockDim.x) { + // Convert `linearIndex` into an offset of tensor: + ${tensorOffsets} + // calculate the results + ${kernelBody} + } + } +} +)"); + +// This snippet enables half support in the jit. Following the pattern for +// reductions, fp16 input data is immediately upconverted to float +// with __half2float(). All mathematical operations are done on float +// values, and if needed the intermediate float representation is +// converted to half with __float2half() when writing to a half tensor. +#if defined(USE_ROCM) +constexpr auto half_support_literal = + R"( +typedef __half half; +)"; +#else +constexpr auto half_support_literal = + R"( +#define __HALF_TO_US(var) *(reinterpret_cast(&(var))) +#define __HALF_TO_CUS(var) *(reinterpret_cast(&(var))) +#if defined(__cplusplus) + struct __align__(2) __half { + __host__ __device__ __half() { } + + protected: + unsigned short __x; + }; + + /* All intrinsic functions are only available to nvcc compilers */ + #if defined(__CUDACC__) + /* Definitions of intrinsics */ + __device__ __half __float2half(const float f) { + __half val; + asm("{ cvt.rn.f16.f32 %0, %1;}\n" : "=h"(__HALF_TO_US(val)) : "f"(f)); + return val; + } + + __device__ float __half2float(const __half h) { + float val; + asm("{ cvt.f32.f16 %0, %1;}\n" : "=f"(val) : "h"(__HALF_TO_CUS(h))); + return val; + } +)" + // MSVC's preprocessor (but not the standard compiler) has a bug + // where it incorrectly tokenizes raw string literals, ending when it sees a + // " this causes the #endif in this string literal to be treated as a + // preprocessor token which, in turn, cause sccache on windows CI to fail. + // See https://godbolt.org/z/eVTIJq as an example. + // This workaround uses string-pasting to separate the " and the #endif into + // different strings + R"( + #endif /* defined(__CUDACC__) */ +#endif /* defined(__cplusplus) */ +#undef __HALF_TO_US +#undef __HALF_TO_CUS + +typedef __half half; +)"; +#endif + +#if defined(USE_ROCM) + +#if ROCM_VERSION >= 70000 +#define BF16_UINT32_DEF "typedef unsigned int uint32_t;\n" +#else +#define BF16_UINT32_DEF "" +#endif + +constexpr auto bfloat16_support_literal = + R"( +#ifndef __align__ +#define __align__(x) __attribute__((aligned(x))) +#endif +)" BF16_UINT32_DEF R"( +typedef struct __align__(2) { + unsigned short x; +} +__nv_bfloat16_raw; + +#if defined(__cplusplus) +struct __align__(2) __nv_bfloat16 { + __host__ __device__ __nv_bfloat16() {} + + __host__ __device__ __nv_bfloat16& operator=(const __nv_bfloat16_raw& hr) { + __x = hr.x; + return *this; + } + + unsigned short __x; +}; + +__device__ unsigned short __internal_float2bfloat16( + const float f, + unsigned int& sign, + unsigned int& remainder) { + unsigned int x; + + x = __float_as_uint(f); + + if ((x & 0x7fffffffU) > 0x7f800000U) { + sign = 0U; + remainder = 0U; + return static_cast(0x7fffU); + } + sign = x >> 31; + remainder = x << 16; + return static_cast(x >> 16); +} + +/* Definitions of intrinsics */ +__device__ __nv_bfloat16 __float2bfloat16(const float a) { + __nv_bfloat16 val; + __nv_bfloat16_raw r; + unsigned int sign; + unsigned int remainder; + r.x = __internal_float2bfloat16(a, sign, remainder); + if ((remainder > 0x80000000U) || + ((remainder == 0x80000000U) && ((r.x & 0x1U) != 0U))) { + r.x++; + } + val = r; + return val; +} + +__device__ float __bfloat162float(const __nv_bfloat16 a) { + union + { + uint32_t int32; + float fp32; + } u = {uint32_t(a.__x) << 16}; + return u.fp32; +} +#endif /* defined(__cplusplus) */ +)"; +#else +constexpr auto bfloat16_support_literal = + R"( +#define __BFLOAT16_TO_US(var) *(reinterpret_cast(&(var))) +#define __BFLOAT16_TO_CUS(var) \ + *(reinterpret_cast(&(var))) + +typedef struct __align__(2) { + unsigned short x; +} +__nv_bfloat16_raw; + +#if defined(__cplusplus) +struct __align__(2) __nv_bfloat16 { + __host__ __device__ __nv_bfloat16() {} + + __host__ __device__ __nv_bfloat16& operator=(const __nv_bfloat16_raw& hr) { + __x = hr.x; + return *this; + } + + protected: + unsigned short __x; +}; + +#if defined(__CUDACC__) +__device__ unsigned short __internal_float2bfloat16( + const float f, + unsigned int& sign, + unsigned int& remainder) { + unsigned int x; + + x = __float_as_uint(f); + + if ((x & 0x7fffffffU) > 0x7f800000U) { + sign = 0U; + remainder = 0U; + return static_cast(0x7fffU); + } + sign = x >> 31; + remainder = x << 16; + return static_cast(x >> 16); +} + +/* Definitions of intrinsics */ +__device__ __nv_bfloat16 __float2bfloat16(const float a) { + __nv_bfloat16 val; +#if __CUDA_ARCH__ >= 800 + asm("{ cvt.rn.bf16.f32 %0, %1;}\n" : "=h"(__BFLOAT16_TO_US(val)) : "f"(a)); +#else + __nv_bfloat16_raw r; + unsigned int sign; + unsigned int remainder; + r.x = __internal_float2bfloat16(a, sign, remainder); + if ((remainder > 0x80000000U) || + ((remainder == 0x80000000U) && ((r.x & 0x1U) != 0U))) { + r.x++; + } + val = r; +#endif + return val; +} + +__device__ float __bfloat162float(const __nv_bfloat16 a) { + float val; + asm("{ mov.b32 %0, {0,%1};}\n" : "=f"(val) : "h"(__BFLOAT16_TO_CUS(a))); + return val; +} +#endif /* defined(__CUDACC__) */ +#endif /* defined(__cplusplus) */ +#undef __BFLOAT16_TO_US +#undef __BFLOAT16_TO_CUS +)"; +#endif + +} // namespace torch::jit::fuser::cuda + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/executor.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/executor.h new file mode 100644 index 0000000000000000000000000000000000000000..aa6c691a0b807558cb4f5ce030dd156afb128a18 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/executor.h @@ -0,0 +1,24 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include + +namespace torch::jit::fuser { + +// Runs the fusion associated with the key (see registerFusion() in interface.h) +// on the inputs taken from the given Stack. +TORCH_API bool runFusion( + const int64_t key, + Stack& stack, + std::string* code_out = nullptr); + +} // namespace torch::jit::fuser + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/fallback.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/fallback.h new file mode 100644 index 0000000000000000000000000000000000000000..393127a6e99dc29fa41aecbb36d7e437e3a5bd51 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/fallback.h @@ -0,0 +1,16 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include + +namespace torch::jit::fuser { + +void runFallback(int64_t key, Stack& stack); + +} // namespace torch::jit::fuser + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/fused_kernel.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/fused_kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..ca2adedd7b196d1db9dddca4b3319c51e7060226 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/fused_kernel.h @@ -0,0 +1,103 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +namespace torch::jit::fuser { + +struct FusedKernel { + AT_DISALLOW_COPY_AND_ASSIGN(FusedKernel); + + FusedKernel( + std::string name, + std::string code, + std::vector input_desc, + std::vector output_desc, + std::vector chunk_desc, + std::vector concat_desc, + bool has_random) + : name_(std::move(name)), + code_(std::move(code)), + input_desc_(std::move(input_desc)), + output_desc_(std::move(output_desc)), + chunk_desc_(std::move(chunk_desc)), + concat_desc_(std::move(concat_desc)), + has_random_(has_random) {} + + virtual ~FusedKernel() = default; + + // arguments is a list of pointers to the arguments for the compiled CUDA/CPU + // code. + // The format of arguments is suitable for directly passing to a call to + // cuLaunchKernel as the kernel arguments. + // Currently the first argument is a pointer to numel (for passing to + // CUDA code), and the remainder are pointers to the TensorInfo structs + // that compiled code uses to load Tensor data. + // launch_with_tensors handles packing at::Tensors into this arguments array. + // CPU code uses the same convention so that launch_with_tensors can be + // shared. + virtual void launch_raw(const uint32_t numel, std::vector& arguments) + const = 0; + virtual at::Backend backend() const = 0; + + // Getters + const std::string& name() const { + return name_; + } + const std::string& code() const { + return code_; + } + const std::vector& inputDesc() const { + return input_desc_; + } + const std::vector& outputDesc() const { + return output_desc_; + } + const std::vector& chunkDesc() const { + return chunk_desc_; + } + const std::vector& concatDesc() const { + return concat_desc_; + } + bool hasRandom() const { + return has_random_; + } + + protected: + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const std::string name_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const std::string code_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const std::vector input_desc_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const std::vector output_desc_; + + // same size as input_desc, describes whether an + // input should be broken into subtensors (chunks) + // to be consumed by the fusion group + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const std::vector chunk_desc_; + + // same size as output_desc, describes whether + // an output is actually a concatenation of + // many subtensors that the fusion group produces + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const std::vector concat_desc_; + + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const bool has_random_; +}; + +} // namespace torch::jit::fuser + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/interface.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/interface.h new file mode 100644 index 0000000000000000000000000000000000000000..516e192a0fb38a1c4af1cd56a9bff94509335347 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/interface.h @@ -0,0 +1,59 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +namespace torch::jit { + +constexpr int kCPUDevice = -1; + +// Assigns a "key" to the given fusion_group that it can use to run its +// fusion later (via runFusion() below). +TORCH_API int64_t registerFusion(const Node* fusion_group); + +// Runs the fusion corresponding to the given key on the inputs +// found on the stack. Outputs are placed on the same stack. +// In some cases a fusion cannot be run and a fallback path where +// PyTorch's interpreter runs the graph instead is attempted. +TORCH_API void runFusion(const int64_t key, Stack& stack); + +// True if the respective devices can fuse, false otherwise +TORCH_API bool canFuseOnCPU(); +TORCH_API bool canFuseOnGPU(); + +// Sets whether fusion on the CPU is allowed (disabled by default due to +// flakiness) +TORCH_API void overrideCanFuseOnCPU(bool value); + +// Sets whether fusion on CPU must use LLVM Codegen and not SimplieIREval +TORCH_API void overrideMustUseLLVMOnCPU(bool value); + +// Sets whether fusion on the GPU is allowed (enabled by default) +TORCH_API void overrideCanFuseOnGPU(bool value); + +// Treats the given graph as a fusion group and launches it on the +// specified device with the given inputs. +// Returns the outputs. +TORCH_API std::vector debugLaunchGraph( + Graph& graph, + at::ArrayRef inputs); + +// Treats the given graph as a fusion group and returns the generated code. +TORCH_API std::string debugGetFusedKernelCode( + Graph& graph, + at::ArrayRef inputs); + +TORCH_API size_t nCompiledKernels(); + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/kernel_cache.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/kernel_cache.h new file mode 100644 index 0000000000000000000000000000000000000000..d2446f6aa8af57c66c8eeef1c5198cf5199e966f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/kernel_cache.h @@ -0,0 +1,38 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace torch::jit::fuser { + +// A thread-safe cache interface. + +// Normalizes the graph by canonicalizing and erasing shape information +TORCH_API std::shared_ptr normalizeGraphForCache( + const std::shared_ptr& graph); + +// Stores the given graph, returning the key used to access it +TORCH_API int64_t store(std::shared_ptr graph); + +// Given a graph, find a KernelSpec based on it +TORCH_API std::optional lookupGraph( + const std::shared_ptr& graph); + +// Returns the graph corresponding to the given key (if it exists) +TORCH_API std::optional retrieve(const int64_t key); + +// Returns the size of the fusion key -> KernelSpec cache. +// Only used for testing. +TORCH_API int64_t debugNumCachedKernelSpecs(); + +} // namespace torch::jit::fuser + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/kernel_spec.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/kernel_spec.h new file mode 100644 index 0000000000000000000000000000000000000000..a84bcc7b3b7c18de8bda1dfc1905a44f77cead26 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/kernel_spec.h @@ -0,0 +1,149 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace torch::jit::fuser { + +// Helper struct containing partition information: the number of tensors +// created and the dimension the partitioning is performed on. +// Note: created during upfront compilation, once the tensors are known +// at runtime the partition info is logically combined with the tensor +// descriptions to create PartitionDesc objects. +struct TORCH_API PartitionInfo { + PartitionInfo(const int64_t _nSubTensors, const int64_t _dim) + : nSubTensors_{_nSubTensors}, dim_{_dim} {} + + int64_t nSubTensors() const { + return nSubTensors_; + } + int64_t dim() const { + return dim_; + } + + private: + int64_t nSubTensors_; + int64_t dim_; +}; + +// "Kernel Specification." - Contains device-independent fusion information. +// Each kernel specification contains a map of instantiated generated functions +// that implement some or most of its functionality. Multiple generated +// functions are needed by each abstract specification because of different +// devices (cpu vs gpu, different gpus) and different inputs (int vs float, +// contiguous vs discontiguous). +// Note: uses a mutex to control access to its kernel store +// Note: unordered containers do not invalidate references/pointers on +// rehashing, which is critical for thread-safety. +// TODO: allow abstract kernels to use multiple generated kernels +// TODO: allow abstract kernels to reuse generated kernels from common pool +struct TORCH_API KernelSpec { + // Note: assumes the spec is a single block + // Note: This is the appropriate place to generalize if you want to add other + // passes to upfront compilation that walk the graph. + KernelSpec(const int64_t _key, const std::shared_ptr& _graph) + : key_{_key}, + graph_{_graph}, + code_{_graph, ""}, + nInputs_{_graph->inputs().size()} + + { + // No need to iterate over reference since n is pointer + for (const auto n : graph_->nodes()) { + static_assert(std::is_pointer_v, "n must be a pointer"); + if (n->kind() == aten::rand_like) { + has_random_ = true; + break; + } + } + nTensorInputs_ = std::count_if( + graph_->inputs().begin(), graph_->inputs().end(), [](const Value* v) { + return v->type()->isSubtypeOf(*TensorType::get()); + }); + } + + // Getters + int64_t key() const { + return key_; + } + std::shared_ptr graph() const { + return graph_; + } + const Code& code() const { + return code_; + } + int64_t nInputs() const { + return nInputs_; + } + int64_t nTensorInputs() const { + return nTensorInputs_; + } + + std::vector>& inputBroadcastGroups() { + return inputBroadcastGroups_; + } + const std::vector>& inputBroadcastGroups() const { + return inputBroadcastGroups_; + } + + std::vector& inputChunks() { + return inputChunks_; + } + const std::vector& inputChunks() const { + return inputChunks_; + } + + bool hasRandom() const { + return has_random_; + } + + // Cache functions + std::optional> findKernel( + const ArgSpec& arg_spec) const { + std::lock_guard guard{mutex_}; + const auto it = kernels_.find(arg_spec); + if (it == kernels_.end()) + return std::nullopt; + return it->second; + } + void cacheKernel( + const ArgSpec& arg_spec, + const std::shared_ptr& kernel) const { + std::lock_guard guard{mutex_}; + kernels_.emplace(arg_spec, kernel); + } + + private: + int64_t key_; + std::shared_ptr graph_; + Code code_; + uint64_t nInputs_; + uint64_t nTensorInputs_{}; + std::vector> inputBroadcastGroups_; + std::vector inputChunks_; + bool has_random_{false}; + mutable std::mutex mutex_; + mutable std:: + unordered_map, c10::hash> + kernels_; +}; + +} // namespace torch::jit::fuser + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/partition_desc.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/partition_desc.h new file mode 100644 index 0000000000000000000000000000000000000000..6eee194e80d162044d5065be72d9e2797df3db2f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/partition_desc.h @@ -0,0 +1,63 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace torch::jit::fuser { + +// Descriptor for chunk-ing an input tensor into subtensors +// OR concat-ing an output tensor from subtensors +// Note: default constructed used for tensors that do not participate in +// chunk or cat operations. +struct TORCH_API PartitionDesc { + PartitionDesc() : nSubTensors_{1}, dim_{0} {} + + PartitionDesc(const TensorDesc& _desc, size_t _nSubTensors, size_t _dim) + : nSubTensors_{_nSubTensors}, dim_{_dim} { + AT_ASSERT(nSubTensors_ > 1); + std::vector cont = _desc.contiguity; + if (dim_ > 0) { + // when we narrow the concatenated output/chunked input + // we make the size[dim] smaller while keeping the stride[dim] the same, + // meaning: stride[dim - 1] != stride[dim]*size[dim] + // so dim - 1 is no longer contiguous + cont[dim_ - 1] = false; + } + subTensorDesc_ = std::make_shared(_desc.scalar_type, cont); + } + + bool isNoop() const { + return (nSubTensors_ == 1); + } + size_t nSubTensors() const { + return nSubTensors_; + } + size_t dim() const { + return dim_; + } + std::shared_ptr subTensorDesc() { + return subTensorDesc_; + } + const std::shared_ptr subTensorDesc() const { + return subTensorDesc_; + } + + private: + size_t nSubTensors_; // == 1 for tensors that should not be operated on via + // chunk/cat + size_t dim_; // dimension along which the chunk/concat occurs + std::shared_ptr + subTensorDesc_; // descriptor for the subtensor, if it exists +}; + +} // namespace torch::jit::fuser + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/tensor_desc.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/tensor_desc.h new file mode 100644 index 0000000000000000000000000000000000000000..0376875925a04b26615051b34d72ff4bf481898f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/tensor_desc.h @@ -0,0 +1,103 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace torch::jit::fuser { + +// type information needed by the compiler for input/outputs +// contiguity[i] is true if the dim i is contiguous with dim i + 1. +// contiguity.back() == true means strides.back() == 1. +struct TORCH_API TensorDesc { + at::ScalarType scalar_type; + std::vector contiguity; + + TensorDesc(const at::ScalarType& type, const std::vector& contiguity) + : scalar_type{type}, contiguity{contiguity} { + if (contiguity.empty()) { + nDim_ = 0; + } else { + nDim_ = std::count(contiguity.begin(), contiguity.end(), false) + + (lastIsContiguous() ? 1 : 0); + } + } + + // Delegating constructors + TensorDesc( + const at::ScalarType& type, + const at::IntArrayRef& sizes, + const at::IntArrayRef& strides) + : TensorDesc(type, TensorDesc::findContiguous(sizes, strides)) {} + + TensorDesc(const at::Tensor& t) + : TensorDesc(t.scalar_type(), t.sizes(), t.strides()) {} + + TensorDesc(const c10::TensorTypePtr& type) + : TensorDesc( + type->scalarType().value(), + type->sizes().concrete_sizes().value(), + type->strides().concrete_sizes().value()) {} + + // number of dimensions after contiguity compression + size_t nDim() const { + return nDim_; + } + + // True iff innermost stride is 1 + bool lastIsContiguous() const { + return (contiguity.empty() || contiguity.back()); + } + + static std::vector findContiguous( + const at::IntArrayRef& sizes, + const at::IntArrayRef& strides) { + AT_ASSERT(sizes.size() == strides.size()); + std::vector cont(sizes.size()); + for (size_t i = 0; i < sizes.size(); ++i) { + const auto expected_stride = + (i + 1 < sizes.size()) ? sizes[i + 1] * strides[i + 1] : 1; + cont[i] = (strides[i] == expected_stride); + } + return cont; + } + + bool operator==(const TensorDesc& desc) const { + return scalar_type == desc.scalar_type && contiguity == desc.contiguity; + } + + bool operator!=(const TensorDesc& desc) const { + return !(*this == desc); + } + + static size_t hash(const TensorDesc& spec) { + return c10::get_hash( + spec.scalar_type, + spec.nDim_, + std::hash>{}(spec.contiguity)); + } + + private: + size_t nDim_; +}; + +inline std::ostream& operator<<(std::ostream& out, const TensorDesc& d) { + out << d.scalar_type << '['; + for (const auto b : d.contiguity) + out << b << ';'; + out << ']'; + return out; +} + +} // namespace torch::jit::fuser + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/tensor_info.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/tensor_info.h new file mode 100644 index 0000000000000000000000000000000000000000..df2c1e12963bdaa58b56e688a3d6b950ee4e2f2d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/fuser/tensor_info.h @@ -0,0 +1,29 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include + +#include +#include + +namespace torch::jit::fuser { + +// Host-side view of TensorInfo +// Note dims[0] - we need to dynamically allocate the dims. +struct TORCH_API TensorInfo { + uint32_t* sizes(size_t nDim) { + return &sizes_strides[0]; + } + uint32_t* strides(size_t nDim) { + return &sizes_strides[nDim]; + } + + void* data; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays) + uint32_t sizes_strides[0]; +}; + +} // namespace torch::jit::fuser + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/LlgaTensorImpl.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/LlgaTensorImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..72f267a4cffaffb73f8d10d2b1b129efe5cb159f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/LlgaTensorImpl.h @@ -0,0 +1,277 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include +#include +#include + +namespace torch::jit::fuser::onednn { + +// Engine represents a device and its context. From the device kind, the engine +// knows how to generate code for the target device and what kind of device +// object to be expected. The device id ensures that there is a unique engine +// being created for each device. The device handle passed from PyTorch allows +// oneDNN Graph implementation to work on the device specified by PyTorch, which +// is currently CPU, so we only have one engine. +// Ref: +// https://oneapi-spec.uxlfoundation.org/specifications/oneapi/latest/elements/onednn/source/graph/programming_model#engine +struct Engine { + // CPU engine singleton + static dnnl::engine& getEngine(); + Engine(const Engine&) = delete; + void operator=(const Engine&) = delete; +}; + +// Stream is the logical abstraction for execution units. It is created on top +// of oneDNN Graph engine. A compiled oneDNN Graph partition is submitted to a +// stream for execution. +struct Stream { + // CPU stream singleton + static dnnl::stream& getStream(); + Stream(const Stream&) = delete; + void operator=(const Stream&) = delete; +}; + +struct LlgaTensorDesc { + using desc = dnnl::graph::logical_tensor; + + LlgaTensorDesc( + size_t tid, + std::vector sizes, + std::vector strides, + desc::data_type dtype, + desc::property_type property_type) + : tid_(tid), + sizes_(std::move(sizes)), + strides_(std::move(strides)), + dtype_(dtype), + property_type_(property_type), + layout_type_(desc::layout_type::strided), + layout_id_(-1) {} + + LlgaTensorDesc(const desc& t) + : tid_(t.get_id()), + sizes_(t.get_dims()), + strides_({-1}), + dtype_(t.get_data_type()), + property_type_(t.get_property_type()), + layout_type_(t.get_layout_type()), + layout_id_(-1) { + if (is_opaque()) { + layout_id_ = t.get_layout_id(); + } + if (is_strided()) { + strides_ = t.get_strides(); + } + } + + LlgaTensorDesc(const torch::jit::Value* v) + : LlgaTensorDesc( + v->unique(), + {}, + {}, + desc::data_type::f32, + get_property_type(v)) { + if (v->type()->isSubtypeOf(TensorType::get())) { + auto tt = v->type()->cast(); + + if (tt->scalarType()) { + dtype_ = getLlgaDataType(tt->scalarType().value()); + } + + auto sizes = tt->sizes(); + if (sizes.sizes()) { + for (auto d : *sizes.sizes()) { + sizes_.push_back(d.value_or(DNNL_GRAPH_UNKNOWN_DIM)); + } + } + + auto strides = tt->strides(); + if (strides.sizes()) { + for (auto d : *strides.sizes()) { + strides_.push_back(d.value_or(DNNL_GRAPH_UNKNOWN_DIM)); + } + } + } + } + + LlgaTensorDesc supplementTensorInfo(const at::Tensor& t) const; + + desc::data_type getLlgaDataType(at::ScalarType dt) const; + + at::ScalarType aten_scalar_type() const; + + const std::vector& sizes() const { + return sizes_; + } + + const std::vector& strides() const { + TORCH_CHECK(!is_opaque(), "Cannot get strides on opaque layout"); + return strides_; + } + + size_t tid() const { + return tid_; + } + + LlgaTensorDesc tid(uint64_t new_id) const { + auto ret = *this; + ret.tid_ = new_id; + return ret; + } + + desc::data_type dtype() const { + return dtype_; + } + + LlgaTensorDesc dtype(desc::data_type new_dtype) const { + return LlgaTensorDesc(tid_, sizes_, strides_, new_dtype, property_type_); + } + + desc::layout_type layout_type() const { + return layout_type_; + } + + LlgaTensorDesc layout_type(desc::layout_type new_layout_type) { + auto ret = *this; + ret.layout_type_ = new_layout_type; + return ret; + } + + desc::property_type get_property_type(const torch::jit::Value* v) { + switch (v->node()->kind()) { + case prim::Constant: + return desc::property_type::constant; + default: + return desc::property_type::variable; + } + } + + LlgaTensorDesc any() { + return layout_type(desc::layout_type::any); + } + + size_t storage_size() const { + return logical_tensor().get_mem_size(); + } + + desc logical_tensor() const { + if (is_dimensionality_unknown()) { + return desc( + tid_, dtype_, DNNL_GRAPH_UNKNOWN_NDIMS, layout_type_, property_type_); + } else if (is_opaque()) { + return desc(tid_, dtype_, sizes_, layout_id_, property_type_); + } else if (is_any()) { + return desc(tid_, dtype_, sizes_, layout_type_, property_type_); + } else { + return desc(tid_, dtype_, sizes_, strides_, property_type_); + } + } + + bool is_strided() const { + return layout_type_ == desc::layout_type::strided; + } + + bool is_any() const { + return layout_type_ == desc::layout_type::any; + } + + bool is_opaque() const { + return layout_type_ == desc::layout_type::opaque; + } + + bool operator==(const LlgaTensorDesc& desc) const { + return tid_ == desc.tid_ && sizes_ == desc.sizes_ && + dtype_ == desc.dtype_ && layout_type_ == desc.layout_type_ && + ((is_opaque() && layout_id_ == desc.layout_id_) || + strides_ == desc.strides_); + } + + bool operator!=(const LlgaTensorDesc& desc) const { + return (tid_ != desc.tid_) || (sizes_ != desc.sizes_) || + (dtype_ != desc.dtype_) || (layout_type_ != desc.layout_type_) || + !((is_opaque() && (layout_id_ == desc.layout_id_)) || + (strides_ == desc.strides_)); + } + + static size_t hash(const LlgaTensorDesc& desc) { + return c10::get_hash( + desc.tid_, + desc.sizes_, + desc.dtype_, + desc.layout_type_, + desc.layout_id_); + } + + void set_compute_inplace() { + compute_inplace_ = true; + } + + void set_input_tensor_index(size_t index) { + input_tensor_index_ = index; + } + + bool reuses_input_tensor() { + return compute_inplace_; + } + + size_t get_input_tensor_index() { + return input_tensor_index_; + } + + private: + bool is_dimensionality_unknown() const { + return sizes_.empty(); + } + + size_t tid_; + std::vector sizes_; + std::vector strides_; + desc::data_type dtype_; + desc::property_type property_type_; + desc::layout_type layout_type_; + size_t layout_id_; + // If this is an output tensor, and querying the compiled partition would + // determine that this tensor would reuse its input tensor, then + // compute_inplace would be true, and input_tensor_index would be the index of + // the corresponding input tensor in inputSpecs_ of the LlgaKernel object. + bool compute_inplace_ = false; + size_t input_tensor_index_{}; +}; + +// Initially, oneDNN Graph also used to have blocked layout for tensors between +// partitions, and the LlgaTensorImpl wrapper helped us bypass guard checks. +// oneDNN Graph has switched over to using strided tensors between partitions, +// but this wrapper still helps us bypass guard checks because the strides of +// tensors between partitions would be different from the ones the guard is +// otherwise expecting. +struct TORCH_API LlgaTensorImpl : public c10::TensorImpl { + LlgaTensorImpl( + at::Storage&& storage, + const caffe2::TypeMeta& data_type, + const LlgaTensorDesc& desc); + + const LlgaTensorDesc& desc() const { + return desc_; + } + + static at::Tensor llga_to_aten_tensor(LlgaTensorImpl* llgaImpl); + + private: + LlgaTensorDesc desc_; +}; + +at::Tensor empty_llga( + const LlgaTensorDesc& desc, + const c10::TensorOptions& options); + +dnnl::graph::tensor llga_from_aten_tensor(const at::Tensor& tensor); + +} // namespace torch::jit::fuser::onednn + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/decompose_silu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/decompose_silu.h new file mode 100644 index 0000000000000000000000000000000000000000..24d20864e42cd77fa0540f8eb6378962af11f52c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/decompose_silu.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit::fuser::onednn { + +void DecomposeSiluForLLGA(std::shared_ptr& graph); + +} // namespace torch::jit::fuser::onednn + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/defer_size_check.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/defer_size_check.h new file mode 100644 index 0000000000000000000000000000000000000000..0bb55003e88bb6c9d7b484ed761540a12a48e99a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/defer_size_check.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit::fuser::onednn { + +void DeferSizeCheck(std::shared_ptr& graph); + +} // namespace torch::jit::fuser::onednn + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/graph_fuser.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/graph_fuser.h new file mode 100644 index 0000000000000000000000000000000000000000..8f14c5e33a9b3ac58392caaddb6b620c3444fc33 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/graph_fuser.h @@ -0,0 +1,52 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::jit::fuser::onednn { + +struct WorkBlock : public std::pair { + using pair::pair; + + Node* begin() { + return this->first; + } + Node* end() { + return this->second; + } +}; + +class GraphRewriter { + public: + GraphRewriter(Block* block, std::shared_ptr graph, AliasDb& aliasDb) + : block_(block), + graph_(std::move(graph)), + aliasDb_(aliasDb), + llgaHelper_(graph_) {} + + void cleanupSubgraphs(); + void buildupSubgraphs(); + + private: + Block* block_; + std::shared_ptr graph_; + AliasDb& aliasDb_; + LlgaGraphHelper llgaHelper_; + std::vector buildWorkBlocks(); + std::pair scanNode( + Node* consumer, + graph_node_list::iterator workblock_begin); + std::optional tryMerge(Node* consumer, Node* producer); +}; + +// This pass creates the subgraphs for oneDNN Graph Fusion Nodes. +// Its code-structure has been vastly inspired from +// torch/csrc/jit/passes/create_autodiff_subgraphs.cpp +void CreateLlgaSubgraphs(std::shared_ptr& graph); + +} // namespace torch::jit::fuser::onednn + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/graph_helper.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/graph_helper.h new file mode 100644 index 0000000000000000000000000000000000000000..582db7e71cf4856f2710c8e5aefe19b4383f957f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/graph_helper.h @@ -0,0 +1,103 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +namespace torch::jit::fuser::onednn { + +#define STRIDED_LAYOUT 0 +#define OPAQUE_LAYOUT 1 + +struct OpPartitionMap { + void add(uint64_t opId, uint64_t partitionId) { + opmap_[opId] = partitionId; + } + void add(Node* n, uint64_t partitionId) { + add(Operator::getId(n), partitionId); + } + bool has(uint64_t opId) { + return opmap_.count(opId) > 0; + } + bool has(Node* n) { + return has(Operator::getId(n)); + } + uint64_t get(uint64_t opId) { + return opmap_[opId]; + } + uint64_t get(Node* n) { + auto opId = Operator::getId(n); + TORCH_CHECK( + has(opId), + "Node ", + n->kind().toQualString(), + " does not belong to any LLGA partition"); + return get(opId); + } + + private: + std::unordered_map opmap_; +}; + +class LlgaGraphHelper { + public: + LlgaGraphHelper( + const std::shared_ptr& graph, + dnnl::graph::partition::policy policy = + dnnl::graph::partition::policy::fusion); + + bool shouldMerge(Node* toMerge, Node* subgraph); + + bool shouldConsiderForMerge(Node* node); + + bool checkForSingleOpPartition(Node* node); + + Node* createSingletonSubgraph(Node* n, AliasDb& db); + + void mergeNodeIntoSubgraph(Node* toMerge, Node* subgraphNode, AliasDb& db); + + void unmergeIfAnyNodeIsMissing(Node* subgraphNode); + + static bool isLlgaSubgraph(const Node* node); + + Operator makeEltwiseOp(Node* node, dnnl::graph::op::kind kind); + + Operator makeBinaryOp(Node* node, dnnl::graph::op::kind kind); + + std::vector getPartitions() const; + + std::map getTensorIdToValue() const; + + Operator createOperator(Node* node); + + private: + size_t countSupportedOps(const std::shared_ptr& graph) const; + std::unique_ptr dnnl_graph_ = nullptr; + std::unique_ptr aliasDb_ = nullptr; + OpPartitionMap opToOwningPartition_; + std::vector partitions_; + std::map + tensorIdToValue_; // map from tensorId to torch::jit::Value +}; + +class LlgaNodeWrapper { + public: + LlgaNodeWrapper(const Node* node); + + void setOpaqueLayout(size_t offset); + + bool useOpaqueLayout(size_t offset) const; + + friend class LlgaGraphHelper; + + private: + Node* n; +}; + +} // namespace torch::jit::fuser::onednn + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/guard_shape.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/guard_shape.h new file mode 100644 index 0000000000000000000000000000000000000000..73ca360ff573d42805ce3d65f350d9f5f8c9433f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/guard_shape.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit::fuser::onednn { + +void prepareFusionGroupAndGuardOutputs(Block* block); + +} // namespace torch::jit::fuser::onednn + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/interface.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/interface.h new file mode 100644 index 0000000000000000000000000000000000000000..68cc22c7d582f3589ab429c621424d86d73ae30d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/interface.h @@ -0,0 +1,63 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include + +namespace torch::jit { +namespace fuser::onednn { + +static std::atomic onednn_enabled{false}; + +static std::atomic& getLlgaEnabled() { + return onednn_enabled; +} + +C10_EXPORT void fuseGraph(std::shared_ptr& g); + +} // namespace fuser::onednn + +struct C10_EXPORT RegisterLlgaFuseGraph + : public PassManager { + static bool setEnabled(bool enabled) { + TORCH_CHECK( + AT_MKLDNN_ENABLED(), + "Running oneDNN Graph fuser is only supported with MKLDNN builds."); + bool oldState = fuser::onednn::getLlgaEnabled(); + fuser::onednn::getLlgaEnabled() = enabled; + if (enabled) { + registerPass(fuser::onednn::fuseGraph); + } else { + clearPass(); + } + return oldState; + } + + static bool isEnabled() { + return fuser::onednn::getLlgaEnabled(); + } + + // override PassManager::registerPass to register pre-pass + static bool registerPass(GraphPass p) { + if (!isRegistered()) { + passID(registerPrePass(std::move(p)), true); + isRegistered(true); + return false; + } + return true; + } + + // override PassManager::clearPass to clear pre-pass + static void clearPass() { + if (isRegistered()) { + clearPrePass(passID()); + isRegistered(true); + } + } +}; + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/kernel.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..f2b358fed94ea1697fb2c5be46f1fb30d42eca75 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/kernel.h @@ -0,0 +1,94 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include + +namespace torch::jit::fuser::onednn { + +using ArgSpec = LlgaTensorDesc; +using ArgSpecs = std::vector; +using RunArg = dnnl::graph::tensor; +using RunArgs = std::vector; +using TensorArgs = std::vector; + +class LlgaKernel { + public: + explicit LlgaKernel(const Node* fusionNode); + + void run(Stack& stack); + + void initialize(const TensorArgs& inputs); + + const std::string& debugName() const { + return debugName_; + } + + private: + bool useOpaqueLayout(size_t offset) const; + + // PyTorch copy constants inside the subgraph instead of referencing them. + // Constants inputs to the partition are no longer in the graph->inputs(). + // Need use the tid retrieved from the partition to find the missing + // constant inputs. + void initializeConstantInputs(); + + ArgSpecs initializeInputSpecs(const TensorArgs& inputs); + + ArgSpecs initializeOutputSpecs() const; + + dnnl::graph::compiled_partition compile( + const dnnl::graph::partition& partition); + + std::map initializeTensorIdToOccurrence() const; + + std::tuple prepareRunArgs( + const TensorArgs& inputs, + TensorArgs& outputs) const; + + static std::string genDebugName() { + static size_t debugId = 0; + return "LlgaPartition_" + std::to_string(debugId++); + } + + static dnnl::graph::logical_tensor toLogicalTensor(const ArgSpec& s) { + return s.logical_tensor(); + } + + at::Device device_ = at::kCPU; + const Node* fusionNode_; + std::shared_ptr graph_; + int64_t nGraphInputs_ = 0; // number of inputs to graph_ on the IR + int64_t nOutputs_ = 0; + std::map tensorIdToValue_; + std::vector runArgsIdx_; + dnnl::graph::partition partition_; + // nPartitionInputs_ is the actual number of inputs to partition_ of graph_ + // needed by the backend. + // nPartitionInputs_ = nGraphInputs_ + constantInputs_.size() since Constant + // inputs are copied to the inside of the subgraph + int64_t nPartitionInputs_; + dnnl::graph::compiled_partition compilation_; + std::set initializedInputIds_; + std::vector constantValues_; + TensorArgs constantInputs_; + ArgSpecs inputSpecs_; + ArgSpecs outputSpecs_; + std::vector constantLogicalTensors_; + std::string debugName_; + c10::once_flag initialized_flag; + bool is_initialized_ = false; +}; + +} // namespace torch::jit::fuser::onednn + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/layout_propagation.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/layout_propagation.h new file mode 100644 index 0000000000000000000000000000000000000000..a654d8e7d15afb46e8c142d1f918ade6a1d20770 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/layout_propagation.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit::fuser::onednn { + +void PropagateLayout(const std::shared_ptr& graph); + +} // namespace torch::jit::fuser::onednn + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/operator.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/operator.h new file mode 100644 index 0000000000000000000000000000000000000000..ab289941e48a7087b30ae65efb9e1da3be51baab --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/operator.h @@ -0,0 +1,151 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace torch::jit::fuser::onednn { + +class Operator { + public: + Operator(const Node* node, dnnl::graph::op::kind kind) + : n(node), o(getId(node), kind, node->kind().toQualString()), k(kind) {} + + // Returns output index if the Value is a graph output. + // Otherwise returns -1 + int32_t graphOutputIdx(Value* v) { + int32_t i = 0; + for (const Value* output : v->owningGraph()->outputs()) { + if (v == output) { + return i; + } + i++; + } + return -1; + } + + Operator& setInputValue(Value* v) { + if (v->mustNotBeNone()) { + if (v->type()->kind() == c10::TensorType::Kind) { + o.add_input(createLogicalTensor(v)); + } + } + return *this; + } + + Operator& setInput(size_t offset) { + return setInputValue(n->input(offset)); + } + + template + Operator& setInput(size_t offset, Ts... other) { + setInput(offset); + return setInput(other...); + } + + Operator& setOutputValue(Value* v) { + if (v->mustNotBeNone()) { + o.add_output(createLogicalTensor(v)); + } + return *this; + } + + // setOutputValue & setOutput require a pointer to the LLGA graph, as output + // logical tensors that are graph outputs should be connected to an End LLGA + // op. A value of NULL can be provided for the graph pointer in order to + // maintain the legacy functionality of this function. + Operator& setOutputValue(Value* v, std::unique_ptr& g) { + if (v->mustNotBeNone()) { + auto output_tensor = createLogicalTensor(v); + o.add_output(output_tensor); + if (g) { + int32_t outputIndex = graphOutputIdx(v); + if (outputIndex != -1) { + dnnl::graph::op newEndNode( + LONG_MAX - outputIndex, + dnnl::graph::op::kind::End, + "EndNodeForGraphOutput"); + newEndNode.add_input(output_tensor); + g->add_op(newEndNode); + } + } + } + return *this; + } + + Operator& setOutput(std::unique_ptr& g, size_t offset) { + return setOutputValue(n->output(offset), g); + } + + Operator& setOutput(size_t offset) { + return setOutputValue(n->output(offset)); + } + + template + Operator& setOutput( + std::unique_ptr& g, + size_t offset, + Ts... other) { + setOutput(g, offset); + return setOutput(g, other...); + } + + template + Operator& setAttr(dnnl::graph::op::attr name, Attr&& attr) { + o.set_attr(name, std::forward(attr)); + return *this; + } + + template + Operator& setAttr(dnnl::graph::op::attr name, const F& fn, size_t offset) { + return setAttr(name, fn(n, offset)); + } + + static float ScalarToFloat(const Node* node, size_t offset) { + return toIValue(node->input(offset))->toScalar().to(); + } + + static std::vector Ints(const Node* node, size_t offset) { + return toIValue(node->input(offset))->toIntVector(); + } + + static int64_t Int(const Node* node, size_t offset) { + return toIValue(node->input(offset))->toInt(); + } + + static float Float(const Node* node, size_t offset) { + return static_cast(toIValue(node->input(offset))->toDouble()); + } + + static bool Bool(const Node* node, size_t offset) { + return toIValue(node->input(offset))->toBool(); + } + + static uint64_t getId(const Node* node) { + return reinterpret_cast(node); // cast node address as op id + } + + dnnl::graph::op::kind kind() const { + return k; + } + + dnnl::graph::op llgaOp() const { + return o; + } + + private: + dnnl::graph::logical_tensor createLogicalTensor(Value* value) const { + return LlgaTensorDesc(value).logical_tensor(); + } + + const Node* n; + dnnl::graph::op o; + dnnl::graph::op::kind k; +}; + +} // namespace torch::jit::fuser::onednn + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/prepare_binary.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/prepare_binary.h new file mode 100644 index 0000000000000000000000000000000000000000..7e46d4d447b4922e96b66dbbf32b8d011af7cbae --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/codegen/onednn/prepare_binary.h @@ -0,0 +1,25 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit::fuser::onednn { + +// Prepare binary ops for LLGA +// +// The pass does the following: +// +// - Convert scalar input of aten::add and aten::mul into Float tensor with +// dimension [1] +// +// - Decompose fused add into aten::mul + aten::add when alpha != 1.0 +// +// - Eliminate identity add/mul, i.e., tensor + 0, tensor * 1 +// +void PrepareBinaryForLLGA(const std::shared_ptr& graph); + +} // namespace torch::jit::fuser::onednn + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/cuda/cuda.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/cuda/cuda.h new file mode 100644 index 0000000000000000000000000000000000000000..ff30c27553f68809ee4008c5c94c87d80c139042 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/cuda/cuda.h @@ -0,0 +1,184 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include +#include +#include +#include + +namespace torch::jit { + +class CUDAEvent; +// This class is a wrapper around c10::cuda::CUDAStream. +// It is needed because TorchBind does not support all of the argument types +// for c10::cuda::CUDAStream. For more details, please refer to +// c10/cuda/CUDAStream.h. +class CUDAStream final : public CustomClassHolder { + public: + CUDAStream( + std::optional device = std::nullopt, + int64_t priority = 0) { + c10::DeviceIndex device_index = + device.has_value() ? device->index() : c10::cuda::current_device(); + stream_ = std::make_unique( + c10::cuda::getStreamFromPool(static_cast(priority), device_index)); + } + + CUDAStream(c10::cuda::CUDAStream s) { + stream_ = std::make_unique(s); + } + + bool query() { + return stream_->query(); + } + + c10::intrusive_ptr recordEvent( + c10::intrusive_ptr event); + + void synchronize() { + stream_->synchronize(); + } + + void waitEvent(const c10::intrusive_ptr& event); + + void waitStream(const c10::intrusive_ptr& stream); + + /// Get the CUDA device index that this stream is associated with. + int64_t device_index() const { + return stream_->device_index(); + } + + /// Get the full Device that this stream is associated with. The Device + /// is guaranteed to be a CUDA device. + c10::Device device() const { + return stream_->device(); + } + + /// Return the stream ID corresponding to this particular stream. + int64_t id() const { + return stream_->id(); + } + + private: + std::unique_ptr stream_; + friend class CUDAEvent; +}; + +// This class is a wrapper around at::cuda::CUDAStream. +// It is needed because TorchBind does not support all of the argument types +// for at::cuda::CUDAEvent. For more details, please refer to +// aten/src/ATen/cuda/CUDAEvent.h. +class CUDAEvent final : public CustomClassHolder { + public: + CUDAEvent( + bool enable_timing = false, + bool blocking = false, + bool interprocess = false) { + int flags = cudaEventDisableTiming; + if (enable_timing) { + flags = cudaEventDefault; + } + if (blocking) { + flags |= cudaEventBlockingSync; + } + if (interprocess) { + TORCH_CHECK(!enable_timing); + flags |= cudaEventInterprocess; + } + + event_ = std::make_unique(flags); + } + + double elapsedTime(const c10::intrusive_ptr& end) { + return event_->elapsed_time(*end->event_); + } + + std::string ipcHandle() { + cudaIpcEventHandle_t handle{}; + event_->ipc_handle(&handle); + std::string str_handle((const char*)&handle, sizeof(handle)); + return str_handle; + } + + bool query() { + return event_->query(); + } + + void record(const c10::intrusive_ptr& stream); + + void synchronize() { + event_->synchronize(); + } + void wait(const c10::intrusive_ptr& stream); + + private: + void recordInternal(CUDAStream* stream); + std::unique_ptr event_; + + friend class CUDAStream; +}; + +inline c10::intrusive_ptr CUDAStream::recordEvent( + c10::intrusive_ptr event) { + if (!event) { + event = c10::make_intrusive(); + } + + event->recordInternal(this); + return event; +} + +inline void CUDAStream::waitEvent(const c10::intrusive_ptr& event) { + event->event_->block(*stream_); +} + +inline void CUDAStream::waitStream( + const c10::intrusive_ptr& stream) { + auto ev = c10::make_intrusive(); + stream->recordEvent(ev); + waitEvent(ev); +} + +inline void CUDAEvent::record(const c10::intrusive_ptr& stream) { + event_->record(*stream->stream_); +} + +inline void CUDAEvent::recordInternal(CUDAStream* stream) { + event_->record(*stream->stream_); +} + +inline void CUDAEvent::wait(const c10::intrusive_ptr& stream) { + event_->block(*stream->stream_); +} + +TORCH_LIBRARY(cuda, m) { + auto stream_class = m.class_("Stream").def( + torch::init, int64_t>(), + "", + {torch::arg("device") = std::nullopt, torch::arg("priority") = 0}); + auto event_class = m.class_("Event").def( + torch::init(), + "", + {torch::arg("enable_timing") = false, + torch::arg("blocking") = false, + torch::arg("interprocess") = false}); + + stream_class.def("query", &CUDAStream::query) + .def("record_event", &CUDAStream::recordEvent) + .def("synchronize", &CUDAStream::synchronize) + .def("wait_event", &CUDAStream::waitEvent) + .def("wait_stream", &CUDAStream::waitStream) + .def("device_index", &CUDAStream::device_index) + .def_property("device", &CUDAStream::device) + .def("id", &CUDAStream::id); + + event_class.def("elapsed_time", &CUDAEvent::elapsedTime) + .def("query", &CUDAEvent::query) + .def("record", &CUDAEvent::record) + .def("synchronize", &CUDAEvent::synchronize) + .def("wait", &CUDAEvent::wait); +} + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/builtin_functions.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/builtin_functions.h new file mode 100644 index 0000000000000000000000000000000000000000..ed412b4acd8d06928e751733ec40f109863fb149 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/builtin_functions.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::jit { + +TORCH_API const std::vector& getAllBuiltinFunctionsFor(Symbol name); +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/canonicalize_modified_loop.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/canonicalize_modified_loop.h new file mode 100644 index 0000000000000000000000000000000000000000..3dc39e392a8954600332b8e79ddf0a0e6a7b6a2f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/canonicalize_modified_loop.h @@ -0,0 +1,19 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include + +#include + +namespace torch::jit { + +struct Graph; + +// Transforms loops so that they can be represented as python +// for or while loops +TORCH_API void CanonicalizeModifiedLoops(std::shared_ptr& graph); + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/concrete_module_type.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/concrete_module_type.h new file mode 100644 index 0000000000000000000000000000000000000000..65e0aff09acc68c5c93d6078d9ccc58bef79ad00 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/concrete_module_type.h @@ -0,0 +1,244 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace torch::jit { + +enum class IterableModuleKind { NONE, LIST, DICT, PARAMLIST, PARAMDICT }; +class ConcreteModuleType; + +// You can think of an nn.Module as a template that corresponds to a family of +// JIT types. The template "arguments" are things like the constant values. +// e.g. +// class M(nn.Module): +// __constants__ = ["const"] +// ... +// +// Is similar to writing the following in C++: +// +// template +// class M { +// ... +// } +// +// We need to consider each different member of the type family a different JIT +// type because, e.g. different constant values lead to different versions of +// the same method. +// +// ConcreteModuleType corresponds to a single member of the type family, with +// all template arguments fully specified. Two Modules that share a +// ConcreteModuleType can share a JIT type, and vice versa. +// +// Why not just use a JIT type to represent concrete types? Because constants, +// function attributes, etc. are currently not representable in the type system, +// so this acts a non-first-class way of tracking concrete types. +// +// ConcreteModuleType is also the source of truth for servicing all +// ModuleValue::attr calls. This is so we can guarantee that if two Module's +// share a JIT type (and thus a ConcreteModuleType), then they behave the same +// way when you access attributes on them. + +// ConcreteModuleType has two phases. +// 1. Creation: First we build it up, during the ScriptModule conversion +// process. This is represented by ConcreteModuleTypeBuilder. +// ...then the converter calls ConcreteModuleTypeBuilder::build(), producing +// a +// ConcreteModuleType ready for querying. +// 2. Querying: We use ConcreteModuleType as a source of truth for +// ModuleValue::attr calls during method compilation. + +// Represents a concrete type during in the process for construction. We use +// this to decide whether we can share types between modules. +class VISIBILITY_HIDDEN ConcreteModuleTypeBuilder { + public: + explicit ConcreteModuleTypeBuilder(py::object pyClass) { + TORCH_INTERNAL_ASSERT(pyClass); + pyClass_ = std::move(pyClass); + } + + void addConstant(std::string name, py::object value); + void addConstant(std::string name, IValue value); + void addAttribute( + std::string name, + const TypePtr& type, + bool isParameter, + bool isBuffer); + void addFunctionAttribute( + std::string name, + const TypePtr& type, + py::object pyFunction); + + void addModule(std::string name, std::shared_ptr meta); + + void addForwardHook(py::object hook); + void addForwardPreHook(py::object pre_hook); + + void addOverload( + std::string methodName, + std::vector overloadedMethodNames); + void addBuiltinFunction(std::string name, const std::string& symbol_name); + void addFailedAttribute(std::string name, std::string failureReason); + void addIgnoredAttribute(std::string name); + void setIterableModuleKind(IterableModuleKind kind); + + // If a ConcreteModuleType is poisoned, it will never compare equal to any + // other concrete type + void setPoisoned(); + + std::shared_ptr build() const { + return std::make_shared(*this); + } + + // This determines whether two modules can share a type. The container structs + // used by ConcreteModuleType have been defined such that operator== + // implements a meaningful comparison in that context. + bool equals(const ConcreteModuleTypeBuilder& other) const; + + struct FunctionAttribute { + FunctionTypePtr function_; + py::object pyFunction_; + + friend bool operator==( + const FunctionAttribute& lhs, + const FunctionAttribute& rhs) { + // Functions are not first class, so we can't do type comparison like a + // regular attribute. So we do a pointer equality check on the actual + // Python function object. + return lhs.pyFunction_.is(rhs.pyFunction_); + } + }; + + struct Attribute { + Attribute(TypePtr type, bool isParam, bool isBuffer) + : type_(std::move(type)), isParam_(isParam), isBuffer_(isBuffer) {} + + friend bool operator==(const Attribute& lhs, const Attribute& rhs) { + return *(lhs.type_) == *(rhs.type_) && lhs.isParam_ == rhs.isParam_; + } + TypePtr type_; + bool isParam_; + bool isBuffer_; + }; + + struct ModuleInfo { + ModuleInfo(std::string name, std::shared_ptr meta) + : name_(std::move(name)), meta_(std::move(meta)) {} + + friend bool operator==(const ModuleInfo& lhs, const ModuleInfo& rhs); + + std::string name_; + std::shared_ptr meta_; + }; + + private: + ConcreteModuleTypeBuilder() = default; + ClassTypePtr createTypeFromThis() const; + + // If true, this type will never compare equally to anything else. This is + // used if we want to ensure that this type is not shared (for example, if it + // came from a traced module) + bool isPoisoned_ = false; + + // The value of any constants defined by the module. + std::unordered_map constants_; + // The types of any attributes + OrderedDict attributes_; + // Overloads, in the same format as `__overloads__` in Python + std::unordered_map> overloads_; + // Any attributes we failed to convert to TorchScript, along with a hint as to + // why + std::unordered_map failedAttributes_; + // Any attributes that were marked as ignored. They cannot be used in + // TorchScript but can still be used in ignored function in Python. + std::unordered_set ignoredAttributes_; + // Any function attributes. These are special right now because functions are + // not first-class in the type system. + std::unordered_map functionAttributes_; + // Function attributes that are calls to builtin functions. These get + // de-sugared directly into the corresponding aten:: call. The map is + // attribute name -> aten symbol name + std::unordered_map builtinFunctions_; + // The concrete types of any submodules + std::vector modules_; + // Hooks to be called before/after forward when the module + // is called directly. Used to ensure modules have different types + // when they have different python hooks + // Actual hooks are added to ClassType directly during compilation + std::vector forwardHooks_; + std::vector forwardPreHooks_; + + // If something is a ModuleDict/ModuleList, it means: + // 1. The order of the submodules matters for comparing the type + // 2. The compiler is allowed to treat it like a dict/tuple + IterableModuleKind iterableModuleKind_ = IterableModuleKind::NONE; + + // The original `nn.Module` class that we derived this ScriptModule from. + py::object pyClass_; + + // NOTE: If you ever add any more state to this struct, you need to make sure + // operator== still makes sense! + friend ConcreteModuleType; +}; + +// Represents a finalized concrete type, used to service ModuleValue::attr calls +// during method compilation. +class VISIBILITY_HIDDEN ConcreteModuleType { + public: + explicit ConcreteModuleType(ConcreteModuleTypeBuilder data); + + static std::shared_ptr fromJitType(TypePtr type); + + TypePtr getJitType() const; + std::optional getPyClass() const; + IterableModuleKind getIterableModuleKind() const; + std::optional> findOverloads( + const std::string& name) const; + std::optional findFunctionAttribute(const std::string& name) const; + std::optional findBuiltinFunction(const std::string& name) const; + std::shared_ptr findSubmoduleConcreteType( + const std::string& name) const; + std::optional findFailedAttribute(const std::string& name) const; + bool isIgnoredAttribute(const std::string& name) const; + + // These getters are only here to return things as types that can be + // automatically converted by pybind. + std::unordered_map getConstantsPy() const; + std::unordered_map> getAttributesPy() + const; + std::vector>> + getModulesPy() const; + + bool equals(const ConcreteModuleType& other) const { + if (jitType_ == other.jitType_) { + // If the computed types are the same, these modules can (obviously) share + // a type. + return true; + } + + return data_.equals(other.data_); + } + bool equals(const ConcreteModuleTypeBuilder& other) const { + return data_.equals(other); + } + + void dump() const; + + private: + ConcreteModuleType() = default; + + // The JIT type derived from this ConcreteModuleType. + ConcreteModuleTypeBuilder data_; + TypePtr jitType_; +}; + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/convert_to_ssa.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/convert_to_ssa.h new file mode 100644 index 0000000000000000000000000000000000000000..d9a3677aa2ef21c2e8a2ee0f35778832f9eb49e8 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/convert_to_ssa.h @@ -0,0 +1,19 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include + +#include +#include + +namespace torch::jit { + +// Convert a graph with Loads & Stores into SSA form +TORCH_API void ConvertToSSA(std::shared_ptr& graph); + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/edit_distance.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/edit_distance.h new file mode 100644 index 0000000000000000000000000000000000000000..711ddee3edd41e1c3e6c0ccccf5ab08c9bb8568b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/edit_distance.h @@ -0,0 +1,18 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::jit { + +TORCH_API size_t ComputeEditDistance( + const char* word1, + const char* word2, + size_t maxEditDistance); + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/error_report.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/error_report.h new file mode 100644 index 0000000000000000000000000000000000000000..041831252736664f16f0547d34e27e2fa6175942 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/error_report.h @@ -0,0 +1,92 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::jit { + +struct Call { + std::string fn_name; + SourceRange caller_range; +}; + +struct TORCH_API ErrorReport : public std::exception { + ErrorReport(const ErrorReport& e); + + explicit ErrorReport(const SourceRange& r); + explicit ErrorReport(const TreeRef& tree) : ErrorReport(tree->range()) {} + explicit ErrorReport(const Token& tok) : ErrorReport(tok.range) {} + + const char* what() const noexcept override; + + class TORCH_API Calls { + private: + std::vector calls_; + mutable std::mutex mutex_; + + public: + void push_back(Call call) { + std::lock_guard lock(mutex_); + calls_.push_back(std::move(call)); + } + + void pop_back() { + std::lock_guard lock(mutex_); + calls_.pop_back(); + } + + bool empty() const { + std::lock_guard lock(mutex_); + return calls_.empty(); + } + + void update_pending_range(const SourceRange& range) { + std::lock_guard lock(mutex_); + calls_.back().caller_range = range; + } + + std::vector get_stack() const { + std::lock_guard lock(mutex_); + return calls_; + } + }; + + struct TORCH_API CallStack { + // These functions are used to report why a function was being compiled + // (i.e. what was the call stack of user functions at compilation time that + // led to this error) + CallStack(const std::string& name, const SourceRange& range); + ~CallStack(); + + // Change the range that is relevant for the current function (i.e. after + // each successful expression compilation, change it to the next expression) + static void update_pending_range(const SourceRange& range); + + private: + std::shared_ptr source_callstack_; + }; + + static std::string current_call_stack(); + + private: + template + friend const ErrorReport& operator<<(const ErrorReport& e, const T& t); + + mutable std::stringstream ss; + OwnedSourceRange context; + mutable std::string the_message; + std::vector error_stack; +}; + +template +const ErrorReport& operator<<(const ErrorReport& e, const T& t) { + e.ss << t; + return e; +} + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/exit_transforms.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/exit_transforms.h new file mode 100644 index 0000000000000000000000000000000000000000..c33e7cb04d7c6cbc3e330f61b6af9ee90b72d8b2 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/exit_transforms.h @@ -0,0 +1,15 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::jit { + +TORCH_API void TransformExits(std::shared_ptr& graph); + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/function_schema_parser.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/function_schema_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..2626cfb7f96042a67194589f4f5a47a214bd2113 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/function_schema_parser.h @@ -0,0 +1,28 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +namespace torch::jit { + +// allow_typevars: If true, we assume that lowercase types that we don't +// understand are type variables. This is only needed for TorchScript (and not +// not needed for custom ops). +// If false, we disallow typevars, except in certain cases for BC reason (i.e. +// your op is in the aten or prim namespace). +TORCH_API std::variant parseSchemaOrName( + const std::string& schemaOrName, + bool allow_typevars = true); +TORCH_API c10::FunctionSchema parseSchema( + const std::string& schema, + bool allow_typevars = true); +TORCH_API c10::OperatorName parseName(const std::string& name); + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/inline_loop_condition.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/inline_loop_condition.h new file mode 100644 index 0000000000000000000000000000000000000000..6dba54dc8a69cc489da51be53469538908f4b849 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/inline_loop_condition.h @@ -0,0 +1,19 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include + +#include +#include + +namespace torch::jit { + +TORCH_API void InlineLoopCondition(std::shared_ptr& graph); +TORCH_API void InlineBlockBeforeNode(Node* before_node, Block* block); + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/ir_emitter.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/ir_emitter.h new file mode 100644 index 0000000000000000000000000000000000000000..4e723618bab2d7f129dcd3a40f11d00237f66d2d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/ir_emitter.h @@ -0,0 +1,24 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace torch::jit { + +TORCH_API void runCleanupPasses(std::shared_ptr& to_clean); + +TORCH_API bool meaningfulName(const std::string& name); + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/lexer.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/lexer.h new file mode 100644 index 0000000000000000000000000000000000000000..d99be3ca74a0c21f9b0b284c19f6a462b194c937 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/lexer.h @@ -0,0 +1,568 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace torch::jit { + +// single character tokens are just the character itself '+' +// multi-character tokens need an entry here +// if the third entry is not the empty string, it is used +// in the lexer to match this token. + +// These kinds are also used in Tree.h as the kind of the AST node. +// Some kinds TK_APPLY, TK_LIST are only used in the AST and are not seen in the +// lexer. + +#define TC_FORALL_TOKEN_KINDS(_) \ + _(TK_EOF, "eof", "") \ + _(TK_WHITESPACE, "whitespace", "") \ + _(TK_WHITESPACE_EOF, "whitespace_eof", "") \ + _(TK_NUMBER, "number", "") \ + _(TK_NEWLINE, "newline", "") \ + _(TK_INDENT, "indent", "") \ + _(TK_DEDENT, "dedent", "") \ + _(TK_DEF, "def", "def") \ + _(TK_EQUIVALENT, "equivalent", "<=>") \ + _(TK_IDENT, "ident", "") \ + _(TK_STRING, "string", "") \ + _(TK_STRINGLITERAL, "string_literal", "") \ + _(TK_CONST, "const", "") \ + _(TK_LIST, "list", "") \ + _(TK_DICT, "dict", "") \ + _(TK_OPTION, "option", "") \ + _(TK_APPLY, "apply", "") \ + _(TK_COMPREHENSION, "comprehension", "") \ + _(TK_RANGE_CONSTRAINT, "range_constraint", "") \ + _(TK_PARAM, "param", "") \ + _(TK_INFERRED, "inferred", "") \ + _(TK_ACCESS, "access", "") \ + _(TK_ASSIGN, "assign", "") \ + _(TK_AUG_ASSIGN, "aug_assign", "") \ + _(TK_ATTRIBUTE, "attribute", "") \ + _(TK_IF, "if", "if") \ + _(TK_ELSE, "else", "else") \ + _(TK_ELIF, "elif", "elif") \ + _(TK_WHILE, "while", "while") \ + _(TK_EXPR_STMT, "expression statement", "") \ + _(TK_RETURN, "return", "return") \ + _(TK_IS, "is", "is") \ + _(TK_ISNOT, "is not", "is not") \ + _(TK_NE, "ne", "!=") \ + _(TK_EQ, "eq", "==") \ + _(TK_LE, "le", "<=") \ + _(TK_GE, "ge", ">=") \ + _(TK_FLOOR_DIV, "floordiv", "//") \ + _(TK_IF_EXPR, "if", "") \ + _(TK_TRUE, "True", "True") \ + _(TK_FALSE, "False", "False") \ + _(TK_NONE, "None", "None") \ + _(TK_AND, "and", "and") \ + _(TK_OR, "or", "or") \ + _(TK_NOT, "not", "not") \ + _(TK_LSHIFT, "<<", "<<") \ + _(TK_RSHIFT, ">>", ">>") \ + _(TK_CAST, "cast", "") \ + _(TK_PLUS_EQ, "+=", "+=") \ + _(TK_MINUS_EQ, "-=", "-=") \ + _(TK_TIMES_EQ, "*=", "*=") \ + _(TK_DIV_EQ, "/=", "/=") \ + _(TK_MOD_EQ, "%=", "%=") \ + _(TK_BIT_OR_EQ, "|=", "|=") \ + _(TK_BIT_AND_EQ, "&=", "&=") \ + _(TK_BIT_XOR_EQ, "^=", "^=") \ + _(TK_LSHIFT_EQ, "<<=", "<<=") \ + _(TK_RSHIFT_EQ, ">>=", ">>=") \ + _(TK_POW_EQ, "**=", "**=") \ + _(TK_GLOBAL, "global", "global") \ + _(TK_BUILT_IN, "built-in", "") \ + _(TK_SUBSCRIPT, "subscript", "") \ + _(TK_VAR, "variable", "") \ + _(TK_NOTHING, "nothing", "") \ + _(TK_DICT_LITERAL, "dict-literal", "") \ + _(TK_LIST_LITERAL, "list-literal", "") \ + _(TK_TUPLE_LITERAL, "tuple-literal", "") \ + _(TK_FOR, "for", "for") \ + _(TK_IN, "in", "in") \ + _(TK_NOTIN, "not in", "not in") \ + _(TK_STARRED, "starred", "") \ + _(TK_UNARY_MINUS, "unary minus", "") \ + _(TK_POW, "pow operator", "**") \ + _(TK_ARROW, "arrow", "->") \ + _(TK_DECL, "decl", "") \ + _(TK_SLICE_EXPR, "slice expr", "") \ + _(TK_TYPE_COMMENT, "type comment", "# type:") \ + _(TK_RAISE, "raise", "raise") \ + _(TK_ASSERT, "assert", "assert") \ + _(TK_DOTS, "dots", "...") \ + _(TK_LIST_COMP, "list comprehension", "") \ + _(TK_DICT_COMP, "dict comprehension", "") \ + _(TK_BREAK, "break", "break") \ + _(TK_CONTINUE, "continue", "continue") \ + _(TK_DELETE, "del", "del") \ + _(TK_PASS, "pass", "pass") \ + _(TK_CLASS_DEF, "class", "class") \ + _(TK_IMPORT, "import", "import") \ + _(TK_WITH, "with", "with") \ + _(TK_WITH_ITEM, "withitem", "") \ + _(TK_AS, "as", "as") \ + _(TK_PROP, "property", "") \ + _(TK_ELLIPSIS, "Ellipsis", "Ellipsis") \ + _(TK_NONE_TYPE, "NoneType", "NoneType") + +enum TokenKind { + // we use characters to represent themselves so skip all valid characters + // before + // assigning enum values to multi-char tokens. + TK_DUMMY_START = 256, +#define DEFINE_TOKEN(tok, _, _2) tok, + TC_FORALL_TOKEN_KINDS(DEFINE_TOKEN) +#undef DEFINE_TOKEN +}; + +TORCH_API std::string kindToString(int kind); +TORCH_API int stringToKind(const std::string& str); + +// nested hash tables that indicate char-by-char what is a valid token. +struct TokenTrie; +using TokenTrieRef = std::unique_ptr; +struct TokenTrie { + TokenTrie() = default; + void insert(const char* str, int tok) { + if (*str == '\0') { + AT_ASSERT(kind == 0); + kind = tok; + return; + } + + for (size_t i = 0, e = child_chars.size(); i < e; ++i) { + if (child_chars[i] == *str) { + child_tries[i]->insert(str + 1, tok); + return; + } + } + + child_chars.emplace_back(*str); + child_tries.emplace_back(std::make_unique()); + child_tries.back()->insert(str + 1, tok); + } + int kind{0}; // 0 == invalid token + + std::vector child_chars; + std::vector child_tries; +}; + +// stuff that is shared against all TC lexers/parsers and is initialized only +// once. +struct TORCH_API SharedParserData { + SharedParserData() : head(new TokenTrie()) { + for (const char* c = valid_single_char_tokens; *c; c++) { + std::string str(1, *c); + head->insert(str.c_str(), *c); + } + +#define ADD_CASE(tok, _, tokstring) \ + if (*(tokstring) != '\0') { \ + head->insert((tokstring), (tok)); \ + } + TC_FORALL_TOKEN_KINDS(ADD_CASE) +#undef ADD_CASE + } + + bool match( + StringCordView::Iterator pos, + bool continuation, // are we inside a scope where newlines don't count + // (e.g. inside parens) + bool whitespace_token, // should we treat whitespace as a token + int* kind, + StringCordView::Iterator* start, + StringCordView::Iterator* end) { + *start = pos; + // skip whitespace + while (pos.has_next() && isblank(*pos)) { + ++pos; + } + + // special handling + if (pos.has_next()) { + if (*pos == '#' && !isTypeComment(pos)) { + // skip comments + while (pos.has_next() && *pos != '\n') + ++pos; + // tail call, handle whitespace and more comments + return match(pos, continuation, whitespace_token, kind, start, end); + } + if (*pos == '\\') { + auto newiter = pos; + ++newiter; + if (newiter.has_next() && *newiter == '\n' && !whitespace_token) { + ++newiter; + return match(newiter, continuation, false, kind, start, end); + } + } + if (*pos == '\n') { + return match(++pos, continuation, !continuation, kind, start, end); + } + } + // we handle white space before EOF because in the case we have something + // like the following where we need to generate the dedent token if foo: + // ... + // else: + // pass + if (whitespace_token) { + *kind = !pos.has_next() ? TK_WHITESPACE_EOF : TK_WHITESPACE; + *end = pos; + return true; + } + if (!pos.has_next()) { + *kind = TK_EOF; + *start = pos; + *end = *start; + return true; + } + // invariant: the next token is not whitespace or newline + *start = pos; + // check for a valid number + size_t len = 0; + if (isNumber(pos.rest_line(), 0, &len)) { + *end = *start; + *end += len; + *kind = TK_NUMBER; + return true; + } + // check for string + if (isString(pos.rest_line(), 0, &len)) { + *kind = TK_STRINGLITERAL; + *end = *start; + *end += len; + return true; + } + + // check for either an ident or a token + // ident tracks whether what we have scanned so far could be an identifier + // matched indicates if we have found any match. + bool matched = false; + bool ident = true; + TokenTrie* cur = head.get(); + // for (size_t i = 0; pos + i < str.size() && (ident || cur != nullptr); + // i++) + for (size_t i = 0; pos.has_next() && (ident || cur != nullptr); + ++pos, ++i) { + ident = ident && validIdent(i, *pos); + if (ident) { + matched = true; + *end = pos.next_iter(); + *kind = TK_IDENT; + } + // check for token second, so that e.g. 'max' matches the token TK_MAX + // rather the + // identifier 'max' + if (cur) { + const auto begin_it = cur->child_chars.begin(); + const auto end_it = cur->child_chars.end(); + const auto ch_it = std::find(begin_it, end_it, *pos); + + cur = (ch_it == end_it) ? nullptr + : cur->child_tries[ch_it - begin_it].get(); + + if (cur && cur->kind != 0) { + matched = true; + *end = pos.next_iter(); + *kind = cur->kind; + } + } + } + return matched; + } + + bool isUnary(int kind, int* prec); + bool isBinary(int kind, int* prec); + bool isRightAssociative(int kind) { + switch (kind) { + case '?': + case TK_POW: + case TK_IF: + return true; + default: + return false; + } + } + + private: + bool validIdent(size_t i, char n) { + return isalpha(n) || n == '_' || (i > 0 && isdigit(n)); + } + + // 1. skip whitespace + // 2. handle comment or newline + // + bool isNumber(std::string_view str, size_t start, size_t* len) { + char first = str[start]; + // strtod allows numbers to start with + or - or nan or inf + // http://en.cppreference.com/w/cpp/string/byte/strtof + // but we want only the number part, otherwise 1+3 will turn into two + // adjacent numbers in the lexer + if (first == '-' || first == '+' || isalpha(first)) + return false; + const char* startptr = str.data() + start; + char* endptr = nullptr; + torch::jit::strtod_c(startptr, &endptr); + *len = endptr - startptr; + // check if the number is complex valued + // access is safe because string is assumed to be null terminated + if (endptr != nullptr && *endptr == 'j') { + *len += 1; + } + return *len > 0; + } + + bool isCharCount(char c, std::string_view str, size_t start, int len) { + // count checks from [start, start + len) + return start + len <= str.size() && + std::count(str.begin() + start, str.begin() + start + len, c) == len; + } + + // python concatenates all adjacent strings "a" "b" == "ab" + // strings can be enclosed with 1 or 3 single or double quotes + // if enclosed with 3 quotes newlines are valid + // as elsewhere, backslash and new line should be ignored + bool isString(std::string_view str, size_t start, size_t* len) { + char quote = str[start]; + if (quote != '\"' && quote != '\'') + return false; + int quote_len = isCharCount(quote, str, start, 3) ? 3 : 1; + + // end is now set past the opening quotation marks + size_t end = start + quote_len; + while (end < str.size() && !isCharCount(quote, str, end, quote_len)) { + if (str[end] == '\n' && quote_len != 3) { + return false; + } + // handle escaped characters. advances past escaped quotation marks, + // escaped newlines and escaped backslashes + // multi-char escapes like \x1A are handled fine here because the + // remainder of the escape are valid string characters anyway + if (str[end] == '\\') { + end++; + } + end++; + } + // set length equal to the complete string including quotations + *len = end - start + quote_len; + // if end finished without going past the last character of the string than + // there is a match + return end < str.size(); + } + + bool isblank(int n) { + return isspace(n) && n != '\n'; + } + + bool isTypeComment(StringCordView::Iterator str_iter) { + std::string_view rest_line = str_iter.rest_line(); + const std::string type_string = "# type:"; + if (rest_line.size() < type_string.length()) { + return false; + } + auto match_string = rest_line.substr(0, type_string.size()); + return match_string == type_string; + } + + // Make an exception ignoring comments for type annotation comments + bool isTypeComment(const StringCordView& str, size_t pos) { + const std::string type_string = "# type:"; + if (str.size() < pos + type_string.length()) { + return false; + } + auto match_string = str.substr(pos, type_string.size()); + return match_string == type_string; + } + + TokenTrieRef head; +}; + +TORCH_API SharedParserData& sharedParserData(); + +struct Token { + int kind; + SourceRange range; + Token(int kind, SourceRange range) : kind(kind), range(std::move(range)) {} + std::string text() const { + return std::string(range.token_text()); + } + + std::string_view text_view() const { + return range.token_text(); + } + + std::string kindString() const { + return kindToString(kind); + } +}; + +struct Lexer { + explicit Lexer(std::shared_ptr source) + : source(std::move(source)), shared(sharedParserData()) { + auto first_indent = lexRaw(true); + indent_stack.push_back(first_indent.range.size()); + lex(); + } + // Return the current token, and then move to the next one + Token next() { + if (next_tokens.empty()) + reportError("Lexer invariant violated: empty token queue"); + Token r = std::move(next_tokens.front()); + next_tokens.erase(next_tokens.begin()); + if (next_tokens.empty()) { + lex(); + } + return r; + } + // Skip the current token if it matches the given kind + bool nextIf(int kind) { + if (cur().kind != kind) + return false; + next(); + return true; + } + + [[noreturn]] void reportError(const std::string& what) { + reportError(what, cur()); + } + [[noreturn]] void reportError(const std::string& what, const Token& t) { + std::stringstream ss; + ss << what << ":\n"; + t.range.highlight(ss); + throw std::runtime_error(ss.str()); + } + [[noreturn]] void expected(const std::string& what, const Token& t) { + std::stringstream ss; + ss << "expected " << what << " but found '" << t.kindString() + << "' here:\n"; + t.range.highlight(ss); + throw std::runtime_error(ss.str()); + } + [[noreturn]] void expected(const std::string& what) { + expected(what, cur()); + } + // Check that the current token has a given kind, return the current token, + // and advance to the next one. + Token expect(int kind) { + if (cur().kind != kind) { + expected(kindToString(kind)); + } + return next(); + } + Token& lookahead() { + if (next_tokens.size() < 2) { + lex(); + } + return next_tokens[1]; + } + Token& cur() { + return next_tokens.front(); + } + + private: + void lex() { + auto r = lexRaw(); + switch (r.kind) { + case '(': + case '[': + case '{': + nesting++; + break; + case ')': + case ']': + case '}': + nesting--; + break; + case TK_WHITESPACE: + case TK_WHITESPACE_EOF: { + const auto depth = + r.kind == TK_WHITESPACE_EOF ? indent_stack.front() : r.range.size(); + // note: TK_WHITESPACE_EOF is whitespace right before the EOF token + // just like we allow the code to be indented to a particular initial + // indent level, we allow the final indent to be anything and set + // it back to the initial indent level. This allows the code to be + // put into string literals inside code without worrying about final + // whitespace + if (depth > indent_stack.back()) { + indent_stack.push_back(depth); + r.kind = TK_INDENT; + } else if (depth == indent_stack.back()) { + r.kind = TK_NEWLINE; + } else { + next_tokens.emplace_back(TK_NEWLINE, r.range); + while (indent_stack.back() != depth) { + indent_stack.pop_back(); + next_tokens.emplace_back(TK_DEDENT, r.range); + if (indent_stack.empty()) { + reportError("invalid indent level " + std::to_string(depth), r); + } + } + return; // We've already queued the tokens + } + } break; + default: + break; + } + next_tokens.push_back(std::move(r)); + } + Token lexRaw(bool whitespace_token = false) { + AT_ASSERT(source); + if (current == nullptr) { + AT_ASSERT(pos == 0); + current = std::make_unique( + source->text_str().begin()); + } + + StringCordView::Iterator start_iter = *current; + StringCordView::Iterator end_iter = *current; + int kind = 0; + if (!shared.match( + *current, + nesting > 0, + whitespace_token, + &kind, + &start_iter, + &end_iter)) { + expected( + "a valid token", + Token( + **current, + SourceRange(source, start_iter, start_iter.pos() + 1))); + } + + auto t = Token(kind, SourceRange(source, start_iter, end_iter.pos())); + pos = end_iter.pos(); + *current = end_iter; + return t; + } + + std::shared_ptr source; + std::unique_ptr current; + size_t pos{0}; + size_t nesting{0}; // depth of ( [ { nesting... + std::vector indent_stack; // stack of indentation level of blocks + // Invariant: this should always contain at least a single element + std::vector next_tokens; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + SharedParserData& shared; +}; +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/mini_environment.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/mini_environment.h new file mode 100644 index 0000000000000000000000000000000000000000..dfb7e43fe4b371b620fe1c1fd99ae675e71936da --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/mini_environment.h @@ -0,0 +1,60 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::jit { + +// Simple data structure for containing a type T in nested control blocks +// Should only be used after initial compilation where type checking and +// loads and stores are emitted + +template +struct MiniEnvironment { + MiniEnvironment(Block* b, std::shared_ptr next = nullptr) + : next(std::move(next)) {} + + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + std::shared_ptr> next; + + T findInThisFrame(const std::string& name) { + auto it = table.find(name); + if (it != table.end()) { + return it->second; + } + return nullptr; + } + + T findInAnyFrame(const std::string& name) { + for (auto runner = this; runner; runner = runner->next.get()) { + if (auto r = runner->findInThisFrame(name)) { + return r; + } + } + return nullptr; + } + + void setVar(const std::string& name, T value) { + table[name] = value; + } + + std::vector definedVariables() { + std::vector result; + result.reserve(table.size()); + for (auto& kv : table) { + result.push_back(kv.first); + } + std::sort(result.begin(), result.end()); + return result; + } + + private: + std::unordered_map table; +}; + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/name_mangler.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/name_mangler.h new file mode 100644 index 0000000000000000000000000000000000000000..2cede9aaaffb8a0fe6c376845796614b8c7cf408 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/name_mangler.h @@ -0,0 +1,30 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::jit { + +/** + * class NameMangler + * + * Utility to mangle qualified names in order to make them unique. We use this + * in various places where we to de-duplicate qualified names. + */ +class TORCH_API NameMangler { + public: + // Given a qualified name, return a mangled version that is guaranteed to be + // unique with respect to previous/future calls of `mangled()` on this name + // mangler instance. + c10::QualifiedName mangle(const c10::QualifiedName& name); + + private: + size_t mangleIndex_ = 0; +}; + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/parse_string_literal.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/parse_string_literal.h new file mode 100644 index 0000000000000000000000000000000000000000..16f32df8d9b12fb47d3f117019380aa3f4344b52 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/parse_string_literal.h @@ -0,0 +1,92 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include + +namespace torch::jit { + +inline bool isCharCount(char c, const std::string& str, size_t start, int len) { + // count checks from [start, start + len) + return start + len <= str.size() && + std::count( + str.begin() + static_cast(start), + str.begin() + static_cast(start + len), + c) == len; +} + +inline std::optional parseOctal(const std::string& str, size_t pos) { + //\xxx where x are 0-7 + if (pos + 3 >= str.size()) + return std::nullopt; + size_t c = 0; + for (size_t i = 1, b = 64; i < 4; ++i, b /= 8) { + auto d = str[pos + i]; + if (d < '0' || d > '7') + return std::nullopt; + c += b * (d - '0'); + } + if (c >= 256) + return std::nullopt; + return c; +} + +inline std::string parseStringLiteral( + const SourceRange& range, + const std::string& str) { + size_t quote_len = isCharCount(str[0], str, 0, 3) ? 3 : 1; + auto ret_str = str.substr(quote_len, str.size() - quote_len * 2); + size_t pos = ret_str.find('\\'); + while (pos != std::string::npos) { + // invariant: pos has to escape a character because it is a valid string + char c = ret_str[pos + 1]; + size_t to_erase = 2; + switch (ret_str[pos + 1]) { + case '\\': + case '\'': + case '\"': + case '\n': + break; + case 'a': + c = '\a'; + break; + case 'b': + c = '\b'; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'v': + c = '\v'; + break; + case 't': + c = '\t'; + break; + case 'x': + throw(ErrorReport(range) << "unsupported hex specifier"); + case 'u': + case 'U': + throw(ErrorReport(range) << "unsupported unicode specifier"); + default: + // octal value in format \nnn, n is [0-7] + if (auto v = parseOctal(ret_str, pos)) { + to_erase = 4; + c = *v; + } else { + throw(ErrorReport(range) << " ill formed octal specifier"); + } + } + ret_str.replace(pos, to_erase, /* num copies */ 1, c); + pos = ret_str.find('\\', pos + 1); + } + return ret_str; +} + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/parser.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/parser.h new file mode 100644 index 0000000000000000000000000000000000000000..77653ee4c4ab4dc00da00851d41d59344768295b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/parser.h @@ -0,0 +1,36 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include + +namespace torch::jit { + +struct Decl; +struct ParserImpl; +struct Lexer; + +TORCH_API Decl mergeTypesFromTypeComment( + const Decl& decl, + const Decl& type_annotation_decl, + bool is_method); + +struct TORCH_API Parser { + explicit Parser(const std::shared_ptr& src); + TreeRef parseFunction(bool is_method); + TreeRef parseClass(); + Decl parseTypeComment(); + Expr parseExp(); + Lexer& lexer(); + ~Parser(); + + private: + std::unique_ptr pImpl; +}; + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/parser_constants.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/parser_constants.h new file mode 100644 index 0000000000000000000000000000000000000000..b71bc27928ebf8667f1b6df5b9d4e4596aa70a23 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/parser_constants.h @@ -0,0 +1,11 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +namespace torch::jit { +static constexpr const char* valid_single_char_tokens = + "+-*/%@()[]:,={}><.?!&^|~"; +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/resolver.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/resolver.h new file mode 100644 index 0000000000000000000000000000000000000000..6be0d3b08423d6260e015246e0a36cd521a0eeab --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/resolver.h @@ -0,0 +1,71 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace torch::jit { + +struct Resolver; +using ResolverPtr = std::shared_ptr; + +/** + * class Resolver + * + * Represents an "outer environment" in which we an look up names and return + * a corresponding SugaredValue. This is used during compilation to resolve + * references to names which are not defined internal to the graph. + * + * Example: PythonResolver looks at the enclosing Python scope for `name`. + * + * NOTE: When adding methods, keep this an abstract class (i.e. all new methods + * should be purely virtual). Resist the urge to provide a default + * implementation; you should explicitly think about how each resolver would + * handle the method. + */ +struct Resolver { + virtual ~Resolver() = default; + + // Resolve a given name to a SugaredValue. This takes the method `m` that the + // caller is currently constructing, since we may need to insert nodes into + // the graph to create a value. + virtual std::shared_ptr resolveValue( + const std::string& name, + GraphFunction& m, + const SourceRange& loc) { + return nullptr; + } + + // Resolve `name` to a TypePtr. + virtual TypePtr resolveType(const std::string& name, const SourceRange& loc) { + return nullptr; + } +}; + +// A resolver that only understands "torch.foo()" lookups. +struct NativeResolver : public Resolver { + std::shared_ptr resolveValue( + const std::string& name, + GraphFunction& m, + const SourceRange& loc) override { + if (name == "torch") { + return std::make_shared("aten"); + } + return nullptr; + } + + TypePtr resolveType(const std::string& name, const SourceRange& loc) + override { + return nullptr; + } +}; + +inline std::shared_ptr nativeResolver() { + return std::make_shared(); +} +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/schema_matching.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/schema_matching.h new file mode 100644 index 0000000000000000000000000000000000000000..c84708353f64269d594eb45c5819c2e293bdfe3f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/schema_matching.h @@ -0,0 +1,73 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include + +#include + +namespace torch::jit { + +// Try to match a list of inputs and keyword 'attributes' to this +// schema. Return the flat list of positional inputs to the call or +// `std::nullopt` on failure (`failure_messages` contains a good error +// report in this case) + +struct MatchedSchema { + std::vector inputs; + std::vector return_types; + c10::OptNameList return_field_names; + std::string schema_name; +}; + +TORCH_API bool isBlockListedSchema(const FunctionSchema& schema); + +TORCH_API MatchedSchema matchSchema( + const ::c10::FunctionSchema& schema, + const SourceRange& loc, + Graph& graph, + at::ArrayRef args, + at::ArrayRef kwargs, + const std::optional& self = std::nullopt); + +TORCH_API std::pair matchSchemas( + const std::vector& schemas, + const SourceRange& loc, + Graph& graph, + at::ArrayRef args, + at::ArrayRef kwargs, + const std::optional& self = std::nullopt, + bool render_errors = false); + +TORCH_API bool convertibleToList( + const TypePtr& type, + const TypePtr& list_type_); + +TORCH_API std::string getFullSchemaName(const ::c10::FunctionSchema& schema); + +TORCH_API Value* emitBuiltinCall( + const SourceRange& loc, + Graph& graph, + Symbol name, + at::ArrayRef args, + at::ArrayRef kwargs, + const std::optional& self = std::nullopt); + +TORCH_API std::optional findInputWithName( + const std::string& name, + at::ArrayRef kwargs, + bool is_aten = false); + +// applies implicit conversion from value trying to turn it into type +// concrete_type it succeeds if the return_value->isSubtypeOf(concrete_type) +TORCH_API Value* tryConvertToType( + const SourceRange& loc, + Graph& graph, + const TypePtr& concrete_type, + Value* value, + bool allow_conversions); +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/schema_type_parser.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/schema_type_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..3d148fe323c4bb54f582590376631af45c446984 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/schema_type_parser.h @@ -0,0 +1,53 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace torch::jit { + +using TypePtr = c10::TypePtr; + +TORCH_API void registerOpaqueType(const std::string& type_name); +TORCH_API void unregisterOpaqueType(const std::string& type_name); +TORCH_API bool isRegisteredOpaqueType(const std::string& type_name); + +struct TORCH_API SchemaTypeParser { + TypePtr parseBaseType(); + std::optional parseAliasAnnotation(); + std::pair> parseType(); + std::tuple> + parseFakeAndRealType(); + std::optional parseTensorDType(const std::string& dtype); + TypePtr parseRefinedTensor(); + + SchemaTypeParser( + Lexer& L, + bool parse_complete_tensor_types, + bool allow_typevars) + : complete_tensor_types(parse_complete_tensor_types), + L(L), + allow_typevars_(allow_typevars) {} + + private: + std::optional tryToParseRequiresGrad(); + std::optional tryToParseDeviceType(); + void parseList( + int begin, + int sep, + int end, + c10::function_ref callback); + + bool complete_tensor_types; + Lexer& L; + size_t next_id = 0; + bool allow_typevars_; +}; +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/script_type_parser.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/script_type_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..aa4105637e51d13b451484ebac382c6f6e32037c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/script_type_parser.h @@ -0,0 +1,58 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include + +namespace torch::jit { + +/** + * class ScriptTypeParser + * + * Parses expressions in our typed AST format (TreeView) into types and + * typenames. + */ +class TORCH_API ScriptTypeParser { + public: + explicit ScriptTypeParser() = default; + explicit ScriptTypeParser(ResolverPtr resolver) + : resolver_(std::move(resolver)) {} + + c10::TypePtr parseTypeFromExpr(const Expr& expr) const; + + std::optional> parseBroadcastList( + const Expr& expr) const; + + c10::TypePtr parseType(const std::string& str); + + FunctionSchema parseSchemaFromDef(const Def& def, bool skip_self); + + c10::IValue parseClassConstant(const Assign& assign); + + private: + c10::TypePtr parseTypeFromExprImpl(const Expr& expr) const; + + std::optional parseBaseTypeName(const Expr& expr) const; + at::TypePtr subscriptToType( + const std::string& typeName, + const Subscript& subscript) const; + std::vector evaluateDefaults( + const SourceRange& r, + const std::vector& default_types, + const std::vector& default_exprs); + std::vector parseArgsFromDecl(const Decl& decl, bool skip_self); + + std::vector parseReturnFromDecl(const Decl& decl); + + ResolverPtr resolver_ = nullptr; + + // Need to use `evaluateDefaults` in serialization + friend struct ConstantTableValue; + friend struct SourceImporterImpl; +}; +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/source_range.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/source_range.h new file mode 100644 index 0000000000000000000000000000000000000000..f58ab00fac5e62175b160977891f89e3f1d17351 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/source_range.h @@ -0,0 +1,608 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace torch::jit { + +class SourceRangeUnpickler; +struct SourceRange; + +// A stringlike class backed by a vector of string_view +// the string represented are logically the concatenation of the string_views +// This has advantage of not needing continues memory. +struct TORCH_API StringCordView { + StringCordView(); + StringCordView(const StringCordView&) = default; + StringCordView(StringCordView&&) noexcept = default; + StringCordView( + std::vector inputs, + std::vector> ownerships); + + StringCordView& operator=(const StringCordView&) = default; + StringCordView& operator=(StringCordView&&) noexcept = default; + + size_t size() const { + return accumulated_sizes_.back(); + } + + size_t find(const std::string& tok, size_t start) const; + size_t find_regex(const std::string& tok, size_t start) const; + StringCordView substr(size_t start, size_t size) const; + + char at(size_t index) const { + return *iter_for_pos(index); + } + char operator[](size_t index) const { + return at(index); + } + + std::string str() const { + std::stringstream ss; + for (auto s : pieces_) { + ss << std::string(s); + } + return ss.str(); + } + + bool operator==(const std::string& rhs) const; + + bool operator==(const StringCordView& rhs) const; + + std::string_view piece(size_t index) const { + return pieces_[index]; + } + + // General-case iterator implementation. + struct IteratorImpl { + IteratorImpl( + const StringCordView* str, + size_t start_line, + size_t start_pos, + size_t size) + : line_(start_line), pos_(start_pos), str_(str), size_(size) {} + explicit IteratorImpl(const StringCordView* str) + : IteratorImpl(str, 0, 0, str->size()) {} + + IteratorImpl() : IteratorImpl(nullptr, 0, 0, 0) {} + + IteratorImpl(const IteratorImpl&) = default; + IteratorImpl(IteratorImpl&&) = default; + IteratorImpl& operator=(const IteratorImpl&) = default; + IteratorImpl& operator=(IteratorImpl&&) = default; + + IteratorImpl& operator++() { + if (size_ == 0) { + return *this; + } + if ((pos_ + 1) < str_->pieces_[line_].size()) { + pos_++; + } else { + line_++; + pos_ = 0; + } + return *this; + } + + IteratorImpl operator++(int) { + IteratorImpl prev(*this); + ++(*this); + return prev; + } + + IteratorImpl next_iter() const { + IteratorImpl next(*this); + ++next; + return next; + } + + IteratorImpl& operator+=(size_t num); + + IteratorImpl operator+(size_t num) const { + IteratorImpl it(*this); + it += num; + return it; + } + + bool operator==(const IteratorImpl& rhs) const { + if (!has_next() && !rhs.has_next()) { + return true; + } + return (str_ == rhs.str_) && (line_ == rhs.line_) && (pos_ == rhs.pos_); + } + + bool operator!=(const IteratorImpl& rhs) const { + return !((*this) == rhs); + } + bool has_next() const { + return size_ > 0 && (line_ < str_->pieces_.size()); + } + + char operator*() const { + TORCH_INTERNAL_ASSERT(line_ < str_->pieces_.size()); + TORCH_INTERNAL_ASSERT(pos_ < str_->pieces_[line_].size()); + return str_->pieces_[line_].at(pos_); + } + + // returns rest of the line of the current iterator + std::string_view rest_line() const { + if (line_ >= str_->pieces_.size()) { + return ""; + } + + std::string_view cur_line = str_->pieces_[line_]; + return cur_line.substr(pos_, std::string::npos); + } + + size_t pos() const { + if (size_ == 0) { + return 0; + } + return str_->accumulated_sizes_[line_] + pos_; + } + + private: + size_t line_; + size_t pos_; + const StringCordView* str_; + size_t size_; + friend struct StringCordView; + }; + + // Either an IteratorImpl, or a simple std::string_view::iterator + // (which is faster) if possible. + struct Iterator { + Iterator() = default; + + Iterator( + const StringCordView* str, + size_t start_line, + size_t start_pos, + size_t size) + : repr_( + str->pieces_.size() == 1 + ? repr_type(FastRepr( + start_line ? str->pieces_[0].end() + : str->pieces_[0].begin() + start_pos, + str)) + : repr_type(IteratorImpl(str, start_line, start_pos, size))) { + } + + Iterator(const StringCordView* str) : Iterator(str, 0, 0, str->size()) {} + + Iterator& operator++() { + if (auto* pit = std::get_if(&repr_)) { + ++(*pit); + } else { + ++fast_repr().it; + } + return *this; + } + + Iterator operator++(int) { + Iterator prev(*this); + ++(*this); + return prev; + } + + Iterator next_iter() const { + Iterator next(*this); + ++next; + return next; + } + + Iterator& operator+=(size_t num) { + if (auto* pit = std::get_if(&repr_)) { + *pit += num; + } else { + fast_repr().it += num; + } + return *this; + } + + Iterator operator+(size_t num) const { + Iterator it(*this); + it += num; + return it; + } + + bool operator==(const Iterator& rhs) const { + return repr_ == rhs.repr_; + } + + bool operator!=(const Iterator& rhs) const { + return repr_ != rhs.repr_; + } + + bool has_next() const { + if (const auto* pit = std::get_if(&repr_)) { + return pit->has_next(); + } else { + return fast_repr().it != fast_repr().str->pieces_[0].end(); + } + } + + char operator*() const { + if (const auto* pit = std::get_if(&repr_)) { + return **pit; + } else { + return *fast_repr().it; + } + } + + std::string_view rest_line() const { + if (const auto* pit = std::get_if(&repr_)) { + return pit->rest_line(); + } else { + // NOTE: std::string_view(it, end) ctor wasn't added until C++20. + const auto fast_repr_end = fast_repr().str->pieces_[0].end(); + if (fast_repr().it != fast_repr_end) { + return std::string_view( + &*fast_repr().it, fast_repr_end - fast_repr().it); + } + return std::string_view(); + } + } + + size_t pos() const { + if (const auto* pit = std::get_if(&repr_)) { + return pit->pos(); + } else { + return fast_repr().it - fast_repr().str->pieces_[0].begin(); + } + } + + private: + // When we have only one entry in pieces_ (importantly, such as + // when called from torch::Library::def during startup), we can + // skip extra complexity and just use string_view::iterator + // directly. + struct FastRepr { + std::string_view::iterator it; + const StringCordView* str; + + FastRepr() : str(nullptr) {} + + explicit FastRepr( + std::string_view::iterator it_, + const StringCordView* str_) + : it(it_), str(str_) {} + + bool operator==(const FastRepr& rhs) const { + return it == rhs.it && str == rhs.str; + } + + bool operator!=(const FastRepr& rhs) const { + return !operator==(rhs); + } + }; + using repr_type = std::variant; + repr_type repr_; + + FastRepr& fast_repr() { + // -Oz refuses to inline std::get. + TORCH_INTERNAL_ASSERT_DEBUG_ONLY(std::holds_alternative(repr_)); + return *std::get_if(&repr_); + } + + const FastRepr& fast_repr() const { + // -Oz refuses to inline std::get. + TORCH_INTERNAL_ASSERT_DEBUG_ONLY(std::holds_alternative(repr_)); + return *std::get_if(&repr_); + } + }; + + Iterator begin() const { + return Iterator(this, 0, 0, size()); + } + Iterator end() const { + return Iterator(this, pieces_.size(), 0, 0); + } + Iterator iter_for_pos(size_t pos) const; + + private: + IteratorImpl begin_impl() const { + return IteratorImpl(this, 0, 0, size()); + } + IteratorImpl end_impl() const { + return IteratorImpl(this, pieces_.size(), 0, 0); + } + IteratorImpl iter_impl_for_pos(size_t pos) const; + std::vector pieces_; + std::vector accumulated_sizes_; + std::vector> owned_strings_; +}; + +// Source represents a code segment. It keeps track of: +// - text_view : the view into text of the code segment +// - filename (optional) : if present, represents the name of the file from +// which the code segment originated. +// - starting_line_no : represents the line in the original file where the +// code segment started. +struct TORCH_API Source { + // Whether or not Source should copy the string passed in the constructor. + enum CopiesString { COPIES_STRING, DONT_COPY }; + + explicit Source( + std::string_view text_view, + std::optional filename = std::nullopt, + size_t starting_line_no = 0, + std::shared_ptr gen_ranges = nullptr, + CopiesString copies_str = COPIES_STRING) + : text_view_(create_text_view(copies_str, text_view)), + filename_(std::move(filename)), + starting_line_no_(starting_line_no), + gen_ranges_(std::move(gen_ranges)) { + calc_line_start_offsets(); + } + + explicit Source( + StringCordView str, + std::optional filename = std::nullopt, + size_t starting_line_no = 0, + std::shared_ptr gen_ranges = nullptr) + : text_view_(std::move(str)), + filename_(std::move(filename)), + starting_line_no_(starting_line_no), + gen_ranges_(std::move(gen_ranges)) { + calc_line_start_offsets(); + } + // Given a line number (within source_), return the byte offset of the + // beginning of that line. + size_t offset_for_line(size_t line) const { + return line_starting_offsets_.at(line); + } + + // Returns number of lines present. + size_t num_lines() const { + return line_starting_offsets_.size(); + } + + // Calculate the line (within the code segment) on which `offset` resides. + size_t lineno_for_offset(size_t offset) const { + auto iter = std::upper_bound( + line_starting_offsets_.begin(), line_starting_offsets_.end(), offset); + return iter - line_starting_offsets_.begin() - 1; + } + + // Calculate the line (within the original source file, if present) on which + // `lineno` resides. + size_t lineno_to_source_lineno(size_t lineno) const { + if (filename_) { + return lineno + starting_line_no_; + } else { + return lineno; + } + } + + StringCordView get_line(size_t lineno) const { + auto start = offset_for_line(lineno); + auto size = (lineno + 1) < num_lines() ? offset_for_line(lineno + 1) - start + : text_view_.size() - start; + return text_view_.substr(start, size); + } + + const StringCordView& text_str() const { + return text_view_; + } + + char char_at(size_t index) const { + return text_view_.at(index); + } + + size_t size() const { + return text_view_.size(); + } + + std::optional& filename() { + return filename_; + } + + size_t starting_line_no() const { + return starting_line_no_; + } + + std::optional findSourceRangeThatGenerated( + const SourceRange& range); + + ~Source() = default; + + private: + void calc_line_start_offsets() { + line_starting_offsets_.clear(); + line_starting_offsets_.push_back(0); + size_t pos = 0; + while ((pos = text_view_.find("\n", pos)) != std::string::npos) { + line_starting_offsets_.push_back(++pos); + } + } + + static StringCordView create_text_view( + CopiesString copies_str, + std::string_view text_view) { + if (copies_str == COPIES_STRING) { + auto allocated_str = + std::make_shared(text_view.data(), text_view.size()); + return StringCordView({*allocated_str}, {allocated_str}); + } else { + return StringCordView({text_view}, {}); + } + } + + StringCordView text_view_; + + std::optional filename_; + // If filename_ is not present, starting_line_no_ is don't care + size_t starting_line_no_; + // Starting offsets for lines into the source. e.g. line 0 starts at + // line_starting_offsets_[0], etc. + std::vector line_starting_offsets_; + + std::shared_ptr gen_ranges_; +}; + +// A SourceRange is a reference to subset of a Source, specified by `start` and +// `end` byte offsets into the source text. +struct TORCH_API SourceRange { + SourceRange(std::shared_ptr source_view, size_t start_, size_t end_) + : source_view_(std::move(source_view)), start_(start_), end_(end_) { + if (source_view_) { + start_iter_ = source_view_->text_str().iter_for_pos(start_); + } + } + + SourceRange() : source_view_(nullptr), start_(0), end_(0) {} + + SourceRange( + std::shared_ptr source_view_, + StringCordView::Iterator start_iter, + size_t end_) + : source_view_(std::move(source_view_)), + start_(start_iter.pos()), + end_(end_), + start_iter_(start_iter) {} + + const std::string_view token_text() const { + size_t size = end() - start(); + return start_iter_.rest_line().substr(0, size); + } + + const StringCordView text() const { + return source_view_->text_str().substr(start(), end() - start()); + } + size_t size() const { + return end() - start(); + } + static const size_t CONTEXT = 3; + void highlight(std::ostream& out) const; + + // Customizable version of 'highlight' method. + void print_with_context( + std::ostream& out, + size_t context, + bool highlight, + const std::string& funcname) const; + + const std::shared_ptr& source() const { + return source_view_; + } + size_t start() const { + return start_; + } + size_t end() const { + return end_; + } + std::string str() const { + std::stringstream ss; + highlight(ss); + return ss.str(); + } + + std::optional> file_line_col() const { + if (!source_view_ || !source()->filename()) { + return std::nullopt; + } + + auto lineno = source_view_->lineno_for_offset(start_); + auto col_offset = (int)start_ - (int)source_view_->offset_for_line(lineno); + // TODO: std::optional<>::value returns an rvalue ref so can't use it here?? + return std::make_tuple( + source_view_->filename().value_or(""), + source_view_->lineno_to_source_lineno(lineno), + (size_t)col_offset); + } + + bool operator==(const SourceRange& rhs) const { + return start() == rhs.start() && end() == rhs.end() && + source() == rhs.source(); + } + + bool operator!=(const SourceRange& rhs) const { + return !(*this == rhs); + } + + std::optional findSourceRangeThatGenerated() const { + if (!source_view_) { + return std::nullopt; + } + return source_view_->findSourceRangeThatGenerated(*this); + } + + protected: + std::shared_ptr source_view_; + + private: + size_t start_; + size_t end_; + StringCordView::Iterator start_iter_; +}; + +// OwnedSourceRange is just like a SourceRange except that it owns a `Source` +// instead of `Source`. Thus OwnedSourceRange owns a copy of source text. +struct OwnedSourceRange : public SourceRange { + explicit OwnedSourceRange(const SourceRange& source_range) + : SourceRange(source_range) { + const auto& source = source_range.source(); + if (source) { + source_view_ = std::make_shared( + source->text_str().str(), + source->filename(), + source->starting_line_no()); + } + } +}; + +struct TORCH_API SourceRangeHasher { + public: + size_t operator()(const torch::jit::SourceRange& key) const; +}; + +struct StackEntry { + std::string filename; + SourceRange range; +}; + +TORCH_API void format_stack_trace( + std::ostream& out, + const std::vector& entries); + +inline std::ostream& operator<<(std::ostream& out, const SourceRange& range) { + range.highlight(out); + return out; +} + +// A pair of (byte offset, SourceRange) describing a specific segment +// of the output stream +struct TaggedRange { + TaggedRange(size_t bytes, SourceRange range) + : bytes(bytes), range(std::move(range)) {} + size_t bytes; + SourceRange range; +}; +using SourceRangeRecords = std::vector; +using SourceRangeTagMap = + std::unordered_map; + +} // namespace torch::jit + +namespace std { +template <> +struct iterator_traits { + using value_type = char; + using difference_type = ptrdiff_t; + using pointer = char*; + using reference = char&; + using iterator_category = std::forward_iterator_tag; +}; +} // namespace std + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/source_ref.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/source_ref.h new file mode 100644 index 0000000000000000000000000000000000000000..c786cc523c9aa42e6f15afd81290e1e6619d0074 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/source_ref.h @@ -0,0 +1,50 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include +#include +#include + +namespace torch::jit { + +/** + * SourceRef does two things: + * 1. Owns a Source object. + * 2. Serves as lookup key to the owned Source in associative containers, for + * runtime data aggregation. + * We don't want to use std::shared_ptr directly because we want to + * support heteogeneous lookup, and also shared_ptr is an implementation detail + * which should be encapsulated. + */ +class TORCH_API SourceRef : public CustomClassHolder { + public: + explicit SourceRef(std::shared_ptr source_view) + : source_view_(std::move(source_view)) {} + bool operator==(const SourceRef& other) const { + return source_view_ == other.source_view_; + } + bool operator<(const Source& other) const { + return source_view_.get() < &other; + } + friend bool operator<(const Source& other, const SourceRef& self) { + return &other < self.source_view_.get(); + } + bool operator<(const SourceRef& other) const { + return *this < *other.source_view_; + } + const Source* operator->() const { + return source_view_.get(); + } + + private: + std::shared_ptr source_view_; +}; + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/strtod.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/strtod.h new file mode 100644 index 0000000000000000000000000000000000000000..fefb4c36e6fd2682401ab299aa8a4fa9fcb6122b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/strtod.h @@ -0,0 +1,15 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit { + +TORCH_API double strtod_c(const char* nptr, char** endptr); +TORCH_API float strtof_c(const char* nptr, char** endptr); + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/sugared_value.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/sugared_value.h new file mode 100644 index 0000000000000000000000000000000000000000..24e3bcf8cb3130700b604ec8d4b7f31993215b74 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/sugared_value.h @@ -0,0 +1,880 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace torch::jit { + +using SugaredValuePtr = std::shared_ptr; + +// The AST can contain nodes like `self`, `self.b` or `python_fn` that +// are not first-class values in the graph representation, but instead +// will be desugared based on how they are used in the AST. + +// SugaredValue is used to temporarily represent these values in a way +// that separates their behavior from the AST -> IR converter itself. +// This allows us to keep dependencies on python minimal. + +struct TORCH_API SugaredValue + : public std::enable_shared_from_this { + // what is this node? for error reporting (e.g. Module, python function) + virtual std::string kind() const = 0; + + // what can we do with this thing? + // use it as a value e.g. `this + 4` + virtual Value* asValue(const SourceRange& loc, GraphFunction& m) { + throw(ErrorReport(loc) << kind() << " cannot be used as a value"); + } + + // select an attribute on it, e.g. `this.field` + virtual std::shared_ptr attr( + const SourceRange& loc, + GraphFunction& m, + const std::string& field) { + throw(ErrorReport(loc) << "attribute lookup is not defined on " << kind()); + } + + virtual bool hasAttr( + const SourceRange& loc, + GraphFunction& m, + const std::string& field) { + throw(ErrorReport(loc) << "attribute lookup is not defined on " << kind()); + } + + // assign an attribute on it, e.g. `this.field = newValue` + virtual void setAttr( + const SourceRange& loc, + GraphFunction& m, + const std::string& field, + Value* newValue) { + throw( + ErrorReport(loc) << "attribute assignment is not defined on " + << kind()); + } + + // use it as a vector of values, e.g. a tuple of values as return value from + // a method invocation + virtual std::vector> asTuple( + const SourceRange& loc, + GraphFunction& m, + const std::optional& size_hint = {}) { + throw(ErrorReport(loc) << kind() << " cannot be used as a tuple"); + } + + // TODO @wconstab refactor to use ModuleValue::asTuple instead of new API + virtual SugaredValuePtr asTupleValue( + const SourceRange& loc, + GraphFunction& m) { + throw(ErrorReport(loc) << kind() << " cannot be used as a tuplevalue"); + } + + virtual std::vector> asType( + const SourceRange& loc, + Method& m) { + throw(ErrorReport(loc) << kind() << " cannot be used as a type"); + } + + // call it like a function, e.g. `outputs = this(inputs)` + virtual std::shared_ptr call( + const SourceRange& loc, + GraphFunction& m, + // note: names for args will be 'argument 0', 'argument 1', etc.. + at::ArrayRef args, + at::ArrayRef kwargs, + size_t n_binders) { + // n_binders is always set to the number of variables an expression is + // syntactically bound to: + // a = foo() # 1 binder (note in this case the single binder might be a + // tuple) a, * b = foo() # 1 binder a, b = foo() # 2 binders foo() # 0 + // binders + // + // In subexpressions, like bar() in foo(bar()), n_binders is always set to + // 1. n_binders is used as a hint to subexpressions to determine how many + // values they should return when that number is ambiguous statically. In + // particular it is currently used to decide how many tensors a call to a + // python function will return. It is only a hint, functions do not have to + // check that n_binders match the number of things they are returning, the + // assignment logic will do that anyway. + + throw(ErrorReport(loc) << "cannot call a " << kind()); + } + + // This function is called when to convert a SugaredValue to its iterator. + // For example, when iterating through a Dict we iterate over its keys + virtual std::shared_ptr iter( + const SourceRange& loc, + GraphFunction& m) { + throw(ErrorReport(loc) << kind() << " cannot be used as an iterable"); + } + + // If we are iterating over a Sugared Value and it returns a value from this + // function, then we emit an unrolled loop over the variable. This allows us + // to support containers of Heterogeneous types, like Module Containers & + // Tuples + virtual std::optional staticLen() { + return std::nullopt; + } + + // When iterating over this SugaredValue, should we emit the for loop as an + // unrolled loop. + bool shouldEmitUnrolled() { + return staticLen() != std::nullopt; + } + + // return length of this thing, if not then it can't be iterated. + // If it does not have a statically-determinable length, then it cannot + // be iterated over with a modulelist. If it does it must return a constant + // Value * + virtual Value* len(const SourceRange& loc, GraphFunction& m) { + throw( + ErrorReport(loc) << "'" << kind() << "'" << " object is not iterable"); + } + + // expression for ith element for iterable value + virtual std::shared_ptr getitem( + const SourceRange& loc, + GraphFunction& m, + Value* idx, + TypePtr type_hint = nullptr) { + throw( + ErrorReport(loc) << "'" << kind() << "'" + << " object is not subscriptable"); + } + + virtual ~SugaredValue() = default; +}; + +// most things in the environment are just simple value types +// and not special python syntax sugar types +struct TORCH_API SimpleValue : public SugaredValue { + SimpleValue(Value* value) : value_(value) {} + std::string kind() const override { + std::stringstream ss; + // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) + ss << "value of type '" << value_->type()->annotation_str() << "'"; + return ss.str(); + } + Value* asValue(const SourceRange& range, GraphFunction& m) override { + return value_; + } + std::vector> asTuple( + const SourceRange& loc, + GraphFunction& m, + const std::optional& size_hint = {}) override; + std::shared_ptr attr( + const SourceRange& loc, + GraphFunction& m, + const std::string& field) override; + + bool hasAttr( + const SourceRange& loc, + GraphFunction& m, + const std::string& field) override; + + void setAttr( + const SourceRange& loc, + GraphFunction& m, + const std::string& field, + Value* newValue) override; + + std::shared_ptr call( + const SourceRange& loc, + GraphFunction& m, + // note: names for args will be 'argument 0', 'argument 1', etc.. + at::ArrayRef args, + at::ArrayRef kwargs, + size_t n_binders) override; + + std::shared_ptr iter(const SourceRange& loc, GraphFunction& m) + override; + + Value* getValue() const { + return value_; + } + + Value* len(const SourceRange& loc, GraphFunction& m) override; + SugaredValuePtr getitem( + const SourceRange& loc, + GraphFunction& m, + Value* idx, + TypePtr type_hint = nullptr) override; + + private: + Value* value_; +}; + +struct TORCH_API BuiltinFunction : public SugaredValue { + BuiltinFunction(Symbol symbol, std::optional self) + : symbol(symbol), self(std::move(self)) {} + + // The symbol of the function (e.g. `aten::relu`). + Symbol symbol; + + // if this is method, then this is the self argument. + std::optional self; + std::string kind() const override { + return "builtin"; + } + std::shared_ptr call( + const SourceRange& loc, + GraphFunction& m, + at::ArrayRef args, + at::ArrayRef kwargs, + size_t n_binders) override; + + // try to create this builtin but if it doesn't exist or the self argument + // cannot possibly match, then return nullptr. Use in situations where it is + // not clear if it is a valid builtin + static std::shared_ptr tryCreate( + Symbol symbol, + std::optional self); +}; + +struct TORCH_API SugaredTupleValue : public SugaredValue { + explicit SugaredTupleValue(std::vector> tup) + : tup_(std::move(tup)) {} + + std::vector> asTuple( + const SourceRange& loc, + GraphFunction& m, + const std::optional& size_hint = {}) override { + return tup_; + } + + Value* asValue(const SourceRange& loc, GraphFunction& m) override { + std::vector vec; + vec.reserve(tup_.size()); + for (const auto& sv : tup_) { + vec.push_back(sv->asValue(loc, m)); + } + Graph& g = *m.graph(); + return g.insertNode(g.createTuple(vec))->output(); + } + + std::string kind() const override { + return "Tuple"; + } + + SugaredValuePtr getitem( + const SourceRange& loc, + GraphFunction& m, + Value* idx, + TypePtr type_hint = nullptr) override { + if (!(idx->type()->cast() && toIValue(idx))) { + throw( + ErrorReport(loc) + << "Expected integer literal for index but got a variable or non-integer. " + << "ModuleList/Sequential indexing is only supported with integer literals. " + << "For example, 'i = 4; self.layers[i](x)' will fail because i is not a literal. " + << "Enumeration is supported, e.g. 'for index, v in enumerate(self): out = v(inp)'"); + } + auto index = toIValue(idx)->toInt(); + int64_t adj_index = + (index < 0) ? index + static_cast(tup_.size()) : index; + if (!(adj_index >= 0 && adj_index < static_cast(tup_.size()))) { + throw( + ErrorReport(loc) << "Index " << index << " out of range of length " + << tup_.size()); + } + return tup_.at(adj_index); + } + + // This function is called when a SugaredValue is used to convert a + // SugaredValue to its iterator. For example, when iterating through a Dict we + // iterate over its keys + std::shared_ptr iter(const SourceRange& loc, GraphFunction& m) + override { + return shared_from_this(); + } + + // Because this is used to contain SugaredValues of Heterogeneous types, + // we define staticLen() so that when this is iterated over it is emitted + // as an unrolled loop. + std::optional staticLen() override { + return static_cast(tup_.size()); + } + + std::vector> tup_; +}; + +struct TORCH_API BuiltinModule : public SugaredValue { + BuiltinModule(std::string name, std::optional version = std::nullopt) + : name(std::move(name)), version(version) {} + + std::string kind() const override { + return "builtin module"; + } + std::shared_ptr attr( + const SourceRange& loc, + GraphFunction& m, + const std::string& field) override { + if (field == "autograd") { + // When referring torch.autograd, it is also considered to be a + // BuiltinModule and we will dispatch to the aten operators for the + // methods under its module. + return std::make_shared("aten", version); + } + + auto sym = Symbol::fromQualString(name + "::" + field); + return std::make_shared(sym, std::nullopt); + } + + private: + std::string name; + // when we add operator versioning, emit this op as it existing at 'version' + // if not set, use the latest version + std::optional version; +}; + +// Represents a class, analogous to `int` or `dict`. Instances of classes, +// like `1` or `{"foo": 5}`, are represented as SimpleValues +struct TORCH_API ClassValue : public SugaredValue { + explicit ClassValue(ClassTypePtr type) : type_(std::move(type)) {} + + // Call the type's constructor, as in: + // n = Foo(constructor_arg) + std::shared_ptr call( + const SourceRange& loc, + GraphFunction& m, + at::ArrayRef args, + at::ArrayRef kwargs, + size_t n_binders) override; + + std::shared_ptr attr( + const SourceRange& loc, + GraphFunction& m, + const std::string& field) override; + + std::string kind() const override { + return type_->str(); + } + + ClassTypePtr type_; +}; + +struct TORCH_API NamedTupleConstructor : public SugaredValue { + explicit NamedTupleConstructor(TupleTypePtr type) : type_(std::move(type)) {} + + std::shared_ptr call( + const SourceRange& loc, + GraphFunction& m, + at::ArrayRef args, + at::ArrayRef kwargs, + size_t n_binders) override; + + std::string kind() const override { + return type_->str(); + } + + TupleTypePtr type_; +}; + +struct FunctionValue : public SugaredValue { + FunctionValue(Function* callee) : callees_({callee}) {} + FunctionValue(const StrongFunctionPtr& p) + : callees_({p.function_}), cu_(p.cu_) {} + FunctionValue(const std::vector& callees) { + for (const StrongFunctionPtr& callee : callees) { + cu_ = cu_ ? cu_ : callee.cu_; + TORCH_INTERNAL_ASSERT(callee.cu_ == cu_); + callees_.push_back(callee.function_); + } + } + + std::string kind() const override { + return "function"; + } + + std::shared_ptr call( + const SourceRange& loc, + GraphFunction& f, + at::ArrayRef args, + at::ArrayRef kwargs, + size_t n_binders) override { + std::vector schemas; + for (Function* callee : callees_) { + try { + callee->ensure_defined(); + } catch (const RecursiveMethodCallError&) { + throw( + ErrorReport(loc) + << " function '" << callee->name() << "' is called recursively. " + << "Recursive calls are not supported"); + } + schemas.push_back(&callee->getSchema()); + } + auto match = matchSchemas(schemas, loc, *f.graph(), args, kwargs); + Value* output = + f.graph()->insertFunctionCall(callees_[match.first], match.second); + output->node()->setSourceRange(loc); + return std::make_shared(output); + } + + const std::vector& callees() { + return callees_; + } + + private: + std::vector callees_; + // TODO holding this thing is creepy + std::shared_ptr cu_; +}; + +struct TORCH_API ClosureValue : public SugaredValue { + ClosureValue(Value* value) : value_(value) { + TORCH_INTERNAL_ASSERT(value_->node()->kind() == prim::Closure); + } + std::string kind() const override { + return "closure"; + } + Value* asValue(const SourceRange& range, GraphFunction& m) override { + return value_; + } + Value* value_; +}; + +// defines how a method obtained from a module/class/interface behaves in script +struct MethodValue : public SugaredValue { + MethodValue(Value* self, std::vector method_names) + : self_(self), method_names_(std::move(method_names)) {} + MethodValue(Value* self, std::string method_name) + : MethodValue(self, std::vector({std::move(method_name)})) {} + + std::string kind() const override { + return "method"; + } + + std::shared_ptr call( + const SourceRange& loc, + GraphFunction& f, + at::ArrayRef args, + at::ArrayRef kwargs, + size_t n_binders) override { + std::vector argsWithSelf = {self_}; + argsWithSelf.insert(argsWithSelf.end(), args.begin(), args.end()); + std::vector schemas; + for (const std::string& method_name : method_names_) { + if (auto class_type = self_->type()->cast()) { + Function& method = class_type->getMethod(method_name); + try { + method.ensure_defined(); + } catch (const RecursiveMethodCallError&) { + throw( + ErrorReport(loc) + << " method '" << method.name() << "' is called recursively. " + << "Recursive calls are not supported"); + } + schemas.push_back(&method.getSchema()); + } else if (auto interface_type = self_->type()->cast()) { + schemas.push_back(interface_type->getMethod(method_name)); + } else { + TORCH_INTERNAL_ASSERT( + false, "method constructed that is not a class or interface"); + } + } + auto match = matchSchemas(schemas, loc, *f.graph(), argsWithSelf, kwargs); + Value* output = + f.graph()->insertMethodCall(method_names_[match.first], match.second); + output->node()->setSourceRange(loc); + return std::make_shared(output); + } + + private: + Value* self_; + std::vector method_names_; +}; + +struct TORCH_API PrintValue : public SugaredValue { + std::string kind() const override { + return "print"; + } + std::shared_ptr call( + const SourceRange& loc, + GraphFunction& m, + at::ArrayRef args, + at::ArrayRef kwargs, + size_t n_binders) override; +}; + +// expressions like int(x) +// these are the same as call prim::Int or equivalent except it +// is a noop when the input is a subtype of 'type' +struct TORCH_API CastValue : public BuiltinFunction { + CastValue(TypePtr type, c10::Symbol method) + : BuiltinFunction(method, std::nullopt), type_(std::move(type)) {} + std::shared_ptr call( + const SourceRange& loc, + GraphFunction& m, + at::ArrayRef args, + at::ArrayRef kwargs, + size_t n_binders) override { + if (args.size() == 1 && kwargs.empty()) { + auto len_op = std::make_shared(aten::len, std::nullopt); + auto gt_op = std::make_shared(aten::gt, std::nullopt); + auto zero = m.graph()->insertConstant(0); + + auto v = args[0].value(*m.graph()); + if (v->type()->isSubtypeOf(*type_)) { + return std::make_shared(v); + } else if ( + *type_ == *BoolType::get() && + (v->type()->isSubtypeOf(*AnyListType::get()) || + v->type()->isSubtypeOf(*StringType::get()) || + v->type()->cast())) { + auto len = len_op->call(loc, m, {v}, {}, 1); + return gt_op->call(loc, m, {len->asValue(loc, m), zero}, {}, 1); + } + } + return BuiltinFunction::call(loc, m, args, kwargs, n_binders); + } + + private: + TypePtr type_; +}; + +struct TORCH_API TensorCastValue : public SugaredValue { + TensorCastValue(at::ScalarType type, NamedValue self) + : dtype_(type), self_(std::move(self)) {} + + std::string kind() const override { + return "Cast"; + } + + std::shared_ptr call( + const SourceRange& loc, + GraphFunction& m, + at::ArrayRef args, + at::ArrayRef kwargs, + size_t n_binders) override { + TORCH_INTERNAL_ASSERT(args.empty() && kwargs.empty()); + Value* dtype_const = m.graph()->insertConstant(dtype_, loc); + std::vector kwargs_{ + self_, NamedValue(loc, "dtype", dtype_const)}; + Value* casted_val = m.graph()->insert( + /*opname=*/Symbol::fromQualString("aten::to"), + /*args=*/args, + /*kwargs=*/kwargs_, + /*range=*/loc); + return std::make_shared(casted_val); + } + + at::ScalarType dtype_; + NamedValue self_; +}; + +// builtins operators and functions that call a method if it exists +// on a class type, like 'len(x)' and 'x + y' +struct TORCH_API MagicMethod : public SugaredValue { + MagicMethod(std::string desugared_name, SugaredValuePtr base) + : base_value_(std::move(base)), + desugared_name_(std::move(desugared_name)) {} + + std::string kind() const override { + return desugared_name_; + } + + std::shared_ptr call( + const SourceRange& loc, + GraphFunction& m, + at::ArrayRef args, + at::ArrayRef kwargs, + size_t n_binders) override; + + private: + SugaredValuePtr base_value_; + std::string desugared_name_; +}; + +// things that look like function applications, but +// perform non-standard evaluation are represented +// with SpecialFormValues, e.g. +// isinstance(x, int) +// fork(fn) +// annotate(int, 3) +// The implementation of each value is handled by a case inside emitApplyExpr +struct TORCH_API SpecialFormValue : public SugaredValue { + SpecialFormValue(Symbol form) : form_(form) {} + std::string kind() const override { + return form_.toUnqualString(); + } + Symbol form() const { + return form_; + } + static std::shared_ptr create(Symbol form) { + return std::make_shared(form); + } + + private: + Symbol form_; +}; + +struct TORCH_API LegacyTensorConstructor : public SpecialFormValue { + LegacyTensorConstructor(Symbol form, at::ScalarType dtype, at::Device device) + : SpecialFormValue(form), device_(device), dtype_(dtype) {} + + static std::shared_ptr create( + Symbol form, + at::ScalarType dtype, + at::Device device) { + return std::make_shared(form, dtype, device); + } + at::ScalarType dtype() const { + return dtype_; + } + + private: + at::Device device_; + at::ScalarType dtype_; +}; + +// matched against for special handling of range expressions +struct TORCH_API RangeValue : SugaredValue { + RangeValue( + const SourceRange& loc, + GraphFunction& m, + std::vector input, + std::optional static_len = std::nullopt); + + std::string kind() const override { + return "range"; + } + Value* len(const SourceRange& loc, GraphFunction& m) override; + SugaredValuePtr getitem( + const SourceRange& loc, + GraphFunction& m, + Value* idx, + TypePtr type_hint = nullptr) override; + std::shared_ptr iter(const SourceRange& loc, GraphFunction& m) + override; + + // When Range is instantiated via enumerate(iterable_with_static_len), + // then it takes the static length of the iterable + std::optional staticLen() override { + return static_len_; + } + + private: + Value* start_{}; + Value* end_{}; + Value* step_{}; + // a flag to determine if it's a simple range() call with only end_ from + // arguments If true, we will not insert length calculation and index + // derivation nodes to simplify the graph and enable more possible + // optimizations + bool has_only_end_{}; + std::optional static_len_; +}; + +// Specialized Tree structure to matched against for special handling +// of builtin functions iterables expressions like zip(), enumerate(), etc. +// zip and enumerate can be modeled as a tree of SimpleValue/RangeValue: +// zip(x, y) -> (x, y) with tuple assignment to each loop target +// enumerate(x) -> (range(0, math.inf, 1), x) +// So a complicated expression like zip(a, enumerate(b), range(0, 100)) will be: +// (a, (range(0, math.inf, 1), b), range(0, 100)) +// We use those base iterables to fill in the loop information like +// max_trip_count and set the value table for loop targets +// Iterables can contain lists of SugaredValues like ModuleLists. If it +// does, then we emit it unrolled and require that all values it contains +// have a statically-determinable length. +struct TORCH_API IterableTree : SugaredValue { + IterableTree() = default; + IterableTree( + const SourceRange& range, + GraphFunction& m, + at::ArrayRef children) { + for (const auto& child : children) { + addChild(range, m, child); + } + } + std::string kind() const override { + return "iterabletree"; + } + + std::shared_ptr iter(const SourceRange& loc, GraphFunction& m) + override { + return shared_from_this(); + } + + void addChild( + const SourceRange& range, + GraphFunction& m, + const SugaredValuePtr& iter_value); + + std::vector get_children() { + return children_; + } + + // If this iterable contains a ModuleList or Tuple, then it will have a + // static length, and we will emit it as an unrolled for loop. + std::optional staticLen() override { + return unroll_length_; + } + + // given a IterableTree node, get all the base iterables/leaves under the + // IterableTree node. This enables + // us to get all the basic SugaredValues that contains valid loop information + // with len() and getitem() + std::vector get_base_iterables(); + + Value* len(const SourceRange& loc, GraphFunction& m) override; + SugaredValuePtr getitem( + const SourceRange& loc, + GraphFunction& m, + Value* idx, + TypePtr type_hint = nullptr) override; + + private: + std::optional unroll_length_ = std::nullopt; + std::vector children_; +}; + +static inline std::vector toValues( + Graph& g, + at::ArrayRef nvs) { + return fmap(nvs, [&](const NamedValue& v) { return v.value(g); }); +} + +struct SimpleSelf : public Self { + explicit SimpleSelf(ClassTypePtr classType) + : Self(), classType_(std::move(classType)) {} + std::shared_ptr makeSugared(Value* v) const override { + v->setType(classType_); + return std::make_shared(v); + } + ClassTypePtr getClassType() const override { + return classType_; + } + + private: + ClassTypePtr classType_; +}; + +// This is not a SimpleValue so it can not pass through the code paths that +// expect a SimpleValue as a sugared value. +struct TORCH_API ExceptionMessageValue : public SugaredValue { + explicit ExceptionMessageValue( + Value* value, + Value* qualified_class_name = nullptr) + : value_(value), qualified_class_name_(qualified_class_name) {} + + std::string kind() const override { + return "exception message"; + } + + Value* getValue() { + return value_; + } + + // qualified python class name + Value* getQualifiedClassName() { + return qualified_class_name_; + } + + private: + Value* value_; + Value* qualified_class_name_; +}; + +struct TORCH_API ExceptionValue : public SugaredValue { + explicit ExceptionValue(std::string message) : message_(std::move(message)) {} + + std::string kind() const override { + return "exception"; + } + + std::shared_ptr call( + const SourceRange& loc, + GraphFunction& m, + at::ArrayRef args, + at::ArrayRef /*attributes*/, + size_t /*n_binders*/) override { + auto exception_message = insertConstant(*m.graph(), message_ + ": ", loc); + for (auto& input : args) { + auto input_str = input.value(*m.graph()); + if (!input_str->type()->isSubtypeOf(*StringType::get())) { + input_str = + emitBuiltinCall(loc, *m.graph(), aten::str, {input_str}, {}); + } + exception_message = emitBuiltinCall( + loc, *m.graph(), aten::add, {exception_message, input_str}, {}); + } + return std::make_shared(exception_message); + } + + std::string message_; +}; + +struct TORCH_API SugaredEnumClass : public SugaredValue { + explicit SugaredEnumClass(EnumTypePtr enum_type) + : enum_type_(std::move(enum_type)) {} + + std::string kind() const override { + return "EnumClass"; + } + + SugaredValuePtr attr( + const SourceRange& loc, + GraphFunction& m, + const std::string& field) override; + + SugaredValuePtr iter(const SourceRange& loc, GraphFunction& m) override; + + private: + EnumTypePtr enum_type_; +}; + +struct TORCH_API SliceValue : public SugaredValue { + explicit SliceValue(Value* start, Value* stop, Value* step) + : start_(start), stop_(stop), step_(step) {} + + std::string kind() const override { + return "Python slice value"; + } + + Value* start() { + return start_; + } + Value* stop() { + return stop_; + } + Value* step() { + return step_; + } + + private: + Value* start_; + Value* stop_; + Value* step_; +}; + +struct TORCH_API TorchCheckValue : public SugaredValue { + explicit TorchCheckValue() = default; + + std::string kind() const override { + return "torch._check sugared value"; + } + + std::shared_ptr call( + const SourceRange& loc, + GraphFunction& m, + at::ArrayRef args, + at::ArrayRef kwargs, + size_t n_binders) override; +}; + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/tracer.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/tracer.h new file mode 100644 index 0000000000000000000000000000000000000000..a3383b06b939c78f776d408f991fa573548e699b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/tracer.h @@ -0,0 +1,418 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +namespace torch::jit { +struct Node; +struct Value; +struct Graph; +struct Module; + +namespace tracer { + +using ::c10::ivalue::Shared; + +using ::c10::IValue; +using ::c10::ivalue::Future; + +using ::c10::ArrayRef; +using ::c10::TupleType; +using ::c10::TupleTypePtr; +using ::c10::ivalue::ConstantString; + +using torch::autograd::Variable; +using variable_list = std::vector; + +TORCH_API std::atomic& getTracerStateWarnMode(); + +struct TORCH_API TracingState + : public std::enable_shared_from_this { + TracingState(); + ~TracingState(); + + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + std::shared_ptr graph; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + bool warn = getTracerStateWarnMode(); + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + bool strict = true; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + bool force_outplace = false; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + std::function lookup_var_name_fn = + [](const Variable& var) { return ""; }; + + void enterFrame() { + env_stack.emplace_back(); + } + + void leaveFrame() { + env_stack.pop_back(); + } + + void setValue(const IValue& v, Value* value); + void delValue(const IValue& var); + Value* getValue(const IValue& var); + Value* getOutput(const IValue& var, size_t i); + bool hasValue(const IValue& var) const; + + Node* createNode(c10::Symbol op_name, size_t num_outputs); + void insertNode(Node* node); + + private: + using WeakIValue = at::WeakIValue; + + struct WeakIValueHasher { + size_t operator()(const WeakIValue& t) const { + return t.hash(); + } + }; + + struct WeakIValueEq { + bool operator()(const WeakIValue& t1, const WeakIValue& t2) const { + return t1.isSameIdentity(t2); + } + }; + + using Frame = + std::unordered_map; + std::vector env_stack; +}; + +// This is meant to be used as a thread local place, where we can store extra +// info that gets lost when we call into ATen from Python bindings. One example +// for when this happens is when we get an IntArrayRef argument with e.g. sizes +// for view. When tracing, those might be tensors, which let us encode extra +// data dependencies, but once they get to the ATen call where we actually have +// the tracing logic, they get converted into a raw IntArrayRef, and we loose +// all information. To prevent this, we temporarily stash it in here. +struct ArgumentStash { + struct IntArrayRefTrace : std::vector { + IntArrayRefTrace(size_t size) : std::vector(size, nullptr) {} + }; + + static bool empty() { + return stash.intlists.empty(); + } + + TORCH_API static void stashIntArrayRefElem( + const std::string& arg_name, + size_t size, + size_t idx, + const Variable& var); + + static bool hasIntArrayRef(const std::string& arg_name) { + return stash.intlists.count(arg_name) > 0; + } + + static IntArrayRefTrace popIntArrayRef(const std::string& arg_name) { + auto info = std::move(stash.intlists.at(arg_name)); + stash.intlists.erase(arg_name); + return info; + } + + // Value stashing: Use these methods to stash arguments which correspond + // to regular Value*'s in the graph. i.e. they don't require special + // handling like in the case of IntArrayRefs + TORCH_API static void stashValue( + const std::string& arg_name, + size_t idx, + const Variable& var, + const c10::TypePtr& type = nullptr); + + static bool hasValue(const std::string& arg_name) { + return stash.values.count(arg_name) > 0; + } + + static Value* popValue(const std::string& arg_name) { + auto info = stash.values.at(arg_name); + stash.values.erase(arg_name); + return info; + } + + private: + static thread_local ArgumentStash stash; + std::unordered_map intlists; + std::unordered_map values; +}; + +// Retrieve or set the current tracing state. Returns a nullptr if tracing is +// disabled. +TORCH_API const std::shared_ptr& getTracingState(); +TORCH_API void setTracingState(std::shared_ptr state); + +inline bool isTracing() { + return static_cast(getTracingState()); +} + +using warn_fn_type = void (*)(const std::string& msg); +TORCH_API extern const char* WARN_PYTHON_DATAFLOW; +TORCH_API extern const char* WARN_CONSTRUCTOR; +TORCH_API extern const char* WARN_RESIZE; +TORCH_API extern const char* STRICT_TRACER_MSG; +TORCH_API void _do_warn(const char* _reason, const char* _kind); +inline void warn(const char* _reason, const char* _kind = nullptr) { + if (const auto& state = getTracingState()) { + if (!state->warn) + return; + _do_warn(_reason, _kind); + } +} +TORCH_API void setWarn(warn_fn_type fn); + +struct TORCH_API NoWarn { + NoWarn() : state(getTracingState()) { + if (state) { + prev = state->warn; + state->warn = false; + } + } + ~NoWarn() { + if (state) { + state->warn = prev; + } + } + std::shared_ptr state; + bool prev{false}; +}; + +struct WithNestedTracingFrame { + WithNestedTracingFrame() { + getTracingState()->enterFrame(); + } + + ~WithNestedTracingFrame() { + getTracingState()->leaveFrame(); + } +}; +TORCH_API void recordSourceLocation(Node* n); +TORCH_API void setRecordSourceLocation(void (*v)(Node*)); + +TORCH_API std::vector pythonCallstack(); +TORCH_API void setPythonCallstack(std::vector (*v)()); + +// Having finished adding a new 'node' to the graph IR 'setValueTrace' +// associates this node with an output variable, so that further operations +// involving this variable know which node in the IR to reference. +TORCH_API void setValueTrace(const IValue& v, Value* value); + +TORCH_API void delValueTrace(const IValue& var); + +TORCH_API std::function pauseTracing(); + +TORCH_API Value* getValueTrace(const IValue& var); + +TORCH_API std::pair, Stack> trace( + Stack inputs, + const std::function& traced_fn, + std::function var_name_lookup_fn, + bool strict = true, + bool force_outplace = false, + Module* self = nullptr, + const std::vector& argument_names = {}); + +TORCH_API void abandon(); + +// NB: those serve both as an intermediate steps in addInputs below, +// as well as the overloads that terminate template recursion +TORCH_API void addInputs(Node* n, const char* name, int64_t value); +TORCH_API void addInputs(Node* n, const char* name, const c10::SymInt& value); +TORCH_API void addInputs( + Node* n, + const char* name, + std::optional value); +TORCH_API void addInputs(Node* n, const char* name, bool value); +TORCH_API void addInputs( + Node* n, + const char* name, + const std::optional& value); +TORCH_API void addInputs(Node* n, const char* name, double value); +TORCH_API void addInputs( + Node* n, + const char* name, + const std::optional& value); +TORCH_API void addInputs(Node* n, const char* name, const at::Scalar& value); +TORCH_API void addInputs( + Node* n, + const char* name, + const std::optional& value); +TORCH_API void addInputs(Node* n, const char* name, const at::Tensor& value); +TORCH_API void addInputs( + Node* n, + const char* name, + const std::optional& value); +TORCH_API void addInputs(Node* n, const char* name, ArrayRef value); +TORCH_API void addInputs(Node* n, const char* name, c10::SymIntArrayRef value); +TORCH_API void addInputs( + Node* n, + const char* name, + std::optional value); +TORCH_API void addInputs( + Node* n, + const char* name, + const std::optional>& value); +TORCH_API void addInputs( + Node* n, + const char* name, + const at::OptionalIntArrayRef& opt_value); +TORCH_API void addInputs( + Node* n, + const char* name, + const at::OptionalSymIntArrayRef& opt_value); +TORCH_API void addInputs( + Node* n, + const char* name, + ArrayRef value, + bool allow_undefined = false); +TORCH_API void addInputs( + Node* n, + const char* name, + const std::vector& value, + bool allow_undefined = false); +TORCH_API void addInputs( + Node* n, + const char* name, + at::ITensorListRef value, + bool allow_undefined = false); +TORCH_API void addInputs( + Node* n, + const char* name, + const List>& value); +TORCH_API void addInputs( + Node* n, + const char* name, + ArrayRef> value, + const c10::ClassTypePtr& class_type); +TORCH_API void addInputs(Node* n, const char* name, ArrayRef value); +TORCH_API void addInputs( + Node* n, + const char* name, + const std::optional>& value); +TORCH_API void addInputs( + Node* n, + const char* name, + const std::string_view value); +TORCH_API void addInputs( + Node* n, + const char* name, + const std::optional& value); +TORCH_API void addInputs(Node* n, const char* name, at::Device value); +TORCH_API void addInputs(Node* n, const char* name, c10::Stream stream); +TORCH_API void addInputs(Node* n, const char* name, at::Layout value); +TORCH_API void addInputs(Node* n, const char* name, at::ScalarType value); +TORCH_API void addInputs( + Node* n, + const char* name, + const std::optional& value); +TORCH_API void addInputs( + Node* n, + const char* name, + const std::optional& value); +TORCH_API void addInputs( + Node* n, + const char* name, + const std::optional& value); +TORCH_API void addInputs(Node* n, const char* name, at::MemoryFormat value); +TORCH_API void addInputs( + Node* n, + const char* name, + std::optional value); +TORCH_API void addInputs( + Node* n, + const char* name, + const std::optional& value); +TORCH_API void addInputs( + Node* n, + const char* name, + const std::optional& value); + +inline void addInputs( + Node* n, + const char* name, + const std::vector& value) { + TORCH_CHECK(false, "Tracing a list of bool type is currently not supported!"); +} + +template +void addInputs(Node* n, const char* name, ArrayRef value) { + TORCH_CHECK( + false, "Tracing a list of arbitrary type is currently not supported!"); +} +template +void addInputs( + Node* n, + const char* name, + const std::unordered_map& value) { + TORCH_CHECK( + false, "Tracing a dict of arbitrary types is currently not supported!"); +} + +template +void addInputs(Node* n, const char* name, std::array value) { + throw std::runtime_error( + "Found an unsupported argument type in the JIT tracer. File a bug report."); +} + +TORCH_API void addInputs( + Node* n, + const char* name, + const c10::intrusive_ptr& obj); + +TORCH_API void ensureUniqueIfOutOfPlaced( + const char* name, + const at::Tensor& tensor); +TORCH_API void ensureUniqueIfOutOfPlaced( + const char* name, + const std::optional& tensor); + +template < + typename T, + typename = std::enable_if_t< + (!std::is_convertible_v, at::TensorList> && + !std::is_convertible_v, c10::List> && + !std::is_convertible_v, at::Tensor> && + !std::is_convertible_v< + std::decay_t, + c10::intrusive_ptr>)>> +void addOutput(Node* node, T&& /*unused*/) { + TORCH_CHECK( + false, + "Found an unsupported argument type ", + c10::demangle_type(), + " in the JIT tracer. File a bug report."); +} +TORCH_API void addOutput(Node* node, const at::Tensor& tensor); +TORCH_API void setOutput(Value* value, const at::Tensor& output); +TORCH_API void addOutput(Node* node, const std::vector& list); +TORCH_API void addOutput(Node* node, const c10::List& list); +TORCH_API void addOutput( + Node* node, + const c10::intrusive_ptr& output); + +TORCH_API autograd::Variable getSizeOf( + const autograd::Variable& var, + int64_t dim); + +TORCH_API autograd::Variable getNumelOf(const autograd::Variable& var); + +} // namespace tracer +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/tree.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/tree.h new file mode 100644 index 0000000000000000000000000000000000000000..99ae0ff06622e087a299ade7da2b39419aa840f6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/tree.h @@ -0,0 +1,227 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace torch::jit { + +// Trees are used to represent all forms of TC IR, pre- and post-typechecking. +// Rather than have a full class hierarchy for all TC statements, trees are a +// slight variation of Lisp s-expressions. For instance, the expression a*b+1 +// is represented as: +// (+ (* (ident a) (ident b)) (const 1)) +// Atoms like 'a', 'b', and '1' are represented by subclasses of Tree which +// define stringValue(). Everything else is a Compound object, which has a +// 'kind' that is a token from lexer.h's TokenKind enum. Single-character +// operators like '+' are represented using the character itself (so, add.kind() +// would be '+'). Each Compound object also contains a list of subtrees and is +// associated with a SourceRange for error reporting. +// Memory management of trees is done using intrusive_ptr. + +struct Tree; +using TreeRef = c10::intrusive_ptr; +using TreeList = at::SmallVector; + +struct Tree : c10::intrusive_ptr_target { + Tree(int kind_) : kind_(kind_) {} + int kind() const { + return kind_; + } + virtual bool isAtom() const { + return true; + } + virtual const SourceRange& range() const { + TORCH_CHECK(false, "is an Atom"); + } + virtual const std::string& stringValue() const { + TORCH_CHECK(false, "stringValue can only be called on TK_STRING"); + } + virtual const TreeList& trees() const { + static const TreeList empty_trees = {}; + return empty_trees; + } + const TreeRef& tree(size_t i) const { + return trees().at(i); + } + virtual TreeRef map(const std::function& fn) { + (void)fn; + c10::raw::intrusive_ptr::incref(this); // we are creating a new pointer + // from a raw `this` pointer + // so we need to bump the refcount + // to account for this ownership + return TreeRef::reclaim(this); + } + template + void match(int k, Args&... args) const { + matchD(k, "unknown", 0, args...); + } + template + void matchD(int k, const char* filename, int lineno, Args&... args) const { + std::initializer_list vars = {args...}; + matchNumSubtreesD(k, filename, lineno, vars.size(), true); + size_t i = 0; + for (TreeRef* v : vars) { + *v = trees()[i++]; + } + } + void matchNumSubtrees(int k, size_t expected_subtrees) { + return matchNumSubtreesD(k, "unknown", 0, expected_subtrees, false); + } + void matchNumSubtreesD( + int k, + const char* filename, + int lineno, + size_t expected_subtrees, + bool allow_more) const { + TORCH_CHECK( + kind() == k, + filename, + ":", + lineno, + ": expecting kind '", + kindToString(k), + "' but found '", + kindToString(kind()), + "'\n"); + if (trees().size() < expected_subtrees || + (!allow_more && trees().size() != expected_subtrees)) { + std::stringstream ss; + ss << filename << ':' << lineno << ": expected at least " + << expected_subtrees << " subtrees, but found only " << trees().size() + << '\n'; + range().highlight(ss); + TORCH_CHECK(false, ss.str()); + } + } + ~Tree() override = default; + + private: + int kind_; +}; + +struct String : public Tree { + String(std::string value) : Tree(TK_STRING), value_(std::move(value)) {} + const std::string& stringValue() const override { + return value_; + } + template + static TreeRef create(Args&&... args) { + return c10::make_intrusive(std::forward(args)...); + } + + private: + std::string value_; +}; + +static SourceRange mergeRanges(SourceRange c, const TreeList& others) { + for (const auto& t : others) { + if (t->isAtom()) + continue; + size_t s = std::min(c.start(), t->range().start()); + size_t e = std::max(c.end(), t->range().end()); + c = SourceRange(c.source(), s, e); + } + return c; +} + +struct Compound : public Tree { + Compound(int kind, SourceRange range) + : Tree(kind), range_(std::move(range)) {} + Compound(int kind, const SourceRange& range_, TreeList&& trees_) + : Tree(kind), + range_(mergeRanges(range_, trees_)), + trees_(std::move(trees_)) {} + const TreeList& trees() const override { + return trees_; + } + static TreeRef create( + int kind, + const SourceRange& range_, + TreeList&& trees_) { + return c10::make_intrusive(kind, range_, std::move(trees_)); + } + bool isAtom() const override { + return false; + } + TreeRef map(const std::function& fn) override { + TreeList ret; + for (auto& t : trees()) { + ret.push_back(fn(t)); + } + return Compound::create(kind(), range(), std::move(ret)); + } + + const SourceRange& range() const override { + return range_; + } + + private: + SourceRange range_; + TreeList trees_; +}; + +// tree pretty printer +struct pretty_tree { + pretty_tree(const TreeRef& tree, size_t col = 40) : tree(tree), col(col) {} + const TreeRef& tree; + size_t col; + std::unordered_map flat_strings; + const std::string& get_flat(const TreeRef& t) { + auto it = flat_strings.find(t); + if (it != flat_strings.end()) + return it->second; + + std::stringstream out; + switch (t->kind()) { + case TK_STRING: + out << t->stringValue(); + break; + default: + out << '(' << kindToString(t->kind()); + for (const auto& e : t->trees()) { + out << ' ' << get_flat(e); + } + out << ')'; + break; + } + auto it_ = flat_strings.emplace(t, out.str()); + return it_.first->second; + } + void print(std::ostream& out, const TreeRef& t, int indent) { + const std::string& s = get_flat(t); + if (indent + s.size() < col || t->isAtom()) { + out << s; + return; + } + std::string k = kindToString(t->kind()); + out << '(' << k; + for (const auto& e : t->trees()) { + out << '\n' << std::string(indent + 2, ' '); + print(out, e, indent + 2); + } + out << ')'; + } +}; + +static inline std::ostream& operator<<(std::ostream& out, pretty_tree t_) { + t_.print(out, t_.tree, 0); + return out << '\n'; +} + +static inline std::ostream& operator<<(std::ostream& out, const TreeRef& t) { + return out << pretty_tree(t); +} + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/tree_views.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/tree_views.h new file mode 100644 index 0000000000000000000000000000000000000000..1dc386d938f69651b4f9dd3cf9d5a335531c63e1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/tree_views.h @@ -0,0 +1,1285 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace torch::jit { + +// clang-format off +// TreeView provides a statically-typed way to traverse the tree, which should +// be formed according to the grammar below. +// +// A few notes on types and their aliases: +// - List is really a Tree with kind TK_LIST and elements as subtrees +// - Maybe is really a Tree with kind TK_OPTION that has 0 or 1 subtree of type T +// - Builtin types are: Ident (TK_IDENT), String (TK_STRING) +// +// Param = Param(Maybe type, Ident name) TK_PARAM +// +// Decl = Decl(List params, Maybe return_type) TK_DECL +// Def = Def(Ident name, Decl decl, List body) TK_DEF +// ClassDef = ClassDef(Ident name, TK_CLASS_DEF +// Maybe superclass, +// List body) +// +// Stmt = If(Expr cond, List true_body, List false_body) TK_IF +// | For(List targets, List iters, List body) TK_FOR +// | While(Expr cond, List body) TK_WHILE +// | Global(List idents) TK_GLOBAL +// -- NB: the only type of Expr's allowed on lhs are Var +// Or a tuple containing Var with an optional terminating Starred +// | Assign(Expr lhs, Maybe rhs, Maybe type) TK_ASSIGN +// | AugAssign(Expr lhs, AugAssignKind aug_op, Expr rhs) TK_AUG_ASSIGN +// | Return(List values) TK_RETURN +// | ExprStmt(List expr) TK_EXPR_STMT +// | Raise(Expr expr) TK_RAISE +// | Def TK_DEF +// | With(List targets, List body) TK_WITH +// +// Expr = TernaryIf(Expr cond, Expr true_expr, Expr false_expr) TK_IF_EXPR +// | BinOp(Expr lhs, Expr rhs) +// | And TK_AND +// | Or TK_OR +// | Lt '<' +// | Gt '>' +// | Eq TK_EQ +// | Le TK_LE +// | Ge TK_GE +// | Ne TK_NE +// | Is TK_IS +// | IsNot TK_ISNOT +// | Add '+' +// | Sub '-' +// | Mul '*' +// | Div '/' +// | Mod '%' +// | MatMult '@' +// | Pow TK_POW +// | UnaryOp(Expr expr) +// | Not TK_NOT +// | USub '-' +// | Const(String value) TK_CONST +// -- NB: x.name(y) is desugared into name(x, y) +// | Apply(Ident name, List args, List kwargs) TK_APPLY +// | Select(Expr value, Ident selector) '.' +// | Subscript(Expr value, List subscript_exprs) TK_SUBSCRIPT +// | SliceExpr(Maybe start, Maybe end) TK_SLICE_EXPR +// | Var(Ident name) TK_VAR +// | ListLiteral(List inputs) TK_LIST_LITERAL +// | TupleLiteral(List inputs) TK_TUPLE_LITERAL +// | Starred(Expr expr) TK_STARRED +// | WithItem(Expr target, Maybe var) TK_WITH_ITEM +// -- NB: only allowed expressions are Const or List(Const) +// (List as a value, not type constructor) +// Attribute = Attribute(Ident name, Expr value) TK_ATTRIBUTE +// +// AugAssignKind = +// | Add() TK_PLUS_EQ +// | Sub() TK_MINUS_EQ +// | Mul() TK_TIMES_EQ +// | Div() TK_DIV_EQ +// | Mod() TK_MOD_EQ +// + +// Each subclass of TreeView should provide: +// 1. Constructor that takes a TreeRef, and checks that it's of the right type. +// 2. Accessors that get underlying information out of the object. If they +// return subtrees, they should wrap them in appropriate views too. +// 3. Static method 'create' that creates the underlying TreeRef object +// for every TreeRef kind that has a TreeView, the parser always uses +// (e.g.) Ident::create rather than Compound::Create, this means that +// changes to the structure of Ident are always made right here rather +// than both in the parser and in this code. +// XXX: these structs should have no fields to prevent slicing when passing by value +// clang-format on +struct TreeView { + explicit TreeView(TreeRef tree) : tree_(std::move(tree)) {} + TreeRef tree() const { + return tree_; + } + const SourceRange& range() const { + return tree_->range(); + } + operator TreeRef() const { + return tree_; + } + const TreeRef& get() const { + return tree_; + } + int kind() const { + return tree_->kind(); + } + void dump() const { + std::cout << tree_; + } + + protected: + const TreeRef& subtree(size_t i) const { + return tree_->trees().at(i); + } + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + TreeRef tree_; +}; + +template +struct ListIterator { + ListIterator(TreeList::const_iterator it) : it(it) {} + bool operator!=(const ListIterator& rhs) const { + return it != rhs.it; + } + bool operator==(const ListIterator& rhs) const { + return it == rhs.it; + } + T operator*() const { + return T(*it); + } + ListIterator& operator+=(std::ptrdiff_t n) { + it += n; + return *this; + } + ListIterator& operator++() { + ++it; + return *this; + } + ListIterator& operator--() { + --it; + return *this; + } + + private: + TreeList::const_iterator it; +}; + +template +struct List : public TreeView { + using iterator = ListIterator; + using const_iterator = ListIterator; + + List(const TreeRef& tree) : TreeView(tree) { + tree->match(TK_LIST); + // Iterate over list to temporarily instantiate Ts that will check the type + for (const T& elem : *this) { + (void)elem; // silence unused warning + } + } + iterator begin() const { + return iterator(tree_->trees().begin()); + } + iterator end() const { + return iterator(tree_->trees().end()); + } + bool empty() const { + return tree_->trees().begin() == tree_->trees().end(); + } + T operator[](size_t i) const { + return T(subtree(i)); + } + TreeRef map(const std::function& fn) { + return tree_->map([&](TreeRef v) { return fn(T(v)); }); + } + static List create(const SourceRange& range, const std::vector& subtrees) { + TreeList type_erased_sub{subtrees.begin(), subtrees.end()}; + return List(Compound::create(TK_LIST, range, std::move(type_erased_sub))); + } + static List unsafeCreate(const SourceRange& range, TreeList&& subtrees) { + return List(Compound::create(TK_LIST, range, std::move(subtrees))); + } + size_t size() const { + return tree_->trees().size(); + } +}; + +template +struct Maybe : public TreeView { + explicit Maybe(const TreeRef& tree) : TreeView(tree) { + tree_->match(TK_OPTION); + if (tree_->trees().size() > 1) + throw(ErrorReport(tree) << "Maybe trees can have at most one subtree"); + } + /* implicit */ Maybe(const T& tree) : TreeView(tree) {} + bool present() const { + return tree_->trees().size() > 0; + } + T get() const { + return T(tree_->trees().at(0)); + } + TreeRef map(const std::function& fn) { + return tree_->map([&](TreeRef v) { return fn(T(v)); }); + } + static Maybe create(const SourceRange& range) { + return Maybe(Compound::create(TK_OPTION, range, {})); + } + static Maybe create(const SourceRange& range, const T& value) { + return Maybe(Compound::create(TK_OPTION, range, {value})); + } +}; + +struct Ident : public TreeView { + explicit Ident(const TreeRef& tree) : TreeView(tree) { + tree_->match(TK_IDENT); + } + const std::string& name() const { + return subtree(0)->stringValue(); + } + static Ident create(const SourceRange& range, std::string name) { + return Ident( + Compound::create(TK_IDENT, range, {String::create(std::move(name))})); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Base types (production LHS) +//////////////////////////////////////////////////////////////////////////////// + +struct Stmt : public TreeView { + explicit Stmt(const TreeRef& tree) : TreeView(tree) { + switch (tree->kind()) { + case TK_IF: + case TK_FOR: + case TK_WHILE: + case TK_GLOBAL: + case TK_ASSIGN: + case TK_AUG_ASSIGN: + case TK_RETURN: + case TK_EXPR_STMT: + case TK_RAISE: + case TK_ASSERT: + case TK_PASS: + case TK_BREAK: + case TK_DELETE: + case TK_CONTINUE: + case TK_DEF: + case TK_WITH: + return; + default: + throw( + ErrorReport(tree) + << kindToString(tree->kind()) << " is not a valid Stmt"); + } + } +}; + +struct Expr : public TreeView { + explicit Expr(const TreeRef& tree) : TreeView(tree) { + switch (tree->kind()) { + case TK_IF_EXPR: + case TK_AND: + case TK_OR: + case '<': + case '>': + case TK_IS: + case TK_ISNOT: + case TK_EQ: + case TK_LE: + case TK_GE: + case TK_NE: + case '+': + case '-': + case TK_UNARY_MINUS: + case '~': + case '*': + case TK_STARRED: + case '/': + case '%': + case TK_NOT: + case TK_CONST: + case TK_STRINGLITERAL: + case TK_TRUE: + case TK_FALSE: + case TK_NONE: + case TK_NONE_TYPE: + case TK_CAST: + case TK_APPLY: + case '.': + case TK_SUBSCRIPT: + case TK_SLICE_EXPR: + case TK_VAR: + case TK_LIST_LITERAL: + case TK_TUPLE_LITERAL: + case TK_DICT_LITERAL: + case '@': + case TK_POW: + case TK_LSHIFT: + case TK_RSHIFT: + case TK_FLOOR_DIV: + case '&': + case '^': + case '|': + case TK_LIST_COMP: + case TK_DICT_COMP: + case TK_DOTS: + case TK_IN: + case TK_WITH_ITEM: + return; + default: + throw( + ErrorReport(tree) + << kindToString(tree->kind()) << " is not a valid Expr"); + } + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Helper nodes (mostly for function arguments) +//////////////////////////////////////////////////////////////////////////////// + +struct Attribute : public TreeView { + explicit Attribute(const TreeRef& tree) : TreeView(tree) { + tree_->match(TK_ATTRIBUTE); + } + Ident name() const { + return Ident(subtree(0)); + } + Expr value() const { + return Expr(subtree(1)); + } + static Attribute create( + const SourceRange& range, + const Ident& name, + const TreeRef& value) { + return Attribute(Compound::create(TK_ATTRIBUTE, range, {name, value})); + } +}; + +struct Param : public TreeView { + explicit Param(const TreeRef& tree) : TreeView(tree) { + tree_->match(TK_PARAM); + } + static Param create( + const SourceRange& range, + const Ident& ident, + const Maybe& type, + const Maybe& def, + bool kwarg_only) { + TreeRef kwarg_only_tree = + Compound::create(kwarg_only ? TK_TRUE : TK_FALSE, range, {}); + return Param(Compound::create( + TK_PARAM, range, {ident, type, def, std::move(kwarg_only_tree)})); + } + Ident ident() const { + return Ident(subtree(0)); + } + Maybe type() const { + return Maybe(subtree(1)); + } + Maybe defaultValue() const { + return Maybe(subtree(2)); + } + bool kwarg_only() const { + return TK_TRUE == subtree(3)->kind(); + } + Param withType(const Maybe& typ) const { + return Param::create(range(), ident(), typ, defaultValue(), kwarg_only()); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Top level definitions +//////////////////////////////////////////////////////////////////////////////// + +struct Decl : public TreeView { + explicit Decl(const TreeRef& tree) : TreeView(tree) { + tree->match(TK_DECL); + } + List params() const { + return List(subtree(0)); + } + Maybe return_type() const { + return Maybe(subtree(1)); + } + static Decl create( + const SourceRange& range, + const List& params, + const Maybe& return_type) { + return Decl(Compound::create(TK_DECL, range, {params, return_type})); + } +}; + +struct Def : public TreeView { + explicit Def(const TreeRef& tree) : TreeView(tree) { + tree->match(TK_DEF); + } + Def withName(std::string new_name) const { + auto new_ident = Ident::create(name().range(), std::move(new_name)); + return create(range(), new_ident, decl(), statements()); + } + Def withDecl(const Decl& decl) const { + return create(range(), name(), decl, statements()); + } + Ident name() const { + return Ident(subtree(0)); + } + Decl decl() const { + return Decl(subtree(1)); + } + List statements() const { + return List(subtree(2)); + } + static Def create( + const SourceRange& range, + const Ident& name, + const Decl& decl, + const List& stmts) { + return Def(Compound::create(TK_DEF, range, {name, decl, stmts})); + } +}; + +// Property represents a named attribute combined with a getter and setter +// method to access and mutate that attribute. +struct Property : public TreeView { + explicit Property(const TreeRef& tree) : TreeView(tree) { + tree->match(TK_PROP); + } + Ident name() const { + return Ident(subtree(0)); + } + Def getter() const { + return Def(subtree(1)); + } + Maybe setter() const { + return Maybe(subtree(2)); + } + static Property create( + const SourceRange& range, + const Ident& name, + const Def& getter, + const Maybe& setter) { + return Property(Compound::create(TK_PROP, range, {name, getter, setter})); + } +}; + +struct Assign; + +struct ClassDef : public TreeView { + explicit ClassDef(const TreeRef& tree) : TreeView(tree) { + tree->match(TK_CLASS_DEF); + } + explicit ClassDef(TreeRef&& tree) : TreeView(std::move(tree)) { + tree_->match(TK_CLASS_DEF); + } + ClassDef withName(std::string new_name) const { + auto new_ident = Ident::create(name().range(), std::move(new_name)); + return create(range(), new_ident, superclass(), body()); + } + Ident name() const { + return Ident(subtree(0)); + } + Maybe superclass() const { + return Maybe(subtree(1)); + } + List body() const { + return List(subtree(2)); + } + Maybe> properties() const { + return Maybe>(subtree(3)); + } + Maybe> assigns() const { + return Maybe>(subtree(4)); + } + static ClassDef create( + const SourceRange& range, + const Ident& name, + const Maybe& superclass, + const List& body) { + return ClassDef(Compound::create( + TK_CLASS_DEF, + range, + {name, + superclass, + body, + Maybe>::create(range), + Maybe>::create(range)})); + } + static ClassDef create( + const SourceRange& range, + const Ident& name, + const Maybe& superclass, + const List& body, + const List& properties, + const List& assigns); +}; + +TORCH_API std::vector getUnresolvedClassAttributes( + const ClassDef& def); + +//////////////////////////////////////////////////////////////////////////////// +// Statements +//////////////////////////////////////////////////////////////////////////////// + +struct If : public Stmt { + explicit If(const TreeRef& tree) : Stmt(tree) { + tree_->match(TK_IF); + } + Expr cond() const { + return Expr(subtree(0)); + } + List trueBranch() const { + return List(subtree(1)); + } + List falseBranch() const { + return List(subtree(2)); + } + If withNewBranches( + const List& true_branch, + const List& false_branch) const { + return create(range(), cond(), true_branch, false_branch); + } + static If create( + const SourceRange& range, + const Expr& cond, + const List& true_branch, + const List& false_branch) { + return If( + Compound::create(TK_IF, range, {cond, true_branch, false_branch})); + } +}; + +struct While : public Stmt { + explicit While(const TreeRef& tree) : Stmt(tree) { + tree_->match(TK_WHILE); + } + Expr cond() const { + return Expr(subtree(0)); + } + List body() const { + return List(subtree(1)); + } + static While create( + const SourceRange& range, + const Expr& cond, + const List& body) { + return While(Compound::create(TK_WHILE, range, {cond, body})); + } +}; + +struct For : public Stmt { + explicit For(const TreeRef& tree) : Stmt(tree) { + tree->match(TK_FOR); + } + List targets() const { + return List(subtree(0)); + } + List itrs() const { + return List(subtree(1)); + } + List body() const { + return List(subtree(2)); + } + static For create( + const SourceRange& range, + const List& targets, + const List& itrs, + const List& body) { + return For(Compound::create(TK_FOR, range, {targets, itrs, body})); + } +}; + +// TODO: supports only single comprehension for now +struct ListComp : public Expr { + explicit ListComp(const TreeRef& tree) : Expr(tree) { + tree->match(TK_LIST_COMP); + } + Expr elt() const { + return Expr(subtree(0)); + } + Expr target() const { + return Expr(subtree(1)); + } + Expr iter() const { + return Expr(subtree(2)); + } + // TODO: no ifs for now + static ListComp create( + const SourceRange& range, + const Expr& elt, + const Expr& target, + const Expr& iter) { + return ListComp(Compound::create(TK_LIST_COMP, range, {elt, target, iter})); + } +}; + +// TODO: supports only single comprehension for now +struct DictComp : public Expr { + explicit DictComp(const TreeRef& tree) : Expr(tree) { + tree->match(TK_DICT_COMP); + } + Expr key() const { + return Expr(subtree(0)); + } + Expr value() const { + return Expr(subtree(1)); + } + Expr target() const { + return Expr(subtree(2)); + } + Expr iter() const { + return Expr(subtree(3)); + } + // TODO: no ifs for now + static DictComp create( + const SourceRange& range, + const Expr& key, + const Expr& value, + const Expr& target, + const Expr& iter) { + return DictComp( + Compound::create(TK_DICT_COMP, range, {key, value, target, iter})); + } +}; + +struct Global : public Stmt { + explicit Global(const TreeRef& tree) : Stmt(tree) { + tree_->match(TK_GLOBAL); + } + List names() { + return List(subtree(0)); + } + static Global create(const SourceRange& range, const List& names) { + return Global(Compound::create(TK_GLOBAL, range, {names})); + } +}; + +struct AugAssignKind : public TreeView { + explicit AugAssignKind(const TreeRef& tree) : TreeView(tree) { + switch (tree->kind()) { + case '+': + case '-': + case '*': + case '/': + case '%': + case '|': + case '&': + case '^': + case TK_POW: + case TK_LSHIFT: + case TK_RSHIFT: + return; + default: + throw(ErrorReport(tree) << "is not a valid AugAssignKind"); + } + } +}; + +// Augmented assignment, like "foo += bar" +struct AugAssign : public Stmt { + explicit AugAssign(const TreeRef& tree) : Stmt(tree) { + tree_->match(TK_AUG_ASSIGN); + } + static AugAssign create( + const SourceRange& range, + const Expr& lhs, + const AugAssignKind& aug_op, + const Expr& rhs) { + return AugAssign( + Compound::create(TK_AUG_ASSIGN, range, {lhs, aug_op, rhs})); + } + Expr lhs() const { + return Expr(subtree(0)); + } + int aug_op() const { + return subtree(1)->kind(); + } + Expr rhs() const { + return Expr(subtree(2)); + } +}; + +struct Assign : public Stmt { + explicit Assign(const TreeRef& tree) : Stmt(tree) { + tree_->match(TK_ASSIGN); + } + static Assign create( + const SourceRange& range, + const List& lhs, + const Maybe& rhs, + const Maybe& type) { + return Assign(Compound::create(TK_ASSIGN, range, {lhs, rhs, type})); + } + + List lhs_list() const { + return List(subtree(0)); + } + + Expr lhs() const { + const auto& li = lhs_list(); + TORCH_INTERNAL_ASSERT(li.size() == 1); + return *li.begin(); + } + + Maybe rhs() const { + return Maybe(subtree(1)); + } + + Maybe type() const { + return Maybe(subtree(2)); + } +}; + +struct Return : public Stmt { + explicit Return(const TreeRef& tree) : Stmt(tree) { + tree_->match(TK_RETURN); + } + Expr expr() const { + return Expr(subtree(0)); + } + static Return create(const SourceRange& range, const Expr& value) { + return Return(Compound::create(TK_RETURN, range, {value})); + } +}; + +struct Raise : public Stmt { + explicit Raise(const TreeRef& tree) : Stmt(tree) { + tree_->match(TK_RAISE); + } + Expr expr() const { + return Expr(subtree(0)); + } + static Raise create(const SourceRange& range, const Expr& expr) { + return Raise(Compound::create(TK_RAISE, range, {expr})); + } +}; + +struct Assert : public Stmt { + explicit Assert(const TreeRef& tree) : Stmt(tree) { + tree_->match(TK_ASSERT); + } + Expr test() const { + return Expr(subtree(0)); + } + Maybe msg() const { + return Maybe(subtree(1)); + } + static Assert create( + const SourceRange& range, + const Expr& test, + const Maybe& msg) { + return Assert(Compound::create(TK_ASSERT, range, {test, msg})); + } +}; + +struct Pass : public Stmt { + explicit Pass(const TreeRef& tree) : Stmt(tree) { + tree_->match(TK_PASS); + } + static Pass create(const SourceRange& range) { + return Pass(Compound::create(TK_PASS, range, {})); + } +}; + +struct Dots : public Expr { + explicit Dots(const TreeRef& tree) : Expr(tree) { + tree_->match(TK_DOTS); + } + static Dots create(const SourceRange& range) { + return Dots(Compound::create(TK_DOTS, range, {})); + } +}; + +struct Break : public Stmt { + explicit Break(const TreeRef& tree) : Stmt(tree) { + tree_->match(TK_BREAK); + } + static Break create(const SourceRange& range) { + return Break(Compound::create(TK_BREAK, range, {})); + } +}; + +struct Continue : public Stmt { + explicit Continue(const TreeRef& tree) : Stmt(tree) { + tree_->match(TK_CONTINUE); + } + static Continue create(const SourceRange& range) { + return Continue(Compound::create(TK_CONTINUE, range, {})); + } +}; + +struct ExprStmt : public Stmt { + explicit ExprStmt(const TreeRef& tree) : Stmt(tree) { + tree_->match(TK_EXPR_STMT); + } + Expr expr() { + return Expr(subtree(0)); + } + static ExprStmt create(const SourceRange& range, const Expr& list) { + return ExprStmt(Compound::create(TK_EXPR_STMT, range, {list})); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Expressions +//////////////////////////////////////////////////////////////////////////////// + +struct BinOp : public Expr { + explicit BinOp(const TreeRef& tree) : Expr(tree) { + switch (tree->kind()) { + case TK_AND: + case TK_OR: + case '<': + case '>': + case TK_IS: + case TK_ISNOT: + case TK_EQ: + case TK_LE: + case TK_GE: + case TK_NE: + case '+': + case '*': + case '/': + case '-': + case '@': + case TK_POW: + case TK_LSHIFT: + case TK_RSHIFT: + case '%': + case '&': + case '^': + case '|': + case TK_FLOOR_DIV: + case TK_IN: + if (tree->trees().size() != 2) + throw( + ErrorReport(tree) + << "BinOp expected 2 subtrees, found " << tree->trees().size()); + return; + default: + throw( + ErrorReport(tree) + << kindToString(tree->kind()) << " is not a valid BinOp"); + } + } + Expr lhs() const { + return Expr(subtree(0)); + } + Expr rhs() const { + return Expr(subtree(1)); + } + static BinOp create( + const SourceRange& range, + int kind, + const Expr& lhs, + const Expr& rhs) { + return BinOp(Compound::create(kind, range, {lhs, rhs})); + } +}; + +struct UnaryOp : public Expr { + explicit UnaryOp(const TreeRef& tree) : Expr(tree) { + switch (tree->kind()) { + case TK_UNARY_MINUS: + case '~': + case TK_NOT: + if (tree->trees().size() != 1) + throw( + ErrorReport(tree) + << "UnaryOp expected 1 subtree, found " << tree->trees().size()); + return; + default: + throw( + ErrorReport(tree) + << kindToString(tree->kind()) << " is not a valid UnaryOp"); + } + } + static UnaryOp create(const SourceRange& range, int kind, const Expr& expr) { + return UnaryOp(Compound::create(kind, range, {expr})); + } +}; + +struct Const : public Expr { + explicit Const(const TreeRef& tree) : Expr(tree) { + tree_->matchNumSubtrees(TK_CONST, 1); + } + bool isFloatingPoint() const { + if (isComplex()) + return false; + + bool is_inf = subtree(0)->stringValue() == "inf"; + return is_inf || + subtree(0)->stringValue().find_first_of(".eE") != std::string::npos; + } + bool isIntegral() const { + return !isFloatingPoint() && !isComplex(); + } + bool isComplex() const { + return subtree(0)->stringValue().find_first_of('j') != std::string::npos; + } + int64_t asIntegral() const { + try { + return std::stoll(subtree(0)->stringValue(), nullptr, 0); + } catch (const std::out_of_range&) { + throw( + ErrorReport(range()) << "Integral constant out of range " + "(must fit in a signed 64 bit integer)"); + } + } + double asFloatingPoint() const { + // We can't pass in nullptr as the dummy pointer gets dereferenced for + // Android version of strtod_c(). + char* dummy = nullptr; + return torch::jit::strtod_c(subtree(0)->stringValue().c_str(), &dummy); + } + c10::complex asComplex() const { + char* dummy = nullptr; + auto str = subtree(0)->stringValue(); + // Complex numbers (a+bj, where a is non-zero) are parsed as an addition + // between float/int a and a complex number "bj". When a is 0, a complex + // number bj is created as above. So, while parsing the string, we don't + // have to worry about the real component of the complex number. + auto imag = + torch::jit::strtod_c(str.substr(0, str.size() - 1).c_str(), &dummy); + return c10::complex(0, imag); + } + const std::string& text() const { + return subtree(0)->stringValue(); + } + static Const create(const SourceRange& range, const std::string& value) { + return Const(Compound::create(TK_CONST, range, {String::create(value)})); + } +}; + +struct StringLiteral : public Expr { + explicit StringLiteral(const TreeRef& tree) : Expr(tree) { + tree_->matchNumSubtrees(TK_STRINGLITERAL, 1); + } + const std::string& text() const { + return subtree(0)->stringValue(); + } + static StringLiteral create( + const SourceRange& range, + const std::string& value) { + return StringLiteral( + Compound::create(TK_STRINGLITERAL, range, {String::create(value)})); + } +}; + +struct Apply : public Expr { + explicit Apply(const TreeRef& tree) : Expr(tree) { + tree_->match(TK_APPLY); + } + Expr callee() const { + return Expr(subtree(0)); + } + List inputs() const { + return List(subtree(1)); + } + List attributes() const { + return List(subtree(2)); + } + static Apply create( + const SourceRange& range, + const Expr& callee, + const List& inputs, + const List& attributes) { + return Apply( + Compound::create(TK_APPLY, range, {callee, inputs, attributes})); + } +}; + +struct Select : public Expr { + explicit Select(const TreeRef& tree) : Expr(tree) { + tree_->match('.'); + } + Expr value() const { + return Expr(subtree(0)); + } + Ident selector() const { + return Ident(subtree(1)); + } + static Select create( + const SourceRange& range, + const Expr& value, + const Ident& selector) { + return Select(Compound::create('.', range, {value, selector})); + } +}; + +struct SliceExpr : public Expr { + explicit SliceExpr(const TreeRef& tree) : Expr(tree) { + tree_->match(TK_SLICE_EXPR); + } + Maybe start() const { + return Maybe(subtree(0)); + } + Maybe end() const { + return Maybe(subtree(1)); + } + Maybe step() const { + return Maybe(subtree(2)); + } + Expr startOr(int64_t alternative) const { + const auto startOption = start(); + return startOption.present() ? startOption.get() : createInt(alternative); + } + Expr endOr(int64_t alternative) const { + const auto endOption = end(); + return endOption.present() ? endOption.get() : createInt(alternative); + } + Expr stepOr(int64_t alternative) const { + const auto stepOption = step(); + return stepOption.present() ? stepOption.get() : createInt(alternative); + } + static SliceExpr create( + const SourceRange& range, + const Maybe& start, + const Maybe& end, + const Maybe& step) { + return SliceExpr( + Compound::create(TK_SLICE_EXPR, range, {start, end, step})); + } + + private: + Expr createInt(int64_t value) const { + return Expr(Const::create(range(), std::to_string(value))); + } +}; + +struct Subscript : public Expr { + explicit Subscript(const TreeRef& tree) : Expr(tree) { + tree_->match(TK_SUBSCRIPT); + } + Expr value() const { + return Expr(subtree(0)); + } + List subscript_exprs() const { + return List(subtree(1)); + } + static Subscript create( + const SourceRange& range, + const Expr& value, + const List& subscript_exprs) { + auto whole_range = SourceRange( + range.source(), range.start(), subscript_exprs.range().end() + 1); + return Subscript( + Compound::create(TK_SUBSCRIPT, whole_range, {value, subscript_exprs})); + } +}; + +struct Var : public Expr { + explicit Var(const TreeRef& tree) : Expr(tree) { + tree_->match(TK_VAR); + } + Ident name() const { + return Ident(subtree(0)); + } + static Var create(const SourceRange& range, const Ident& name) { + return Var(Compound::create(TK_VAR, range, {name})); + } +}; + +// WithItem represents an item using with a WithStmt. +struct WithItem : public Expr { + explicit WithItem(const TreeRef& tree) : Expr(tree) { + tree_->match(TK_WITH_ITEM); + } + + Expr target() const { + return Expr(subtree(0)); + } + + Maybe var() const { + return Maybe(subtree(1)); + } + + static WithItem create( + const SourceRange& range, + const Expr& target, + const Maybe& var) { + return WithItem(Compound::create(TK_WITH_ITEM, range, {target, var})); + } +}; + +// With represents a with statement consisting of a list of with items and a +// body of statements. +struct With : public Stmt { + explicit With(const TreeRef& tree) : Stmt(tree) { + tree_->match(TK_WITH); + } + + List targets() const { + return List(subtree(0)); + } + + List body() const { + return List(subtree(1)); + } + + static With create( + const SourceRange& range, + const List& targets, + const List& body) { + return With(Compound::create(TK_WITH, range, {targets, body})); + } +}; + +struct TernaryIf : public Expr { + explicit TernaryIf(const TreeRef& tree) : Expr(tree) { + tree_->matchNumSubtrees(TK_IF_EXPR, 3); + } + Expr cond() const { + return Expr(subtree(0)); + } + Expr true_expr() const { + return Expr(subtree(1)); + } + Expr false_expr() const { + return Expr(subtree(2)); + } + static TernaryIf create( + const SourceRange& range, + const Expr& cond, + const Expr& true_expr, + const Expr& false_expr) { + return TernaryIf( + Compound::create(TK_IF_EXPR, range, {cond, true_expr, false_expr})); + } +}; + +struct ListLiteral : public Expr { + explicit ListLiteral(const TreeRef& tree) : Expr(tree) { + tree_->match(TK_LIST_LITERAL); + } + List inputs() const { + return subtree(0); + } + static ListLiteral create( + const SourceRange& range, + const List& inputs) { + return ListLiteral(Compound::create(TK_LIST_LITERAL, range, {inputs})); + } +}; + +struct TupleLiteral : public Expr { + explicit TupleLiteral(const TreeRef& tree) : Expr(tree) { + tree_->match(TK_TUPLE_LITERAL); + } + List inputs() const { + return subtree(0); + } + static TupleLiteral create( + const SourceRange& range, + const List& inputs) { + return TupleLiteral(Compound::create(TK_TUPLE_LITERAL, range, {inputs})); + } +}; + +struct DictLiteral : public Expr { + explicit DictLiteral(const TreeRef& tree) : Expr(tree) { + tree_->match(TK_DICT_LITERAL); + } + List key_inputs() const { + return subtree(0); + } + List value_inputs() const { + return subtree(1); + } + static DictLiteral create( + const SourceRange& range, + const List& keys, + const List& values) { + return DictLiteral( + Compound::create(TK_DICT_LITERAL, range, {keys, values})); + } +}; + +struct Starred : public Expr { + explicit Starred(const TreeRef& tree) : Expr(tree) { + tree_->match(TK_STARRED); + } + Expr expr() const { + return Expr(subtree(0)); + } + static Starred create(const SourceRange& range, const Expr& expr) { + return Starred(Compound::create(TK_STARRED, range, {expr})); + } +}; + +struct Delete : public Stmt { + explicit Delete(const TreeRef& tree) : Stmt(tree) { + tree_->match(TK_DELETE); + } + List targets() const { + return subtree(0); + } + static Delete create(const SourceRange& range, const List& targets) { + return Delete(Compound::create(TK_DELETE, range, {targets})); + } +}; + +/* + * NOTE: transforming PEP 604 union into equivalent union type + * + * NOTE: Union[int, float] parses into: + * expr:(subscript + * (variable (ident Union)) + * (list + * (variable (ident int)) + * (variable (ident float)))) + * subscript + * + * NOTE: (int | float) parses into: + * expr:(| + * (variable (ident int)) + * (variable (ident float))) + * | + */ + +inline void _flatten_pep604_union( + const torch::jit::Expr& node, + std::vector* result) { + // flatten possibly nested union expressions like (int | (float | str)) + // into a flat list of expressions like [int, float, str] + if (node.kind() == '|') { + auto as_binop = torch::jit::BinOp(node); + _flatten_pep604_union(as_binop.lhs(), result); + _flatten_pep604_union(as_binop.rhs(), result); + } else { + result->push_back(node); + } +} + +inline std::vector get_pep604_union_members(const Expr& node) { + std::vector result; + _flatten_pep604_union(node, &result); + return result; +} + +// Flattens a PEP 604 union into a classical union. +// For example, ((x | y) | z) is transformed into Union[x, y, z]. +inline Expr pep604union_to_union(const Expr& expr) { + // noop if not a pep604 union + if (expr.kind() != '|') + return expr; + + // In order to support unions with more than 2 operands ((x|y)|z), we need to + // recursively flatten the tree of | expressions. + auto members = get_pep604_union_members(expr); + auto synthesised_union = Subscript::create( + expr.range(), + Var::create(expr.range(), Ident::create(expr.range(), "Union")), + List::create(expr.range(), members)); +#if defined(__clang__) + return std::move(synthesised_union); +#else + return synthesised_union; +#endif +} + +} // namespace torch::jit + +namespace std { + +template +struct iterator_traits> + : std::iterator_traits {}; + +} // namespace std + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/versioned_symbols.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/versioned_symbols.h new file mode 100644 index 0000000000000000000000000000000000000000..b8cb099cc27a3237256f2fa139e1973efc4f6ea7 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/frontend/versioned_symbols.h @@ -0,0 +1,24 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include + +namespace torch::jit { +// Maps the given symbol into an implementation of its behavior at the +// given version. +// See note [Versioned Symbols] +TORCH_API Symbol +get_symbol_for_version(const Symbol name, const uint64_t version); + +// Maps the given kind to the minimum version that supports it. +// See note [Dynamic Versions and torch.jit.save vs. torch.save] +TORCH_API uint64_t get_min_version_for_kind(const NodeKind& kind); +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/alias_analysis.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/alias_analysis.h new file mode 100644 index 0000000000000000000000000000000000000000..598426bd6807d67c4e9c8e00441bb0680e0ca91a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/alias_analysis.h @@ -0,0 +1,368 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace torch::jit { + +class ValueAndMemoryLocationSet; + +/** + * Alias analysis pass. + * + * This pass produces an AliasDb that contains aliasing and mutation + * information about the graph. Users can use this information to determine + * whether mutations to the graph are safe, i.e. they don't reorder/change + * nodes in a way that affects output. + * + * Every value with a mutable type (Tensors, Lists, Tuples, etc.) will be + * associated with one or more "alias sets". If two values share an alias set, + * that means they may alias, implying that a mutation to one value cannot be + * reordered past a use of the other. Only reordering two reads of an alias set + * is considered safe. + * + * There is a special alias set called the "wildcard set", which indicates that + * we're not sure what this value may alias. To be conservative, we consider the + * wildcard alias set as potentially aliasing any other wildcard value within + * the same type class. Whenever a value becomes contained by another value, + * such as when a Tensor is appended to a List[Tensor], the contained element + * becomes part of the wildcard set. + * + * Values that contain other mutable types, such as List[Tensor], are + * initialized as containing the Wildcard set for all contained mutable types. + * + * The AliasDb API references the idea of "mutable" vs "immutable" + * types. "Mutable" means that the object's value can change, while + * "immutable" means that the value is fixed. (For example, `List` is + * mutable, so you can add and delete elements from it. On the other + * hand, you can't modify a Tuple once you create it, making `Tuple` an + * immutable container.) + * + * `isFrozen` - if the Module is frozen then consider attributes as freshly + * created objects. Freezing API invokes alias analysis to check if they are + * mutated internally. + * + * `descendFunctionCalls` - recursively analyze function and method calls + * instead of conservative analysis. Generally analysis should be done after + * inlining so the implementation for recursive analysis is unoptimized. + */ +class AliasDb { + public: + TORCH_API explicit AliasDb( + std::shared_ptr graphi, + bool isFrozen = false, + bool descendFunctionCalls = false); + TORCH_API ~AliasDb(); + + // There are limitations to what effects the alias analysis can track. Two + // kinds of nodes may have untracked effects: + // 1. Nodes that write to a value that may alias the graph inputs (since + // the inputs can be used outside the graph). + // 2. Nodes that write to something in the wildcard set. + // + // These nodes are considered not safe to eliminate or mutate under any + // circumstances. + bool writesToWildcard(Node* n) const; + + // Does `n` write to an alias of one of the values in `vs`? + // if `recurseBlocks` is true, consider writes on the nodes in `n`s sub-blocks + TORCH_API bool writesToAlias(Node* n, const ValueSet& vs) const; + + // Does `n` write to any of the values in `vls`? + TORCH_API bool writesToAlias(Node* n, const ValueAndMemoryLocationSet& vls) + const; + + TORCH_API ValueAndMemoryLocationSet getValueAndMemoryLocationSet() const; + + // Does `a` and `b` potentially share a memory location or do either + // hold in memory any element that exists in the other + TORCH_API bool mayContainAlias(Value* a, Value* b) const; + + TORCH_API bool mayContainAlias(Value* a, const at::ArrayRef b) const; + + // Do any values in group `a` share a memory location or hold in memory + // any element that exists in group `b` + TORCH_API bool mayContainAlias( + const at::ArrayRef a, + const at::ArrayRef b) const; + + // Do `a` and `b` potentially share a memory location? + TORCH_API bool mayAlias(const Value* a, const Value* b) const; + // Do any values in group `a` potentially share a memory location with any + // value in group `b`? i.e. may they overlap? + TORCH_API bool mayAlias(const ValueSet& a, const ValueSet& b) const; + + // Do any nodes write to an alias set input to `n`? + TORCH_API bool hasInputWriters(const Node* n) const; + + // Do any nodes write to an alias set output by `n`? + TORCH_API bool hasOutputWriters(const Node* n) const; + + // Do any nodes write to an alias set inputted/outputted by `n`? + TORCH_API bool hasWriters(const Node* n) const; + + // Do any nodes write to `v`s memory location? + TORCH_API bool hasWriters(const Value* v) const; + + // Is the operation in-place? i.e. doesn't write anywhere but locations it + // reads from. + TORCH_API bool isMutable(Node* n) const; + + TORCH_API bool escapesScope(const at::ArrayRef& vs) const; + + // Is it safe to change whether `a` and `b` alias each other ? + TORCH_API bool safeToChangeAliasingRelationship( + const at::ArrayRef& a, + const at::ArrayRef& b) const; + + // Move `n` (already in the graph) after `movePoint` in the topological order. + // + // Tries to preserve value dependencies, so other nodes might be moved. We + // make two guarantees about the postcondition of the node list: + // - `n` is directly after `movePoint`. + // - only nodes between `n` and `movePoint` have been moved. + // + // Returns `false` if it's impossible to move `n` after `MovePoint` without + // violating dependencies, otherwise executes the move and returns `true` + TORCH_API bool moveAfterTopologicallyValid(Node* n, Node* movePoint); + TORCH_API bool moveBeforeTopologicallyValid(Node* n, Node* movePoint); + + bool couldMoveAfterTopologically(Node* n, Node* movePoint); + bool couldMoveBeforeTopologically(Node* n, Node* movePoint); + + // For debugging: print alias db state to stdout + TORCH_API void dump() const; + TORCH_API std::string toString() const; + + // Generates a DOT (www.graphviz.org) graph representation + // + // Returns `true` if the output file was successfully generated + // + // WARNING: The output dot file path can't include shell specific notations, + // for example you can't use "~/temp/aliasdb.dot" + // (instead, use "/home/user/temp/aliasdb.dot") + // + TORCH_API bool dumpToGraphvizFile(const char* filename) const; + TORCH_API std::string toGraphviz() const; + + // Returns `true` if the given element is mutable or if it is a + // container type with an internal mutable element (e.g. + // `Tuple[int, Tensor]` has an internal mutable type `Tensor`, so + // it would be considered a "mutable type" in AliasDb) + static bool isMutableType(const Value* v); + static bool isMutableType(const TypePtr& type); + + /** + * Mutation API + * + * These methods allow you to update AliasDb in-place if you are performing + * graph mutation. + * + * WARNING: These methods should be considered INTERNAL. They do not perform + * very many correctness checks, the user is responsible for making sure they + * are updating AliasDb correctly. `Lint()`ing the AliasDb can help with + * this. + */ + // Copy `existing`s aliasing info to `new_value`, and remove `existing`. + TORCH_API void replaceWithNewValue(Value* existing, Value* new_value); + // Copy `from`s aliasing info to `to`. + TORCH_API void copyValue(Value* from, Value* to); + // Create a new `value` that does not alias anything else. + TORCH_API void createValue(const Value* value); + + // Enable more precise treatment of prim::TupleConstruct. + void enablePreciseTupleContainerAnalysis(); + + friend struct MutationRemover; + friend class ValueAndMemoryLocationSet; + + private: + // Helper for topologically-safe node moves. + class WorkingSet; + enum class MoveSide { BEFORE, AFTER }; + bool tryMove(Node* toMove, Node* movePoint, MoveSide moveSide, bool dryRun); + void move(Node* toMove, Node* movePoint, MoveSide moveSide); + bool isBeforeOrAfter(const Node* n, MoveSide moveSide) const; + + bool isMutableTypeInternal(const Value* v) const; + bool isMutableTypeInternal(const TypePtr& type) const; + + /** + * Write and read internal API + */ + // Get all the values that `n` writes to. + // NOTE: this only returns values directly written to, not aliases thereof + // + // if `recurseBlocks` is true, gather writes on the nodes in `n`s sub-blocks + MemoryLocations getWrites(Node* n) const; + void getWritesImpl(Node* n, MemoryLocations& ret) const; + // Register the fact that `n` writes to `v`. + void registerWrite(const Value* v, Node* n, bool writeToContained = false); + // Get all the values that `n` reads from. + // if `recurseBlocks` is true, gather reads on the nodes in `n`s sub-blocks + MemoryLocations getReads(Node* n) const; + void getReadsImpl(Node* n, MemoryLocations& ret) const; + MemoryLocations getMemoryLocations(Value* v) const; + + /** + * Wildcard methods + */ + // Register `v` as a wildcard value. + std::optional setWildcard(const Value* v); + + // Is this a value which will not alias? + bool nonAliasingValue(const Value* elem) const; + + /** + * Special analysis methods + */ + void analyze(const std::shared_ptr& graph); + void analyze(Block* block); + void analyze(Node* node); + void analyzeImpl(Node* node); + void analyzeIf(Node* node); + void analyzeLoop(Node* node); + void analyzeSubgraph(Node* node, const std::shared_ptr& subgraph); + void analyzeSubgraph(Node* node); + void analyzeCreator(Node* node); + void analyzeExtractor(Node* node); + void analyzeChunk(Node* node); + void analyzeBroadcastingChunk(Node* node); + void analyzeFork(Node* node); + void analyzeWait(Node* node); + void analyzeAwaitable(Node* node); + void analyzeAwaitableWait(Node* node); + void analyzeRpcAsync(Node* node); + void analyzeBatchNorm(Node* node); + void analyzeInstanceNorm(Node* node); + void analyzeGradOf(Node* node); + void analyzeSetAttr(Node* node); + void analyzeConservative(Node* node); + void analyzeContainerConstruct(Node* node); + bool tryRegisteredAnalysis(Node* node); + + /** + * Alias manipulation methods + */ + void makeAllAlias(const std::vector& values); + void makePointerTo(const Value* value, const Value* to); + TORCH_API void addToContainedElements( + const Value* element, + const Value* container); + void mapAliases(at::ArrayRef to, at::ArrayRef from); + void giveFreshAlias( + const Value* value, + bool add_wildcard_to_contained_elems = true); + Element* getOrCreateElement(const Value* value); + + const AliasTypeSet* mapTypeToAliasTypeSetPtr(const TypePtr& type) const; + bool functionalNonEscapingListUse(const Use& use) const; + bool functionalNonEscapingTupleUse(const Use& use) const; + + std::shared_ptr graph_; + + // If the Module is frozen then consider attributes as freshly created + // objects. Freezing API invokes alias analysis to check if they are mutated + // internally. + bool isFrozen_; + + bool descend_function_calls_; + std::unordered_map>> + function_call_copies_; + + // The points-to graph that stores aliasing relationships + std::unique_ptr memoryDAGBuilder_; + std::unique_ptr memoryDAG_; + + // Mapping of values to MemoryDAG elements + ska::flat_hash_map elementMap_; + // All wildcard Elements (one for each unique mutable type) + ska::flat_hash_map wildcardIndex_; + Element* getWildcard(const TypePtr& type) const; + std::optional tryGetOrCreateWildcard(const TypePtr& type); + void addContainedTypesToFreshElement( + Element* container_elem, + const AliasTypeSet& mut_types); + void pointUnionTypeElementToAllContainedTypes( + Element* container_elem, + const AliasTypeSet& mut_types); + + std::vector getElements(at::ArrayRef vs) const; + bool mayAliasWildcard(const Value* v) const; + bool mayAliasWildcard(const at::ArrayRef vs) const; + bool hasWriters(const at::ArrayRef& values) const; + + // Cached mapping of type ptrs to their mutable types + mutable ska::flat_hash_map mapped_mutable_types_; + + /** + * State for tracking write info. + */ + // Write registry where the analysis can record the writes as it sees them. + // This information is later denormalized into various caches to improve query + // efficiency. + struct WriteRegistry; + std::unique_ptr writeRegistry_; + + // Map of nodes to the memory locations that they write to + using TWriteIndex = ska::flat_hash_map; + std::optional writeIndex_; + // Collection of all memory locations that are written to. + std::optional writtenToLocationsIndex_; + void buildWrittenToLocationsIndex(); + + std::unordered_set wildcards_; + + std::string getElementName(const Element* e) const; + + friend void Lint(const AliasDb* db); +}; + +// Helper check that invariants over AliasDb are maintained. +// Useful if you are using the AliasDb mutation API and want to check you did +// the right thing. +TORCH_API void Lint(const AliasDb* db); + +/** + * ValueAndMemoryLocationSet + * + * A insert-only set of values which also maintains a MemoryLocations bitset + * of the memory locations that the values alias. It is insert-only. It + * should be constructed by calling aliasDb.getValueAndMemoryLocationSet(). + * + * WARNING: + * * The AliasDb must not be mutated after construction of a + * ValueAndMemoryLocationsSet, or else the MemoryLocations stored in the + * ValueAndMemoryLocationSet will no longer be accurate. + * * A ValueAndMemoryLocationsSet is tied to an instance of AliasDb but + * does not own the AliasDb. It is the user's responsibility to ensure + * that the AliasDb outlives the ValuesAndMemoryLocationsSet. + * + * The use case for this is to be able to implement writesToAlias + * more efficiently for a set of values. + */ +class ValueAndMemoryLocationSet { + public: + TORCH_API void insert(Value* v); + TORCH_API ValueSet& getValueSet(); + + friend class AliasDb; + + private: + ValueAndMemoryLocationSet(const AliasDb* db) : aliasDb_(db) {} + + const AliasDb* aliasDb_; + ValueSet valueSet_; + MemoryLocations memoryLocations_; +}; + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/attributes.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/attributes.h new file mode 100644 index 0000000000000000000000000000000000000000..35dfe7a87642f60500ce791979e3f9d610e84994 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/attributes.h @@ -0,0 +1,185 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include + +#include +#include + +#include + +namespace torch::jit { + +using ::c10::Symbol; + +constexpr int max_tensor_display_size = 10; + +enum class AttributeKind { + f, + fs, + c, + cs, + i, + is, + s, + ss, + t, + ts, + g, + gs, + ty, + tys, + ival +}; +static inline const char* toString(AttributeKind kind) { + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays) + static constexpr const char* names[] = { + "f", + "c", + "cs", + "fs", + "i", + "is", + "s", + "ss", + "t", + "ts", + "g", + "gs", + "ty", + "tys", + "ival"}; + AT_ASSERT(size_t(kind) < sizeof(names) / sizeof(*names)); + return names[int(kind)]; +} + +struct AttributeValue { + AttributeValue(Symbol name) : name(name) {} + using Ptr = std::unique_ptr; + Symbol name; + virtual AttributeKind kind() const = 0; + virtual Ptr clone() const = 0; + virtual ~AttributeValue() = default; +}; + +template +struct ScalarAttributeValue : public AttributeValue { + using ConstructorType = T; + using ValueType = T; + ScalarAttributeValue(Symbol name, ConstructorType value_) + : AttributeValue(name), value_(std::move(value_)) {} + ValueType& value() { + return value_; + } + Ptr clone() const override { + return Ptr(new ScalarAttributeValue(name, value_)); + } + AttributeKind kind() const override { + return Kind; + } + + private: + ValueType value_; +}; + +template +struct VectorAttributeValue : public AttributeValue { + using ConstructorType = std::vector; + using ValueType = std::vector; + VectorAttributeValue(Symbol name, ConstructorType value_) + : AttributeValue(name), value_(std::move(value_)) {} + ValueType& value() { + return value_; + } + AttributeKind kind() const override { + return Kind; + } + std::unique_ptr clone() const override { + auto copy = value_; + return Ptr(new VectorAttributeValue(name, std::move(copy))); + } + + private: + ValueType value_; +}; + +using ComplexAttr = + ScalarAttributeValue, AttributeKind::c>; +using ComplexValsAttr = + VectorAttributeValue, AttributeKind::cs>; +using FloatAttr = ScalarAttributeValue; +using FloatsAttr = VectorAttributeValue; +using IntAttr = ScalarAttributeValue; +using IntsAttr = VectorAttributeValue; +using StringAttr = ScalarAttributeValue; +using StringsAttr = VectorAttributeValue; +using TensorAttr = ScalarAttributeValue; +using TensorsAttr = VectorAttributeValue; +using TypeAttr = ScalarAttributeValue; +using TypesAttr = VectorAttributeValue; +using IValueAttr = ScalarAttributeValue; + +struct Graph; + +// We special case Graph attributes like this because we want to ensure that +// Graph::copy() is called when we clone() these attributes. +struct TORCH_API GraphAttr : public AttributeValue { + using ConstructorType = std::shared_ptr; + using ValueType = std::shared_ptr; + GraphAttr(Symbol name, ConstructorType value_) + : AttributeValue(name), value_(std::move(value_)) {} + ValueType& value() { + return value_; + } + Ptr clone() const override; + AttributeKind kind() const override { + return AttributeKind::g; + } + + private: + std::shared_ptr value_; +}; + +struct TORCH_API GraphsAttr : public AttributeValue { + using ConstructorType = std::vector>; + using ValueType = std::vector>; + GraphsAttr(Symbol name, ConstructorType value_) + : AttributeValue(name), value_(std::move(value_)) {} + ValueType& value() { + return value_; + } + AttributeKind kind() const override { + return AttributeKind::gs; + } + std::unique_ptr clone() const override; + + private: + ValueType value_; +}; + +struct IRAttributeError : public std::exception { + IRAttributeError(Symbol name, bool defined) { + std::stringstream ss; + // NOLINTNEXTLINE(bugprone-branch-clone) + if (!defined) { + ss << "required keyword attribute '" << name.toUnqualString() + << "' is undefined"; + } else { + ss << "required keyword attribute '" << name.toUnqualString() + << "' has the wrong type"; + } + msg = ss.str(); + } + const char* what() const noexcept override { + return msg.c_str(); + } + + private: + std::string msg; +}; +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/constants.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/constants.h new file mode 100644 index 0000000000000000000000000000000000000000..f7fd7f01304ca0fff41a52a4f1de7fd7b1e9ca6d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/constants.h @@ -0,0 +1,65 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include +#include + +// helpers for handling constants in the IR +// - create constant nodes from ints, floats, complex, intlist, Tensors, and +// other types +// - implement primitive constant ops. + +namespace torch::jit { + +using ::c10::IValue; + +struct Graph; +struct Value; + +// thrown when insertConstant cannot encode the IValue into a graph +struct TORCH_API constant_not_supported_error : public std::runtime_error { + using runtime_error::runtime_error; +}; + +TORCH_API Value* insertConstant( + Graph& g, + const IValue& val, + std::optional loc = std::nullopt, + std::optional scope = std::nullopt); + +// note: prefer g.insertConsant(val, loc) which does exactly the same thing +// this function is only declared/defined here because its implementation is +// closely related to the implementation of prim::Constant that is also in +// constants.cpp. +// +// returns a std::nullopt if the IValue kind cannot be inserted as a constant +TORCH_API std::optional tryInsertConstant( + Graph& g, + const IValue& val, + std::optional loc = std::nullopt, + std::optional scope = std::nullopt); + +//////////////////////////////////////////////////////////////////////////////// +// Helper for retrieving constants +//////////////////////////////////////////////////////////////////////////////// + +// attempt to convert a (possibly constant) Value* into an interpreter value +// (IValue). returns std::nullopt if the Value* was not constant +TORCH_API std::optional toIValue(const Value* v); + +// if a value is a constant then try to turn into type T using the +// same rules as the interpreter +template +std::optional constant_as(const Value* v) { + if (auto ivalue = toIValue(v)) { + return ivalue->to(); + } + return std::nullopt; +} +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/graph_node_list.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/graph_node_list.h new file mode 100644 index 0000000000000000000000000000000000000000..e1ffa81efea513b2046ea9f86acc495b1f48e45c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/graph_node_list.h @@ -0,0 +1,204 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit { + +// Intrusive doubly linked lists with sane reverse iterators. +// The header file is named generic_graph_node_list.h because it is ONLY +// used for Graph's Node lists, and if you want to use it for other +// things, you will have to do some refactoring. +// +// At the moment, the templated type T must support a few operations: +// +// - It must have a field: T* next_in_graph[2] = { nullptr, nullptr }; +// which are used for the intrusive linked list pointers. +// +// - It must have a method 'destroy()', which removes T from the +// list and frees a T. +// +// In practice, we are only using it with Node and const Node. 'destroy()' +// needs to be renegotiated if you want to use this somewhere else. +// +// Regardless of the iteration direction, iterators always physically point +// to the element they logically point to, rather than +// the off-by-one behavior for all standard library reverse iterators like +// std::list. + +// The list is includes two sentinel nodes, one at the beginning and one at the +// end with a circular link between them. It is an error to insert nodes after +// the end sentinel node but before the beginning node: + +// Visualization showing only the next() links: +// HEAD -> first -> second -> ... -> last -> TAIL +// ^------------------------------------------ + +// Visualization showing only the prev() links: +// HEAD <- first <- second <- ... <- last <- TAIL +// ------------------------------------------^ + +static constexpr int kNextDirection = 0; +static constexpr int kPrevDirection = 1; + +template +struct generic_graph_node_list; + +template +struct generic_graph_node_list_iterator; + +struct Node; +using graph_node_list = generic_graph_node_list; +using const_graph_node_list = generic_graph_node_list; +using graph_node_list_iterator = generic_graph_node_list_iterator; +using const_graph_node_list_iterator = + generic_graph_node_list_iterator; + +template +struct generic_graph_node_list_iterator { + generic_graph_node_list_iterator() : cur(nullptr), d(kNextDirection) {} + generic_graph_node_list_iterator(T* cur, int d) : cur(cur), d(d) {} + generic_graph_node_list_iterator( + const generic_graph_node_list_iterator& rhs) = default; + generic_graph_node_list_iterator( + generic_graph_node_list_iterator&& rhs) noexcept = default; + generic_graph_node_list_iterator& operator=( + const generic_graph_node_list_iterator& rhs) = default; + generic_graph_node_list_iterator& operator=( + generic_graph_node_list_iterator&& rhs) noexcept = default; + T* operator*() const { + return cur; + } + T* operator->() const { + return cur; + } + generic_graph_node_list_iterator& operator++() { + AT_ASSERT(cur); + cur = cur->next_in_graph[d]; + return *this; + } + generic_graph_node_list_iterator operator++(int) { + generic_graph_node_list_iterator old = *this; + ++(*this); + return old; + } + generic_graph_node_list_iterator& operator--() { + AT_ASSERT(cur); + cur = cur->next_in_graph[reverseDir()]; + return *this; + } + generic_graph_node_list_iterator operator--(int) { + generic_graph_node_list_iterator old = *this; + --(*this); + return old; + } + + // erase cur without invalidating this iterator + // named differently from destroy so that ->/. bugs do not + // silently cause the wrong one to be called. + // iterator will point to the previous entry after call + void destroyCurrent() { + T* n = cur; + cur = cur->next_in_graph[reverseDir()]; + n->destroy(); + } + generic_graph_node_list_iterator reverse() { + return generic_graph_node_list_iterator(cur, reverseDir()); + } + + private: + int reverseDir() { + return d == kNextDirection ? kPrevDirection : kNextDirection; + } + T* cur; + int d; // direction 0 is forward 1 is reverse, see next_in_graph +}; + +template +struct generic_graph_node_list { + using iterator = generic_graph_node_list_iterator; + using const_iterator = generic_graph_node_list_iterator; + generic_graph_node_list_iterator begin() { + return generic_graph_node_list_iterator(head->next_in_graph[d], d); + } + generic_graph_node_list_iterator begin() const { + return generic_graph_node_list_iterator(head->next_in_graph[d], d); + } + generic_graph_node_list_iterator end() { + return generic_graph_node_list_iterator(head->next_in_graph[!d], d); + } + generic_graph_node_list_iterator end() const { + return generic_graph_node_list_iterator( + head->next_in_graph[!d], d); + } + generic_graph_node_list_iterator rbegin() { + return reverse().begin(); + } + generic_graph_node_list_iterator rbegin() const { + return reverse().begin(); + } + generic_graph_node_list_iterator rend() { + return reverse().end(); + } + generic_graph_node_list_iterator rend() const { + return reverse().end(); + } + generic_graph_node_list reverse() { + return generic_graph_node_list(head->next_in_graph[!d], !d); + } + const generic_graph_node_list reverse() const { + return generic_graph_node_list(head->next_in_graph[!d], !d); + } + T* front() { + return head->next_in_graph[d]; + } + const T* front() const { + return head->next_in_graph[d]; + } + T* back() { + return head->next_in_graph[!d]; + } + const T* back() const { + return head->next_in_graph[!d]; + } + generic_graph_node_list(T* head, int d) : head(head), d(d) {} + + private: + T* head; // both head and tail are sentinel nodes + // the first real node is head->next_in_graph[d] + // the tail sentinel is head->next_in_graph[!d] + int d; +}; + +template +static inline bool operator==( + generic_graph_node_list_iterator a, + generic_graph_node_list_iterator b) { + return *a == *b; +} + +template +static inline bool operator!=( + generic_graph_node_list_iterator a, + generic_graph_node_list_iterator b) { + return *a != *b; +} + +} // namespace torch::jit + +namespace std { + +template +struct iterator_traits> { + using difference_type = int64_t; + using value_type = T*; + using pointer = T**; + using reference = T*&; + using iterator_category = bidirectional_iterator_tag; +}; + +} // namespace std + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/graph_utils.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/graph_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..fe3c83f45e44792baf30e582f6cdbada415afc23 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/graph_utils.h @@ -0,0 +1,28 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include + +namespace torch::jit { + +TORCH_API TypePtr getTensorType(const at::Tensor& t, bool complete); + +TORCH_API TypePtr inferShapeAndTypeForInput( + TypePtr input_type, + Stack::const_iterator& s_iter, + const Stack::const_iterator& s_iter_end, + bool complete); + +TORCH_API void setInputTensorTypes( + Graph& g, + const Stack& stack, + bool complete, + const std::vector& param_count_list = {}); + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/ir.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/ir.h new file mode 100644 index 0000000000000000000000000000000000000000..6fe375e6ad1b0d05f0e38cc1b697f1a3eb285301 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/ir/ir.h @@ -0,0 +1,1828 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +// Forward declare, the real meat is in python_ir.cpp +template +class THPPointer; +using THPObjectPtr = THPPointer; +using pyobj_list = std::vector; + +namespace torch::jit { +namespace utils { +TORCH_API std::string getNodesModuleHierarchy(const Node& n); +} // namespace utils +class AliasDb; + +using ::c10::Argument; +using ::c10::FunctionSchema; +using ::c10::Symbol; + +using ::c10::ivalue::Shared; + +using ::c10::IValue; +using ::c10::ivalue::Future; + +using ::c10::ivalue::ConstantString; + +#define C10_USING(T) using ::c10::T; +C10_FORALL_TYPES(C10_USING) +#undef C10_USING + +#define C10_USING(T) using ::c10::T##Ptr; +C10_FORALL_TYPES(C10_USING) +#undef C10_USING + +using ::c10::Type; +using ::c10::TypeEnv; +using ::c10::TypePtr; + +using ::c10::getTypePtr; +using ::c10::MatchTypeReturn; +using ::c10::TypeKind; + +using ::c10::fmap; + +namespace prim = ::c10::prim; +namespace attr = ::c10::attr; +namespace aten = ::c10::aten; +namespace cuda = ::c10::cuda; + +struct Function; +struct GraphFunction; +struct MatchedSchema; + +// A Graph represents one "function" of computation. +// It uses a simple ownership model where the graph owns all the nodes inside +// it. All references inside the graph are raw pointers. Destroying the Graph +// will invalidate any pointers to nodes in the graph. +struct Graph; + +// Node is the base class of the IR graph. It represents one computation +// and dependencies on a list of Values. The "prim-ops", so to speak. +struct Node; + +// A Value represents an input or output to node that is either a +// Tensor or an opaque Handle object, as determined by type(). +struct Value; + +TORCH_API std::ostream& operator<<(std::ostream& out, const Graph& g); +TORCH_API std::ostream& operator<<(std::ostream& out, const Node& n); + +// A list of nodes, with inputs and outputs +struct Block; + +// Each use is represented by this type, see 'Node::uses()' +// 'user' is the consumer of the value, 'offset' is the index into +// 'user's input this where the producers will be found. +struct Use { + Use(Node* user, size_t offset) : user(user), offset(offset) {} + Node* user; + size_t offset; + + bool operator==(const Use& b) { + return user == b.user && offset == b.offset; + } +}; + +// Note [User node does not uniquely identify use] +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// A while back, we wrote some code manipulating uses that looked like this: +// +// for (auto& use : used_val->uses_) { +// if (use.user == this_node) { +// use.offset += 1; +// break; +// } +// } +// +// This code is trying to find a particular use (our node's use) to update it. +// However, it's wrong: there may be *multiple* uses of a value %x in a node, +// as might be the case in this IR: +// +// %y = Add %x %x +// +// In this case, there are two uses of %x whose user is the node 'Add %x %x'. +// So, "use induced by this node" is not a well-formed concept. +// +// If you are looking for "use induced by an input", it's best to use +// findUseForInput() to get it. + +// the list types are intentionally simple, but we type-def +// them here so if we need to change them, refactoring will be easier +using node_list = std::vector; +using value_list = std::vector; +using use_list = std::vector; +template +using ArrayRef = at::ArrayRef; +using NodeKind = Symbol; +using topo_position_t = int64_t; +using ValueSet = std::unordered_set; + +struct OperatorSet; +template +struct OperatorMap; + +// This is a wrapper to allow invalidating the Python object +// safely when the C++ object for a Node/Value/Block is deleted +// like much of graph, it isn't safe for different threads to +// access the same graph +template +struct Wrap { + explicit Wrap(T* p) : elem(p) {} + void clear() { + if (clear_cb) { + clear_cb(elem); + } + elem = nullptr; + } + T* elem; + void (*clear_cb)(void*){nullptr}; +}; + +struct Value { + AT_DISALLOW_COPY_AND_ASSIGN(Value); + Value(Node* node_, size_t offset_); + + private: + friend struct Node; + friend struct Graph; + Node* node_; + size_t offset_; + size_t unique_ = 0; // unique id + use_list uses_; + std::string unique_name_; + TypePtr type_; + // a managing wrapper for Python to allow invalidation + std::shared_ptr> wrap_; + + public: + Value* setType(TypePtr type); + TORCH_API void inferTypeFrom(const at::Tensor& output); + TORCH_API void inferTypeFrom( + const c10::intrusive_ptr& output); + const TypePtr& type() const { + AT_ASSERT(type_ != nullptr); + return type_; + } + bool requires_grad() const { + return type()->requires_grad(); + } + bool isCompleteTensor() const { + if (auto pt = type()->cast()) { + return pt->isComplete(); + } + return false; + } + TORCH_API bool mustBeNone() const; + TORCH_API bool mustNotBeNone() const; + size_t unique() const { + return unique_; + } + bool hasDebugName() const { + return !unique_name_.empty(); + } + static bool isValidName(const std::string& name); + TORCH_API Value* setDebugName(const std::string& name); + std::string debugName() const { + if (hasDebugName()) { + return unique_name_; + } + return std::to_string(unique()); + } + TORCH_API std::string debugNameBase() const; + Node* node() { + return node_; + } + size_t offset() const { + return offset_; + } + void setOffset(size_t offset) { + offset_ = offset; + } + const Node* node() const { + return node_; + } + + /** + * @warning NEVER pass raw pointer of smart pointer managed Graph to Python. + * Check #87343 for details. + */ + Graph* owningGraph(); + const Graph* owningGraph() const; + // TODO: make this more const correct + const use_list& uses() const { + return uses_; + } + + bool hasUses() const { + return !uses().empty(); + } + + TORCH_API void replaceFirstUseWith(Value* newValue); + + // Replaces all uses of this value with 'newValue'. + // + // Given: %3 = f(%1, %2) + // %4 = g(%3) + // %5 = h(%3, %3) + // Execute: %3.replaceAllUsesWith(%6) + // Result: %3 = f(%1, %2) + // %4 = g(%6) + // %5 = h(%6, %6) + TORCH_API void replaceAllUsesWith(Value* newValue); + + // Replaces all uses of this value with 'newValue' after 'node'. + // Given: %3 = f(%1, %2) + // %4 = g(%3) + // %5 = inplace_(%3) + // %6 = h(%3, %3) + // Execute: %3.replaceAllUsesAfterNodeWith(%5.node(), %5) + // Result: %3 = f(%1, %2) + // %4 = g(%3) + // %5 = inplace_(%3) + // %6 = h(%5, %5) + // XXX: does not check scoping legality, consider using + // replaceAllUsesDominatedByNodeWith + TORCH_API void replaceAllUsesAfterNodeWith(const Node* node, Value* newValue); + + // Replaces all uses of this value with 'newValue' that are dominated by + // 'node'. Given: + // x = op(...). + // if cond: + // z = foo(..) + // bar(x) + // else: + // print(x) + // x.replaceAllUsesDominatedByNodeWith(foo, z) would replace bar(x) + // but not print(x) because print is not dominated by foo. + // replaceAllUsesAfterNode does not check domination, so in this example + // it would produce invalid IR. + TORCH_API void replaceAllUsesDominatedByNodeWith( + const Node* node, + Value* newValue); + + TORCH_API Value* copyMetadata(Value* from); + + TORCH_API std::shared_ptr> wrap() { + if (!wrap_) { + wrap_ = std::make_shared>(this); + } + return wrap_; + } + + virtual ~Value() { + if (wrap_) { + wrap_->clear(); + } + } +}; + +struct TORCH_API Node { + AT_DISALLOW_COPY_AND_ASSIGN(Node); + friend struct Graph; + friend struct Block; + friend struct Value; + friend graph_node_list; + friend const_graph_node_list; + friend graph_node_list_iterator; + friend const_graph_node_list_iterator; + + private: + const NodeKind kind_; + std::vector inputs_; + std::vector outputs_; + // subblocks + std::vector blocks_; + Graph* graph_; + Block* owning_block_{nullptr}; + std::optional source_range_; + ScopePtr scope_; + std::optional callstack_; + // Assumes FunctionSchemas are persistent, so we don't manage their lifetime. + // This field is effective a cache that's populated on attribute lookups and + // invalidated every time we perform an operation that could potentially + // change the schema. note: mutable because schema_ is effectively a cache + mutable const Operator* op_{nullptr}; + topo_position_t topo_position_ = 0; + // a managing wrapper for Python to allow invalidation + std::shared_ptr> wrap_; + // Stores the full schema name, if the operator is historic + // When the operator is deprecated or the name of the operator + // is changed, we need to rely on this name + // to retrieve old schemas to successfully apply upgraders + // for this operator. + std::optional historic_schema_name_ = std::nullopt; + + protected: + Node(Graph* graph_, NodeKind kind_); // defined after graph + public: + // Each Node but Return/Param Nodes are associated with exactly one + // place in the Node list of the Graph. The Graph itself is a circular + // doubly-linked list. The Return Node is used as the sentinel for the + // "beginning"/"end" of the list. This means that you can tell when + // you've traversed the entire list without means worrying about null + // pointers. `next_in_graph[0]` is the pointer to the next Node, while + // `next_in_graph[1]` is the pointer to the previous Node. The + // linked list is implemented as an array to allow the same iterator + // class for forward and reversed Node lists. Taken together, this + // list also represents a topological sort of the Nodes in the Graph. + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,cppcoreguidelines-non-private-member-variables-in-classes,modernize-avoid-c-arrays) + Node* next_in_graph[2] = {nullptr, nullptr}; + + std::shared_ptr> wrap() { + if (!wrap_) { + wrap_ = std::make_shared>(this); + } + return wrap_; + } + + const std::optional getHistoricSchemaName() { + return historic_schema_name_; + } + + void setHistoricSchemaName(const std::string& name) { + historic_schema_name_ = name; + } + + Node*& next() { + return next_in_graph[kNextDirection]; + } + Node*& prev() { + return next_in_graph[kPrevDirection]; + } + Node* const& next() const { + return next_in_graph[kNextDirection]; + } + Node* const& prev() const { + return next_in_graph[kPrevDirection]; + } + + NodeKind kind() const { + return kind_; + } + Node* setSourceRange(SourceRange r) { + source_range_ = std::move(r); + return this; + } + SourceRange sourceRange() const; + + /** + * @warning NEVER pass raw pointer of smart pointer managed Graph to Python. + * Check #87343 for details. + */ + Graph* owningGraph() { + return graph_; + } + const Graph* owningGraph() const { + return graph_; + } + Block* owningBlock() { + return owning_block_; + } + const Block* owningBlock() const { + return owning_block_; + } + ScopePtr scope() { + return scope_; + } + void setScope(ScopePtr scope) { + scope_ = std::move(scope); + } + std::string scopeName() const { + if (!scope_) { + return ""; + } + return scope_->namesFromRoot(); + } + + // Copies the source range, scope and callstack from another node. + Node* copyMetadata(Node* from) { + this->setSourceRange(from->sourceRange()); + this->setScope(from->scope()); + if (auto cs = from->callstack()) { + this->setCallStack(*cs); + } + return this; + } + + std::optional callstack() const { + return callstack_; + } + void setCallStack(InlinedCallStackPtr cs) { + callstack_ = std::move(cs); + } + + // NB: This returns an ArrayRef; that means that it will + // get invalidated if you resize inputs (e.g., using addInput) + // We can't return a std::vector& because there's no + // way to soundly cast to std::vector (an insane + // implementation of std::vector could make this representationally + // different.) + at::ArrayRef inputs() { + return inputs_; + } + at::ArrayRef inputs() const { + // Vectors are not convertible in const-ness of elements, but + // raw pointers are. + return {inputs_.data(), inputs_.size()}; + } + // NB: This returns an ArrayRef; that means that it will + // get invalidated if you resize inputs (e.g., using addInput) + // We can't return a std::vector& because there's no + // way to soundly cast to std::vector (an insane + // implementation of std::vector could make this representationally + // different.) + at::ArrayRef outputs() { + return outputs_; + } + at::ArrayRef outputs() const { + // Vectors are not convertible in const-ness of elements, but + // raw pointers are. + return {outputs_.data(), outputs_.size()}; + } + Value* output(size_t i) const { + return outputs_.at(i); + } + bool hasUses() const { + for (auto o : outputs()) { + if (!o->uses().empty()) { + return true; + } + } + return false; + } + + void replaceAllUsesWith(Node* n); + + // replaces `this` with a new node with the same inputs and outputs + // but a new node symbol. does not destroy `this` + Node* replaceWithNewSymbol(Symbol new_symbol); + + // Checks if this node is dominated by `dominator` which means that + // `dominator` will always be executed before `this` and `dominator` + // is in scope of `this. + bool isDominatedBy(const Node* dominator) const; + + // lots of things like chunk have a single input or single output, so we have + // a helper to make accessing it easier + Value* input() { + AT_ASSERT(inputs_.size() == 1); + return inputs_.at(0); + } + Value* output() { + AT_ASSERT(outputs_.size() == 1); + return outputs_.at(0); + } + const Value* output() const { + AT_ASSERT(outputs_.size() == 1); + return outputs_.at(0); + } + const Value* input() const { + AT_ASSERT(inputs_.size() == 1); + return inputs_.at(0); + } + // Access a particular input. This is a checked index. + Value* input(size_t i) const { + return inputs_.at(i); + } + + bool hasNamedInput(const std::string& unqualName) const; + Value* namedInput(const std::string& unqualName) const; + Value* namedInput(Symbol name) const; + + std::optional get(Symbol name) const; + + template + std::optional get(Symbol name) const { + if (auto v = get(name)) { + return v->template to(); + } + return std::nullopt; + } + + // Returns true if the value of input name is statically known + bool is_constant(Symbol name) const { + return static_cast(get(name)); + } + bool mustBeNone() const; + + bool isNondeterministic() const; + bool hasSideEffects() const; + + // instructions lowered by the interpreter and not run in the optimized graph + bool notExecutedOp() const { + return kind_ == prim::Constant || kind_ == prim::profile || + kind_ == prim::profile_ivalue; + } + + // Graphs + + // Note [Topological invariant] + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // We always maintain an up-to-date topological ordering of all nodes via + // the next()/prev() links. All transformations to graphs must preserve + // this topological ordering: for example, it is only valid to 'addInput' + // with an input which is topologically before the current node. + // + // Usually, it is obvious whether or not topological order is maintained; + // for example, if you are adding nodes to the end of the topsort, it's + // impossible for them to refer to inputs that are not in the topsort. + // If it is not obvious, please comment accordingly. + + // Add 'node' as an input to 'this' at the end of existing + // arguments. Returns the added node for ease of chaining. + // + // Given: %3 = f(%1, %2) + // Execute: %3.addInput(%4) + // Result: %3 = f(%1, %2, %4) + Value* addInput(Value* value); + + // Add 'value' as an input to 'this' at the specified position in the + // arguments. Returns the added value for ease of chaining. + Value* insertInput(size_t i, Value* value); + + // Replace the input of 'this' at position 'i' with + // 'newValue', returning the old node. + // + // Given: %3 = f(%1, %2) + // Execute: %3.replaceInput(1, %4) + // Result: %3 = f(%1, %4) + Value* replaceInput(size_t i, Value* newValue); + + // Replace all occurrences of 'from' in the inputs of this + // node with 'to'. Corresponds to llvm's replaceUsesOfWith. + // + // Given: %3 = f(%1, %2, %1) + // Execute: %3.replaceInputWith(%1, %4) + // Result: %3 = f(%4, %2, %4) + void replaceInputWith(Value* from, Value* to); + + Value* addOutput(); + + Value* insertOutput(size_t i); + + void eraseOutput(size_t i); + + Block* addBlock(); + void eraseBlock(size_t i); + + // Each Node can have a list of subblocks. These are used to define structured + // nested control flow operators such as If and Loop. + // The meaning of a block is specific to the kind of node it is in, but + // all blocks share these semantics: + // * Nested lexical scoping: If a node 'Parent' has a subblock which contains + // a node 'Child', Child can use any value that was in scope for the Parent + // node in addition to any values defined before 'Child' in the subblock. + // * The list of inputs to the block are in scope for the duration of the + // block + // * the outputs of the Parent node are not in scope for the subblocks + // Typically the inputs to a block that represents control flow act as + // as the equivalents phi-nodes in standard SSA form, + // defining a new Value to represent any term that has multiple + // definitions depending on how control flowed. Outputs of the node containing + // control flow serve a similar purpose defining new values for variables + // that would have different definitions depending on which way control + // flowed. + + at::ArrayRef blocks() { + return blocks_; + } + at::ArrayRef blocks() const { + // Vectors are not convertible in const-ness of elements, but + // raw pointers are. + return {blocks_.data(), blocks_.size()}; + } + + // Is 'this' before 'n' in the topological order? + bool isBefore(const Node* n) const; + + // Is 'this' after 'n' in the topological order? + bool isAfter(const Node* n) const; + + // Insert unattached 'this' node before 'n' in the topological order. + // Returns this (for chaining). + // + // Given: %3 = f(%1, %2) + // %4 = g(%3) + // and unattached: %5 = h(%1) + // Execute: %5.insertBefore(%4) + // Result: %3 = f(%1, %2) + // %5 = h(%1) + // %4 = g(%3) + Node* insertBefore(Node* n); + + // Insert unattached 'this' node after 'n' in the topological order. + // Returns this (for chaining). + // + // Given: %3 = f(%1, %2) + // %4 = g(%3) + // and unattached: %5 = h(%1) + // Execute: %5.insertAfter(%4) + // Result: %3 = f(%1, %2) + // %4 = g(%3) + // %5 = h(%1) + Node* insertAfter(Node* n); + + // Move 'this' (already in the graph) after 'n' in the topological order. + // + // NOTE: Does not check that value dependencies are preserved, see + // AliasDb::moveAfterTopologicallyValid + // + // Given: %2 = f(%1) + // %3 = g(%1) + // Execute: %2.moveAfter(%3) + // Result: %3 = g(%1) + // %2 = f(%1) + // + void moveAfter(Node* n); + + // Move a node 'n' (already in the graph) before 'this' in the topological + // order. + // + // NOTE: Does not check that value dependencies are preserved, see + // AliasDb::moveBeforeTopologicallyValid + // + // Given: %2 = f(%1) + // %3 = g(%1) + // Execute: %3.moveBefore(%2) + // Result: %3 = g(%1) + // %2 = f(%1) + void moveBefore(Node* n); + + // Remove the input at 'i' from this node. + // + // WARNING: This is O(n) in the number of inputs, so avoid repeatedly calling + // removeInput. + // + // Given: %3 = f(%1, %2) + // Execute: %3.removeInput(1) + // Result: %3 = f(%1) + void removeInput(size_t i); + + // Remove all inputs from a node. + // + // Given: %3 = f(%1, %2) + // Execute: %3.removeAllInputs() + // Result: %3 = f() + void removeAllInputs(); + + // Remove all outputs from a node. + // + // Given: %1, %2 = f() + // Execute:removeAllInputs() + // Result: = f() + void removeAllOutputs(); + + // Rearrange the ordering of inputs or outputs of a node + // Given: %3 = f(%1, %2) + // Execute: %3.permuteInputs({1, 0}) + // Result: %3 = f(%2, %1) + // Each index must appear exactly once + void permuteInputs(const std::vector& new_inputs); + void permuteOutputs(const std::vector& new_inputs); + + // iterators of the node list starting at this node + // useful for resuming a search starting at this node + inline graph_node_list_iterator iterator() { + return {this, 0}; + } + inline graph_node_list_iterator reverseIterator() { + return iterator().reverse(); + } + inline const_graph_node_list_iterator iterator() const { + return {this, 0}; + } + inline const_graph_node_list_iterator reverseIterator() const { + return iterator().reverse(); + } + + // Remove 'this' from the instruction list and deallocate it. + // + // Invariant: no outputs of 'this' may have any uses. + // + // Given: %2 = f(%1) + // %3 = g(%1) + // Execute: %2.destroy() + // Result: %3 = g(%1) + void destroy(); + + // Dynamically cast this node to the subclass indicated by the + // template variable, returning nullptr if the cast is invalid.. + // + // Example usage: if(auto s = n.cast to stride as arg VarHandle + std::unordered_map, VarHandle, SmallSizeTPairHash> + strideArgToVar_; + std::unordered_map< + const torch::jit::Value*, + std::vector> + symbolic_strides_; + + // Memory layout to be propagated with fusion group + MemoryLayoutPolicy memory_layout_policy_ = MemoryLayoutPolicy::kContiguous; +}; + +TORCH_API int& getTECudaPointwiseLoopLevels(); +TORCH_API int& getTECudaPointwiseBlockCount(); +TORCH_API int& getTECudaPointwiseBlockSize(); +TORCH_API bool& getTEGenerateBlockCode(); +TORCH_API bool& getTEMustUseLLVMOnCPU(); +TORCH_API bool fallbackAllowed(); +TORCH_API bool setFallbackAllowed(bool value); +TORCH_API bool& getCatWoConditionals(); +TORCH_API bool& getOptConditionals(); + +TORCH_API std::optional pickDeviceType( + const at::ArrayRef& inputs); + +bool isContiguous( + const torch::jit::Value* v, + at::MemoryFormat memory_format = at::MemoryFormat::Contiguous); + +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/llvm_codegen.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/llvm_codegen.h new file mode 100644 index 0000000000000000000000000000000000000000..f253224710956595b35d147f0687e0763ee74fd1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/llvm_codegen.h @@ -0,0 +1,148 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef TORCH_ENABLE_LLVM +#include + +#include +#include +#include + +#include + +#include +#include + +namespace torch { +namespace jit { +namespace tensorexpr { + +class LLVMCodeGenImpl; +class LLVMCodeGenCallee; + +class TORCH_API LLVMCodeGen : public CodeGen { + public: + explicit LLVMCodeGen( + StmtPtr stmt, + const std::vector& args, + at::Device device = at::kCPU, + const std::string& kernel_func_name = "func", + Dtype dtype = kInt, + std::optional triple = std::nullopt, + std::optional cpu = std::nullopt, + std::optional attrs = std::nullopt); + explicit LLVMCodeGen(StmtPtr stmt); + + LLVMCodeGen() = delete; + ~LLVMCodeGen() override; + + // Cleans up all the memory used during LLVM code generation pass except + // the generated kernel. After calling this method, users should not call + // methods like `getCodeText` that require the LLVMCodeGenImpl data. However, + // users can continue to call this kernel using `call` and `call_raw`. + void cleanup_memory(); + + TORCH_API void call(const std::vector& args) override; + TORCH_API void call_raw(const std::vector& args) override; + TORCH_API void call_with_numel(void** args, int64_t numel) override; + + at::Tensor empty_strided( + c10::IntArrayRef size, + c10::IntArrayRef stride, + std::optional dtype_opt, + std::optional layout_opt, + std::optional device_opt, + std::optional pin_memory_opt) override; + + template + T value() { + return value(nullptr); + } + + template + T value(std::vector& args) { + return value(args.data()); + } + + template + T value(void** args) { + T (*fp)(void**) = (T(*)(void**))getKernelAddress(callee_.get()); + T rv = fp(args); + return rv; + } + + std::string getCodeText(const std::string& attr = "") override; + + private: + void* getKernelAddress(LLVMCodeGenCallee* callee); + + std::unique_ptr callee_; + std::unique_ptr impl_; +}; + +struct TORCH_API LLVMCodeGenBuilder { + using BufferArg = CodeGen::BufferArg; + + LLVMCodeGenBuilder(StmtPtr stmt, std::vector args) + : stmt_(stmt), args_(std::move(args)) {} + + LLVMCodeGenBuilder& device(at::Device device) { + device_ = device; + return *this; + } + + LLVMCodeGenBuilder& kernelFuncName(std::string name) { + kernelFuncName_ = std::move(name); + return *this; + } + + LLVMCodeGenBuilder& dtype(Dtype d) { + dtype_ = d; + return *this; + } + + LLVMCodeGenBuilder& triple(std::string triple) { + triple_ = std::move(triple); + return *this; + } + + LLVMCodeGenBuilder& cpu(std::string cpu) { + cpu_ = std::move(cpu); + return *this; + } + + LLVMCodeGenBuilder& attrs(std::string attrs) { + attrs_ = std::move(attrs); + return *this; + } + + std::unique_ptr build() { + return std::make_unique( + stmt_, args_, device_, kernelFuncName_, dtype_, triple_, cpu_, attrs_); + } + + private: + StmtPtr stmt_; + std::vector args_; + at::Device device_ = at::kCPU; + std::string kernelFuncName_ = "func"; + Dtype dtype_ = kInt; + std::optional triple_ = std::nullopt; + std::optional cpu_ = std::nullopt; + std::optional attrs_ = std::nullopt; +}; + +TORCH_API std::optional& LLVMTargetTriple(); +TORCH_API std::optional& LLVMTargetCPU(); +TORCH_API std::optional& LLVMTargetAttrs(); +TORCH_API bool& LLVMAOTWorkflow(); + +} // namespace tensorexpr +} // namespace jit +} // namespace torch + +#endif // TORCH_ENABLE_LLVM + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/llvm_jit.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/llvm_jit.h new file mode 100644 index 0000000000000000000000000000000000000000..deece5fe694540855646f8a33f723ed5babf5bbe --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/llvm_jit.h @@ -0,0 +1,84 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifdef TORCH_ENABLE_LLVM +#include +#include +#include +#include + +C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED("-Wsuggest-override") +#include +C10_DIAGNOSTIC_POP() +C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED("-Wextra-semi") +#include +#include +#include +C10_DIAGNOSTIC_POP() + +#include +#include + +namespace torch { +namespace jit { +namespace tensorexpr { + +inline std::string formatError(llvm::Error&& err, const char* msg) { + static constexpr const char* defaultErrorMsg = + "Unexpected failure in LLVM JIT"; + std::string errorMsg(msg ? msg : defaultErrorMsg); + llvm::raw_string_ostream ss(errorMsg); + ss << ": " << err; + return ss.str(); +} + +template +T assertSuccess(llvm::Expected valOrErr, const char* msg = nullptr) { + TORCH_INTERNAL_ASSERT(valOrErr, formatError(valOrErr.takeError(), msg)); + return std::move(*valOrErr); +} + +inline void assertSuccess(llvm::Error err, const char* msg = nullptr) { + TORCH_INTERNAL_ASSERT(!err, formatError(std::move(err), msg)); +} + +} // namespace tensorexpr +} // namespace jit +} // namespace torch + +namespace llvm { +namespace orc { + +class PytorchLLVMJITImpl; + +class TORCH_API PytorchLLVMJIT { + public: + PytorchLLVMJIT( + std::optional triple, + std::optional cpu, + std::optional attrs); + ~PytorchLLVMJIT(); + + void addModule(std::unique_ptr M, std::unique_ptr C); + + JITSymbol findSymbol(const std::string Name); + + bool hasSymbol(const std::string& Name); + + TargetMachine& getTargetMachine(); + + const DataLayout& getDataLayout(); + + private: + // Use the PImpl idiom here to hide the no-rtti parts of the JIT structure. + std::unique_ptr impl_; +}; + +} // end namespace orc +} // end namespace llvm + +#endif // ENABLE LLVM + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/loopnest.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/loopnest.h new file mode 100644 index 0000000000000000000000000000000000000000..fe3f27c0861dc6b643f5ffbd3cceb53517642cec --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/loopnest.h @@ -0,0 +1,622 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace torch::jit::tensorexpr { + +class Expr; +class Var; +class Buf; +class Tensor; +class Function; +class Stmt; +class For; +class Block; +class Store; +class Dtype; + +class TORCH_API LoopNest { + public: + // A constructor for building a LoopNest from a list of Tensors + LoopNest( + const std::vector& output_tensors, + const std::vector& tensors_to_compute); + + // A convenience constructor for the case when all tensors are output tensors + LoopNest(const std::vector& output_tensors); + + // A constructor for building a LoopNest from an Stmt and a list of output + // buffers. + LoopNest(StmtPtr stmt, std::unordered_set output_bufs); + + // A constructor for building a LoopNest from another loopnest. It clones the + // other loopnest's stmt. + LoopNest(const LoopNest& other); + + StmtPtr root_stmt() const { + return root_stmt_; + } + + std::vector getLoopStmtsFor(const Tensor& /*t*/) const; + std::vector getLoopStmtsFor(const BufPtr& /*buf*/) const; + std::vector getLoopStmtsFor(StmtPtr /*s*/) const; + StmtPtr getLoopBodyFor(const Tensor& /*t*/) const; + StmtPtr getLoopBodyFor(BufPtr /*buf*/) const; + + // Returns the For stmt indexed by 'indices' in the 'root' For stmt. + //'indices' indicates the path to the returned loop from 'root' in AST, e.g., + // + // root: for(int i...){ + // j_loop: for (int j...){ + // k1_loop: for (int k1...){ + // A[i, j, k1] = .... + // } + // B[i, j] = ... + // k2_loop: for (int k2...){ + // A[i, j, k2] = ... + // } + // } + // } + // + // the path from 'root' to 'j_loop' is [0] + // the path from 'root' to 'k1_loop' is [0, 0] + // the path from 'root' to 'k2_loop' is [0, 2] + ForPtr getLoopAt(ForPtr root, const std::vector& indices) const; + + // Returns the For stmt that is immediately enclosing the given stmt. + static ForPtr getParentLoop(const StmtPtr& st); + + // Returns the list of For stmts corresponding to the loopnest that is + // enclosing the given stmt. + static std::vector getEnclosingLoopNest(const StmtPtr& st); + + // Returns a list of all Stmts that write to the given buf. + std::vector getAllWritesToBuf(BufPtr /*buf*/) const; + + // The following methods return the For loops that contain writes to + // the given buf. + // + // For example, consider the following code: + // for i1 + // for j1 + // a[i1,j1] = + // for i2 + // for j2 + // for k2 + // a[i2,j2] = + // for j3 + // a[i2,j3] = + + // Returns a list of For loops which directly contain a Stmt that writes + // to buf. + // For the above example: + // getAllInnermostLoopsWritingToBuf(a) => {j1, k2, j3} + std::vector getAllInnermostLoopsWritingToBuf(BufPtr /*buf*/) const; + + // Returns a list of For loopnests which contain a Stmt that writes to + // the given buf. Each loopnest here is a vector For loops. + // For the above example: + // getAllLoopNestsWritingToBuf(a) => {{i1,j1}, {i2,j2,k2}, {i2,j3}} + std::vector> getAllLoopNestsWritingToBuf( + BufPtr /*buf*/) const; + + StmtPtr simplify(); + + // Sanitize variables and buffer names. + // The pass assigns predefined names for loop index variables + // (i,j,k,l,m,n,o,p,i1,j1,k1,...) and ensures these names are not conflicting + // anywhere. It also removes duplicates from other Buf nad Var names as well + // as replaces illegal characters in them with underscores. + // + // Note: since it's currently technically possible to use the same variable + // as index in two different loops, this transformation finds such cases and + // introduces new variables to avoid duplication. + static StmtPtr sanitizeNames(StmtPtr s); + + bool computeInline(const StmtPtr& s); + bool computeInline(const BufPtr& b); + void inlineIntermediateBufs(bool allow_duplicated_work); + + // Optimizes conditionals. + // + // Currently, only the following pattern of conditionals is optimized. + // This corresponds to the conditional format that is generated to handle + // `aten::cat` op. + // + // for (int i = 0; i < 20; i++) { + // A[i] = IfThenElse(i<5 ? 1 : 0, B[i], C[i-5]) + // } + // + // Constraints that must be satisfied for this optimization: + // * All conditions should be of the form "var < expr". + // * All conditions should have the same variable, say v. + // * The condition variable found should be the same as the inner-most + // loop variable. TODO: Remove this constraint. + // * If there are multiple stores that contain conditionals using the same + // loop variable, only the first conditional will be optimized. + // TODO: Remove this constraint. + bool optimizeConditionals(); + + // Splits the given loop into 2 nested loops with the given factor as the + // inner loop bound. If the factor does not evenly divide the loop bound, + // then the remaining iterations are extracted into a tail loop that is + // added after the given loop. + // + // For example, consider the following code: + // for (int i = 0; i < 100; ++i) { + // A[i] = + // } + // + // splitWithTail(i, 8, ...) will result in: + // for (int i_outer = 0; i_outer < 12; ++i_outer) { + // for (int i_inner = 0; i_inner < 8; ++i_inner) { + // A[i_outer * 8 + i_inner] = + // } + // } + // for (int i_tail = 0; i_tail < 4; ++i_tail) { + // A[i_tail + 96] = + // } + // + // The given loop will be transformed to the outer loop after splitting. + // So, the pointer to the input loop should be valid after splitting and + // will point to the outer loop. The `inner` and `tail` parameters will be + // set to point to the inner and tail loops that are generated. + static void splitWithTail( + const ForPtr& f, + int factor, + ForPtr* inner, + ForPtr* tail); + // A convenience wrapper when the caller does not need to access the + // split loops. + static void splitWithTail(const ForPtr& f, int factor); + + // Splits the given loop into 2 nested loops with the given factor as the + // inner loop bound. If the factor does not evenly divide the loop bound, + // then a conditional is inserted into the body to handle the remaining + // iterations appropriately. + // + // For example, consider the following code: + // for (int i = 0; i < 100; ++i) { + // A[i] = + // } + // + // splitWithMask(i, 8, ...) will result in: + // for (int i_outer = 0; i_outer < 13; ++i_outer) { + // for (int i_inner = 0; i_inner < 8; ++i_inner) { + // if (i_outer * 8 + i_inner < 100) { + // A[i_outer * 8 + i_inner] = + // } + // } + // } + // + // The given loop will be transformed to the outer loop after splitting. + // So, the pointer to the input loop should be valid after splitting and + // will point to the outer loop. The `inner` parameter will be set to point + // to the inner loop that is generated. + static void splitWithMask(const ForPtr& f, int factor, ForPtr* inner); + // A convenience wrapper when the caller does not need to access the + // split loops. + static void splitWithMask(const ForPtr& f, int factor); + + // The following methods support loop distribution. + // For example, consider the following code. This will be used to + // demonstrate the methods below. + // + // S0: for m + // S1: for i + // S2: A[i] = 0 + // S3: for j + // S4: A[i] = A[i] + + // S5: B[i] = A[i] + // S6: for k + // S7: B[i] = B[i] + + + // This method distributes the given loop over its body by splitting + // after every given pivot stmt. + // + // NOTE: Pivot stmts that are not in the given loop's body will be ignored. + // + // For the above example: + // distributeLoop(S1, {S3, S5}) + // will result in: + // S0: for m + // S1: for i + // S2: A[i] = 0 + // S3: for j + // S4: A[i] = A[i] + + // : for i + // S5: B[i] = A[i] + // : for i + // S6: for k + // S7: B[i] = B[i] + + static std::vector distributeLoop( + const ForPtr& loop, + const std::unordered_set& pivots); + + // This method distributes the given loop over every stmt in its body. + // + // For the above example: + // distributeLoop(S1) + // will result in: + // S0: for m + // S1: for i + // S2: A[i] = 0 + // : for i + // S3: for j + // S4: A[i] = A[i] + + // : for i + // S5: B[i] = A[i] + // : for i + // S6: for k + // S7: B[i] = B[i] + + static std::vector distributeLoop(const ForPtr& loop); + // Same as above, but also distribute parent loops. + // Returns the result of distributing the outermost loop. + // + // For the above example: + // distributeLoopAndParents(S1) will result in: + // S0: for m + // S1: for i + // S2: A[i] = 0 + // : for m + // : for i + // S3: for j + // S4: A[i] = A[i] + + // : for m + // : for i + // S5: B[i] = A[i] + // : for m + // : for i + // S6: for k + // S7: B[i] = B[i] + + static std::vector distributeLoopAndParents(const ForPtr& loop); + + // This method distributes the given loop over its body by splitting + // after every For stmt in its body. + // + // For the above example: + // distributeLoopOverInnerLoops(S1) + // will result in: + // S0: for m + // S1: for i + // S2: A[i] = 0 + // S3: for j + // S4: A[i] = A[i] + + // : for i + // S5: B[i] = A[i] + // S6: for k + // S7: B[i] = B[i] + + static std::vector distributeLoopOverInnerLoops(const ForPtr& loop); + // Same as above, but also distribute parent loops. + // Returns the result of distributing the outermost loop. + // + // For the above example: + // distributeLoopAndParentsOverInnerLoops(S1) + // will result in: + // S0: for m + // S1: for i + // S2: A[i] = 0 + // S3: for j + // S4: A[i] = A[i] + + // : for m + // : for i + // S5: B[i] = A[i] + // S6: for k + // S7: B[i] = B[i] + + static std::vector distributeLoopAndParentsOverInnerLoops( + const ForPtr& loop); + + // This method performs loop fusion. + // For example, consider the following code. + // + // S1: for m + // S2: A[m] = 0 + // S3: for j + // S4: A[m] = A[m] + + // S5: for n + // S5: B[n] = A[n] + // S6: for k + // S7: B[n] = B[n] + + // + // fuseLoops({S1, S5}), will return the following loop: + // S1: for m + // S2: A[m] = 0 + // S3: for j + // S4: A[m] = A[m] + + // S5: B[m] = A[m] + // S6: for k + // S7: B[m] = B[m] + + // + // This transformation is unsafe as it simply add all loops into the body of + // the first loop for fusion without correctness checks. + // + // Below are the two requirements to apply unsafeFuseLoops: + // * All the loops have the same parent. + // * There are no statements between these loops in their parent body. + static bool unsafeFuseLoops(const std::vector& loops, ForPtr* fused); + + // Loop fusion is done only when all the conditions below are satisfied. + // * All the loops have the same parent. + // * There are no statements between these loops in their parent body. + // * The start bounds are the same for all loops. + // * The stop bounds are the same for all loops. + // * Fusing the loops does not violate or add any dependencies. + static bool fuseLoops(const std::vector& loops, ForPtr* fused); + + static void reorderAxis(const ForPtr& a, const ForPtr& b); + + // Reorder the given list of loops according to the permutation specified. + // Here `permutation[i]` represents the position of the loop in the input + // which will end up at position `i` after the reorder. + // + // For example, consider the following code: + // for p + // for q + // for r + // for s + // A[p,q,r,s] = + // + // reorder({p, q, r, s}, {2, 3, 0, 1}) will return the list of loops in the + // following form: + // for r + // for s + // for p + // for q + // A[p,q,r,s] = + static std::vector reorder( + const std::vector& loops, + const std::vector& permutation); + + // Tile takes a 2d domain (x, y) and splits it into small rectangular blocks + // each with shape (x_factor, y_factor). The traversal over the domain turns + // into an outer iteration over the blocks and an inner traversal over all + // points in the block. + // Note that if x dim % x_factor or y dim % y_factor does not equal to 0, the + // loop body will generate corresponding tailing loops. + // The transformation is in-place and returns 'xtail'. + // + // For example, consider the following code: + // for i: [0, 64) + // for j: [0, 64) + // for k: [0, 32) + // A[i, j] = B[i, k] + C[j, k] + // + // tile(i, j, 4, 8) will transform "i" for-stmt into the following nested + // loop: + // for i_outer: [0, 16) + // for j_outer: [0, 8) + // for i_inner: [0, 4) + // for j_inner: [0, 8) + // for k: [0, 32) + // A[i_outer * 4 + i_inner, j_outer * 8 + j_inner] = + // B[i_outer * 4 + i_inner, k] + C[j_outer * 8 + j_inner, k] + // + // tile(i, j, 4, 9) will transform "i" for-stmt into the following nested + // loop: + // for i_outer: [0, 16) + // for j_outer: [0, 7) + // for i_inner: [0, 4) + // for j_inner: [0, 9) + // for k: (0, 32) + // A[i_outer * 4 + i_inner, j_outer * 9 + j_inner] = + // B[i_outer * 4 + i_inner, k] + C[j_outer * 9 + j_inner, k] + // for j_tail: [0, 1) + // for i_inner: [0, 4) + // for k: (0, 32) + // A[i_outer * 4 + i_inner, 7 * 9 + j_tail] = + // B[i_outer * 4 + i_inner, k] + C[7 * 9 + j_tail, k] + ForPtr tile(const ForPtr& x, const ForPtr& y, int x_factor, int y_factor); + + // Returns true if the given loops are perfectly nested, i.e., every loop + // (except the innermost) should have exactly one statement in its body + // and that statement must be the next inner loop. + static bool areLoopsPerfectlyNested(const std::vector& loops); + + // Returns true if the given loop has a loop-carried dependence. + static bool hasLoopCarriedDependence(const ForPtr& loop); + + // Unrolls all the iterations of the given loop. + // Requires that the loop bounds are constant. + static void fullUnroll(const ForPtr& f, StmtPtr* unrolled); + static void fullUnroll(const ForPtr& f); + + // Unrolls the given loop for the specified factor. + // This does not require constant bounds for the loop being unrolled. + static void unroll(const ForPtr& f, int factor, ForPtr* tail); + static void unroll(const ForPtr& f, int factor); + + static bool normalize(const ForPtr& f); + static bool isNormalized(const ForPtr& f); + + static bool flatten(const std::vector& f, ForPtr* flattened); + static bool flatten(const std::vector& f); + + // Compresses the given buffer based on its use in the given Stmts. + // + // NOTE: This API assumes that there are no accesses to the given buffer + // outside the given statement. So, this should be called with the entire + // kernel statement to avoid incorrect buffer compressions. + // + // For example, given the input: + // + // for (int i = 0; i < 100; ++i) { + // for (int j = 0; j < 200; ++j) { + // A[i,j] = sin(i*j) + // } + // for (int j = 0; j < 199; ++j) { + // B[i,j] = A[i,j] + A[i, j+1] + // } + // } + // + // compressBuffer(A, ...) will compress buffer A from + // [100, 200] to [1, 200] and modify the code as follows: + // + // for (int i = 0; i < 100; ++i) { + // for (int j = 0; j < 200; ++j) { + // A[0,j] = sin(i*j) + // } + // for (int j = 0; j < 199; ++j) { + // B[i,j] = A[0,j] + A[0, j+1] + // } + // } + static void compressBuffer(const BufPtr& buf, const StmtPtr& stmt); + + // Compresses all buffers in the given statement. + // + // NOTE: This API assumes that there are no accesses to buffers outside + // the given statement. So, this should be called with the entire + // kernel statement to avoid incorrect buffer compressions. + // + // TODO: Add an IR verifier check to detect invalidly compressed buffers. + static void compressAllBuffers(const StmtPtr& stmt); + + // Get 'num' loops from the loopnest starting at 'f'. + static std::vector getLoopStmtsInLoopNest( + const ForPtr& f, + size_t num); + + // LoopOptions are propagated to tail. + static void sliceHead( + const ForPtr& f, + int factor, + ForPtr* head, + ForPtr* tail); + static void sliceHead(const ForPtr& f, int factor); + // LoopOptions are propagated to head. + static void sliceTail( + const ForPtr& f, + int factor, + ForPtr* head, + ForPtr* tail); + static void sliceTail(const ForPtr& f, int factor); + + using AccessResult = std::pair; + // Insert a cache for the consumer's usages of the buffer produced in + // consumer, and redirect reads and writes in the consumer to that cache. + // Returns a pair of the new cache buffer, and the new rewritten consumer. + static AccessResult cacheAccesses( + const BufPtr& producer, + const std::string& name, + const StmtPtr& consumer); + + // Insert a temporary computation of statement S in the scope of loop AT. + // S is assumed to be a Store or a Block containing a Store. Along with the + // computation itself, this transformation inserts Alloc/Free statements for + // the temporary buffer used in the computation. + static void computeAt(const StmtPtr& s, const ForPtr& at); + + // Rfactor a reduction axis into a normal axis. + // + // Requirements: + // * S is the reduction store + // * S is the only statement in the innermost loop + // * There is at least two reduction arguments in S + // * OUTER_REDUCTION_FOR loop corresponds to the outermost reduction variable + // used in the store and all other reduction variables are index variables of + // children loops of OUTER_REDUCTION_FOR + // * OUTER_REDUCTION_FOR is a perfect loop nest, i.e. it has only loops + // corresponding to the other reduction variables and the store, nested into + // each other + // + // What it does: + // * Introduce a new buffer with an extra dimension of a size equal to the + // span of the loop OUTER_REDUCTION_FOR (the new buffer is returned via + // RFAC_BUF_PTR) + // * Insert an initialization store for the new buffer in + // OUTER_REDUCTION_FOR before its nested loop + // * Replace the reduction store to the original buffer with the reduction + // store to the temp buffer, removing the index var of OUTER_REDUCTION_FOR + // from reduction arguments + // * Insert a final reduction store over the extra dimension of the new + // buffer to the original buffer + // * Returns TRUE if the transformation succeeded and FALSE otherwise + // + // Example: + // Original IR: + // S1: for i # normal axis + // S2: X[i] = 0 + // S3: for j # reduction axis + // S4: for k # reduction axis + // S5: X[i] = ReduceOp(X[i] + Y[i,j,k], reduce_axis={j,k}) + // + // After RFACTOR(S5, S3) + // S1: for i # normal axis + // S2: X[i] = 0 + // S3: for j # reduction axis for X, normal axis for X_rfac + // X_rfac[i,j] = 0 + // S4: for k # reduction axis + // X_rfac[i,j] = ReduceOp(X_rfac[i,j] + Y[i,j,k], reduce_axis={k}) + // X[i] = ReduceOp(X[i] + X_rfac[i,j], reduce_axis={j}) + static bool rfactor(const StmtPtr& s, const ForPtr& outer_reduction_for); + static bool rfactor( + const StmtPtr& s, + const ForPtr& outer_reduction_for, + BufPtr* rfac_buf_ptr); + + // Vectorize the given loop. This method requires that the given loop + // does not perform a reduction. + // It returns true if vectorization is successful and false otherwise. + static bool vectorize(const ForPtr& /*f*/); + + // Find the inner-most loops and vectorize them. Currently, this only works + // for the LLVM backend, when no reductions are involved. + void vectorizeInnerLoops(); + + void eliminateDeadStores(); + + void prepareForCodegen(); + + const std::unordered_set getInputBufs() const; + const std::unordered_set getOutputBufs() const { + return output_bufs_; + } + std::vector getIntermediateBufs() const; + + // Finds which is the outer For between a and b for loops. If neither of the 2 + // Fors is an ancestor of the other, it returns nullptr. + static ForPtr findOuterFor(ForPtr a, ForPtr b); + + private: + void initialize( + const std::vector& output_tensors, + const std::vector& tensors_to_compute); + + StmtPtr root_stmt_; + + std::unordered_set output_bufs_; +}; + +TORCH_API StmtPtr FlattenIndexes(const StmtPtr& s); + +// TODO: Revisit this once we decide on how dependencies analysis should look +// like. Maybe we would choose to use a different API and BufUse would be +// removed, or if we decide to keep it we need to properly document its API. +struct BufLoadOrStoreUse { + StmtPtr s; + bool isStore; +}; + +/* + * Returns a map ( Buf -> uses of this Buf), uses are represented as vectors of + * BufUse elements, which are StmtPtr and a bool isStore flag. The order of uses + * in the vectors reflects the order in which the uses appear in the given + * statement. + */ +std::unordered_map> findLoadOrStoreUses( + const StmtPtr& s); + +// replaces all invalid characters with underscore +TORCH_API std::string sanitizeName(const std::string& input_name); + +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/loopnest_randomization.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/loopnest_randomization.h new file mode 100644 index 0000000000000000000000000000000000000000..674fd337b0ea8ceb9cb6d09f122489eaa56cdc30 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/loopnest_randomization.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +namespace torch::jit::tensorexpr { + +// Applies a series of loop optimizations chosen randomly. This is only for +// testing purposes. This allows automatic stress testing of NNC loop +// transformations. +void loopnestRandomization(int64_t seed, LoopNest& l); +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/lowerings.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/lowerings.h new file mode 100644 index 0000000000000000000000000000000000000000..79a75576d509dbe9b143daf2611cde26d7149d7d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/lowerings.h @@ -0,0 +1,50 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// This file defines classes for registering standard lowerings from JIT to TE +// IR. +#pragma once + +#include +#include +#include +#include +#include + +namespace torch::jit::tensorexpr { + +using ArgNone = std::monostate; +using BufList = std::vector; +using DoubleList = std::vector; +using IntList = std::vector; +using ArgValue = std::variant< + tensorexpr::BufHandle, + tensorexpr::VarHandle, + double, + int64_t, + bool, + BufList, + DoubleList, + IntList, + std::string, + ArgNone>; + +using NNCLoweringFunction = std::function&, + const std::vector&, + const std::vector&, + const std::optional&, + at::Device)>; + +TORCH_API FunctionSchemaMap& getNNCLoweringRegistry(); +TORCH_API NNCLoweringFunction getStandardLoweringFor(const std::string& op); + +struct RegisterNNCLoweringsFunction { + RegisterNNCLoweringsFunction( + const std::vector& schemas, + const NNCLoweringFunction& fn); +}; + +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/mem_dependency_checker.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/mem_dependency_checker.h new file mode 100644 index 0000000000000000000000000000000000000000..8e5b9e292d862bf890e19729b0a4ba206d4a85bb --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/mem_dependency_checker.h @@ -0,0 +1,414 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace torch::jit::tensorexpr::analysis { + +enum class AccessType { + Input, + Output, + Load, + Store, + Call, + AtomicAdd, + Alloc, + Free +}; +const char* AccessToString(AccessType a); + +class AccessInfo; +using DependencySet = std::unordered_set>; + +/* AccessInfo + * + * Represents a single bounded memory access to a buffer, for instance a Load or + * a Store. Holds information relating to the specific access and links to + * connected accesses in the dependency graph. + */ +class TORCH_API AccessInfo { + public: + AccessInfo( + size_t id, + AccessType type, + StmtPtr stmt, + VarPtr var, + IndexBounds bounds) + : id_(id), + type_(type), + stmt_(std::move(stmt)), + expr_(nullptr), + var_(std::move(var)), + bounds_(std::move(bounds)) {} + + AccessInfo( + size_t id, + AccessType type, + ExprPtr expr, + StmtPtr stmt, + VarPtr var, + IndexBounds bounds) + : id_(id), + type_(type), + stmt_(std::move(stmt)), + expr_(std::move(expr)), + var_(std::move(var)), + bounds_(std::move(bounds)) {} + + // Id is a unique int representing the order this access occurred in the + // graph. + size_t id() const { + return id_; + } + + // The type of the access (Load, Store, etc). + AccessType type() const { + return type_; + } + + // The enclosing Stmt this access represents. E.g. if this is a Store then + // Stmt is the Store itself, while if the access is caused by an Expr, this is + // the most immediate parent Stmt. + StmtPtr stmt() const { + return stmt_; + } + + // If the access is represented by an Expr (such as Load or Call) then this is + // it, otherwise it's nullptr. + ExprPtr expr() const { + return expr_; + } + + // The Var representing the underlying Buffer. + VarPtr var() const { + return var_; + } + + // A vector of Bounds representing the start and end expression for each + // dimension. + IndexBounds& bounds() { + return bounds_; + } + + // Each access that this depends upon, + // eg. if this is a Load, then it contains every Store that immediately + // contributes to a load of the bounds. + // or: if this is a Store, it contains all reads on the RHS of the Store. + const std::map>& dependencies() const { + return dependencies_; + } + + // Each access that depends on this one. + // ie. this access is present in the dependencies map of all accesses that are + // dependent. + std::map> dependents() const { + std::map> res; + for (const auto& kv : dependents_) { + res.emplace(kv.first, kv.second.lock()); + } + return res; + } + + // Returns the symbolic expression of the indices of this access. + std::vector getIndices() const; + + // Establishes a dependency or dependent relationship with another access. + void addDependency(const std::shared_ptr& write); + void addDependent(const std::shared_ptr& read); + + // helper for checking dependencies. + bool hasDependency(const std::shared_ptr& info) const; + + // Returns the set of all nodes that are direct (immediate) dependencies of + // this access. + DependencySet getDirectDependencies(); + // likewise, returns all nodes that directly depend on this one. + DependencySet getDirectDependents(); + + // Returns the full list of all nodes in the graph that this access depends + // on, and all nodes they depend on, and so forth, back to the inputs. + DependencySet getIndirectDependencies(); + // likewise, returns the full list of all nodes that depend on this node, and + // all nodes that depend on those nodes and so on down to the outputs. + DependencySet getIndirectDependents(); + + // Does this access represent a read of memory (Load, ReduceOp, Call, etc). + bool isRead() const; + // Does this access represent a write of memory (Store, etc). + bool isWrite() const; + + // Helpers for dumping accesses in various formats. + void print() const; + void dumpDOT(std::ostream& os) const; + const char* AccessTypeColour() const; + + private: + size_t id_; + AccessType type_; + StmtPtr stmt_; + ExprPtr expr_; + VarPtr var_; + IndexBounds bounds_; + + // Yes these should be sorted. + std::map> dependencies_; + std::map> dependents_; +}; + +using VarBoundMap = std::unordered_map; + +/* MemDependencyChecker analyses a IR fragment and builds a dependency graph of + * accesses contained within. + * + * It's possible to retrieve the entire graph in node-object form, or can be + * used as an oracle for answering dependency questions. e.g: + * + * analyzer.hasIndirectDependency(BufA, BufB); or, + * analyzer.hasDirectDependency(LoadA, StoreB); + */ +class TORCH_API MemDependencyChecker : public IRVisitor { + struct Scope; + + public: + MemDependencyChecker(); + MemDependencyChecker( + const std::unordered_set& inputs, + const std::unordered_set& outputs); + MemDependencyChecker( + const std::vector& inputs, + const std::vector& outputs); + + ~MemDependencyChecker() override = default; + + // Whether or not to allow loop execution order to influence dependency + // calculation. If the loop may later be parallelized you don't want this. + bool allowLoopExecutionOrderAnalysis(bool allow = true); + + // Dependency Checking API. + // The goal is to have enough overloads here so you don't really have to think + // about it. + + // Returns true if any read in A has a direct dependence on a write in B. + bool dependsDirectly(const StmtPtr& A, const StmtPtr& B); + bool dependsDirectly(const ExprPtr& A, const StmtPtr& B); + + // Returns true of the output depends directly on a write contained in B. + bool dependsDirectly(const BufPtr& output, const StmtPtr& B); + + // Returns true if a read in A depends directly on the provided input. + bool dependsDirectly(const StmtPtr& A, const BufPtr& input); + bool dependsDirectly(const ExprPtr& A, const BufPtr& input); + + // Outputs/inputs cannot depend directly. + + // Returns true if the access A has B as an immediate dependency. + bool dependsDirectly( + const std::shared_ptr& A, + const std::shared_ptr& B); + + // Returns true if any read in A has an ancestor write contained in B. + bool dependsIndirectly(const StmtPtr& A, const StmtPtr& B); + bool dependsIndirectly(const ExprPtr& A, const StmtPtr& B); + + // Returns true of the output depends indirectly on a write contained in B. + bool dependsIndirectly(const BufPtr& output, const StmtPtr& B); + + // Returns true if a read in A depends indirectly on the provided input. + bool dependsIndirectly(const StmtPtr& A, const BufPtr& input); + bool dependsIndirectly(const ExprPtr& A, const BufPtr& input); + + // returns true if the output uses any load of the input. + bool dependsIndirectly(const BufPtr& output, const BufPtr& input); + + // Returns true if the access A has a dependency chain to access B. + bool dependsIndirectly( + const std::shared_ptr& A, + const std::shared_ptr& B); + + // Returns the AccessInfo + std::shared_ptr accessFor(const StmtPtr& A) const; + std::shared_ptr accessFor(const ExprPtr& A) const; + + // Returns all AccessInfos. + std::unordered_set> accessesWithin( + const StmtPtr& A) const; + // TODO: this will return only the AccessInfo for A. It's included for + // completeness but be aware it won't return accesses used in the computation + // of A. + std::unordered_set> accessesWithin( + const ExprPtr& A) const; + + // Accesses relating to input and output buffers. + std::shared_ptr input(const BufPtr& B) const; + std::shared_ptr output(const BufPtr& B) const; + + // Returns the full history of reads and writes. + const std::vector>& getHistory() const; + + // Dumps the dependency graph in DOT format. + void dumpDAG(const std::string& filename) const; + + private: + // Node visitors. + void visit(const StorePtr& v) override; + void visit(const LoadPtr& v) override; + void visit(const ForPtr& v) override; + void visit(const CondPtr& v) override; + void visit(const IfThenElsePtr& v) override; + void visit(const CompareSelectPtr& v) override; + void visit(const BlockPtr& v) override; + void visit(const LetPtr& v) override; + void visit(const AtomicAddPtr& v) override; + void visit(const AllocatePtr& v) override; + void visit(const FreePtr& v) override; + + using BoundRelationship = std::pair>; + + // An internal struct holding the accesses found within a scope Block. + struct Scope { + Scope(BlockPtr b, std::shared_ptr p) + : block(std::move(b)), parent(std::move(p)) {} + + BlockPtr block; + std::shared_ptr parent; + + std::unordered_map shadowedVarBounds; + std::unordered_set localVars; + + std::vector> accesses_; + + std::unordered_map> openWrites_; + }; + std::shared_ptr currentScope_; + + bool allowExecutionOrderAnalysis_{false}; + + std::unordered_multimap> stmtToAccess_; + std::unordered_multimap> exprToAccess_; + std::unordered_map>> + scopeToAccesses_; + + VarBoundMap knownVarBounds_; + + // Finds all accesses that are reads within the scope of v. + template + DependencySet getAllReadsWithin(const StmtOrExprPtr& v) { + DependencySet reads; + auto insertAllReads = [&](const auto& nodes) { + for (const auto& l : nodes) { + auto bound = exprToAccess_.equal_range(l); + for (auto it = bound.first; it != bound.second; ++it) { + if (it->second->isRead()) { + reads.insert(it->second); + } + } + } + }; + + // Look for and insert accesses belonging to all nodes that act like + // reads. + insertAllReads(NodeFinder::find(v)); + insertAllReads(NodeFinder::find(v)); + + return reads; + } + + // Finds all accesses that are writes within the scope of v. + // Writes cannot occur in Exprs, so this is a little simpler. + DependencySet getAllWritesWithin(const StmtPtr& v) { + DependencySet writes; + + // writes just Store currently. + auto stores = NodeFinder::find(v); + for (const auto& s : stores) { + auto bound = stmtToAccess_.equal_range(s); + for (auto it = bound.first; it != bound.second; ++it) { + if (it->second->isWrite()) { + writes.insert(it->second); + } + } + } + return writes; + } + + // Templated helpers to work on either Exprs or Stmts. + template + bool dependsDirectlyHelper(const StmtOrExprPtr& A, const StmtPtr& B) { + auto aReads = getAllReadsWithin(A); + auto bWrites = getAllWritesWithin(B); + + for (auto& read : aReads) { + for (auto& depPair : read->dependencies()) { + if (bWrites.count(depPair.second) != 0) { + return true; + } + } + } + + return false; + } + + template + bool dependsIndirectlyHelper(StmtOrExprPtr A, const StmtPtr& B) { + auto aReads = getAllReadsWithin(A); + auto bWrites = getAllWritesWithin(B); + + auto aDeps = getAllWriteDependencies(aReads); + + for (auto& dependency : aDeps) { + if (bWrites.count(dependency) != 0) { + return true; + } + } + + return false; + } + + DependencySet getAllWriteDependencies(const DependencySet& products); + + // Maps for inputs and outputs, since they aren't present directly in the IR. + std::unordered_map> inputs_; + std::unordered_map> outputs_; + std::unordered_map> intermediates_; + + // Inserts accesses for Buf's: specifically for inputs and outputs. + void insertBuffers( + std::unordered_map>& bufs, + AccessType type); + + // Update the write history with a new write, adding dependencies and closing + // any overlapped writes (if possible). + void updateWriteHistory( + std::list& writeHistory, + const std::shared_ptr& info, + size_t latestAccessToClose, + bool closeOverlapped = true, + bool insert = true); + + // Merge a child scope into a parent scope, adding dependencies for open + // writes in the parent to accesses in the child. + void mergeScope( + const std::shared_ptr& child, + const std::shared_ptr& parent, + bool closeOverlapped = true); + + // Binds symbolic vars in indices with the low and high bound for those vars. + std::vector getIndicesBounds(const std::vector& indices); + + size_t nextAccess_{0}; + StmtPtr lastStmt_{nullptr}; +}; + +} // namespace torch::jit::tensorexpr::analysis + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/conv2d.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/conv2d.h new file mode 100644 index 0000000000000000000000000000000000000000..ca63d7b9be1773cec3ada78416bd2c865427722d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/conv2d.h @@ -0,0 +1,106 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::jit::tensorexpr { + +// An API to compute 2D depthwise convolutions with bias. +TORCH_API Tensor conv2d_depthwise( + BufHandle input, + BufHandle weight, + BufHandle bias, + int stride, + int pad, + int groups); + +// An API to compute 2D depthwise convolutions without bias. +TORCH_API Tensor conv2d_depthwise( + BufHandle input, + BufHandle weight, + int stride, + int pad, + int groups); + +TORCH_API Tensor conv2d_depthwise( + BufHandle input, + BufHandle weight, + BufHandle bias, + ExprHandle N, + ExprHandle C, + ExprHandle H, + ExprHandle W, + ExprHandle K, + ExprHandle CperG, + ExprHandle R, + ExprHandle S, + ExprHandle stride, + ExprHandle pad, + ExprHandle groups); + +TORCH_API Tensor conv2d_depthwise( + BufHandle input, + BufHandle weight, + ExprHandle N, + ExprHandle C, + ExprHandle H, + ExprHandle W, + ExprHandle K, + ExprHandle CperG, + ExprHandle R, + ExprHandle S, + ExprHandle stride, + ExprHandle pad, + ExprHandle groups); + +bool conv2dIsSupported( + const TensorInfo& input, + const TensorInfo& weight, + const TensorInfo& bias, + const std::vector& stride, + const std::vector& pad, + const std::vector& dilation, + int64_t groups); +bool mkldnnPrepackedConvIsSupported( + const TensorInfo& input, + const TensorInfo& weight, + const std::vector& stride, + const std::vector& pad, + const std::vector& dilation, + int64_t groups); +Tensor computeConv2d( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); +Tensor computeConv1d( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); +Tensor computePrepackedConv2dClampRun( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); +Tensor computePrepackedLinearClampRun( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); +Tensor computeMkldnnPrepackedConvRun( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/matmul.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/matmul.h new file mode 100644 index 0000000000000000000000000000000000000000..1090455818d68d23348eb870b8930d1def34358b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/matmul.h @@ -0,0 +1,25 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit::tensorexpr { + +Tensor computeMatmul( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); +Tensor computeAddMM( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/misc.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/misc.h new file mode 100644 index 0000000000000000000000000000000000000000..6a1f61a2fb09e0342292b72c2c23d3a801df3a10 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/misc.h @@ -0,0 +1,99 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace torch::jit::tensorexpr { + +struct TensorInfo { + std::vector dims; + c10::ScalarType dtype; +}; +std::optional getTensorInfo(const BufHandle& b); + +int64_t normalizeAndCheckIndex(int64_t idx, int64_t list_size); + +// Convert boolean to integer, if needed. +ExprHandle boolToInteger(const ExprHandle& x); +ExprHandle promoteToDtype(ExprHandle e, ScalarType dt); +void promoteInputs( + std::vector& inputs, + const int typeConstraints = kAllTypes); +ExprHandle promoteIntegerToDefaultType(const ExprHandle& e); +ExprHandle promoteHalfToFloat(const ExprHandle& e); +ExprHandle demoteOutput( + const ExprHandle& e, + const std::optional type); + +std::vector broadcastShapes( + std::vector> shapes); +std::vector broadcastShapes( + const std::vector& a, + const std::vector& b); + +std::vector valueShape(const ArgValue& v); +ExprHandle tensorOrConstant( + const ArgValue& v, + const std::vector& axes); +ExprHandle scalarOrConstant(const ArgValue& v); +ExprHandle broadcast(const BufHandle& b, const std::vector& axes); +ExprHandle constant(const ArgValue& v); + +ExprHandle clamp( + const ExprHandle& cmin, + const ExprHandle& cmax, + const ExprHandle& input); + +Tensor computeChunk( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); +Tensor computeTranspose( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); +Tensor computeExpand( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); +Tensor computeReshape( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); +Tensor computeFlatten( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); +Tensor computeCatWoConditionals( + const std::vector& inputs, + const std::vector& outputShape); +Tensor computeCat( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); +Tensor computeEmbedding( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/norm.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/norm.h new file mode 100644 index 0000000000000000000000000000000000000000..3d712cca1beae7547bd5f24f366f050d8783e5c5 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/norm.h @@ -0,0 +1,19 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit::tensorexpr { + +Tensor computeBatchNorm( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/operators.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/operators.h new file mode 100644 index 0000000000000000000000000000000000000000..8625cbf737729e3f33095526e2b712a3f35575c8 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/operators.h @@ -0,0 +1,15 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/pointwise.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/pointwise.h new file mode 100644 index 0000000000000000000000000000000000000000..cd8035fdaf773a5467a015e5113b8b5f4bd20fe8 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/pointwise.h @@ -0,0 +1,87 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit::tensorexpr { + +TORCH_API Tensor computeSign( + const std::vector& inputs, + const std::vector& outputShape, + const std::optional>& outputStrides = std::nullopt); + +Tensor computeOneOperand( + const std::string& name, + const std::vector& inputValues, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + const std::function& innerExpr, + const int checkParamTypes = kAllTypes); +Tensor computeTwoOperand( + const std::string& name, + const std::vector& inputValues, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + const std::function& + innerExpr); +Tensor computeTwoOperandWithAlpha( + const std::string& name, + const std::vector& inputValues, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + const std::function& + innerExpr); +Tensor computeConditionWithTwoOperand( + const std::string& name, + const std::vector& inputValues, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + const std::function< + ExprHandle(const ExprHandle&, const ExprHandle&, const ExprHandle&)>& + innerExpr); +Tensor computeThreeOperand( + const std::string& name, + const std::vector& inputValues, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + const std::function< + ExprHandle(const ExprHandle&, const ExprHandle&, const ExprHandle&)>& + innerExpr, + bool promote_inputs = true); +Tensor computeFourOperand( + const std::string& name, + const std::vector& inputValues, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + const std::function& innerExpr); +Tensor computeNoop( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +Tensor computeScalar( + const std::string& name, + const std::vector& inputValues, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + const std::function& + innerExpr); + +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/quantization.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/quantization.h new file mode 100644 index 0000000000000000000000000000000000000000..9ebd11bc633c053ad5a3ff6df24f56f0f95bdc35 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/quantization.h @@ -0,0 +1,154 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit::tensorexpr { + +TORCH_API ExprHandle quantizePerTensorQParamFromArg(ArgValue arg); + +TORCH_API double immQScale(const BufHandle& qx); + +TORCH_API int64_t immQZero(const BufHandle& qx); + +TORCH_API ScalarType immQDType(const BufHandle& qx); + +TORCH_API bool isQuantized(const BufHandle& qx); + +TORCH_API Tensor computeQuantizePerTensor( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeQuantizePerTensorExternalCall( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeQuantizedConv1d( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeQuantizedConv2dPrepack( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeQuantizedConv2d( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeQuantizedConv2dRelu( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeQuantizedLinear( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeQuantizedLinearRelu( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeQuantizedAdd( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +Tensor computeQuantizedAddExternalCall( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeQuantizedMul( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeQuantizedMulScalar( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeQuantizedCat( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeQuantizedRelu( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeDequantize( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeDequantizeExternalCall( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeUpsampleNearest2d( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeUpsampleNearest2dExternalCall( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +TORCH_API Tensor computeQuantizedSigmoidExternalCall( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device /*unused*/); +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/reduction.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/reduction.h new file mode 100644 index 0000000000000000000000000000000000000000..c9e3cb67920a3984118cea1c7ddb1837d4080cec --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/reduction.h @@ -0,0 +1,37 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit::tensorexpr { + +TORCH_API Tensor computeSum( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); +TORCH_API Tensor computeMean( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); +TORCH_API Tensor computeAdaptiveAvgPool2d( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); +Tensor computeMax( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + const std::optional& outputType, + at::Device device); + +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/softmax.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/softmax.h new file mode 100644 index 0000000000000000000000000000000000000000..675a6c0bc795913bc588be6084aad749eb4bf153 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/operators/softmax.h @@ -0,0 +1,18 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::jit::tensorexpr { + +Tensor computeSoftmax( + const std::vector& inputs, + const std::vector& outputShape, + const std::vector& outputStrides, + bool log_softmax); + +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/reduction.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/reduction.h new file mode 100644 index 0000000000000000000000000000000000000000..9faee10a839d2b3aa0ecd62724dd899e2f9f284a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/reduction.h @@ -0,0 +1,311 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace torch::jit::tensorexpr { + +using ParameterList = const std::vector; +using ReduceInteraction = std::function; + +// A Reducer is a user interface describing a particular reduction +// operation. It has three components: An initialization value, a way of +// interacting each value with the accumulation, and a method for obtaining the +// current value to be reduced. It is materialized into a ReduceOp when loop +// variables are known. +class TORCH_API Reducer { + public: + Reducer(ExprHandle init, ReduceInteraction& interaction) + : init_(init.node()), interaction_(interaction) {} + + template + Reducer(ExprHandle init, RI interaction) + : init_(init.node()), interaction_(std::move(interaction)) {} + + ExprPtr initializer() const { + return init_; + } + + ExprHandle operator()( + const BufHandle& result_buf, + ExprHandle body, + const std::vector& output, + const std::vector& inner) const; + + ReduceOpPtr operator()( + const BufPtr& result_buf, + ExprPtr body, + const std::vector& output, + const std::vector& inner) const; + + ExprHandle operator()( + const BufHandle& result_buf, + BufHandle acc_buf, + const ExprHandle& body, + const std::vector& output, + const std::vector& inner) const; + + // Polymorphic handling of Body functions with a variety of parameters. + static ExprHandle getReduceBody( + const std::function& func, + const std::vector& vars) { + return func(vars); + } + + static ExprHandle getReduceBody( + const std::function& func, + const std::vector& vars) { + if (vars.size() != 1) { + throw malformed_input("mismatch between reduce body and arg size (1)"); + } + + return func(vars[0]); + } + + static ExprHandle getReduceBody( + const std::function& func, + const std::vector& vars) { + if (vars.size() != 2) { + throw malformed_input("mismatch between reduce body and arg size (2)"); + } + return func(vars[0], vars[1]); + } + + static ExprHandle getReduceBody( + const std::function< + ExprHandle(const VarHandle&, const VarHandle&, const VarHandle&)>& + func, + const std::vector& vars) { + if (vars.size() != 3) { + throw malformed_input("mismatch between reduce body and arg size (3)"); + } + return func(vars[0], vars[1], vars[2]); + } + + static ExprHandle getReduceBody( + const std::function& func, + const std::vector& vars) { + if (vars.size() != 4) { + throw malformed_input("mismatch between reduce body and arg size (4)"); + } + return func(vars[0], vars[1], vars[2], vars[3]); + } + + // Completes the reduction operator by applying the interaction function to + // the accumulation and the body expression. + static ExprPtr complete( + const BufPtr& accumulator, + const ReduceInteraction& interaction, + ExprHandle body, + const std::vector& output_args, + const std::vector& reduce_args) { + ExprHandle accum = + ExprHandle(alloc(body.dtype(), accumulator, output_args)); + auto e = interaction(std::move(accum), std::move(body)); + return e.node(); + } + static ExprHandle complete( + const BufHandle& accumulator, + const ReduceInteraction& interaction, + ExprHandle body, + const std::vector& output_args, + const std::vector& reduce_args) { + ExprHandle accum = Load::make(body.dtype(), accumulator, output_args); + auto e = interaction(std::move(accum), std::move(body)); + return e; + } + + private: + ExprPtr init_; + ReduceInteraction interaction_; +}; + +// An expression representing a Reduction operation (e.g. Sum, Max) broken into +// it's component parts: initialization, accumulation var, acquisition of value +// to be reduced and interaction. +// +// This is intended to be expanded in the loopnest and not make it to codegen. +class TORCH_API ReduceOp : public ExprNode { + public: + ReduceOp( + const ExprPtr& body, + std::vector reduce_args, + Reducer reducer) + : ExprNodeBase(body->dtype()), + body_(body), + reduce_args_(std::move(reduce_args)), + reducer_(std::move(reducer)) { + result_buf_ = nullptr; + acc_buf_ = nullptr; + ri_operand_ = nullptr; + } + + ReduceOp( + const ExprPtr& body, + std::vector reduce_args, + BufPtr result_buf, + BufPtr acc_buf, + ExprPtr ri_operand, + Reducer reducer) + : ExprNodeBase(body->dtype()), + body_(body), + reduce_args_(std::move(reduce_args)), + result_buf_(std::move(result_buf)), + acc_buf_(std::move(acc_buf)), + ri_operand_(std::move(ri_operand)), + reducer_(std::move(reducer)) {} + + static ExprHandle make( + ExprHandle body, + const std::vector& reduce_args, + const Reducer& reducer); + + static ExprHandle make( + ExprHandle body, + const std::vector& reduce_args, + BufHandle result_buf, + BufHandle acc_buf, + ExprHandle ri_operand, + const Reducer& reducer); + + // return the body expression which obtains the value to be reduced. + ExprPtr body() const { + return body_; + } + + // Returns the original Reducer factory that can create ReduceOps. + const Reducer& reducer() const { + return reducer_; + } + + // returns variables associated with the axes of reduction. + const std::vector& reduce_args() const { + return reduce_args_; + } + + void setAccBuf(BufHandle acc_buf) { + acc_buf_ = acc_buf.node(); + } + BufPtr getAccBuf() { + return acc_buf_; + } + + void setResultBuf(BufHandle buf) { + result_buf_ = buf.node(); + } + BufPtr getResultBuf() { + return result_buf_; + } + + void setRiOperand(ExprHandle ri_operand) { + ri_operand_ = ri_operand.node(); + } + ExprPtr getRiOperand() { + return ri_operand_; + } + + private: + // body_ = reducer_->interaction_(result_buf_, ri_operand_) + ExprPtr body_; + std::vector reduce_args_; + + BufPtr result_buf_; + BufPtr acc_buf_; + ExprPtr ri_operand_; + + const Reducer reducer_; +}; + +class Sum : public Reducer { + public: + Sum() + : Reducer(ExprHandle(0), [](const ExprHandle& a, const ExprHandle& b) { + return a + b; + }) {} +}; + +inline ExprHandle maximumVal(ScalarType type) { + switch (type) { +#define MAX_BY_TYPE_CASE(Type, Name) \ + case ScalarType::Name: \ + return ExprHandle(std::numeric_limits::max()); + AT_FORALL_SCALAR_TYPES_AND3(Bool, Half, BFloat16, MAX_BY_TYPE_CASE) +#undef MAX_BY_TYPE_CASE + default: + throw unsupported_dtype(); + } + return ExprHandle(); +} + +inline ExprHandle minimumVal(ScalarType type) { + switch (type) { +#define MAX_BY_TYPE_CASE(Type, Name) \ + case ScalarType::Name: \ + return ExprHandle(std::numeric_limits::min()); + AT_FORALL_SCALAR_TYPES_AND3(Bool, Half, BFloat16, MAX_BY_TYPE_CASE) +#undef MAX_BY_TYPE_CASE + default: + throw unsupported_dtype(); + } +} + +class Maximum : public Reducer { + public: + // TODO possible to remove this arg by deferring the init value until we + // know the dtype of the body. + Maximum(Dtype dtype) + : Reducer( + minimumVal(dtype.scalar_type()), + [](const ExprHandle& a, const ExprHandle& b) { + return Max::make(a, b, true); + }) {} + Maximum(ExprHandle initializer) + : Reducer( + std::move(initializer), + [](const ExprHandle& a, const ExprHandle& b) { + return Max::make(a, b, true); + }) {} +}; + +class Minimum : public Reducer { + public: + Minimum(Dtype dtype) + : Reducer( + maximumVal(dtype.scalar_type()), + [](const ExprHandle& a, const ExprHandle& b) { + return Min::make(a, b, true); + }) {} + Minimum(const ExprHandle& initializer) + : Reducer(initializer, [](const ExprHandle& a, const ExprHandle& b) { + return Min::make(a, b, true); + }) {} +}; + +class ReductionExpander : public IRMutator { + public: + StmtPtr expand(const StmtPtr& s) { + return s->accept_mutator(this); + } + + ExprPtr mutate(const ReduceOpPtr& v) override { + return v->body(); + } +}; + +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/registerizer.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/registerizer.h new file mode 100644 index 0000000000000000000000000000000000000000..29236965a87abe2217ca1727d52b2133227e7b77 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/registerizer.h @@ -0,0 +1,431 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +namespace torch::jit::tensorexpr { +namespace registerizer { + +/* The Registerizer performs scalar replacement by looking for common Stores and +Loads to a single item in a buffer and replacing them with a local temporary +scalar which is cheaper to write. + +For example it can replace: + +{ + A[0] = 0; + for(const auto x : c10::irange(10)) { + A[0] = (A[0]) + x; + } +} + +with: + +{ + int A_ = 0; + for(const auto x : c10::irange(10)) { + A_ = x + A_; + } + A[0] = A_; +} + +This is particularly useful on GPUs when parallelizing, since after replacing +loops with metavars we have a lot of accesses like this. */ + +class Scope; + +/* Holds analysis information about accesses to a specific range of a + buffer, including the number of loads and stores and the lowest common parent + Block. + */ +class AccessInfo { + public: + AccessInfo() = default; + AccessInfo( + SimplifierHashType h, + BufPtr b, + std::vector i, + size_t accessOrder) + : hash_(h), + buf_(std::move(b)), + indices_(std::move(i)), + store_cost_(alloc(0)), + load_cost_(alloc(0)), + accessOrder_(accessOrder) {} + + // Adds a Store to this access, which is in the provided scope. + void addStore(const StorePtr& store, const std::shared_ptr& scope); + + // Adds a Load to this access, which occurs in the usage Stmt in the provided + // scope. + void addLoad( + const LoadPtr& load, + const std::shared_ptr& scope, + const StmtPtr& usage); + + // Merge another AccessInfo into this one. + void merge(const std::shared_ptr& other); + + // Returns true if the other AccessInfo's bounds may overlap this one. + bool overlaps(const std::shared_ptr& other); + + // Returns true if the indices of this access depend on the provided Var. + bool dependsOnVar(const VarPtr& v); + + // Clone this AccessInfo, and set this as the new accesses' hiddenAccess. + static std::shared_ptr cloneWithHiddenInfo( + const std::shared_ptr& orig); + + // print for debugging. + void print() const; + + SimplifierHashType hash() const { + return hash_; + } + + BufPtr buf() const { + return buf_; + } + + const std::vector& indices() const { + return indices_; + } + + BlockPtr block() const { + return block_; + } + + void setEnclosingBlock(BlockPtr b) { + block_ = std::move(b); + } + + StmtPtr first_usage() const { + return first_usage_; + } + StmtPtr last_usage() const { + return last_usage_; + } + + void setUsageMarks(StmtPtr first, StmtPtr last) { + first_usage_ = std::move(first); + last_usage_ = std::move(last); + } + + bool firstUsageOverlapped() const { + return firstUsageOverlapped_; + } + + ExprPtr store_cost() const { + return store_cost_; + } + + ExprPtr load_cost() const { + return load_cost_; + } + + const std::vector& stores() const { + return stores_; + } + + const std::vector& loads() const { + return loads_; + } + + void hoistCosts(const ExprPtr& extent) { + store_cost_ = IRSimplifier::simplify(alloc(store_cost_, extent)); + load_cost_ = IRSimplifier::simplify(alloc(load_cost_, extent)); + } + + size_t conditionId() const { + return conditionId_; + } + + void setConditionId(size_t c) { + conditionId_ = c; + } + + size_t accessOrder() const { + return accessOrder_; + } + + std::shared_ptr hiddenAccess() const { + return hiddenAccess_; + } + + // Holds state relating to the scalar variable we will insert to replace some + // number of loads and stores. + struct ScalarReplacement { + VarPtr var{nullptr}; + BufPtr var_wrapper{nullptr}; + LetPtr initializer{nullptr}; + }; + + ScalarReplacement& replacement() { + return replacement_; + } + + private: + SimplifierHashType hash_; + BufPtr buf_; + std::vector indices_; + BlockPtr block_{nullptr}; + + StmtPtr first_usage_{nullptr}; + StmtPtr last_usage_{nullptr}; + + // Whether or not this access is overlapped in the first Stmt it appears. This + // means we cannot use it's first Store as the initializer. + bool firstUsageOverlapped_{false}; + + // The cost in real ops that this access represents, to enable + // filtering accesses that won't save any loads or stores. + ExprPtr store_cost_; + ExprPtr load_cost_; + + // The actual Stores and Loads which represent this access. + // Be careful with these, any mutator will invalidate these pointers. + std::vector stores_; + std::vector loads_; + + // An identifier representing the conditional block, if any, this access + // depends on. + size_t conditionId_{0}; + + // An identifier representing the order this access was first encountered, for + // sorting returned results. + size_t accessOrder_{0}; + + // Sometimes when traversing the tree we need to record what would happen if + // we hoisted an access, but sometimes it doesn't work out. This lets us + // "undo" some mutation and return to the internal hidden AccessInfo. + // It will be removed after any further additions to this AccessInfo. + std::shared_ptr hiddenAccess_; + + ScalarReplacement replacement_; +}; + +using AccessHashMap = + std::unordered_map>; + +// Represents a scope block and holds all accesses contained within it. +class Scope { + public: + Scope(BlockPtr b, std::shared_ptr parent, size_t conditionId = 0) + : block_(std::move(b)), + parent_(std::move(parent)), + conditionId_(conditionId) {} + + AccessHashMap& getAccessMapByBuf(const BufPtr& b); + + std::unordered_map& openAccesses() { + return openAccesses_; + } + + std::vector>& closedAccesses() { + return closedAccesses_; + } + + BlockPtr block() const { + return block_; + } + + std::shared_ptr parent() const { + return parent_; + } + + size_t conditionId() const { + return conditionId_; + } + + const std::unordered_set& localVars() const { + return localVars_; + } + void addLocalVar(VarPtr v) { + localVars_.insert(std::move(v)); + } + + void closeAccess(const std::shared_ptr& info); + + void filterClosed(); + + private: + // Map of map to access, narrowing by Buf then by hash(Buf+Indices). + // This allows us to find a candidate access easily, and also check for + // overlap with other accesses to the same buf. Buf -> + // Hash -> + // Access + std::unordered_map openAccesses_; + std::vector> closedAccesses_; + + // The Block object this scope represents. + BlockPtr block_; + + // The enclosing scope object. + std::shared_ptr parent_; + + // An identifier representing the condition block this scope depends on. + size_t conditionId_; + + // A set of variables local to this scope (e.g. loop vars). + std::unordered_set localVars_; +}; + +/* Analyzes the graph and collects accesses to the same symbolic tensor element + * which can be replaced by a single local scalar. + * + * This works by recursively walking the tree in postfix order, building sets of + * accesses to the same symbolic element by scope and then merging lower scopes + * into their enclosing scope. + * + * It is safe to move two accesses of the same Tensor element to a local scalar + * Var if between all usages of the element there are no other Loads or Stores + * that may refer to it. In the comments I refer to this as overlapping the + * access, or "cutting" the existing AccessInfo. In the case where a candidate + * for registerization is cut, it may be possible to finalize the access early + * by writing it back to the Tensor and then create a new scalar variable after + * the overlapping access is complete. We will attempt to do this when it saves + * memory accesses. + * + * There are a few cases that make this more challenging: + * + * - For: Loops change the number of real usages of a buffer by the loop + * extent, but only if we can pull the definition and finalization of the scalar + * variable out of the loop block. + * + * - Cond: Conditions complicate lifting scalars out of internal scopes. + * Generally we cannot lift an access outside of a conditional scope unless + * there is already a reference to that same access at the higher scope, since + * we don't know if the condition was guarding an array access not safe at the + * higher scope. In the comments I refer to this as the condition "hiding" the + * access, and the outer access "unhiding" it. + * + * - IfThenElse: Same situation as Cond, except since IfThenElse is an Expr + * rather than a Stmt we cannot insert the scalar definition or finalizer + * within the conditional scope. Accesses inside an IfThenElse can be safely + * combined with external accesses but cannot exist completely within. + * + * - Let: Accesses dependent on local variables via Let Stmts, or loop vars, + * cannot be raised outside of the scope of the dependent var. + */ +class TORCH_API RegisterizerAnalysis : public IRVisitor { + public: + RegisterizerAnalysis() + : currentScope_(std::make_shared(nullptr, nullptr, 0)) {} + ~RegisterizerAnalysis() override = default; + + void visit(const ForPtr& v) override; + + void visit(const CondPtr& v) override; + + void visit(const BlockPtr& v) override; + + void visit(const StorePtr& v) override; + + void visit(const LoadPtr& v) override; + + void visit(const IfThenElsePtr& v) override; + + void visit(const LetPtr& v) override; + +#define STMT_ON_STACK(Op) \ + void visit(const Op##Ptr& v) override { \ + stmtStack_.push_front(v); \ + IRVisitor::visit(v); \ + stmtStack_.pop_front(); \ + } + + STMT_ON_STACK(AtomicAdd) + STMT_ON_STACK(Allocate) + STMT_ON_STACK(Free) + +#undef STMT_ON_STACK + + std::vector> getCandidates(); + + private: + void mergeCurrentScopeIntoParent(); + void mergeHiddenScope(bool allowClosed); + void closeAccessIntoScope( + const std::shared_ptr& info, + const std::shared_ptr& scope); + + std::unordered_set exprConditionals_; + + // A stack of enclosing Stmts for tracking the usage Stmt of Loads. + std::deque stmtStack_; + + // The current scope being analyzed. + std::shared_ptr currentScope_; + + HashProvider hasher_; + + size_t conditionId_{0}; + size_t accessOrder_{0}; +}; + +/* Replaces each registerizable access with a Scalar variable, including + * definition, initializer and finalizer. + */ +class TORCH_API RegisterizerReplacer : public IRMutator { + public: + RegisterizerReplacer(std::vector>& vec) + : infoSet_(vec) { + buildReplacements(); + } + + ExprPtr mutate(const LoadPtr& v) override; + + StmtPtr mutate(const StorePtr& v) override; + + StmtPtr mutate(const BlockPtr& v) override; + + private: + struct ReplacerScope { + std::unordered_map>> + initializerPoints_; + std::unordered_map>> + finalizePoints_; + }; + + // Creates the various ReplacerScope objects and builds internal maps. + void buildReplacements(); + + // State relating to the accesses yet to be replaced. + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + std::vector>& infoSet_; + std::unordered_map> storeToAccess_; + std::unordered_map> loadToAccess_; + std::unordered_map parentToAccesses_; + + // Holds the set of Stores that should be pulled into an initializer, so they + // can be eliminated. + std::set eliminatedIntializers_; + + // Tracks the number of times we've seen each buffer, so we can name the + // scalar Vars appropriately. + std::unordered_map bufferAccessCounts_; + unsigned int getBufferAccessCount(const BufPtr& b) { + return ++bufferAccessCounts_[b]; + } +}; +} // namespace registerizer + +// Apply scalar replacement to all accesses in s. +// To produce safe code, this must occur after handling parallelized axes and +// atomics. +TORCH_API StmtPtr registerize(StmtPtr s); + +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/stmt.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/stmt.h new file mode 100644 index 0000000000000000000000000000000000000000..331fc954825ce4d2416ec55877203891df1cee59 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/stmt.h @@ -0,0 +1,1017 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include + +#include + +namespace torch::jit::tensorexpr { + +// The common base between all statement node. +class TORCH_API Stmt : public std::enable_shared_from_this { + public: + Stmt() = default; + virtual ~Stmt() = default; + virtual void accept(IRVisitor* visitor) = 0; + virtual StmtPtr accept_mutator(IRMutator* mutator) = 0; + + StmtPtr get_parent() const { + return parent_ ? parent_->getptr() : nullptr; + } + + /* + * Make a deep copy of the given statement. + * + * All statements and expressions used in children of the statement are + * cloned. Note that the variables are not deep-copied since they are + * immutable. + */ + static StmtPtr clone(const StmtPtr& s); + + protected: + static void set_parent(const StmtPtr& s, Stmt* new_parent) { + s->parent_ = new_parent; + } + std::shared_ptr getptr() { + return shared_from_this(); + } + + private: + Stmt* parent_ = nullptr; +}; + +template +class StmtNode : public Stmt { + public: + using StmtNodeBase = StmtNode; + void accept(IRVisitor* visitor) override { + visitor->visit(static_to(getptr())); + } + StmtPtr accept_mutator(IRMutator* mutator) override; + friend Op; + + private: + StmtNode() = default; +}; + +template +StmtPtr StmtNode::accept_mutator(IRMutator* mutator) { + return mutator->mutate(static_to(getptr())); +} + +// Concrete Stmt classes +class TORCH_API Block : public StmtNode { + public: + static BlockPtr make(const std::vector& stmts) { + std::vector valid_stmts; + for (auto& stmt : stmts) { + if (!stmt) { + continue; + } + valid_stmts.push_back(stmt); + } + if (valid_stmts.empty()) { + return nullptr; + } + return alloc(valid_stmts); + } + + size_t nstmts() const { + return stmts_.size(); + } + bool empty() const { + return stmts_.empty(); + } + + void prepend_stmt(const StmtPtr& s) { + if (s->get_parent()) { + throw malformed_input("Block prepend Stmt with existing parent", s); + } + + stmts_.push_front(s); + set_parent(s, this); + } + void append_stmt(const StmtPtr& s) { + if (s->get_parent()) { + throw malformed_input("Block append Stmt with existing parent", s); + } + + stmts_.push_back(s); + set_parent(s, this); + } + + void insert_stmt_before(const StmtPtr& s, const StmtPtr& before) { + if (s->get_parent()) { + throw malformed_input("Block append Stmt with existing parent", s); + } + + auto pos = std::find(stmts_.begin(), stmts_.end(), before); + if (pos == stmts_.end()) { + throw malformed_input( + "Inserting after statement that is not in block", s); + } + + stmts_.insert(pos, s); + set_parent(s, this); + } + + void insert_stmt_after(const StmtPtr& s, const StmtPtr& after) { + if (s->get_parent()) { + throw malformed_input("Block append Stmt with existing parent", s); + } + + auto pos = std::find(stmts_.begin(), stmts_.end(), after); + if (pos == stmts_.end()) { + throw malformed_input( + "Inserting after statement that is not in block", s); + } + + ++pos; + + stmts_.insert(pos, s); + set_parent(s, this); + } + + bool replace_stmt(const StmtPtr& old_stmt, const StmtPtr& new_stmt) { + if (new_stmt->get_parent()) { + throw malformed_input( + "Block replace Stmt with existing parent", new_stmt); + } + + auto pos = std::find(stmts_.begin(), stmts_.end(), old_stmt); + if (pos == stmts_.end()) { + return false; + } + stmts_.insert(pos, new_stmt); + stmts_.erase(pos); + set_parent(old_stmt, nullptr); + set_parent(new_stmt, this); + return true; + } + + // Creates a new block by cloning `this` block and replacing the given + // statement with a new statement. Note that `old_stmt` refers to a statement + // in `this` block. If the `old_stmt` is not found, it will return `nullptr`. + BlockPtr clone_and_replace(const StmtPtr& old_stmt, const StmtPtr& new_stmt) { + if (new_stmt->get_parent()) { + throw malformed_input( + "Block replace Stmt with existing parent", new_stmt); + } + + std::vector stmts(stmts_.begin(), stmts_.end()); + std::vector cloned_stmts(stmts.size()); + bool found = false; + for (int i = 0; i < static_cast(stmts.size()); ++i) { + if (stmts[i] == old_stmt) { + found = true; + cloned_stmts[i] = new_stmt; + } else { + cloned_stmts[i] = Stmt::clone(stmts[i]); + } + } + if (!found) { + return nullptr; + } + return alloc(cloned_stmts); + } + + bool remove_stmt(const StmtPtr& stmt) { + auto pos = std::find(stmts_.begin(), stmts_.end(), stmt); + if (pos == stmts_.end()) { + return false; + } + + set_parent(stmt, nullptr); + stmts_.erase(pos); + return true; + } + + std::list stmts() const { + return stmts_; + } + + void clear() { + for (const auto& s : stmts_) { + set_parent(s, nullptr); + } + stmts_.clear(); + } + + void set_stmts(const std::vector& stmts) { + clear(); + init(stmts); + } + + explicit Block(const std::vector& stmts) { + init(stmts); + } + + typedef std::list::iterator iterator; + typedef std::list::const_iterator const_iterator; + + iterator begin() { + return stmts_.begin(); + } + + const_iterator begin() const { + return stmts_.begin(); + } + + iterator end() { + return stmts_.end(); + } + + const_iterator end() const { + return stmts_.end(); + } + + StmtPtr front() { + return stmts_.front(); + } + + StmtPtr front() const { + return stmts_.front(); + } + + StmtPtr back() { + return stmts_.back(); + } + + StmtPtr back() const { + return stmts_.back(); + } + + void splice(Block::iterator it, const BlockPtr& other) { + for (const StmtPtr& s : *other) { + set_parent(s, this); + } + + stmts_.splice(it, other->stmts_); + } + + static BlockPtr getSharedParent(StmtPtr p1, StmtPtr p2) { + std::unordered_set enclosing; + + StmtPtr p1_p = std::move(p1); + while (p1_p) { + if (BlockPtr b = to(p1_p)) { + enclosing.insert(b); + } + p1_p = p1_p->get_parent(); + } + + StmtPtr p2_p = std::move(p2); + while (p2_p) { + if (BlockPtr b = to(p2_p)) { + if (enclosing.count(b) != 0) { + return b; + } + } + p2_p = p2_p->get_parent(); + } + + return nullptr; + } + + // returns the immediate child containing statement s. + StmtPtr getEnclosedRoot(StmtPtr s) const { + while (s && s->get_parent().get() != this) { + s = s->get_parent(); + } + return s; + } + + private: + std::list stmts_; + + void init(const std::vector& stmts) { + for (const StmtPtr& s : stmts) { + if (!s) { + continue; + } + if (!s->get_parent()) { + // If we get here, it's a bug, but we cannot throw an error from a + // constructor. But IR verifier would catch this. + set_parent(s, this); + } + + stmts_.push_back(s); + } + } +}; + +class TORCH_API Store : public StmtNode { + public: + VarPtr base_handle() const { + return buf_->base_handle(); + } + std::vector indices() const { + return indices_; + } + ExprPtr flat_index() const { + TORCH_CHECK(indices_.size() == 1, "Indices haven't been flattened."); + return indices_[0]; + } + ExprPtr value() const { + return value_; + } + BufPtr buf() const { + return buf_; + } + + void set_buf(BufPtr buf) { + buf_ = std::move(buf); + } + + void set_indices(std::vector indices) { + indices_ = std::move(indices); + } + + void set_value(ExprPtr value) { + value_ = std::move(value); + } + + static StorePtr make( + const BufHandle& buf, + const std::vector& indices, + const ExprHandle& value); + + Store(BufPtr buf, std::vector indices, ExprPtr value); + + private: + BufPtr buf_; + std::vector indices_; + ExprPtr value_; +}; + +// Allocate a buffer of given shapes and dtypes and bind it with the given +// buffer var. The life span is at most through the current program, until it is +// explicitly freed. An unfreed memory is likely considered an error. +class TORCH_API Allocate : public StmtNode { + public: + static AllocatePtr make(const BufHandle& buf_handle) { + return alloc(buf_handle.node()); + } + + VarPtr buffer_var() const { + return buf_->base_handle(); + } + + Dtype dtype() const { + return buf_->dtype(); + } + + const std::vector dims() const { + return buf_->dims(); + } + + BufPtr buf() const { + return buf_; + } + + void set_buf(BufPtr buf) { + buf_ = std::move(buf); + } + + explicit Allocate(BufPtr buf) : buf_(std::move(buf)) {} + + private: + BufPtr buf_; + // TODO: add memory types. +}; + +// PlacementAllocate is a variation of the Allocate operator in NNC IR. It does +// not allocate memory but reuse the memory of another buffer for the given +// buffer. +class TORCH_API PlacementAllocate : public StmtNode { + public: + static PlacementAllocatePtr make( + const BufHandle& buf_handle, + const BufHandle& buf_handle_to_reuse) { + return alloc( + buf_handle.node(), buf_handle_to_reuse.node()); + } + + BufPtr buf() const { + return buf_; + } + + BufPtr buf_to_reuse() const { + return buf_to_reuse_; + } + + void set_buf(BufPtr buf) { + buf_ = std::move(buf); + } + + void set_buf_to_reuse(BufPtr buf) { + buf_to_reuse_ = std::move(buf); + } + + explicit PlacementAllocate(BufPtr buf, BufPtr buf_to_reuse) + : buf_(std::move(buf)), buf_to_reuse_(std::move(buf_to_reuse)) {} + + private: + BufPtr buf_; + BufPtr buf_to_reuse_; +}; + +// Free the specific buffer. It is an error. +class TORCH_API Free : public StmtNode { + public: + static FreePtr make(const BufHandle& buf_handle) { + return alloc(buf_handle.node()); + } + + VarPtr buffer_var() const { + return buf_->base_handle(); + } + + BufPtr buf() const { + return buf_; + } + + void set_buf(BufPtr buf) { + buf_ = std::move(buf); + } + + explicit Free(BufPtr buf) : buf_(std::move(buf)) {} + + private: + BufPtr buf_; +}; + +class TORCH_API FreeExt : public StmtNode { + public: + static FreeExtPtr make(const std::vector& bufs); + + std::vector bufs() const { + return bufs_; + } + + void set_bufs(std::vector bufs) { + bufs_ = std::move(bufs); + } + + explicit FreeExt(std::vector bufs) : bufs_(std::move(bufs)) {} + + private: + std::vector bufs_; +}; + +class TORCH_API Let : public StmtNode { + public: + static LetPtr make(const VarHandle& var, const ExprHandle& val) { + return alloc(var.node(), val.node()); + } + + Let(VarPtr var, ExprPtr val) : var_(std::move(var)), val_(std::move(val)) {} + + VarPtr var() const { + return var_; + } + + ExprPtr value() const { + return val_; + } + + void set_var(VarPtr var) { + var_ = std::move(var); + } + + void set_val(ExprPtr val) { + val_ = std::move(val); + } + + private: + VarPtr var_; + ExprPtr val_; +}; + +class TORCH_API Cond : public StmtNode { + public: + static CondPtr make( + const ExprHandle& condition, + const StmtPtr& true_stmt, + const StmtPtr& false_stmt) { + return alloc(condition.node(), true_stmt, false_stmt); + } + + ExprPtr condition() const { + return condition_; + } + + BlockPtr true_stmt() const { + return true_stmt_; + } + + BlockPtr false_stmt() const { + return false_stmt_; + } + + void set_condition(ExprPtr condition) { + condition_ = std::move(condition); + } + + void set_true_stmt(StmtPtr true_stmt) { + if (true_stmt) { + BlockPtr b = to(true_stmt); + if (!b) { + b = alloc(std::vector({std::move(true_stmt)})); + } + true_stmt_ = b; + set_parent(true_stmt_, this); + } + } + + void set_false_stmt(StmtPtr false_stmt) { + if (false_stmt) { + BlockPtr b = to(false_stmt); + if (!b) { + b = alloc(std::vector({std::move(false_stmt)})); + } + false_stmt_ = b; + set_parent(false_stmt_, this); + } + } + + Cond(ExprPtr condition, StmtPtr true_stmt, StmtPtr false_stmt) + : condition_(std::move(condition)) { + set_true_stmt(std::move(true_stmt)); + set_false_stmt(std::move(false_stmt)); + } + + CondPtr cloneWithNewBodies( + const StmtPtr& true_stmt, + const StmtPtr& false_stmt) { + return alloc(condition_, true_stmt, false_stmt); + } + + CondPtr cloneWithNewBody(const StmtPtr& true_stmt) { + return alloc(condition_, true_stmt, nullptr); + } + + private: + ExprPtr condition_; + BlockPtr true_stmt_ = nullptr; + BlockPtr false_stmt_ = nullptr; +}; + +class TORCH_API LoopOptions { + public: + enum { + IDX_UNSET = -1, + IDX_X = 0, + IDX_Y = 1, + IDX_Z = 2, + IDX_W = 3, + IDX_MAX = IDX_W, + }; + // GPU Block Index + bool is_gpu_block_index() const { + return gpu_block_index_ != IDX_UNSET; + } + + int gpu_block_index() const { + return gpu_block_index_; + } + + std::string gpu_block_index_str() const { + if (!is_gpu_block_index()) { + throw malformed_input("Has no GPU block index"); + } + + // NOLINTNEXTLINE(modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays) + static constexpr const char* kBlockIndexNames[] = { + "blockIdx.x", + "blockIdx.y", + "blockIdx.z", + "blockIdx.w", + }; + + if (gpu_block_index_ < IDX_X || gpu_block_index_ > IDX_MAX) { + throw malformed_input("invalid GPU block index"); + } + + return kBlockIndexNames[gpu_block_index_]; + } + + void set_gpu_block_index(int index) { + if (index == IDX_UNSET) { + gpu_block_index_ = IDX_UNSET; + } + + if (is_gpu_thread_index()) { + throw std::runtime_error("Cannot set both gpu block and thread index"); + } + if (is_gpu_block_index() && gpu_block_index() != index) { + throw std::runtime_error("Cannot set a previously set block index"); + } + gpu_block_index_ = index; + } + + // GPU Thread Index + bool is_gpu_thread_index() const { + return gpu_thread_index() != IDX_UNSET; + } + + int gpu_thread_index() const { + return gpu_thread_index_; + } + + std::string gpu_thread_index_str() const { + if (!is_gpu_thread_index()) { + throw malformed_input("has no GPU thread index"); + } + + // NOLINTNEXTLINE(modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays) + static constexpr const char* kThreadIndexNames[] = { + "threadIdx.x", "threadIdx.y", "threadIdx.z", "threadIdx.w"}; + + if (gpu_thread_index_ < IDX_X || gpu_thread_index_ > IDX_MAX) { + throw malformed_input("invalid GPU thread index"); + } + + return kThreadIndexNames[gpu_thread_index_]; + } + + void set_gpu_thread_index(int index) { + if (index == IDX_UNSET) { + gpu_thread_index_ = IDX_UNSET; + } + + if (is_gpu_block_index()) { + throw std::runtime_error("Cannot set both gpu thread and block index"); + } + if (is_gpu_thread_index() && gpu_thread_index() != index) { + throw std::runtime_error("Cannot set a previously set thread index"); + } + gpu_thread_index_ = index; + } + + void set_parallel() { + is_parallel_ = true; + } + + bool is_parallel() const { + return is_parallel_; + } + + std::string ToString() const { + if (is_gpu_block_index()) { + return gpu_block_index_str(); + } else if (is_gpu_thread_index()) { + return gpu_thread_index_str(); + } else if (is_parallel()) { + return "parallel"; + } + return ""; + } + + bool isDefault() const { + return gpu_block_index_ == IDX_UNSET && gpu_thread_index_ == IDX_UNSET && + !is_parallel_; + } + + void set_buffer_mapping(const std::unordered_map& map) { + map_input_to_tensor_bufs_ = map; + } + + std::unordered_map get_buffer_mapping() const { + return map_input_to_tensor_bufs_; + } + + private: + int gpu_block_index_{IDX_UNSET}; + int gpu_thread_index_{IDX_UNSET}; + bool is_parallel_{false}; + std::unordered_map map_input_to_tensor_bufs_; +}; + +class TORCH_API For : public StmtNode { + public: + VarPtr var() const { + return var_; + } + ExprPtr start() const { + return start_; + } + ExprPtr stop() const { + return stop_; + } + BlockPtr body() const { + return body_; + } + static ForPtr make( + const VarHandle& var, + const ExprHandle& start, + const ExprHandle& stop, + const StmtPtr& body) { + if (!body) { + return nullptr; + } + return alloc(var.node(), start.node(), stop.node(), body); + } + static ForPtr make( + const VarHandle& var, + const ExprHandle& start, + const ExprHandle& stop, + const StmtPtr& body, + const LoopOptions& loop_options) { + if (!body) { + return nullptr; + } + return alloc( + var.node(), start.node(), stop.node(), body, loop_options); + } + const LoopOptions loop_options() const { + return loop_options_; + } + + For(VarPtr var, ExprPtr start, ExprPtr stop, StmtPtr body) + : var_(std::move(var)), start_(std::move(start)), stop_(std::move(stop)) { + BlockPtr b = to(body); + if (!b) { + b = alloc(std::vector({std::move(body)})); + } + body_ = b; + set_parent(body_, this); + } + + For(VarPtr var, + ExprPtr start, + ExprPtr stop, + StmtPtr body, + LoopOptions loop_options) + : var_(std::move(var)), + start_(std::move(start)), + stop_(std::move(stop)), + loop_options_(std::move(loop_options)) { + if (!var_) { + throw malformed_input("invalid Var in For loop"); + } else if (!start_) { + throw malformed_input("invalid Start in For loop"); + } else if (!stop_) { + throw malformed_input("invalid Stop in For loop"); + } else if (!body || body->get_parent()) { + throw malformed_input("invalid Body in For loop"); + } + + BlockPtr b = to(body); + if (!b) { + b = alloc(std::vector({std::move(body)})); + } + body_ = b; + set_parent(body_, this); + } + + void set_gpu_block_index(int block_index) { + loop_options_.set_gpu_block_index(block_index); + } + + void set_gpu_thread_index(int thread_index) { + loop_options_.set_gpu_thread_index(thread_index); + } + + void set_parallel() { + loop_options_.set_parallel(); + } + + bool is_parallel() const { + return loop_options_.is_parallel(); + } + + void set_buffer_map(const std::unordered_map& map) { + loop_options_.set_buffer_mapping(map); + } + + ForPtr cloneWithNewBody(const StmtPtr& body) const { + return alloc(var_, start_, stop_, body, loop_options_); + } + + BlockPtr removeBody() { + auto res = body_; + set_parent(res, nullptr); + body_ = nullptr; + return res; + } + + void set_body(StmtPtr body) { + BlockPtr b = to(body); + if (!b) { + b = alloc(std::vector({std::move(body)})); + } + body_ = b; + set_parent(body_, this); + } + + void set_start(ExprPtr start) { + start_ = std::move(start); + } + + void set_stop(ExprPtr stop) { + stop_ = std::move(stop); + } + + void set_var(VarPtr var) { + var_ = std::move(var); + } + + private: + VarPtr var_; + ExprPtr start_; + ExprPtr stop_; + BlockPtr body_; + LoopOptions loop_options_; +}; + +// A backend specific IR Node that implements atomic-add. +// This node could only shows up as an internal with GPU backends. +// TODO: move to this an internal IR. +// TODO: make IR nodes extensible. +class TORCH_API AtomicAdd : public StmtNode { + public: + AtomicAdd(BufPtr buf, std::vector indices, ExprPtr value) + : buf_(std::move(buf)), + indices_(std::move(indices)), + value_(std::move(value)) {} + + VarPtr base_handle() const { + return buf_->base_handle(); + } + + BufPtr buf() const { + return buf_; + } + + ExprPtr flat_index() const { + TORCH_CHECK(indices_.size() == 1, "Indices haven't been flattened."); + return indices_[0]; + } + + ExprPtr value() const { + return value_; + } + + const std::vector& indices() const { + return indices_; + } + + void set_buf(BufPtr buf) { + buf_ = std::move(buf); + } + + void set_indices(std::vector indices) { + indices_ = std::move(indices); + } + + void set_value(ExprPtr value) { + value_ = std::move(value); + } + + private: + BufPtr buf_; + std::vector indices_; + ExprPtr value_; +}; + +class TORCH_API SyncThreads : public StmtNode { + public: + SyncThreads() = default; +}; + +/* + * ExternalCall statement represents a call to an external function that would + * compute the contents of the output buffer. An ExternalCall statement consists + * of: + * 1) output buffer - the buffer that'll be initialized by the call + * 2) external function name - a key from the NNC function registry to lookup + * the actual function to call + * 3) buffer arguments - the input buffers used by the function + * 4) non-buffer arguments - scalar arguments to pass to the function + * + * An example: + * A = nnc_conv2d(buf_args={Input, Weight, Bias}, args={1}) + * Here 'A' is the output buffer, "nnc_conv2d" is the function name, the buffer + * arguments are 'Input', 'Weight', and 'Bias', and there is a single non-buffer + * argument - 1. + * + * The semantics of the scalar arguments is defined solely by the implementation + * of the external function. + */ +class TORCH_API ExternalCall : public StmtNode { + public: + static ExternalCallPtr make( + BufHandle buf, + const std::string& func_name, + const std::vector& buf_args, + const std::vector& args); + + BufPtr buf() const { + return buf_; + } + + std::string func_name() const { + return func_name_; + } + + std::vector buf_args() const { + return buf_args_; + } + + std::vector args() const { + return args_; + } + + void set_buf(BufPtr buf) { + buf_ = std::move(buf); + } + + void set_buf_args(std::vector buf_args) { + buf_args_ = std::move(buf_args); + } + + void set_args(std::vector args) { + args_ = std::move(args); + } + + ExternalCall( + BufPtr buf, + std::string func_name, + std::vector buf_args, + std::vector args) + : buf_(std::move(buf)), + func_name_(std::move(func_name)), + buf_args_(std::move(buf_args)), + args_(std::move(args)) {} + + private: + BufPtr buf_; + std::string func_name_; + std::vector buf_args_; + std::vector args_; +}; + +class TORCH_API ExternalCallWithAlloc : public StmtNode { + public: + static ExternalCallWithAllocPtr make( + const std::string& func_name, + const std::vector& buf_out_args, + const std::vector& buf_args, + const std::vector& args); + + std::vector buf_out_args() const { + return buf_out_args_; + } + + std::string func_name() const { + return func_name_; + } + + std::vector buf_args() const { + return buf_args_; + } + + std::vector args() const { + return args_; + } + + void set_buf_out_args(std::vector buf_out_args) { + buf_out_args_ = std::move(buf_out_args); + } + + void set_buf_args(std::vector buf_args) { + buf_args_ = std::move(buf_args); + } + + void set_args(std::vector args) { + args_ = std::move(args); + } + + ExternalCallWithAlloc( + std::string func_name, + std::vector buf_out_args, + std::vector buf_args, + std::vector args) + : func_name_(std::move(func_name)), + buf_out_args_(std::move(buf_out_args)), + buf_args_(std::move(buf_args)), + args_(std::move(args)) {} + + private: + std::string func_name_; + std::vector buf_out_args_; + std::vector buf_args_; + std::vector args_; +}; + +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/tensor.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/tensor.h new file mode 100644 index 0000000000000000000000000000000000000000..54ff410d9de8bad9027a6e8fac7698f50722cc35 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/tensor.h @@ -0,0 +1,326 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace torch::jit::tensorexpr { + +class TORCH_API Tensor { + public: + Tensor(BufPtr buf, const std::vector& args, const ExprPtr& body) + : buf_(std::move(buf)) { + stmt_ = constructStmt(args, body, {}, {}); + } + Tensor(BufHandle buf, const std::vector& args, ExprHandle body) + : Tensor(buf.node(), VarHandleVectorToVarVector(args), body.node()) {} + + Tensor( + BufPtr buf, + const std::vector& args, + const std::vector& reduce_dims, + const std::vector& reduce_args, + const ExprPtr& body) + : buf_(std::move(buf)) { + stmt_ = constructStmt(args, body, reduce_dims, reduce_args); + } + Tensor( + BufHandle buf, + const std::vector& args, + const std::vector& reduce_dims, + const std::vector& reduce_args, + ExprHandle body) + : Tensor( + buf.node(), + VarHandleVectorToVarVector(args), + ExprHandleVectorToExprVector(reduce_dims), + VarHandleVectorToVarVector(reduce_args), + body.node()) {} + + Tensor(BufPtr buf, StmtPtr stmt) + : buf_(std::move(buf)), stmt_(std::move(stmt)) {} + + BufPtr buf() const { + return buf_; + } + + StmtPtr stmt() const { + return stmt_; + } + + template + inline ExprHandle load(const std::vector& args) const; + template + inline ExprHandle load(const Ts&... ts) const; + + private: + StmtPtr constructStmt( + const std::vector& args, + const ExprPtr& body, + const std::vector& reduce_dims, + const std::vector& reduce_args) const; + + BufPtr buf_; + StmtPtr stmt_; +}; + +TORCH_API Tensor Compute( + const std::string& func_name, + const std::vector& dims, + const std::optional>& strides, + const std::function& body_func); +TORCH_API Tensor Compute( + const std::string& func_name, + const std::vector& dims, + const std::function& body_func); +TORCH_API Tensor Compute( + const std::string& func_name, + const std::vector& dims, + const std::optional>& strides, + const std::function& + body_func); +TORCH_API Tensor Compute( + const std::string& func_name, + const std::vector& dims, + const std::function& + body_func); +TORCH_API Tensor Compute( + const std::string& func_name, + const std::vector& dims, + const std::optional>& strides, + const std::function< + ExprHandle(const VarHandle&, const VarHandle&, const VarHandle&)>& + body_func); +TORCH_API Tensor Compute( + const std::string& func_name, + const std::vector& dims, + const std::function< + ExprHandle(const VarHandle&, const VarHandle&, const VarHandle&)>& + body_func); +TORCH_API Tensor Compute( + const std::string& func_name, + const std::vector& dims, + const std::optional>& strides, + const std::function& body_func); +TORCH_API Tensor Compute( + const std::string& func_name, + const std::vector& dims, + const std::function& body_func); +TORCH_API Tensor Compute( + const std::string& func_name, + const std::vector& dims, + const std::optional>& strides, + const std::function&)>& body_func); +TORCH_API Tensor Compute( + const std::string& func_name, + const std::vector& dims, + const std::function&)>& body_func); + +inline std::vector create_index_vars( + const std::vector& dims) { + std::vector vars; + vars.reserve(dims.size()); + for (const ExprHandle& dim : dims) { + vars.emplace_back(alloc( + "i", dim.dtype().scalar_type() == ScalarType::Long ? kLong : kInt)); + } + return vars; +} + +// Handle reductions over a Reducer and a body_func which produces values. +template +Tensor Reduce( + const std::string& func_name, + const std::vector& dims, + const std::optional>& strides, + const Reducer& reducer, + const InitFunc& init_func, + const BodyFunc& body_func, + const std::vector& reduce_dims) { + std::vector vars = create_index_vars(dims); + std::vector reduce_vars = create_index_vars(reduce_dims); + + // If reduce_vars is empty, then it's not a reduction, but rather a simple + // copy + if (reduce_vars.empty()) { + ExprHandle body = Reducer::getReduceBody(body_func, vars); + BufHandle func_result = + Buf::make(func_name, dims, body.dtype(), std::nullopt, strides); + return Tensor(std::move(func_result), vars, std::move(body)); + } + + std::vector all_vars; + all_vars.insert(all_vars.end(), vars.begin(), vars.end()); + all_vars.insert(all_vars.end(), reduce_vars.begin(), reduce_vars.end()); + + ExprHandle body = Reducer::getReduceBody(body_func, all_vars); + std::vector output_args(vars.begin(), vars.end()); + ExprHandle init_expr = Cast::make(body.dtype(), init_func(vars)); + BufHandle func_result = Buf::make(func_name, dims, body.dtype(), init_expr); + + ExprHandle reduce_op = reducer(func_result, body, output_args, reduce_vars); + if (body.dtype() == kBFloat16) { + ExprHandle init_expr_acc = Cast::make(kFloat, init_func(vars)); + BufHandle func_result_acc = + Buf::make(func_name + "_acc", dims, kFloat, init_expr_acc); + reduce_op = reducer( + func_result, + std::move(func_result_acc), + body, + output_args, + reduce_vars); + } + + Tensor t = Tensor( + std::move(func_result), + vars, + reduce_dims, + reduce_vars, + std::move(reduce_op)); + return t; +} +template +Tensor Reduce( + const std::string& func_name, + const std::vector& dims, + const Reducer& reducer, + const InitFunc& init_func, + const BodyFunc& body_func, + const std::vector& reduce_dims) { + return Reduce( + func_name, + dims, + std::nullopt, + reducer, + init_func, + body_func, + reduce_dims); +} + +template +Tensor Reduce( + const std::string& func_name, + const std::vector& dims, + const std::optional>& strides, + const Reducer& reducer, + const BodyFunc& body_func, + const std::vector& reduce_dims) { + return Reduce( + func_name, + dims, + strides, + reducer, + [&](ParameterList& p [[maybe_unused]]) { + return ExprHandle(reducer.initializer()); + }, + body_func, + reduce_dims); +} +template +Tensor Reduce( + const std::string& func_name, + const std::vector& dims, + const Reducer& reducer, + const BodyFunc& body_func, + const std::vector& reduce_dims) { + return Reduce( + func_name, dims, std::nullopt, reducer, body_func, reduce_dims); +} + +// Overload which allows inline lambda functions for the body_func. +template +Tensor Reduce( + const std::string& func_name, + const std::vector& dims, + const std::optional>& strides, + const Reducer& reducer, + const BodyFunc&& body_func, + const std::vector& reduce_dims) { + return Reduce(func_name, dims, strides, reducer, body_func, reduce_dims); +} +template +Tensor Reduce( + const std::string& func_name, + const std::vector& dims, + const Reducer& reducer, + const BodyFunc&& body_func, + const std::vector& reduce_dims) { + return Reduce(func_name, dims, std::nullopt, reducer, body_func, reduce_dims); +} + +TORCH_API Tensor Reduce( + const std::string& name, + const std::vector& dims, + const std::optional>& strides, + const Reducer& reducer, + const BufHandle& buffer, + const std::vector& reduce_dims); +TORCH_API Tensor Reduce( + const std::string& name, + const std::vector& dims, + const Reducer& reducer, + const BufHandle& buffer, + const std::vector& reduce_dims); + +// Overload for the common case of all dimensions of a previously Computed +// Tensor. +TORCH_API Tensor Reduce( + const std::string& func_name, + const std::vector& dims, + const std::optional>& strides, + const Reducer& reducer, + const Tensor& tensor, + const std::vector& reduce_dims); +TORCH_API Tensor Reduce( + const std::string& func_name, + const std::vector& dims, + const Reducer& reducer, + const Tensor& tensor, + const std::vector& reduce_dims); + +template +inline ExprHandle Tensor::load(const Ts&... ts) const { + std::vector params({ExprHandle(ts)...}); + return Load::make(BufHandle(this->buf()), params); +} + +template +inline ExprHandle Tensor::load(const std::vector& args) const { + std::vector params(args.begin(), args.end()); + return Load::make(BufHandle(this->buf()), params); +} + +template +inline ExprHandle BufHandle::load(const Ts&... ts) const { + std::vector params({ExprHandle(ts)...}); + return ExprHandle(alloc(node(), ExprHandleVectorToExprVector(params))); +} + +template +inline ExprHandle BufHandle::load(const std::vector& args) const { + std::vector params(args.begin(), args.end()); + return ExprHandle(alloc(node(), ExprHandleVectorToExprVector(params))); +} + +inline ExprHandle BufHandle::load(const std::vector& args) const { + return this->template load(args); +} + +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/tensorexpr_init.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/tensorexpr_init.h new file mode 100644 index 0000000000000000000000000000000000000000..247b679de43aa244ab779527304da5adb74e9e7b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/tensorexpr_init.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::jit { +// Initialize Python bindings for Tensor Expressions +void initTensorExprBindings(PyObject* module); +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/types.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/types.h new file mode 100644 index 0000000000000000000000000000000000000000..5615ba08951841b9e8086df7156d70d565ca155c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/types.h @@ -0,0 +1,163 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include +#include +#include + +#include + +namespace torch::jit::tensorexpr { + +using int32 = std::int32_t; + +class Dtype; +TORCH_API std::ostream& operator<<(std::ostream& stream, const Dtype& dtype); + +using ScalarType = c10::ScalarType; + +enum ElementType { + kAllTypes = 0, + kIntegralTypes = 1 << 0, + kFloatingPointTypes = 1 << 1, + kBoolType = 1 << 2, + kComplexTypes = 1 << 3, + kQintTypes = 1 << 4, + kNonComplexOrQintTypes = kIntegralTypes | kBoolType | kFloatingPointTypes, +}; + +// Data types for scalar and vector elements. +class TORCH_API Dtype { + public: + explicit Dtype(int8_t type) + : scalar_type_(static_cast(type)), lanes_(1) {} + explicit Dtype(ScalarType type) : scalar_type_(type), lanes_(1) {} + Dtype(int8_t type, int64_t lanes) + : scalar_type_(static_cast(type)), lanes_(lanes) {} + Dtype(ScalarType type, int64_t lanes) : scalar_type_(type), lanes_(lanes) {} + Dtype(Dtype type, int64_t lanes) + : scalar_type_(type.scalar_type_), lanes_(lanes) { + if (type.lanes() != 1) { + throw malformed_input("dtype lanes dont match"); + } + } + int64_t lanes() const { + return lanes_; + } + ScalarType scalar_type() const { + return scalar_type_; + } + Dtype scalar_dtype() const; + bool operator==(const Dtype& other) const { + return scalar_type_ == other.scalar_type_ && lanes_ == other.lanes_; + } + bool operator!=(const Dtype& other) const { + return !(*this == other); + } + int byte_size() const; + std::string ToCppString() const; + + bool is_integral() const { + return c10::isIntegralType(scalar_type_, true); + } + bool is_floating_point() const { + return c10::isFloatingType(scalar_type_); + } + bool is_signed() const { + return c10::isSignedType(scalar_type_); + } + + Dtype cloneWithScalarType(ScalarType nt) const { + return Dtype(nt, lanes_); + } + + private: + friend TORCH_API std::ostream& operator<<( + std::ostream& stream, + const Dtype& dtype); + ScalarType scalar_type_; + int64_t lanes_; // the width of the element for a vector time +}; + +extern TORCH_API Dtype kHandle; + +#define NNC_DTYPE_DECLARATION(ctype, name) extern TORCH_API Dtype k##name; + +AT_FORALL_SCALAR_TYPES_AND3(Bool, Half, BFloat16, NNC_DTYPE_DECLARATION) +NNC_DTYPE_DECLARATION(c10::quint8, QUInt8) +NNC_DTYPE_DECLARATION(c10::qint8, QInt8) +#undef NNC_DTYPE_DECLARATION + +template +TORCH_API Dtype ToDtype(); + +#define NNC_TODTYPE_DECLARATION(ctype, name) \ + template <> \ + inline Dtype ToDtype() { \ + return k##name; \ + } +AT_FORALL_SCALAR_TYPES_AND3(Bool, Half, BFloat16, NNC_TODTYPE_DECLARATION) +NNC_TODTYPE_DECLARATION(c10::quint8, QUInt8) +NNC_TODTYPE_DECLARATION(c10::qint8, QInt8) +#undef NNC_TODTYPE_DECLARATION + +TORCH_API Dtype ToDtype(ScalarType type); + +inline Dtype promoteTypes(Dtype a, Dtype b) { + if (a.lanes() != b.lanes()) { + throw malformed_input("promoting types with different lanes"); + } + return Dtype( + static_cast(c10::promoteTypes( + static_cast(a.scalar_type()), + static_cast(b.scalar_type()))), + a.lanes()); +} + +inline Dtype BinaryOpDtype( + Dtype op1_dtype, + Dtype op2_dtype, + ScalarType ret_type = ScalarType::Undefined) { + if (op1_dtype == op2_dtype) { + if (ret_type == ScalarType::Undefined) { + return op1_dtype; + } + + return ToDtype(ret_type); + } + + if (op1_dtype.lanes() != op2_dtype.lanes()) { + throw malformed_input("lanes dont match"); + } + int64_t lanes = op1_dtype.lanes(); + + Dtype resultType = promoteTypes(op1_dtype, op2_dtype); + if (resultType.scalar_type() == ScalarType::Undefined) { + throw malformed_input("scalar type doesn't match"); + } + + if (lanes == 1) { + // Use the fixed scalar Dtypes. + return ToDtype(resultType.scalar_type()); + } + + return resultType; +} + +} // namespace torch::jit::tensorexpr + +namespace std { + +using torch::jit::tensorexpr::Dtype; +std::string to_string(const Dtype& dtype); +using torch::jit::tensorexpr::ScalarType; +std::string to_string(const ScalarType& dtype); + +} // namespace std + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/unique_name_manager.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/unique_name_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..7ef8ec508cbffcf573d68d34f65636b4f04e11b4 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/unique_name_manager.h @@ -0,0 +1,38 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include +#include + +namespace torch::jit::tensorexpr { + +class VarHandle; +class Var; + +using VarNameMap = std::unordered_map; + +// A manager to get unique names from vars. +// It starts with the name hints of the var and append "_" + $counter until it +// hits a unique name. +class TORCH_API UniqueNameManager { + public: + const std::string& get_unique_name(const VarHandle& v); + + const std::string& get_unique_name(const VarPtr& v); + + private: + friend class ScopedVarName; + VarNameMap unique_name_mapping_; + std::unordered_map unique_name_count_; + std::unordered_set all_unique_names_; +}; + +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/var_substitutor.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/var_substitutor.h new file mode 100644 index 0000000000000000000000000000000000000000..b74c53c9c9cb33318ccc10822058a0b0bea1448f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/tensorexpr/var_substitutor.h @@ -0,0 +1,66 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace torch::jit::tensorexpr { + +using VarMapping = std::vector>; + +class VarSubMutator : public IRMutator { + public: + VarSubMutator(const VarMapping& var_mapping) { + for (auto& entry : var_mapping) { + VarPtr key_var = entry.first; + ExprPtr value = entry.second; + if (!key_var) { + throw malformed_input("missing key in VarSubMutator"); + } + var_mapping_[std::move(key_var)] = std::move(value); + } + } + + ExprPtr mutate(const VarPtr& var) override { + auto iter = var_mapping_.find(var); + if (iter == var_mapping_.end()) { + return var; + } + return iter->second; + } + + ExprPtr mutate(const ReduceOpPtr& var) override { + auto body = var->body()->accept_mutator(this); + std::vector new_inner; + + for (const auto& v : var->reduce_args()) { + ExprPtr e = v->accept_mutator(this); + if (VarPtr new_var = to(e)) { + new_inner.push_back(std::move(new_var)); + } else { + VarFinder varFinder; + e->accept(&varFinder); + auto varlist = varFinder.vars(); + new_inner.insert(new_inner.end(), varlist.begin(), varlist.end()); + } + } + + return alloc(body, new_inner, var->reducer()); + } + + private: + std::unordered_map var_mapping_; +}; + +} // namespace torch::jit::tensorexpr + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/testing/catch_utils.hpp b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/testing/catch_utils.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a361da0933df1d61e9f4fea6a50120f8a26daffb --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/testing/catch_utils.hpp @@ -0,0 +1,15 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#define CATCH_CONFIG_PREFIX_ALL +#include + +// CATCH_REQUIRE_THROWS is not defined identically to REQUIRE_THROWS and causes +// warning; define our own version that doesn't warn. +#define _CATCH_REQUIRE_THROWS(...) \ + INTERNAL_CATCH_THROWS( \ + "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__) + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/testing/file_check.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/testing/file_check.h new file mode 100644 index 0000000000000000000000000000000000000000..d21536d075419323681874e9cb02caa1fe713b5e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/testing/file_check.h @@ -0,0 +1,84 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace torch::jit { + +struct Graph; + +namespace testing { + +struct FileCheckImpl; + +struct FileCheck { + public: + TORCH_API explicit FileCheck(); + TORCH_API ~FileCheck(); + + // Run FileCheck against test string + TORCH_API void run(const std::string& test_string); + + // Run FileCheck against dump of graph IR + TORCH_API void run(const Graph& graph); + + // Parsing input checks string and run against test string / dump of graph IR + TORCH_API void run( + const std::string& input_checks_string, + const std::string& test_string); + TORCH_API void run( + const std::string& input_checks_string, + const Graph& graph); + + // Checks that the string occurs, starting at the end of the most recent match + TORCH_API FileCheck* check(const std::string& str); + + // Checks that the string does not occur between the previous match and next + // match. Consecutive check_nots test against the same previous match and next + // match + TORCH_API FileCheck* check_not(const std::string& str); + + // Checks that the string occurs on the same line as the previous match + TORCH_API FileCheck* check_same(const std::string& str); + + // Checks that the string occurs on the line immediately following the + // previous match + TORCH_API FileCheck* check_next(const std::string& str); + + // Checks that the string occurs count number of times, starting at the end + // of the previous match. If exactly is true, checks that there are exactly + // count many matches + TORCH_API FileCheck* check_count( + const std::string& str, + size_t count, + bool exactly = false); + + // A series of consecutive check_dags get turned into a group of checks + // which can appear in any order relative to each other. The checks begin + // at the end of the previous match, and the match for the check_dag group + // is the minimum match of all individual checks to the maximum match of all + // individual checks. + TORCH_API FileCheck* check_dag(const std::string& str); + + // Checks that source token is highlighted in str (usually an error message). + TORCH_API FileCheck* check_source_highlighted(const std::string& str); + + // Checks that the regex matched string occurs, starting at the end of the + // most recent match + TORCH_API FileCheck* check_regex(const std::string& str); + + // reset checks + TORCH_API void reset(); + + private: + bool has_run = false; + std::unique_ptr fcImpl; +}; +} // namespace testing +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/testing/hooks_for_testing.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/testing/hooks_for_testing.h new file mode 100644 index 0000000000000000000000000000000000000000..5547574692493b6585214a68622523c962308322 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/testing/hooks_for_testing.h @@ -0,0 +1,24 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include + +namespace torch::jit { +struct Module; + +using ModuleHook = std::function; +using FunctionHook = std::function; + +TORCH_API void didFinishEmitModule(Module module); +TORCH_API void didFinishEmitFunction(StrongFunctionPtr defined); +TORCH_API void setEmitHooks(ModuleHook for_module, FunctionHook for_fn); + +TORCH_API std::pair getEmitHooks(); + +} // namespace torch::jit + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/backend/backend_data.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/backend/backend_data.h new file mode 100644 index 0000000000000000000000000000000000000000..75f05b99b69aca3439c9b5be53685dd65622ebcc --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/backend/backend_data.h @@ -0,0 +1,64 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace torch::lazy { + +class TORCH_API BackendData { + public: + struct Info { + /** + * Used by Lazy Graph Executor to tag info on BackendData objs + * */ + virtual ~Info() = default; + }; + /** + * Represents (Tensor) data stored on a backend device + * in its native format. + * */ + using Handle = int64_t; + + BackendData(BackendDevice device, Shape shape) + : device_(std::move(device)), shape_(std::move(shape)) {} + + virtual ~BackendData() = default; + + const BackendDevice& device() const { + return device_; + } + + const Shape& shape() const { + return shape_; + } + + Info* info() const { + return info_.get(); + } + + std::shared_ptr SetInfo(std::shared_ptr info) { + std::swap(info, info_); + return info; + } + + virtual Handle GetHandle() = 0; + + virtual void Assign(const BackendData& data) = 0; + + virtual bool HasValue() const = 0; + + private: + BackendDevice device_; + Shape shape_; + std::shared_ptr info_; +}; + +using BackendDataPtr = std::shared_ptr; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/backend/backend_device.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/backend/backend_device.h new file mode 100644 index 0000000000000000000000000000000000000000..99872dc5b1bb353e64761a4f603d0d8e52ebd11c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/backend/backend_device.h @@ -0,0 +1,105 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include +#include +#include +#include + +namespace c10 { +struct Device; +} + +namespace torch::lazy { + +// Backend should extend it and define their own supported hardware types. +struct TORCH_API BackendDeviceType { + int8_t type{(int8_t)at::kCPU}; + // Note: previous default value was '0', which actually maps to at::kCPU, at + // least now it is explicit, we may want to make default/undefined semantics + // more clear though + BackendDeviceType() = default; + BackendDeviceType(int8_t type) : type(type) {} + + virtual ~BackendDeviceType() = default; + virtual std::string toString() const { + return "Unknown"; + } +}; + +class TORCH_API BackendDevice { + public: + // The default constructor will set both the device type and ordinal + // to backend specific defaults. + BackendDevice(); + BackendDevice(std::shared_ptr&& type, int64_t ordinal); + + int8_t type() const; + int64_t ordinal() const { + return ordinal_; + } + + bool operator==(const BackendDevice& other) const { + return compare(other) == 0; + } + bool operator!=(const BackendDevice& other) const { + return compare(other) != 0; + } + bool operator<(const BackendDevice& rhs) const { + return compare(rhs) < 0; + } + + std::string toString() const; + + private: + int compare(const BackendDevice& rhs) const; + + // Use shared_ptr instead of unique_ptr so that BackendDevice can be copied. + std::shared_ptr type_; + int64_t ordinal_; +}; + +TORCH_API std::ostream& operator<<( + std::ostream& os, + const BackendDevice& device); + +// Helpers for converting a c10::Device to BackendDevice and vice versa. +TORCH_API BackendDevice atenDeviceToBackendDevice(const c10::Device& device); +TORCH_API c10::Device backendDeviceToAtenDevice(const BackendDevice& device); + +// Tries to extract the backend device out of the lazy tensor. Returns nullopt +// if the input is not a lazy tensor. +TORCH_API std::optional GetBackendDevice( + const at::ITensorListRef tensors); +TORCH_API std::optional GetBackendDevice( + const at::TensorList tensors); +TORCH_API std::optional GetBackendDevice( + const at::Tensor& tensor); +TORCH_API std::optional GetBackendDevice( + const std::optional& device); + +// For variadic template. +TORCH_API std::optional GetBackendDevice(); + +C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED("-Winfinite-recursion") +template +std::optional GetBackendDevice( + const T& tensor, + const Args&... forward_tensors) { + auto optional_device = GetBackendDevice(tensor); + if (optional_device) { + return optional_device; + } + return GetBackendDevice(forward_tensors...); +} +C10_DIAGNOSTIC_POP() + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/backend/backend_interface.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/backend/backend_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..9f885d4d4c71618d6c824f197ef109b0c0c76dfc --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/backend/backend_interface.h @@ -0,0 +1,160 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace torch::lazy { + +struct IrBuilder; + +/** + * Work in progress- don't treat this as a stable interface yet! + */ +class TORCH_API BackendImplInterface { + public: + virtual ~BackendImplInterface() = default; + + /** + * Initialization/Teardown + * */ + // No-op by default. Allows custom functionality to be exposed through + // extension bindings. + virtual void InitializeAtenBindings() const {} + + virtual void PrepareToExit() const = 0; + + /** + * Configuration + * */ + + virtual void SetRngSeed(size_t seed) const = 0; + + /** + * IR Tracing + * */ + + virtual const IrBuilder* GetIrBuilder() const = 0; + + /** + * Data Transfer + * */ + + virtual BackendDataPtr MakeComputationDataFromTensor( + const at::Tensor& tensor, + const Shape& shape, + const BackendDevice& device) const = 0; + virtual BackendDataPtr MakeComputationDataFromScalar( + const at::Scalar& scalar, + const torch::lazy::BackendDevice& device) const = 0; + virtual BackendDataPtr CreateDataPlaceholder( + const BackendDevice& device, + const Shape& shape) const = 0; + + // Gets backend data if the node is a device data node. Otherwise returns + // nullptr + virtual BackendDataPtr GetComputationDataFromNode(const Node*) const = 0; + + virtual at::Tensor MakeTensorFromComputationData( + const BackendDataPtr data, + std::optional logical_scalar_type) const = 0; + + /** + * Lowering, Compilation, Execution + * */ + + virtual std::unique_ptr CreateLoweringContext( + const std::string& name, + BackendDevice device, + c10::ArrayRef post_order, + Util::EmissionMap emit_status) const = 0; + + virtual std::unique_ptr CreateLoweringContext( + const std::string& name, + BackendDevice device) const = 0; + + // TODO(whc) need to keep this? + virtual std::vector GetCompilationDevices( + const std::string& device, + c10::ArrayRef devices) const = 0; + + virtual std::vector Compile( + std::vector instances) const = 0; + + virtual std::vector ExecuteComputation( + torch::lazy::ComputationPtr computation, + c10::ArrayRef arguments, + const BackendDevice& device) const = 0; + + /** + * Device Configuration + * */ + + // Set or get the default device type. + // For backends used with virtual c10::Devices, this configures what real + // device type the backend should use, and matters if the backend supports + // more than one type of real device. + virtual std::shared_ptr GetDefaultDeviceType() const = 0; + virtual void SetDefaultDeviceType(int8_t type) = 0; + + // Set or get the default device ordinal. + // For backends that supports multi-device, this configures what the + // default device the backend should use. + virtual int64_t GetDefaultDeviceOrdinal() const = 0; + virtual void SetDefaultDeviceOrdinal(int64_t) = 0; + + // Specify which aten device should be used for eager fallback + // may change depending on current 'Default' DeviceType + virtual at::DeviceType EagerFallbackDeviceType() const = 0; + + // Query all available backend devices + virtual std::vector GetBackendDevices() const = 0; + + virtual std::string CreateMetricReport() const { + return ""; + } + + // Map a particular c10:: device to a concrete backend device + // Note:: c10:: devices may be virtual or concrete. xla:: and lazy:: are + // virtual devices, meaning they may map to a gpu, tpu, etc. behind the + // scenes. In the future, non-virtual c10:: devices may also use lazy tensors + // through a mode, in which case these APIs should still work, but should be + // identity mappings. + virtual BackendDevice GetBackendDevice(c10::Device device) const = 0; + + // TODO(whc) + // Additional APIs expected for supporting distributed training, to be + // designed + + /** + * Debug/Metrics + * */ + + // virtual std::map GetMetrics() const = 0; + + // virtual MemoryInfo GetMemoryInfo(const std::string& device) = 0; + + virtual std::string GetComputationBackendText( + const ComputationPtr computation) const = 0; +}; + +class TORCH_API BackendRegistrar { + public: + BackendRegistrar(const BackendImplInterface* backend_impl_interface); +}; + +TORCH_API bool hasBackend(); +TORCH_API const BackendImplInterface* getBackend(); + +TORCH_API const IrBuilder* getIrBuilder(); + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/backend/lowering_context.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/backend/lowering_context.h new file mode 100644 index 0000000000000000000000000000000000000000..8de72ec167fdd9d27412ba13b8ac143e16d2c0b1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/backend/lowering_context.h @@ -0,0 +1,115 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include +#include +#include +#include + +namespace torch::lazy { + +class TORCH_API Computation { + public: + virtual int parameters_size() const = 0; + + virtual const std::vector& parameter_shapes() const = 0; + + virtual const std::vector& parameter_names() const = 0; + + virtual const Shape& result_shape() const = 0; + + virtual const std::string to_string() const = 0; + + virtual ~Computation() = default; + + // Indicates whether this computation is being executed inside a mark step + // Assume false unless set otherwise + bool in_mark_step = false; +}; + +using ComputationPtr = std::shared_ptr; + +// Keeps track of the code generation state. +class TORCH_API LoweringContext { + public: + LoweringContext(const std::string& name, BackendDevice device); + LoweringContext( + const std::string& name, + BackendDevice device, + c10::ArrayRef post_order, + Util::EmissionMap emit_status); + + virtual ~LoweringContext() = default; + + static std::unique_ptr Create( + const std::string& name, + BackendDevice device, + c10::ArrayRef post_order, + Util::EmissionMap emit_status); + + static std::unique_ptr Create( + const std::string& name, + BackendDevice device); + + const BackendDevice& device() const { + return device_; + } + + // Retrieves the vector holding all the tensors associated with the parameter + // instructions which have been created. + const std::vector& GetParametersData() const; + + // Adds a new input/output alias. + virtual void SetUpAlias( + const std::vector& output_index, + int64_t param_number, + const std::vector& param_index, + bool must_alias = false) { + // Dummy default implementation to do nothing. + } + + // Check if parameter shape matches result at index. + virtual bool CheckResultShape( + const BackendDataPtr& parameter_data, + size_t result_idx) { + // Dummy default implementation to do nothing. + return false; + } + + // Adds the given output as a component of the result tuple and returns its + // assigned position within the tuple. + virtual size_t AddResult(const torch::lazy::Output& output) = 0; + + // Associates the given output with the input parameter of the given index and + // shape. Only used for the operator-by-operator execution, mostly for + // debugging purposes. + virtual void AddParameter( + const torch::lazy::Output& output, + size_t index, + const Shape& shape, + const std::string& name) = 0; + + // Build the computation capturing all the operations created with the + // embedded builder (returned by the builder() API). + virtual ComputationPtr Build() = 0; + + size_t GetEmittedNodeCount() const { + return emit_status_.size(); + } + + protected: + BackendDevice device_; + std::vector parameters_; + std::vector parameter_sequence_; + Util::EmissionMap emit_status_; +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/cache.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/cache.h new file mode 100644 index 0000000000000000000000000000000000000000..a34161654e64d8277e0af2508360dcaa9aa782b8 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/cache.h @@ -0,0 +1,148 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +/** + * Cache utils in this file is adapted from PyTorch/XLA + * https://github.com/pytorch/xla/blob/e0e5f937a0ba8d904f9608137dc8c51ba439df2d/third_party/xla_client/cache.h + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace torch::lazy { + +// Generic key and object cache with LRU expiration policy. The objects of type +// T will be stored as std::shared_ptr and taken and returned as such, by the +// cache API. +template < + typename K, + typename T, + typename H = std::hash, + typename E = std::equal_to> +class Cache { + public: + using TypePtr = std::shared_ptr; + using Element = std::pair; + + explicit Cache(size_t max_size) : max_size_(max_size) {} + + // Adds an object to the cache, unless it already exists. If the cache grows + // beyond the limit set during construction, the oldest used object will be + // removed from the cache. + TypePtr Add(K key, TypePtr object) { + if (!max_size_) { + return object; + } + std::lock_guard slock(lock_); + element_list_.emplace_front(Element(std::move(key), std::move(object))); + auto it = element_list_.begin(); + auto emplace_result = element_map_.emplace(&it->first, it); + if (!emplace_result.second) { + element_list_.erase(it); + DoLRU(emplace_result.first->second); + } else if (element_list_.size() > max_size_) { + Element* last = &element_list_.back(); + element_map_.erase(&last->first); + element_list_.pop_back(); + } + return emplace_result.first->second->second; + } + + // Retrieves the existing object if it exists. If it does, its position in + // the LRU list gets moved to the head of the list. + // Returns nullptr if no object with the specified key is found within the + // cache. + TypePtr Get(const K& key) { + if (!max_size_) { + return nullptr; + } + std::lock_guard slock(lock_); + auto it = element_map_.find(&key); + if (it == element_map_.end()) { + return nullptr; + } + DoLRU(it->second); + return it->second->second; + } + + TypePtr GetLatest() { + std::lock_guard g(lock_); + TORCH_CHECK(!element_list_.empty()); + return element_list_.front().second; + } + + bool Erase(const K& key) { + if (!max_size_) { + return false; + } + std::lock_guard slock(lock_); + auto it = element_map_.find(&key); + if (it == element_map_.end()) { + return false; + } + auto lit = it->second; + element_map_.erase(it); + element_list_.erase(lit); + return true; + } + + void Clear() { + if (!max_size_) { + return; + } + std::lock_guard slock(lock_); + element_map_.clear(); + element_list_.clear(); + } + + int Numel() const { + if (!max_size_) { + return 0; + } + std::lock_guard g(lock_); + TORCH_CHECK(element_map_.size() == element_list_.size()); + return element_map_.size(); + } + + private: + using ElementList = std::list; + + struct Hasher { + size_t operator()(const K* key) const { + return hasher(*key); + } + + H hasher; + }; + + struct Equaler { + bool operator()(const K* k1, const K* k2) const { + return equaler(*k1, *k2); + } + + E equaler; + }; + + using ElementMap = std:: + unordered_map; + + void DoLRU(typename ElementList::iterator it) { + element_list_.splice(element_list_.begin(), element_list_, it); + } + + mutable std::mutex lock_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const size_t max_size_ = 0; + ElementList element_list_; + ElementMap element_map_; +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/config.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/config.h new file mode 100644 index 0000000000000000000000000000000000000000..83ff42b145fa390c600e4f005c29c1993fdbbff9 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/config.h @@ -0,0 +1,31 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include + +TORCH_DECLARE_bool(torch_lazy_ir_debug); +TORCH_DECLARE_bool(torch_lazy_handle_special_scalars); +TORCH_DECLARE_bool(torch_lazy_all_numbers_special_scalars); +TORCH_DECLARE_bool(torch_lazy_param_aliasing); +TORCH_DECLARE_bool(torch_lazy_reuse_ir); +TORCH_DECLARE_bool(torch_lazy_use_thread_pool); +TORCH_DECLARE_bool(torch_lazy_enable_device_data_cache); + +TORCH_DECLARE_int(torch_lazy_compilation_cache_size); +TORCH_DECLARE_int(torch_lazy_device_data_cache_size); +TORCH_DECLARE_int(torch_lazy_io_thread_pool_size); +TORCH_DECLARE_int(torch_lazy_metrics_samples); +TORCH_DECLARE_int(torch_lazy_trim_graph_check_frequency); +TORCH_DECLARE_int(torch_lazy_trim_graph_size); + +TORCH_DECLARE_string(torch_lazy_metrics_percentiles); + +TORCH_DECLARE_int(torch_lazy_shape_cache_size); + +namespace torch::lazy { +TORCH_API std::string& getLTCForceFallback(); +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/debug_util.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/debug_util.h new file mode 100644 index 0000000000000000000000000000000000000000..7c3ce3171ce299d10a487dc5f85a9861d7d123c6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/debug_util.h @@ -0,0 +1,50 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include + +namespace torch::lazy { + +TORCH_API std::function()>& +GetPythonFramesFunction(); + +TORCH_API std::string GetFirstUserFrameInPython(); + +class TORCH_API DebugUtil { + public: + enum GraphFormat { + kText, + kDot, + kBackend, + }; + + static GraphFormat GetDefaultGraphFormat(); + + // Dumps the current Python frame and the IR Graph whose roots are the IR + // values held at the tensors. If indices is not nullptr, it selects the + // indices of the tensors whose graph will be emitted. + static std::string GetTensorsGraphInfo( + c10::ArrayRef tensors, + const std::vector* indices, + GraphFormat format = GetDefaultGraphFormat()); + + // If the environment variable LTC_SAVE_TENSORS_FILE is set to the proper + // output path, an instance of the report returned by GetTensorsGraphInfo() is + // saved. + static void SaveTensorsGraphInfo( + const char* name, + c10::ArrayRef tensors, + const std::vector* indices, + GraphFormat format = GetDefaultGraphFormat()); + + static bool ExperimentEnabled(const std::string& name); +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/dynamic_ir.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/dynamic_ir.h new file mode 100644 index 0000000000000000000000000000000000000000..d21d6feb0ba58ad5e17f7e92b1e14c4334c3475e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/dynamic_ir.h @@ -0,0 +1,53 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +namespace torch::lazy { + +/** + * The goal of "dynamic" Nodes is to patch a hole in our tracing. + * Previously, if a user called `sizes` on a Tensor, it would leak out + * of our tracing system, as `sizes` returns a torch.Size or an int. To + * prevent this from happening, we introduce DimensionNode, a new type + * of Node that abstracts the operation of getting the dimensions of a + * Tensor. + * + * Consider the following example: + * ``` + * numel = x.shape()[0] * x.shape()[1] + * ``` + * + * Here, `x.shape()[i]` will be a SizeNode (subclass of DimensionNode), + * and the multiplication of the two SizeNodes will be represented by + * a SizeMul (also a subclass of DimensionNode). Through this, we can + * prevent `numel` from being represented as a Python int and thus + * burned into the Graph. + */ + +class TORCH_API DimensionNode { + public: + virtual bool isSymbolic() const { + return false; + } + virtual int64_t getDynamicValue() const { + TORCH_CHECK(false, "NYI"); + } + virtual int64_t getStaticValue() const { + TORCH_CHECK(false, "NYI"); + } + virtual ~DimensionNode() = default; +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/hash.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/hash.h new file mode 100644 index 0000000000000000000000000000000000000000..f224aae7bf62257f83e4e5db89c843a9323777a1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/hash.h @@ -0,0 +1,247 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +/** + * Hash utils in this file is adapted from PyTorch/XLA + * https://github.com/pytorch/xla/blob/e0e5f937a0ba8d904f9608137dc8c51ba439df2d/third_party/xla_client/util.h + */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace torch::lazy { + +using size_t = std::size_t; + +class TORCH_API hash_t : public c10::uint128 { + public: + // Switch from typedef hash_t = uint128 to provide explicit casters + hash_t(int8_t val) : uint128(static_cast(val)) {} + hash_t(int16_t val) : uint128(static_cast(val)) {} + hash_t(int32_t val) : uint128(static_cast(val)) {} + hash_t(int64_t val) : uint128(static_cast(val)) {} + hash_t(uint32_t val) : uint128(val) {} + hash_t(uint64_t val) : uint128(val) {} + hash_t(uint128 val) : uint128(val) {} + hash_t(uint64_t top, uint64_t bottom) : uint128(top, bottom) {} + hash_t() = default; +}; + +// Std* functions use 64-bit hash +size_t TORCH_API StdDataHash(const void* data, size_t size); + +size_t TORCH_API StdHashCombine(uintmax_t a, uintmax_t b); + +// Other functions are all 128-bit +hash_t TORCH_API HashBlock(const void* data, size_t n, const hash_t& seed); + +hash_t TORCH_API DataHash(const void* data, size_t size); + +hash_t TORCH_API HashCombine(const hash_t& a, const hash_t& b); + +size_t TORCH_API HashReduce(const hash_t& a); + +// Returns a string representation of a hash +std::string TORCH_API HashToString(const hash_t& a); + +struct HashReducer { + size_t operator()(const hash_t& value) const { + return HashReduce(value); + } +}; + +static inline hash_t StringHash(const char* data) { + return DataHash(data, std::strlen(data)); +} + +// Automatic templated implementation for 'arithmetic' types +template >* = nullptr> +hash_t Hash(const T& value) { + return DataHash(&value, sizeof(value)); +} + +// added because on macos builds the vector specialization +// breaks falling through to the templated arithmetic types above +hash_t TORCH_API Hash(const std::vector& value); + +// Specialized implementations for proprietary types +static inline hash_t Hash(const c10::ScalarType& value) { + return DataHash(&value, sizeof(value)); +} + +static inline hash_t Hash(const c10::MemoryFormat& value) { + return DataHash(&value, sizeof(value)); +} + +static inline hash_t Hash(const c10::DeviceType& value) { + return DataHash(&value, sizeof(value)); +} + +static inline hash_t Hash(const c10::Device& value) { + return HashCombine(Hash(value.type()), Hash(value.index())); +} + +static inline hash_t Hash(const c10::Layout& value) { + return DataHash(&value, sizeof(value)); +} + +static inline hash_t Hash(const c10::Scalar& value) { + switch (value.type()) { + case c10::ScalarType::ComplexDouble: + return Hash(value.toComplexDouble()); + case c10::ScalarType::Double: + return Hash(value.toDouble()); + case c10::ScalarType::Long: + return Hash(value.toLong()); + case c10::ScalarType::Bool: + return Hash(value.toBool()); + default: + TORCH_INTERNAL_ASSERT(false, "Unknown scalar type.", value.type()); + } +} + +static inline hash_t TensorHash(const at::Tensor& tensor) { + at::Tensor ctensor = tensor.contiguous(); + int64_t size = ctensor.numel() * ctensor.element_size(); + switch (ctensor.scalar_type()) { + case at::ScalarType::Bool: + return DataHash(ctensor.const_data_ptr(), size); + case at::ScalarType::Byte: + return DataHash(ctensor.const_data_ptr(), size); + case at::ScalarType::Char: + return DataHash(ctensor.const_data_ptr(), size); + case at::ScalarType::Short: + return DataHash(ctensor.const_data_ptr(), size); + case at::ScalarType::Int: + return DataHash(ctensor.const_data_ptr(), size); + case at::ScalarType::Long: + return DataHash(ctensor.const_data_ptr(), size); + case at::ScalarType::Float: + return DataHash(ctensor.const_data_ptr(), size); + case at::ScalarType::Double: + return DataHash(ctensor.const_data_ptr(), size); + case at::ScalarType::BFloat16: + return DataHash(ctensor.const_data_ptr(), size); + case at::ScalarType::Half: + return DataHash(ctensor.const_data_ptr(), size); + case at::ScalarType::ComplexFloat: + return DataHash(ctensor.const_data_ptr>(), size); + case at::ScalarType::ComplexDouble: + return DataHash(ctensor.const_data_ptr>(), size); + case at::ScalarType::UInt16: + return DataHash(ctensor.const_data_ptr(), size); + case at::ScalarType::UInt32: + return DataHash(ctensor.const_data_ptr(), size); + case at::ScalarType::UInt64: + return DataHash(ctensor.const_data_ptr(), size); + default: + TORCH_INTERNAL_ASSERT( + false, "Unsupported scalar type:", ctensor.scalar_type()); + } +} + +static inline hash_t Hash(const std::string& value) { + return DataHash(value.data(), value.size()); +} + +static inline hash_t Hash(const std::string_view& value) { + return DataHash(value.data(), value.size()); +} + +static inline hash_t Hash(const at::Generator& value) { + return TensorHash(value.get_state()); +} + +// Taken from glibc's implementation of hashing optionals, +// we want to include a contribution to the hash to distinguish +// cases where one or another option was null, but we hope it doesn't +// collide with an actually scalar value. +// +// Use an arbitrary randomly-selected 64-bit integer rather than a +// small constant that we then hash at runtime so we don't have to +// repeatedly hash a constant at runtime. +// NOLINTNEXTLINE(*-narrowing-conversions) +static const int64_t kNullOpt = 0x8655d738f3678dda; + +// Hashing for std::optional types contributes to hash +// for optionals with null value, important to distinguish +// between and cases +template +hash_t Hash(const std::optional& value) { + if (value.has_value()) { + return Hash(value.value()); + } else { + return kNullOpt; + } +} + +// Hashing of containers +// Forward declare to allow hashes of vectors of vectors to work. +template +hash_t ContainerHash(const T& values); + +template +hash_t Hash(const std::vector& values) { + return ContainerHash(values); +} + +// Need a special case for std::optional? +template +hash_t Hash(const std::optional>& value) { + if (value.has_value()) { + return ContainerHash(value.value()); + } else { + return kNullOpt; + } +} + +template +hash_t Hash(const std::set& values) { + return ContainerHash(values); +} + +template +hash_t Hash(const std::pair& values) { + return HashCombine(Hash(values.first), Hash(values.second)); +} + +static inline hash_t Hash(const hash_t& value) { + return value; +} + +template +hash_t Hash(c10::ArrayRef values) { + return ContainerHash(values); +} + +template +hash_t ContainerHash(const T& values) { + hash_t h(static_cast(0x85ebca77c2b2ae63)); + for (const auto& value : values) { + h = HashCombine(h, Hash(value)); + } + return h; +} + +// Varargs hashing +template +hash_t MHash() { + return hash_t(static_cast(0x165667b19e3779f9)); +} + +template +hash_t MHash(T value, Targs... Fargs) { + return HashCombine(Hash(value), MHash(Fargs...)); +} + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/helpers.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/helpers.h new file mode 100644 index 0000000000000000000000000000000000000000..440e880fcb76b7e60e7a383d6b820ab6a3c7ae34 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/helpers.h @@ -0,0 +1,75 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +// TODO: Consolidate this file with util.h + +namespace torch::lazy { + +// Converts an iterable container to a vector of int64's. +template +static std::vector ToI64Vector(const S& input) { + return ToVector(input); +} + +// Creates a set of dimension by dropping the drop_dims ones. +TORCH_API std::vector DropDimensions( + c10::ArrayRef sizes, + c10::ArrayRef drop_dims); + +// Get the canonical dimension index in the [0, rank) interval. Negative +// indices are interpreted as follows: -1 is rank-1, -2 is rank-2 etc. +TORCH_API int64_t GetCanonicalDimensionIndex(int64_t dim, int64_t rank); + +// Same as above, for multiple dimensions. +TORCH_API std::vector GetCanonicalDimensionIndices( + c10::ArrayRef dimensions, + int64_t rank); + +// Returns the canonical position in the dim dimension, handling negative +// values for the position. +TORCH_API int64_t GetCanonicalPosition( + c10::ArrayRef dimensions, + int64_t dim, + int64_t pos); + +// Creates a transposition from the given input and dimensions. +TORCH_API std::vector MakeTransposePermutation( + int64_t dim0, + int64_t dim1, + int64_t rank); + +// Calculates the protomoted shape to which the input shapes should be +// broadcasted for an elementwise operation. The size of the common dimensions +// (2,3,4 for shape1, and 0,1,2 for shape2) must either match, or either one +// of the two be 1. +// Example: +// shape1 = [9, 7, 6, 1, 2] +// shape2 = [6, 5, 2] +// result_shape = [9, 7, 6, 5, 2] +TORCH_API std::vector GetPromotedShape( + c10::ArrayRef shape1_dims, + c10::ArrayRef shape2_dims); + +TORCH_API Shape +GetPromotedBinaryOpShape(const Shape& shape1, const Shape& shape2); + +TORCH_API std::vector StrSplit(std::string_view text, char delim); + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/internal_ops/ltc_ops.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/internal_ops/ltc_ops.h new file mode 100644 index 0000000000000000000000000000000000000000..29c0ebbbe8c4471051f45a7a00e3138c2e54c2f8 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/internal_ops/ltc_ops.h @@ -0,0 +1,54 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include + +#include + +namespace torch::lazy { + +class TORCH_API OpKindWrapper { + public: + explicit OpKindWrapper(const char* name) : name_(name) {} + + const OpKind& operator*() const { + return get(); + } + + operator OpKind() const { + return get(); + } + + private: + const OpKind& get() const { + c10::call_once(once_, [this]() { op_kind_ = OpKind::Get(name_); }); + return op_kind_; + } + + const char* name_; + mutable OpKind op_kind_; + mutable c10::once_flag once_; +}; + +const OpKindWrapper ltc_all_to_all("lazy_tensors::all_to_all"); +const OpKindWrapper ltc_cast("lazy_tensors::cast"); +const OpKindWrapper ltc_collective_permute("lazy_tensors::collective_permute"); +const OpKindWrapper ltc_cross_replica_sum("lazy_tensors::cross_replica_sum"); +const OpKindWrapper ltc_device_data("lazy_tensors::device_data"); +const OpKindWrapper ltc_get_dimensions_size( + "lazy_tensors::ltc_get_dimensions_size"); +const OpKindWrapper ltc_moving_average("lazy_tensors::moving_average"); +const OpKindWrapper ltc_nms("lazy_tensors::nms"); +const OpKindWrapper ltc_not_supported("lazy_tensors::not_supported"); +const OpKindWrapper ltc_replication_pad("lazy_tensors::replication_pad"); +const OpKindWrapper ltc_replication_pad_backward( + "lazy_tensors::replication_pad_backward"); +const OpKindWrapper ltc_tensor_data("lazy_tensors::tensor_data"); + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ir.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ir.h new file mode 100644 index 0000000000000000000000000000000000000000..79a4655a62810aa3bbe6fe843f42cd0408567b2a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ir.h @@ -0,0 +1,302 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +TORCH_DECLARE_bool(ltc_enable_dynamic_shapes); + +namespace torch::lazy { + +static const hash_t kHashSeed(static_cast(0x5a2d296e9)); + +class Node; +struct Output; +struct Value; + +using NodePtr = std::shared_ptr; + +// The Kind of operation a Node can be associated to. +struct TORCH_API OpKind { + OpKind() = default; + explicit OpKind(c10::Symbol op) : op(op) {} + + bool operator==(const OpKind& rhs) const { + return op == rhs.op; + } + bool operator!=(const OpKind& rhs) const { + return !operator==(rhs); + } + bool operator<(const OpKind& rhs) const { + return c10::unique_t(op) < c10::unique_t(rhs.op); + } + + hash_t hash() const; + + std::string ToString() const { + return op.toQualString(); + } + + // Retrieves an existing operation object, or creates a new one. Operations + // that are specific to lazy tensors, should live within the 'lazy_tensors::' + // namespace. + static OpKind Get(const std::string& name); + + c10::Symbol op; +}; + +inline std::ostream& operator<<(std::ostream& stream, const OpKind& op) { + stream << op.ToString(); + return stream; +} + +using OpList = c10::ArrayRef; + +hash_t OperandHashes( + const OpList& operands, + const hash_t& seed, + bool bakeInSizes); +// A node in the graph. Nodes for operations which require extra data to be +// stored for lowering should inherit from this class and add an operation +// specific member there. For example, a constant might create a new +// NodeConstant class (inheriting from Node) with an extra lazy_tensors::Literal +// field, or a tensor value might create a new NodeTensor with a computation +// client data handle in it. +class TORCH_API Node { + public: + static bool enableDynamicShape(); + + // Creates a new node with the given op name. The op is a unique identifier + // for the operation. The num_outputs tells how many outputs a given operation + // generates. + // + // None leaf node's node_hash does not contains shape information always. + // So we pass in the hash value rather than a function. + Node(OpKind op, size_t num_outputs); + + // Construct node with operands and shapes + Node( + OpKind op, + OpList operands, + std::vector&& shapes, + size_t num_outputs = 1); + + // Construct node with operands and no shape + Node(OpKind op, OpList operands, size_t num_outputs = 1); + + // Construct node with shape and no operands + Node(OpKind op, Shape shape, size_t num_outputs = 1); + + Node(const Node& rhs); + + Node(Node&& rhs); + + virtual ~Node(); + + Node& operator=(const Node& rhs); + + Node& operator=(Node&& rhs); + + const OpKind& op() const { + return op_; + } + + size_t num_outputs() const { + return num_outputs_; + } + + // Retrieves the full shape of the IR Node. + virtual c10::ArrayRef shapes() const; + + virtual const Shape& shape(size_t output_index = 0) const; + + // Add the shape computed by the shape_fn + void addComputedShape(const std::function& shape_fn); + + // Compute the shape using the provided shape_fn if not previously cached + Shape computeShape(const std::function& shape_fn); + + virtual const std::vector& operands() const; + + virtual const Output& operand(size_t i) const; + + // Gets operand at index i if index is valid, or kNullOutput otherwise. + virtual const Output& nullable_operand(size_t i) const; + + // Returns the hash of the dag used to look up the compiled graph + virtual hash_t hash() const = 0; + + // Returns the hash of the dag used to for shape caching + virtual hash_t shapeHash() const = 0; + + const MetaData& metadata() const { + return metadata_; + } + + UserMetaData* user_metadata() const { + return user_metadata_.get(); + } + + std::shared_ptr SetUserMetadata( + std::shared_ptr user_meta) { + std::swap(user_metadata_, user_meta); + return user_meta; + } + + virtual std::string ToString() const; + + private: + // The ID of the operation captured by this node. + OpKind op_; + size_t num_outputs_ = 1; + + // The IR specific metadata attached to the IR node. + MetaData metadata_; + // The IR framework user can attach a user defined metadata object deriving + // from UserMetaData. + std::shared_ptr user_metadata_; + + protected: + // Adds node's index output number as operand. + void AddOperand(const NodePtr& node, size_t index = 0); + + std::vector shapes_; + // A node holds a real reference to its operands. + std::vector operands_; + // Outputs do not hold references on the nodes, and neither do the uses, since + // otherwise we get into circular reference counting. + std::vector operands_as_outputs_; +}; + +inline std::ostream& operator<<(std::ostream& stream, const Node& node) { + stream << node.ToString(); + return stream; +} + +// Note: Keep this version of NodeCast for smooth PyTorch/XLA migration, and +// clean up once the migration is done. +template +const T* NodeCast(const Node* node, OpKind op) { + if (op != node->op()) { + return nullptr; + } +#ifdef NDEBUG + return static_cast(node); +#else + return &dynamic_cast(*node); +#endif +} + +template +const T* NodeCast(const Node* node) { + if (T::ClassOpKind() != node->op()) { + return nullptr; + } + // TODO: Some IR classes share the same opkind, such as Mean and MeanDim, so + // static_cast is not safe here. Unless we have opkind unique for each class, + // we have to use dynamic_cast here. + return dynamic_cast(node); +} + +// Represents a specific output produced by a node. Since the output of a node +// can be composed by multiple outputs, the node+index coordinates fully qualify +// each single output. +struct TORCH_API Output { + struct Hasher { + size_t operator()(const Output& output) const; + }; + + Output() = default; + explicit Output(const Node* node, size_t index = 0) + : node(node), index(index) {} + + hash_t hash() const; + hash_t shapeHash() const; + + bool operator==(const Output& rhs) const { + return node == rhs.node && index == rhs.index; + } + + // To compare the operands of to-be-constructed node and to-be-reused node + bool operator==(const Value& rhs) const; + + bool operator!=(const Output& rhs) const { + return !operator==(rhs); + } + + const Shape& shape() const { + return node->shape(index); + } + + std::string ToString() const; + + // The node providing the output. + const Node* node{nullptr}; + // The index in the node's output this output refers to. + size_t index{0}; +}; + +inline std::ostream& operator<<(std::ostream& stream, const Output& output) { + stream << output.ToString(); + return stream; +} + +template +using OutputMap = std::unordered_map; + +// Represents an input/operand for a Node object. +struct TORCH_API Value { + Value() = default; + /* implicit */ Value(NodePtr&& node, size_t index = 0) + : node(std::move(node)), index(index) {} + /* implicit */ Value(const NodePtr& node, size_t index = 0) + : node(node), index(index) {} + + hash_t hash() const; + hash_t shapeHash() const; + + operator bool() const { + return node != nullptr; + } + + operator Output() const { + return Output(node.get(), index); + } + + const Shape& shape() const { + return node->shape(index); + } + + Node* operator->() const { + return node.get(); + } + + NodePtr node; + size_t index = 0; +}; + +} // namespace torch::lazy + +namespace c10 { +// Explicit template instantiation to make ArrayRef work +template class at::ArrayRef; +} // namespace c10 + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ir_builder.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ir_builder.h new file mode 100644 index 0000000000000000000000000000000000000000..c1b1c2abc8f342f42fea0e315b2d6762cace2d33 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ir_builder.h @@ -0,0 +1,153 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +// This file is part of the backend interface. So, ops shouldn't be added or +// removed without due process The exception to this being the view ops which +// will be removed soon pending functionalization + +namespace torch::lazy { + +template +NodePtr ReuseNode(Args&&... args) { + if (FLAGS_torch_lazy_reuse_ir) { + return LookupNodeFromTrieCache(std::forward(args)...); + } + return nullptr; +} + +// Caching an IR node into TrieCache +static inline void CacheNode(NodePtr node) { + if (FLAGS_torch_lazy_reuse_ir) { + TrieCache::Get()->Insert(std::move(node)); + } +} + +template +NodePtr MakeNode(Args&&... args) { + return std::make_shared(std::forward(args)...); +} + +// op is passed in for a more efficient node casting, see the implementation of +// NodeCast +template +NodePtr ReuseOrMakeNode(Args&&... args) { + NodePtr node = ReuseNode(std::forward(args)...); + if (!node) { + node = MakeNode(std::forward(args)...); + CacheNode(node); + } + return node; +} + +struct IrBuilder { + virtual NodePtr MakeDeviceData( + const std::shared_ptr& data) const = 0; + virtual NodePtr MakeScalar( + const at::Scalar& value, + const at::ScalarType& type) const = 0; + virtual NodePtr MakeExpand( + const Value& input0, + const std::vector& size, + const bool& is_scalar_expand) const = 0; + virtual NodePtr MakeCast( + const Value& input0, + const at::ScalarType& dtype, + const std::optional& stype = std::nullopt) const = 0; + virtual NodePtr MakeTensorList(const OpList& inputs) const = 0; + virtual NodePtr MakeGeneric( + const OpKind& op, + const OpList& operands, + const Shape& shape, + const size_t& num_outputs = 1, + const hash_t& hash_seed = static_cast(0x5a2d296e9)) const = 0; + + // dynamic ir nodes + virtual NodePtr MakeSizeNode(const Value& input, size_t dim) const = 0; + virtual NodePtr MakeSizeAdd(const Value& a, const Value& b) const = 0; + virtual NodePtr MakeSizeMul(const Value& a, const Value& b) const = 0; + virtual NodePtr MakeSizeDiv(const Value& a, const Value& b) const = 0; + + virtual ~IrBuilder() = default; +}; + +static inline NodePtr MakeDeviceData(const std::shared_ptr& data) { + return getIrBuilder()->MakeDeviceData(data); +} +static inline NodePtr MakeScalar( + const at::Scalar& value, + const at::ScalarType& type) { + return getIrBuilder()->MakeScalar(value, type); +} +static inline NodePtr MakeExpand( + const Value& input0, + const std::vector& size, + const bool& is_scalar_expand) { + return getIrBuilder()->MakeExpand(input0, size, is_scalar_expand); +} +static inline NodePtr MakeCast( + const Value& input0, + const at::ScalarType& dtype, + const std::optional& stype = std::nullopt) { + return getIrBuilder()->MakeCast(input0, dtype, stype); +} +static inline NodePtr MakeTensorList(const OpList& inputs) { + return getIrBuilder()->MakeTensorList(inputs); +} +static inline NodePtr MakeGeneric( + const OpKind& op, + const OpList& operands, + const Shape& shape, + const size_t& num_outputs = 1, + const hash_t& hash_seed = static_cast(0x5a2d296e9)) { + return getIrBuilder()->MakeGeneric( + op, operands, shape, num_outputs, hash_seed); +} + +// dynamic ir nodes +static inline NodePtr MakeSizeNode(const Value& input, size_t dim) { + return getIrBuilder()->MakeSizeNode(input, dim); +} +static inline NodePtr MakeSizeAdd(const Value& a, const Value& b) { + return getIrBuilder()->MakeSizeAdd(a, b); +} +static inline NodePtr MakeSizeMul(const Value& a, const Value& b) { + return getIrBuilder()->MakeSizeAdd(a, b); +} +static inline NodePtr MakeSizeDiv(const Value& a, const Value& b) { + return getIrBuilder()->MakeSizeDiv(a, b); +} + +inline Value GetSymIntValue(const c10::SymInt& a) { + if (auto ma = a.maybe_as_int()) { + return Value(MakeScalar(*ma, at::kLong), 0); + } else { + return Value( + dynamic_cast(a.toSymNodeImplUnowned()) + ->node_, + 0); + } +} + +// TODO: this should return Value +inline std::vector GetSymIntArrayRefValue(c10::SymIntArrayRef arr) { + std::vector r; + for (const auto& a : arr) { + r.emplace_back(a.guard_int(__FILE__, __LINE__)); + } + return r; +} + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ir_dump_util.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ir_dump_util.h new file mode 100644 index 0000000000000000000000000000000000000000..7a27bd8dbec82daf15acb6ac695a8aba86dac08d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ir_dump_util.h @@ -0,0 +1,35 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include + +namespace torch::lazy { + +class BackendDevice; + +class TORCH_API DumpUtil { + public: + static std::string ToDot(c10::ArrayRef nodes); + + static std::string PostOrderToDot( + c10::ArrayRef post_order, + c10::ArrayRef roots); + + static std::string ToText(c10::ArrayRef nodes); + + static std::string PostOrderToText( + c10::ArrayRef post_order, + c10::ArrayRef roots); + + static std::string ToBackend( + c10::ArrayRef values, + const BackendDevice& device); +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ir_metadata.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ir_metadata.h new file mode 100644 index 0000000000000000000000000000000000000000..8b913e2342810b322e4470fb01332a98a40d5116 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ir_metadata.h @@ -0,0 +1,56 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include +#include + +namespace torch::lazy { +struct SourceLocation { + std::string file; + std::string function; + int line = -1; +}; + +TORCH_API void EmitShortFrameInfo( + std::ostream& stream, + const std::vector& frames); + +TORCH_API std::ostream& operator<<( + std::ostream& stream, + const std::vector& frames); + +// The base class for user defined metadata which is possible to attach to IR +// nodes. +struct TORCH_API UserMetaData { + virtual ~UserMetaData() = default; +}; + +struct TORCH_API MetaData { + std::string scope; + std::vector frame_info; +}; + +// TODO(whc) is this going to be used outside of in IR decompositions? +// RAII data structure to be used a stack variable to enter a new IR scope. IR +// scope names will appear in the IR and will help identifying the source of the +// single IR nodes. +struct TORCH_API ScopePusher { + explicit ScopePusher(const std::string& name); + ~ScopePusher(); + ScopePusher(ScopePusher&& other) = delete; + ScopePusher(const ScopePusher&) = delete; + ScopePusher& operator=(const ScopePusher&) = delete; + ScopePusher& operator=(ScopePusher&&) = delete; + + static void ResetScopes(); +}; + +TORCH_API MetaData GetMetaDataIfDebugging(); + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ir_util.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ir_util.h new file mode 100644 index 0000000000000000000000000000000000000000..bb2f2420a1028cd6aa1d5b58e456dcf767904e5e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ir_util.h @@ -0,0 +1,50 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include + +namespace torch::lazy { + +class TORCH_API Util { + public: + // Tracks the emission status of the nodes during the post-order generation. + // It helps tracking loops within the computation graphs. + enum EmitStatus { + kNotEmitted, + kEmitting, + kEmitted, + }; + + using EmissionMap = std::unordered_map; + + // Computes the post order from the given node, without using recursion. The + // emission map can be used as saved state, for multiple separate calls to + // this API. The returned post-order can be empty if the node has already been + // emitted inside the emission map. An error is generated if a loop is + // detected. + static std::vector ComputePostOrder( + const Node* node, + EmissionMap* emap); + + static std::vector ComputePostOrder( + c10::ArrayRef nodes, + EmissionMap* emap); + + // Same as above, but computes the post order on the set of nodes specified as + // argument. + static std::vector ComputePostOrder( + c10::ArrayRef nodes); + + // Retrieves the number of nodes within the graph whose sink are passed in the + // nodes argument. + static size_t GetGraphSize(c10::ArrayRef nodes); +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/lazy_graph_executor.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/lazy_graph_executor.h new file mode 100644 index 0000000000000000000000000000000000000000..f7937602a8f3877b698ec06844bb5445d3e580ea --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/lazy_graph_executor.h @@ -0,0 +1,434 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace torch::lazy { + +class TORCH_API LazyGraphExecutor { + public: + struct DeviceDataInfo : public BackendData::Info { + DeviceDataInfo(int64_t tensor_id, bool read_only) + : tensor_id(tensor_id), read_only(read_only) {} + + int64_t tensor_id = 0; + bool read_only = false; + }; + + // Register a lazy graph executor instance that can be retrieved using Get() + static void Register(LazyGraphExecutor* /*executor*/); + static LazyGraphExecutor* Get(); + + virtual ~LazyGraphExecutor() = default; + + // Override these methods to perform custom tensor registration and + // unregistration Note: It is vital that the parent implementations are also + // called in order for the tensors to show up in the live tensor list + virtual void RegisterTensor(std::shared_ptr data); + virtual void UnregisterTensor(LazyTensor::Data* data); + + // Seed for random generator. + // Override to supply your own DeviceContextArena. + virtual Value GetRngSeed(const BackendDevice& device); + virtual uint64_t GetRunningSeed(const BackendDevice& device); + virtual void SetRngSeed(const BackendDevice& device, uint64_t seed); + + void DeviceBarrier(const BackendDevice& device); + + BackendDataPtr GetDeviceData( + const at::Tensor& tensor, + const BackendDevice& device); + + BackendDataPtr GetDeviceData( + const at::Scalar& value, + at::ScalarType scalar_type, + const BackendDevice& device); + + // Retrieves the set of lazy tensors which are currently live in the system, + // for the given device. If device is nullptr, the live tensors for all + // devices will be returned. Returned tensors are sorted by device as primary + // key, and by unique ID as secondary key. + std::vector GetLiveTensors(const BackendDevice* device); + + // Makes sure that any outstanding IR operation accumulated over live tensors, + // gets turned into device data. If wait is true, the sync operation will be + // run synchronously. The devices argument, if not empty, tells the devices + // which should be partecipating into the replicated computation. + virtual void SyncLiveTensorsGraph( + const BackendDevice* device, + c10::ArrayRef devices, + bool wait); + + // Applies all the pending IR operations queued over the input tensors. All + // the tensors must be on the same device. If wait is true, the sync operation + // will be run synchronously. The devices argument, if not empty, tells the + // devices which should be partecipating into the replicated computation. + void SyncTensorsGraph( + std::vector* tensors, + c10::ArrayRef devices, + bool wait, + bool sync_ltc_data); + + // Marks an execution step, which allows the tensor framework to understand + // the computation boundaries. + // Override to supply your own DeviceContextArena. + virtual void MarkStep(const BackendDevice& device); + + // Waits for all the outstanding operations on all the supplied devices. + // If devices is empty, the wait will happen for all local devices. + void WaitDeviceOps(c10::ArrayRef devices); + + // Retrieves the PyTorch CPU tensors behind the lazy tensors IR operations. + // All the tensors must be on the same device. + std::vector GetTensors(std::vector* tensors); + + size_t IncTrimCounter() const; + + // Dumps the backend specific text of the computation accumulated in the graph + // which is attached the tensors. + std::string DumpBackendComputation(const std::vector& tensors); + + Value GetDeviceDataIrValue( + const at::Scalar& value, + c10::ScalarType type, + const BackendDevice& device); + Value GetIrValueForScalar( + const at::Scalar& value, + c10::ScalarType type, + const BackendDevice& device); + Value GetIrValueForScalar( + const at::Scalar& value, + const BackendDevice& device); + + // TODO: even though this API is currently used **only** in codegen to + // generate real scalar IR values vs scalar tensors, we would like to + // use it in other cases where `GetIrValueForXXXScalar` is used, as well + // In order to do that, we need to untangle the cases where we don't need + // `expand` and where we don't expect a scalar tensor + Value GetIrValueForScalarFromCodegen( + const at::Scalar& value, + const BackendDevice& device); + Value GetIrValueForExpandedScalar( + const at::Scalar& value, + const Shape& shape, + const BackendDevice& device); + + struct CachedComputation { + explicit CachedComputation(ComputationPtr computation) + : computation(std::move(computation)) {} + + ComputationPtr computation; + }; + + using ComputationCache = Cache; + + ComputationCache* GetComputationCache(); + + hash_t GetGraphHash(const std::vector& tensors); + + // Clear the computation cache. + void ClearComputationCache(); + // Remove a specific computation cache entry from its hash. + void RemoveFromComputationCache(const hash_t& hash); + + protected: + // TODO(alanwaketan): Revisit if all of them need to be accessible to + // derived classes. + + struct SyncTensorsConfig { + // Whether we want to force data on the target tensors (hence trimming + // the IR graph above them). + bool force_ltc_data = true; + // Whether when setting the data, the other properties of the tensor + // state should be reset. + bool sync_ltc_data = true; + }; + + struct SyncTensorCollection { + SyncTensorCollection() : hash(0) {} + + SyncTensorsConfig config; + std::vector indices; + hash_t hash; + std::vector unlocker; + BackendDevice device; + }; + + struct PostOrderData { + std::vector post_order; + Util::EmissionMap emission_map; + std::vector parameters_data; + std::vector parameter_sequence; + }; + + // Locking: + // We perform two kinds of operations of tensors, synchronous and + // asynchronous. The ApplyPendingGraph() are synchronous, as we need the + // device data result immediately. Before the synchronous operations can + // start, they need to wait that the pending asynchronous operations have + // completed. Synchronous operations do not hold device locks, since they are + // strictly sequential, dictated by the PyTorch execution order. The + // SyncTensorsGraph() is asynchronous, and returns immediately after having + // scheduled the asynchronous operation. While executing, the asynchronous + // operations will hold locks on all the participating devices (in most common + // cases there will be only one device). + // Since asynchronous operations capture device locks, only one asynchronous + // operation can execute at the same time, on a given device. Tensor + // operations which send data to device do not need to hold any device locks + // while doing so. Only operations which _use_ device data (computations, and + // transfer from server) need to wait for asynchronous operations to complete + // (barrier). + + class DeviceLocker { + public: + explicit DeviceLocker(BackendDevice device) : device_(std::move(device)) {} + + const BackendDevice& device() const { + return device_; + } + + void Lock(); + void Unlock(std::exception_ptr exptr); + void Barrier(); + + private: + void CheckResetException(); + + BackendDevice device_; + std::mutex mutex_; + std::condition_variable cv_; + bool locked_ = false; + std::exception_ptr exptr_; + }; + + class DeviceLockerArena { + public: + static DeviceLockerArena* Get(); + + std::shared_ptr GetLocker(const BackendDevice& device); + + void DeviceBarrier(const BackendDevice& device); + + // Use a set to impose an order on the device locking sequence (ABBA + // prevention). + std::vector LockDevices( + const std::set& devices); + + private: + ExceptionCleanup LockDevice(const BackendDevice& device); + + std::mutex mutex_; + std::map> lockers_; + }; + + class DataCacheArena { + public: + static DataCacheArena* Get(); + + BackendDataPtr GetDeviceData( + const at::Tensor& tensor, + const BackendDevice& device); + + BackendDataPtr GetDeviceData( + const at::Scalar& value, + at::ScalarType scalar_type, + const BackendDevice& device); + + private: + struct TensorHasher { + size_t operator()(const at::Tensor& tensor) const; + }; + struct TensorComparer { + bool operator()(const at::Tensor& tensor1, const at::Tensor& tensor2) + const; + }; + + explicit DataCacheArena(size_t max_cache_size); + + using DataCache = + Cache; + + DataCache* GetDataCache(const BackendDevice& device); + + size_t max_cache_size_ = 0; + std::mutex mutex_; + std::map> device_caches_; + }; + + // The DeviceContextArena holds per device live information and statistics, + // among which the lazy tensors which are currently alive in the system. This + // is used to create computation "barriers" in order to flush pending + // operations and ensure the same computations are created during the training + // loops. + // TODO(alanwaketan): Add a registry such that we don't need to make all + // related methods virtual. + class DeviceContextArena { + protected: + struct DeviceContext { + std::mutex lock; + std::map> tensors_data; + uint64_t seed = 101; + uint64_t running_seed = 101; + Value seed_ir_value; + }; + + public: + static DeviceContextArena* Get(); + virtual ~DeviceContextArena() = default; + + void RegisterTensor(std::shared_ptr data); + void UnregisterTensor(LazyTensor::Data* data); + + std::vector GetLiveTensors(const BackendDevice* device); + + // Overriding it allow derived class to use their own IRs for Value. + virtual Value GetRngSeed(const BackendDevice& device); + uint64_t GetRunningSeed(const BackendDevice& device); + void SetRngSeed(const BackendDevice& device, uint64_t seed); + + void MarkStep(const BackendDevice& device); + + std::vector GetActiveDevices(); + + protected: + DeviceContext* GetDeviceContext(const BackendDevice& device); + + void ForAllDeviceContexts( + const std::function& fn, + const BackendDevice* device); + + // Overriding it allow derived class to use their own conversions. + virtual Value IrValueFromScalar( + const at::Scalar& value, + at::ScalarType scalar_type, + const BackendDevice& device); + + private: + std::vector GetAllDeviceContexts(); + + std::mutex lock_; + std::map device_contexts_; + }; + + struct Async { + Async( + SyncTensorCollection* coll, + std::vector parameters_data, + std::vector tensors_data, + ComputationCache::TypePtr cached_computation); + virtual ~Async() = default; + + void Wait(); + + MultiWait mwait; + std::vector indices; + std::vector unlocker; + std::vector parameters_data; + BackendDevice device; + ComputationCache::TypePtr cached_computation; + std::vector tensors_data; + }; + + void ResetTrimCounter() const; + + // Waits for this SyncTensorCollection's device barrier and acquire the lock. + virtual void TensorCollectionBarrier(SyncTensorCollection* coll); + + // One can override to insert your own profiler. + virtual PostOrderData RunPostOrder( + const std::vector& ir_values, + SyncTensorCollection* coll); + + private: + struct CompilationResult { + BackendDevice device; + size_t emitted_nodes = 0; + ComputationPtr computation; + std::vector parameters_data; + }; + + virtual bool ShouldSyncTensor(const LazyTensorPtr& tensor) const; + + SyncTensorCollection CollectSyncTensors( + const std::vector& tensors, + const SyncTensorsConfig& config); + + std::vector CollectRoots( + const std::vector& tensors, + c10::ArrayRef indices); + + std::vector SetTensorData( + std::vector* tensors, + const SyncTensorsConfig& config, + c10::ArrayRef indices, + const std::vector& tensor_data_vec); + + void ExtractIRAndPrepareTensorData( + std::vector* tensors, + const SyncTensorsConfig& config, + c10::ArrayRef indices, + std::vector& ir_values, + std::vector& tensor_data_vec); + + std::shared_ptr TryRunCachedSync( + std::vector* tensors, + SyncTensorCollection* coll, + PostOrderData* po_data, + const std::vector& tensor_data_vec); + + CompilationResult Compile( + const std::vector& tensors, + c10::ArrayRef devices, + const SyncTensorCollection& coll, + PostOrderData* po_data, + const std::vector& ir_values); + + ComputationCache::TypePtr LookupCachedCompile(const hash_t& hash); + + std::shared_ptr SyncTensorsGraphInternal( + std::vector* tensors, + c10::ArrayRef devices, + const SyncTensorsConfig& config); + + // Schedules the execution of a sync tensors operation in background. The + // asynchronous operation will hold the device locks by capturing the ones + // present within the coll structure. + std::shared_ptr ScheduleSyncTensorsGraph( + SyncTensorCollection* coll, + std::vector parameters_data, + std::vector tensors_data, + ComputationCache::TypePtr cached_computation); + + std::shared_ptr ScheduleSyncTensorsGraph( + std::vector* tensors, + SyncTensorCollection* coll, + std::vector parameters_data, + ComputationCache::TypePtr cached_computation, + const std::vector& tensor_data_vec); + + std::vector GetTensorsFused(std::vector* tensors); + + std::vector FetchTensors( + std::vector* tensors, + c10::ArrayRef tensors_data, + const std::vector* indices); + + // Gathers the device data for all the input tensors, after an + // asynchronous operation. + std::vector GatherTensorsData( + const std::vector& tensors, + c10::ArrayRef indices, + c10::ArrayRef tensors_data); +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/metrics.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/metrics.h new file mode 100644 index 0000000000000000000000000000000000000000..a175d9358ce87beb902226c1700403b5c0f70bc5 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/metrics.h @@ -0,0 +1,293 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +/** + * This file is adapted from PyTorch/XLA + * https://github.com/pytorch/xla/blob/e0e5f937a0ba8d904f9608137dc8c51ba439df2d/third_party/xla_client/metrics.h + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace torch::lazy { + +struct TORCH_API Sample { + Sample() = default; + Sample(int64_t timestamp_ns, double value) + : timestamp_ns(timestamp_ns), value(value) {} + + int64_t timestamp_ns = 0; + double value = 0; +}; + +using MetricReprFn = std::function; + +// Class used to collect time-stamped numeric samples. The samples are stored in +// a circular buffer whose size can be configured at constructor time. +class TORCH_API MetricData { + public: + // Creates a new MetricData object with the internal circular buffer storing + // max_samples samples. The repr_fn argument allow to specify a function which + // pretty-prints a sample value. + MetricData(MetricReprFn repr_fn, size_t max_samples); + + // Returns the total values of all the samples being posted to this metric. + double Accumulator() const; + + size_t TotalSamples() const; + + void AddSample(int64_t timestamp_ns, double value); + + // Returns a vector with all the current samples, from the oldest to the + // newer. If accumulator is not nullptr, it will receive the current value of + // the metrics' accumulator (the sum of all posted values). If total_samples + // is not nullptr, it will receive the count of the posted values. + std::vector Samples(double* accumulator, size_t* total_samples) const; + + std::string Repr(double value) const { + return repr_fn_(value); + } + + void Reset(); + + bool IsValid() const { + return TotalSamples() > 0; + } + + private: + mutable std::mutex lock_; + MetricReprFn repr_fn_; + size_t count_ = 0; + std::vector samples_; + double accumulator_ = 0.0; +}; + +// Counters are a very lightweight form of metrics which do not need to track +// sample time. +class TORCH_API CounterData { + public: + CounterData() : value_(0) {} + + void AddValue(int64_t value) { + value_ += value; + } + + int64_t Value() const { + return value_; + } + + void Reset() { + value_ = 0; + } + + bool IsValid() const { + return value_ > 0; + } + + private: + std::atomic value_; +}; + +class TORCH_API MetricsArena { + public: + static MetricsArena* Get(); + + void ResetCounters(); + void ResetMetrics(); + + // Registers a new metric in the global arena. + void RegisterMetric( + const std::string& name, + MetricReprFn repr_fn, + size_t max_samples, + std::shared_ptr* data); + + void RegisterCounter( + const std::string& name, + std::shared_ptr* data); + + void ForEachMetric( + const std::function& metric_func); + + void ForEachCounter( + const std::function& + counter_func); + + std::vector GetMetricNames(); + + MetricData* GetMetric(const std::string& name); + + std::vector GetCounterNames(); + + CounterData* GetCounter(const std::string& name); + + private: + std::mutex lock_; + std::map> metrics_; + std::map> counters_; +}; + +// Emits the value in a to_string() conversion. +TORCH_API std::string MetricFnValue(double value); +// Emits the value in a humanized bytes representation. +TORCH_API std::string MetricFnBytes(double value); +// Emits the value in a humanized time representation. The value is expressed in +// nanoseconds EPOCH time. +TORCH_API std::string MetricFnTime(double value); + +// The typical use of a Metric is one in which it gets created either in a +// global scope context: +// static Metric* metric = new Metric("RpcCount"); +// Or within a function scope: +// void MyFunction(...) { +// static Metric* metric = new Metric("RpcCount"); +// ... +// metric->AddSample(ts_nanos, some_value); +// } +class TORCH_API Metric { + public: + explicit Metric( + std::string name, + MetricReprFn repr_fn = MetricFnValue, + size_t max_samples = 0); + + const std::string& Name() const { + return name_; + } + + double Accumulator() const; + + void AddSample(int64_t timestamp_ns, double value); + + void AddSample(double value); + + std::vector Samples(double* accumulator, size_t* total_samples) const; + + std::string Repr(double value) const; + + private: + MetricData* GetData() const; + + std::string name_; + MetricReprFn repr_fn_; + size_t max_samples_; + mutable std::shared_ptr data_ptr_; + mutable std::atomic data_; +}; + +// A Counter is a lightweight form of metric which tracks an integer value which +// can increase or decrease. +// A typical use is as: +// static Counter* counter = new Counter("MyCounter"); +// ... +// counter->AddValue(+1); +class TORCH_API Counter { + public: + explicit Counter(std::string name); + + void AddValue(int64_t value) { + GetData()->AddValue(value); + } + + int64_t Value() const { + return GetData()->Value(); + } + + private: + CounterData* GetData() const; + + std::string name_; + mutable std::shared_ptr data_ptr_; + mutable std::atomic data_; +}; + +#define TORCH_LAZY_COUNTER(name, value) \ + do { \ + static ::torch::lazy::Counter* __counter = \ + new ::torch::lazy::Counter(name); \ + __counter->AddValue(value); \ + } while (0) + +#define TORCH_LAZY_FN_COUNTER(ns) TORCH_LAZY_COUNTER(c10::str(ns, __func__), 1) + +#define TORCH_LAZY_VALUE_METRIC(name, value) \ + do { \ + static ::torch::lazy::Metric* __metric = \ + new ::torch::lazy::Metric(name, torch::lazy::MetricFnValue); \ + __metric->AddSample(value); \ + } while (0) + +// Creates a report with the current metrics statistics. +TORCH_API std::string CreateMetricReport(); + +// Creates a report with the selected metrics statistics. +TORCH_API std::string CreateMetricReport( + const std::vector& counter_names, + const std::vector& metric_names); + +// Returns the currently registered metric names. Note that the list can grow +// since metrics are usually function initialized (they are static function +// variables). +TORCH_API std::vector GetMetricNames(); + +// Retrieves the metric data of a given metric, or nullptr if such metric does +// not exist. +TORCH_API MetricData* GetMetric(const std::string& name); + +// Returns the currently registered counter names. Note that the list can grow +// since counters are usually function initialized (they are static function +// variables). +TORCH_API std::vector GetCounterNames(); + +// Retrieves the counter data of a given counter, or nullptr if such counter +// does not exist. +TORCH_API CounterData* GetCounter(const std::string& name); + +// Retrieves the current EPOCH time in nanoseconds. +TORCH_API int64_t NowNs(); + +// Scope based utility class TORCH_API to measure the time the code takes within +// a given C++ scope. +class TORCH_API TimedSection { + public: + explicit TimedSection(Metric* metric) : metric_(metric), start_(NowNs()) {} + + TimedSection(TimedSection&& other) = delete; + TimedSection(const TimedSection&) = delete; + TimedSection& operator=(const TimedSection&) = delete; + TimedSection& operator=(TimedSection&&) = delete; + ~TimedSection() { + int64_t now = NowNs(); + metric_->AddSample(now, static_cast(now - start_)); + } + + double Elapsed() const { + return 1e-9 * static_cast(NowNs() - start_); + } + + private: + Metric* metric_; + int64_t start_; +}; + +#define TORCH_LAZY_TIMED(name) \ + static torch::lazy::Metric* timed_metric = \ + new torch::lazy::Metric(name, torch::lazy::MetricFnTime); \ + torch::lazy::TimedSection timed_section(timed_metric) + +#define TORCH_LAZY_FN_COUNTER_TIMED_TRACING(ns) \ + TORCH_LAZY_FN_COUNTER(ns); \ + TORCH_LAZY_TIMED("LazyTracing") + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/multi_wait.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/multi_wait.h new file mode 100644 index 0000000000000000000000000000000000000000..c808d3cc6dc6221ea61fee86f86e114e5fdee08c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/multi_wait.h @@ -0,0 +1,65 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +/** + * This file is adapted from PyTorch/XLA + * https://github.com/pytorch/xla/blob/e0e5f937a0ba8d904f9608137dc8c51ba439df2d/third_party/xla_client/multi_wait.h + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace torch::lazy { + +// Support waiting for a number of tasks to complete. +class TORCH_API MultiWait { + public: + explicit MultiWait(size_t count) : count_(count) {} + + // Signal the completion of a single task. + void Done(); + + // Waits until at least count (passed as constructor value) completions + // happened. + void Wait(); + + // Same as above, but waits up to wait_seconds. + void Wait(double wait_seconds); + + // Resets the threshold counter for the MultiWait object. The completed count + // is also reset to zero. + void Reset(size_t count); + + // Creates a completer functor which signals the mult wait object once func + // has completed. Handles exceptions by signaling the multi wait with the + // proper status value. This API returns a function which captures a MultiWait + // reference, so care must be taken such that the reference remains valid for + // the whole lifetime of the returned function. + std::function Completer(std::function func); + + // Similar as the above API, but with explicit capture of the MultiWait shared + // pointer. + static std::function Completer( + std::shared_ptr mwait, + std::function func); + + private: + void Complete(const std::function& func); + + std::mutex mutex_; + std::condition_variable cv_; + size_t count_ = 0; + size_t completed_count_ = 0; + std::exception_ptr exptr_; +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ops/arithmetic_ir_ops.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ops/arithmetic_ir_ops.h new file mode 100644 index 0000000000000000000000000000000000000000..ff4fe2341d2bd27f1e13d716782ddaced8cb2b79 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ops/arithmetic_ir_ops.h @@ -0,0 +1,17 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::lazy { + +TORCH_API NodePtr operator+(const Value& node1, const Value& node2); +TORCH_API NodePtr operator-(const Value& node1, const Value& node2); +TORCH_API NodePtr operator*(const Value& node1, const Value& node2); +TORCH_API NodePtr operator/(const Value& node1, const Value& node2); + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ops/utils.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ops/utils.h new file mode 100644 index 0000000000000000000000000000000000000000..f900b65fa2280f3cf08fc43942ba815ee3e6c45f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/ops/utils.h @@ -0,0 +1,44 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include + +#include +#include + +namespace torch::lazy { + +TORCH_API bool StrideIsSupported(c10::ArrayRef stride); + +TORCH_API std::vector GetArrayStridePermutation( + c10::ArrayRef stride); + +TORCH_API Shape MakeDiagonalShape( + const Shape& shape, + int64_t offset, + int64_t dim1, + int64_t dim2); + +TORCH_API Shape +MakePermuteShape(const Shape& source_shape, c10::ArrayRef permutation); + +TORCH_API Shape MakeSelectShape( + const Shape& shape, + int64_t dim, + int64_t start, + int64_t end, + int64_t stride); + +TORCH_API int64_t GetStride(int64_t start, int64_t end, int64_t stride); + +TORCH_API std::vector BuildSqueezedDimensions( + c10::ArrayRef dimensions, + int64_t squeeze_dim); + +TORCH_API std::vector BuildUnsqueezedDimensions( + c10::ArrayRef dimensions, + int64_t squeeze_dim); + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/permutation_util.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/permutation_util.h new file mode 100644 index 0000000000000000000000000000000000000000..6a3d5aaa7946fb920ac8d63c3b7524925a4b7b3c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/permutation_util.h @@ -0,0 +1,46 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include + +namespace torch::lazy { + +TORCH_API std::vector InversePermutation( + c10::ArrayRef input_permutation); + +TORCH_API bool IsPermutation(c10::ArrayRef permutation); + +// Gathers the input using the order specified by the permutation. For each i, +// output[i] = dimensions[permutation[i]]. The given permutation must be the +// same size as the input. +template +std::vector PermuteDimensions( + c10::ArrayRef permutation, + const Container& dimensions) { + using T = typename Container::value_type; + TORCH_CHECK( + dimensions.size() == permutation.size(), + "Invalid permutation specified. dimensions.size() != permutation.size() (", + dimensions.size(), + " vs. ", + permutation.size(), + ")"); + TORCH_CHECK( + IsPermutation(permutation), + "Invalid permutation specified. Permutation is not permutation"); + std::vector output(dimensions.size()); + for (const auto i : c10::irange(permutation.size())) { + output[i] = dimensions[permutation[i]]; + } + return output; +} + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/shape.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/shape.h new file mode 100644 index 0000000000000000000000000000000000000000..7d4fdb375aa018a79d2df149297705c7cc4bc3f3 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/shape.h @@ -0,0 +1,83 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include +#include +#include + +TORCH_DECLARE_bool(ltc_enable_symbolic_shapes); + +namespace torch::lazy { + +class TORCH_API Shape { + public: + Shape() = default; + + Shape( + at::ScalarType scalar_type, + c10::ArrayRef sizes, + std::optional> is_symbolic = std::nullopt); + + std::string to_string() const; + + c10::ScalarType scalar_type() const { + return scalar_type_; + } + void set_scalar_type(at::ScalarType value) { + scalar_type_ = value; + } + + int64_t dim() const { + return static_cast(sizes_.size()); + } + c10::ArrayRef sizes() const { + return sizes_; + } + int64_t size(int64_t dim) const { + return sizes_.at(dim); + } + void set_size(int64_t dim, int64_t size) { + sizes_.at(dim) = size; + } + + const std::optional>& is_symbolic() const { + return is_symbolic_; + } + + // Makes a copy with symbolic dims applied + Shape with_symbolic_dims( + std::optional> symbolic_dims) const; + + size_t numel() const; + hash_t hash(bool bakeInSizes) const; + + bool operator==(const Shape& other) const; + + private: + c10::ScalarType scalar_type_{c10::ScalarType::Undefined}; + + // Sizes are the upper bound sizes for a tensor, used by XLA. + std::vector sizes_; + // Stores which dimensions are symbolic + // If nullopt, either it hasn't been initialized or the symbolic + // dimensions are not calculable + std::optional> is_symbolic_ = std::nullopt; +}; + +TORCH_API std::ostream& operator<<(std::ostream& out, const Shape& shape); + +TORCH_API bool symbolicShapeEnabled(); +// Calculate and applies symbolic shapes onto the +// Shape objects passed to result_shapes +TORCH_API void applySymbolicShapesOnLT( + const char* schema_str, + std::vector args, + std::vector& result_shapes); +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/shape_inference.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/shape_inference.h new file mode 100644 index 0000000000000000000000000000000000000000..9d1e9a1cd4c0087e9361f29e5c5319586cb05a3f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/shape_inference.h @@ -0,0 +1,127 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace torch::lazy { +// Turn clang-format off, as we rely on the whole signature being on one line +// for codegen. +// clang-format off +TORCH_API std::vector compute_shape__adaptive_avg_pool2d(const at::Tensor & self, at::IntArrayRef output_size); +TORCH_API std::vector compute_shape__adaptive_avg_pool2d_backward(const at::Tensor & grad_output, const at::Tensor & self); +TORCH_API std::vector compute_shape__adaptive_avg_pool3d(const at::Tensor & self, at::IntArrayRef output_size); +TORCH_API std::vector compute_shape__adaptive_avg_pool3d_backward(const at::Tensor & grad_output, const at::Tensor & self); +TORCH_API std::vector compute_shape_abs(const at::Tensor & self); +TORCH_API std::vector compute_shape_arange_out(const at::Scalar & start, const at::Scalar & end, const at::Scalar & step, at::Tensor & out); +TORCH_API std::vector compute_shape_bernoulli(const at::Tensor & self, ::std::optional generator); +TORCH_API std::vector compute_shape_bernoulli(const at::Tensor & self, double p, ::std::optional generator); +TORCH_API std::vector compute_shape_binary_cross_entropy(const at::Tensor & self, const at::Tensor & target, const ::std::optional & weight, int64_t reduction); +TORCH_API std::vector compute_shape_binary_cross_entropy_backward(const at::Tensor & grad_output, const at::Tensor & self, const at::Tensor & target, const ::std::optional & weight, int64_t reduction); +TORCH_API std::vector compute_shape_cat(at::TensorList tensors, int64_t dim); +TORCH_API std::vector compute_shape_cholesky(const at::Tensor & self, bool upper); +TORCH_API std::vector compute_shape_clamp_min(const at::Tensor & self, const at::Scalar & min); +TORCH_API std::vector compute_shape_clone(const at::Tensor & self, ::std::optional memory_format); +TORCH_API std::vector compute_shape_constant_pad_nd(const at::Tensor & self, at::IntArrayRef pad, const at::Scalar & value); +TORCH_API std::vector compute_shape_convolution(const at::Tensor & input, const at::Tensor & weight, const ::std::optional & bias, at::IntArrayRef stride, at::IntArrayRef padding, at::IntArrayRef dilation, bool transposed, at::IntArrayRef output_padding, int64_t groups); +TORCH_API std::vector compute_shape_convolution_backward(const at::Tensor & grad_output, const at::Tensor & input, const at::Tensor & weight, at::OptionalIntArrayRef bias_sizes, at::IntArrayRef stride, at::IntArrayRef padding, at::IntArrayRef dilation, bool transposed, at::IntArrayRef output_padding, int64_t groups, ::std::array output_mask); +TORCH_API std::vector compute_shape_embedding(const at::Tensor & weight, const at::Tensor & indices, int64_t padding_idx, bool scale_grad_by_freq, bool sparse); +TORCH_API std::vector compute_shape_embedding_dense_backward(const at::Tensor & grad_output, const at::Tensor & indices, int64_t num_weights, int64_t padding_idx, bool scale_grad_by_freq); +TORCH_API std::vector compute_shape_expand(const at::Tensor & self, at::IntArrayRef size, bool implicit); +TORCH_API std::vector compute_shape_expand(const at::Tensor & self, c10::SymIntArrayRef size, bool implicit); +TORCH_API std::vector compute_shape_flip(const at::Tensor & self, at::IntArrayRef dims); +TORCH_API std::vector compute_shape_glu_backward(const at::Tensor & grad_output, const at::Tensor & self, int64_t dim); +TORCH_API std::vector compute_shape_glu_jvp(const at::Tensor & glu, const at::Tensor & x, const at::Tensor & dx, int64_t dim); +TORCH_API std::vector compute_shape_grid_sampler_2d(const at::Tensor & input, const at::Tensor & grid, int64_t interpolation_mode, int64_t padding_mode, bool align_corners); +TORCH_API std::vector compute_shape_grid_sampler_2d_backward(const at::Tensor & grad_output, const at::Tensor & input, const at::Tensor & grid, int64_t interpolation_mode, int64_t padding_mode, bool align_corners, ::std::array output_mask); +TORCH_API std::vector compute_shape_index_select(const at::Tensor & self, int64_t dim, const at::Tensor & index); +TORCH_API std::vector compute_shape_inverse(const at::Tensor & self); +TORCH_API std::vector compute_shape_isnan(const at::Tensor & self); +TORCH_API std::vector compute_shape_log_sigmoid_backward(const at::Tensor & grad_output, const at::Tensor & self, const at::Tensor & buffer); +TORCH_API std::vector compute_shape_log_sigmoid_forward(const at::Tensor & self); +TORCH_API std::vector compute_shape_logdet(const at::Tensor & self); +TORCH_API std::vector compute_shape_logical_and(const at::Tensor & self, const at::Tensor & other); +TORCH_API std::vector compute_shape_logical_not(const at::Tensor & self); +TORCH_API std::vector compute_shape_logical_or(const at::Tensor & self, const at::Tensor & other); +TORCH_API std::vector compute_shape_logical_xor(const at::Tensor & self, const at::Tensor & other); +TORCH_API std::vector compute_shape_masked_fill(const at::Tensor & self, const at::Tensor & mask, const at::Scalar & value); +TORCH_API std::vector compute_shape_masked_fill(const at::Tensor & self, const at::Tensor & mask, const at::Tensor & value); +TORCH_API std::vector compute_shape_max(const at::Tensor & self); +TORCH_API std::vector compute_shape_mean(const at::Tensor & self, ::std::optional dtype); +TORCH_API std::vector compute_shape_min(const at::Tensor & self); +TORCH_API std::vector compute_shape_mv(const at::Tensor & self, const at::Tensor & vec); +TORCH_API std::vector compute_shape_native_batch_norm(const at::Tensor & input, const ::std::optional & weight, const ::std::optional & bias, const ::std::optional & running_mean, const ::std::optional & running_var, bool training, double momentum, double eps); +TORCH_API std::vector compute_shape_native_batch_norm_backward(const at::Tensor & grad_out, const at::Tensor & input, const ::std::optional & weight, const ::std::optional & running_mean, const ::std::optional & running_var, const ::std::optional & save_mean, const ::std::optional & save_invstd, bool train, double eps, ::std::array output_mask); +TORCH_API std::vector compute_shape_native_dropout(const at::Tensor & input, double p, ::std::optional train); +TORCH_API std::vector compute_shape_native_dropout_backward(const at::Tensor & grad_output, const at::Tensor & mask, double scale); +TORCH_API std::vector compute_shape_native_layer_norm(const at::Tensor & input, at::IntArrayRef normalized_shape, const ::std::optional & weight, const ::std::optional & bias, double eps); +TORCH_API std::vector compute_shape_native_layer_norm_backward(const at::Tensor & grad_out, const at::Tensor & input, at::IntArrayRef normalized_shape, const at::Tensor & mean, const at::Tensor & rstd, const ::std::optional & weight, const ::std::optional & bias, ::std::array output_mask); +TORCH_API std::vector compute_shape_new_empty_strided(const at::Tensor & self, at::IntArrayRef size, at::IntArrayRef stride, ::std::optional dtype, ::std::optional layout, ::std::optional device, ::std::optional pin_memory); +TORCH_API std::vector compute_shape_nll_loss2d_backward(const at::Tensor & grad_output, const at::Tensor & self, const at::Tensor & target, const ::std::optional & weight, int64_t reduction, int64_t ignore_index, const at::Tensor & total_weight); +TORCH_API std::vector compute_shape_nll_loss2d_forward(const at::Tensor & self, const at::Tensor & target, const ::std::optional & weight, int64_t reduction, int64_t ignore_index); +TORCH_API std::vector compute_shape_nonzero(const at::Tensor & self); +TORCH_API std::vector compute_shape_normal_functional(const at::Tensor & self, double mean, double std, ::std::optional generator); +TORCH_API std::vector compute_shape_random(const at::Tensor & self, ::std::optional generator); +TORCH_API std::vector compute_shape_random(const at::Tensor & self, int64_t to, ::std::optional generator); +TORCH_API std::vector compute_shape_random(const at::Tensor & self, int64_t from, ::std::optional to, ::std::optional generator); +TORCH_API std::vector compute_shape_relu(const at::Tensor & self); +TORCH_API std::vector compute_shape_repeat(const at::Tensor & self, at::IntArrayRef repeats); +TORCH_API std::vector compute_shape_slogdet(const at::Tensor & self); +TORCH_API std::vector compute_shape_smooth_l1_loss_backward(const at::Tensor & grad_output, const at::Tensor & self, const at::Tensor & target, int64_t reduction, double beta); +TORCH_API std::vector compute_shape_sort(const at::Tensor & self, int64_t dim, bool descending); +TORCH_API std::vector compute_shape_stack(at::TensorList tensors, int64_t dim); +TORCH_API std::vector compute_shape_std(const at::Tensor & self, bool unbiased); +TORCH_API std::vector compute_shape_std(const at::Tensor & self, at::OptionalIntArrayRef dim, bool unbiased, bool keepdim); +TORCH_API std::vector compute_shape_std(const at::Tensor & self, at::OptionalIntArrayRef dim, const ::std::optional & correction, bool keepdim); +TORCH_API std::vector compute_shape_sum(const at::Tensor & self, ::std::optional dtype); +TORCH_API std::vector compute_shape__to_copy(const at::Tensor & self, ::std::optional dtype, ::std::optional layout, ::std::optional device, ::std::optional pin_memory, bool non_blocking, ::std::optional memory_format); +TORCH_API std::vector compute_shape_take(const at::Tensor & self, const at::Tensor & index); +TORCH_API std::vector compute_shape_trace(const at::Tensor & self); +TORCH_API std::vector compute_shape_zero(const at::Tensor & self); +TORCH_API std::vector compute_shape_narrow_copy_symint(const at::Tensor & self, int64_t dim, int64_t start, c10::SymInt length); +TORCH_API std::vector compute_shape_hardswish(const at::Tensor & self); +TORCH_API std::vector compute_shape_hardswish_backward(const at::Tensor & grad_output, const at::Tensor & self); +TORCH_API std::vector compute_shape_selu(const at::Tensor & self); +TORCH_API std::vector compute_shape_uniform(const at::Tensor & self, double from, double to, ::std::optional generator); + +// Non-Native ops +TORCH_API std::vector compute_shape_scalar(const at::Scalar& value, const at::ScalarType& type); +TORCH_API std::vector compute_shape_expand(const Output& input0, const std::vector& size, const bool& is_scalar_expand); +TORCH_API std::vector compute_shape_view(const Output& input0, const std::vector& output_sizes); +TORCH_API std::vector compute_shape_cast(const Output& input0, const at::ScalarType& dtype, const ::std::optional& stype); + +// View Ops +// (Now that functionalization pass is used, we should kill these in a later PR) +TORCH_API std::vector compute_shape_as_strided_view_update(const Output& target, const Output& input, const std::vector& size, const std::vector& stride, const int64_t& storage_offset); +TORCH_API std::vector compute_shape_as_strided(const Output& input, const std::vector& size, const std::vector& stride, const int64_t& storage_offset); +TORCH_API std::vector compute_shape_diagonal_view_update(const Output& target, const Output& input, const int64_t& offset, const int64_t& dim1, const int64_t& dim2); +TORCH_API std::vector compute_shape_diagonal(const Output& input, const int64_t& offset, const int64_t& dim1, const int64_t& dim2); +TORCH_API std::vector compute_shape_narrow_view_update(const Output& input, const Output& source, const std::vector& base_indices); +TORCH_API std::vector compute_shape_narrow(const Output& input, const std::vector& base_indices, const std::vector& sizes); +TORCH_API std::vector compute_shape_permute(const Output& input, const std::vector& dims); +TORCH_API std::vector compute_shape_resize(const Output& input, const std::vector& size); +TORCH_API std::vector compute_shape_select_view_update(const Output& target, const Output& source, const int64_t& dim, const int64_t& start, const int64_t& end, const int64_t& stride); +TORCH_API std::vector compute_shape_select(const Output& input, const int64_t& dim, const int64_t& start, const int64_t& end, const int64_t& stride); +TORCH_API std::vector compute_shape_squeeze(const Output& input, const int& dim); +TORCH_API std::vector compute_shape_unsqueeze(const Output& input, const int& dim); + +TORCH_API std::vector compute_shape_select_scatter(const at::Tensor & self, const at::Tensor & src, int64_t dim, int64_t index); +TORCH_API std::vector compute_shape_diagonal_scatter(const at::Tensor & self, const at::Tensor & src, int64_t offset, int64_t dim1, int64_t dim2); +TORCH_API std::vector compute_shape_slice_scatter_symint(const at::Tensor & self, const at::Tensor & src, int64_t dim, ::std::optional start, ::std::optional end, c10::SymInt step); +TORCH_API std::vector compute_shape_as_strided_scatter_symint(const at::Tensor & self, const at::Tensor & src, c10::SymIntArrayRef size, c10::SymIntArrayRef stride, ::std::optional storage_offset); +// clang-format on +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/tensor.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/tensor.h new file mode 100644 index 0000000000000000000000000000000000000000..16a363079fa8fe784f82d8b0dc391264e6edd76f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/tensor.h @@ -0,0 +1,270 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace torch::lazy { + +class TORCH_API SymNodeImpl : public c10::SymNodeImpl { + public: + SymNodeImpl(NodePtr ptr) : node_(std::move(ptr)) {} + NodePtr node_; +}; + +class LazyTensor; +using LazyTensorPtr = c10::intrusive_ptr; + +class TORCH_API LazyTensor : public c10::intrusive_ptr_target { + public: + // This is the core lazy tensor data structure where all the tensor data is + // held. The lazy tensor is nothing more than a shared pointer to a Data + // object. + struct Data { + Data(BackendDataPtr handle, BackendDevice device) + : handle(std::move(handle)), + device(std::move(device)), + unique_id(GetNextTensorId()) {} + Data(Value ir_value, BackendDevice device) + : ir_value(std::move(ir_value)), + device(std::move(device)), + unique_id(GetNextTensorId()) {} + Data(at::Tensor tensor_data, BackendDevice device) + : tensor_data(std::move(tensor_data)), + device(std::move(device)), + unique_id(GetNextTensorId()) {} + // TODO(alanwaketan): Remove this ctor. This is a + // temporary ctor to ease XLA LTC migration. It depends on + // XLA's Functionalization integration. + Data(BackendDevice device) + : device(std::move(device)), unique_id(GetNextTensorId()) {} + + Data(Data&& other) = delete; + Data(const Data&) = delete; + Data& operator=(const Data&) = delete; + Data& operator=(Data&&) = delete; + virtual ~Data(); + + BackendDataPtr handle; + Value ir_value; + std::optional tensor_data; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const BackendDevice device; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const int64_t unique_id = 0; + size_t generation = 1; + }; + + static LazyTensorPtr Create( + const at::Tensor& tensor, + const BackendDevice& device); + static LazyTensorPtr Create(Value ir_value, const BackendDevice& device); + static LazyTensorPtr Create(const BackendDataPtr& handle); + static LazyTensorPtr Create(std::shared_ptr data); + + // The default ctor previously created a null LazyTensor (one with no 'data' + // obj). Creating a null LazyTensor is no longer possible, since the same can + // be achieved by creating a null LazyTensorPtr and it is way too confusing to + // have to check both lazy_tensor_ptr && *lazy_tensor_ptr, so everywhere that + // used to rely on a LazyTensor obj with a null Data can now rely on a null + // LazyTensorPtr instead. + LazyTensor() = delete; + LazyTensor(const LazyTensor&) = default; + LazyTensor(LazyTensor&&) noexcept = default; + LazyTensor& operator=(const LazyTensor&) = default; + LazyTensor& operator=(LazyTensor&&) noexcept = default; + + ~LazyTensor() override = default; + + size_t generation() const { + return data()->generation; + } + + // Override it to use your own Shape. + virtual int64_t size(int64_t dim) const; + + // Override it to use your own graph executor. + virtual at::Tensor ToTensor(bool detached); + + void ShallowCopyTo(const LazyTensorPtr& dest) const; + + // Assigns the tensor value to the lazy tensor. + void SetTensor(at::Tensor tensor); + + void UpdateFromTensor(const at::Tensor& tensor, bool sync); + void UpdateFromTensorOut(const at::Tensor& tensor); + void UpdateFromTensorOut(const LazyTensorPtr& tensor); + + const std::shared_ptr& data() const; + + // Override it to use your own type conversion. + virtual at::ScalarType dtype() const; + + MaybeRef shape() const; + + const BackendDevice& GetDevice() const; + int64_t GetUniqueId() const; + + // Fetches the data behind the tensor. If the tensor has a graph defining + // its current value, executes the graph and fetches the data result. + BackendDataPtr GetDataHandle(); + + // Fetches the current value of the data, which can be missing (nullptr) + // in case the tensor has a graph defining its current value, + BackendDataPtr CurrentDataHandle() const; + + void SetDataHandle(BackendDataPtr handle); + void SetDataHandle(BackendDataPtr handle, bool sync); + + // Retrieves the current IR Node, or nullptr in case no active IR Node is + // available. + Value CurrentIrValue() const; + + // Retrieves the IR Node representing this LazyTensor. One will be created if + // missing. Note that although this is a const API, it actually changes the + // internal state of the object. + Value GetIrValue() const; + + void SetIrValue(Value ir_value); + void SetInPlaceIrValue(Value ir_value); + + std::optional CurrentTensorData() const; + + std::vector MakeOutputTensors(const NodePtr& node) const; + + LazyTensorPtr CopyTensorToDevice(const BackendDevice& device); + + // Applies the queue of operations in preparation for using the data. + // Override it to use your own graph executor. + virtual void ApplyPendingGraph(); + + // Override it to set extra information. + virtual void AssignIrValue(Value ir_value) const; + + protected: + explicit LazyTensor(std::shared_ptr data); + + void SetTensorData(at::Tensor tensor_data); + + // We build a graph accumulating operations, but at a given point we + // need to force a rendering, otherwise the graph can grow without control. + // Think: + // for i in range(0, 100000): + // a = a + b + void TryLimitGraphSize(); + + // Override it to instantiate your own data. + virtual Value GetIrValueForTensor( + const at::Tensor& tensor, + const BackendDevice& device) const; + + Value CreateTensorNode(const BackendDataPtr& data, bool read_only) const; + + private: + LazyTensor(const at::Tensor& tensor, const BackendDevice& device); + LazyTensor(Value ir_value, const BackendDevice& device); + explicit LazyTensor(const BackendDataPtr& handle); + + static int64_t GetNextTensorId(); + + std::shared_ptr data_; +}; + +// Utils to convert at::Tensor to LazyTensor, and vice versa. + +// Section 0: c10::Tensorlist ==> lazy::TensorList +// note: GetTensorList is not totally parallel to GetLtcTensor; A TensorList +// skips +// the LazyTensor wrappers, assuming that the list of underlying IR nodes +// is actually more useful for downstream computations. TBD. +TORCH_API torch::lazy::Value GetTensorList(at::ITensorListRef tensors); + +// Section 1: at::Tensor => LazyTensor. +// Extracts the LazyTensor out of an at::Tensor. Returns a null LazyTensor +// if the tensor is not a lazy tensor. +TORCH_API LazyTensorPtr TryGetLtcTensor(const at::Tensor& tensor); + +// Extracts the LazyTensor out of an at::Tensor. Throws an exception +// if the tensor is not a lazy tensor. +TORCH_API LazyTensorPtr GetLtcTensor(const at::Tensor& tensor); + +// Same as above, applied to a list of tensors. +TORCH_API std::vector GetLtcTensors( + c10::ArrayRef tensors); + +// If tensor is a lazy tensor type, returns the LazyTensor embedded within it, +// otherwise creates a new lazy tensor type with tensor as data. +TORCH_API LazyTensorPtr GetOrCreateLtcTensor( + const std::optional& tensor, + const BackendDevice& device); + +TORCH_API LazyTensorPtr GetLtcTensorOrCreateForWrappedNumber( + const at::Tensor& tensor, + const BackendDevice& device); + +// Section 2: LazyTensor => at::Tensor. +// Creates an ATen tensor from an LazyTensor. +TORCH_API at::Tensor CreateAtenFromLtcTensor(const LazyTensorPtr& ltc_tensor); +TORCH_API at::Tensor CreateAtenFromLtcTensor(LazyTensor&& ltc_tensor); + +// Note [Lazy Tensor Functionalization] +// The functionalization pass is implemented by wrapping all TensorImpl +// objects in C++ with an extra FunctionalTensorWrapper object, +// that knows how to perform functionalization +// +// Certain functions in the aten API serve as entry/exit points for +// functionalization, where we need to perform the wrapping/unwrapping: +// - aten::to.device +// - aten::empty + +// Given a non-lazy tensor, this function creates a lazy tensor on the specified +// (lazy) device. The functionalize_output determines whether or not we should +// wrap the output in a "functional wrapper". +// +// How do you know whether to pass true/false for functionalize_output? +// +// Case 1: nonlazy -> lazy +// If you're implementing a function that takes in nonlazy tensors and returns +// lazy tensors, then you should think of that function as an "entrypoint" to +// functionalization, and use functionalize_output=true Examples include: +// - factory functions (the LTC kernel for at::empty) +// - CPU -> Lazy device conversions (the LTC kernel for at::to_device) +// +// Case 2: lazy -> lazy +// If you're implementing a function that takes in lazy tensors and returns +// lazy tensors, +// **but** requires creating lazy tensors internally, +// then you can assume that the current function is running inside of some +// outer context where functionalization is already running, that will take +// care of doing the wrapping for you, and use functionalize_output=true +// Examples include: +// - CPU fallback (takes in lazy tensors, converts to cpu, calls kernel, +// converts returns back to lazy tensors). +TORCH_API at::Tensor to_lazy_tensor( + const at::Tensor& self, + const c10::TensorOptions& options, + at::Device device, + bool non_blocking, + bool functionalize_output); + +template +auto TupleAtenFromLtcTensorsImpl( + const std::vector& tensors, + std::index_sequence /*unused*/) { + return std::make_tuple(CreateAtenFromLtcTensor(tensors[Indices])...); +} + +template +auto TupleAtenFromLtcTensors(const std::vector& tensors) { + return TupleAtenFromLtcTensorsImpl(tensors, std::make_index_sequence{}); +} + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/tensor_impl.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/tensor_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..161008918c8ccb22011e0f13ef2cae0e16f5b133 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/tensor_impl.h @@ -0,0 +1,66 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include + +namespace torch::lazy { + +// Tensor implementation class used to be fed to the at::Tensor. +// Its scope is just to handle an LazyTensor. +class TORCH_API LTCTensorImpl final : public c10::TensorImpl { + public: + explicit LTCTensorImpl(const LazyTensorPtr& tensor); + explicit LTCTensorImpl(const LazyTensor& tensor); + explicit LTCTensorImpl(LazyTensor&& tensor); + + LazyTensorPtr tensor() { + return tensor_; + } + + void set_tensor(const LazyTensorPtr& lazy_tensor); + + void force_refresh_sizes() { + generation_ = 0; + } + + c10::intrusive_ptr shallow_copy_and_detach( + const c10::VariableVersion& version_counter, + bool allow_tensor_metadata_change) const override; + + c10::intrusive_ptr shallow_copy_and_detach( + c10::VariableVersion&& version_counter, + bool allow_tensor_metadata_change) const override; + + void shallow_copy_from(const c10::intrusive_ptr& impl) override; + + at::IntArrayRef sizes_custom() const override; + at::IntArrayRef strides_custom() const override; + int64_t numel_custom() const override; + int64_t storage_offset_custom() const override; + int64_t dim_custom() const override; + bool is_strides_like_custom(at::MemoryFormat memory_format) const override; + c10::SymBool sym_is_non_overlapping_and_dense_custom() const override; + + c10::SymBool sym_is_contiguous_custom( + at::MemoryFormat memory_format) const override; + c10::SymIntArrayRef sym_sizes_custom() const override; + c10::SymIntArrayRef sym_strides_custom() const override; + c10::SymInt sym_numel_custom() const override; + + private: + void setup_size_properties(); + + LazyTensorPtr tensor_; + mutable std::optional> sym_sizes_; + size_t generation_{0}; +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/tensor_util.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/tensor_util.h new file mode 100644 index 0000000000000000000000000000000000000000..e47484f16265b9675645aa947f06d5cdf59d54cf --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/tensor_util.h @@ -0,0 +1,81 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include + +#include +#include + +namespace torch::lazy { + +TORCH_API std::vector ComputeArrayStrides( + c10::ArrayRef sizes); + +TORCH_API std::vector DataHandlesToTensors( + c10::ArrayRef data_handles, + at::ScalarType dest_element_type); + +// Uploads an ATEN tensor data to the device and fetches the corresponding +// device data handle. +TORCH_API BackendDataPtr +TensorToDataHandle(const at::Tensor& tensor, const BackendDevice& device); + +// Retrieves the device data handles by parallel uploading data onto the +// corresponding devices. +TORCH_API std::vector CreateTensorsData( + const std::vector& tensors, + const std::vector& devices); + +// Makes a deep copy of an ATEN tensor. +inline at::Tensor CopyTensor(const at::Tensor& ref) { + return ref.to(ref.options(), /*non_blocking=*/false, /*copy=*/true); +} + +// Same as above, with an additional cast. +inline at::Tensor CopyTensor( + const at::Tensor& ref, + at::ScalarType dest_type, + bool copy = true) { + return ref.to(ref.options().dtype(dest_type), /*non_blocking=*/false, copy); +} + +template +T OptionalOr(const std::optional& value, T defval) { + return value ? static_cast(*value) : defval; +} + +// Unwraps tensor to target dtype if it's a wrapped number. +inline at::Tensor UnwrapNumber(const at::Tensor& tensor, at::ScalarType dtype) { + return tensor.unsafeGetTensorImpl()->is_wrapped_number() ? tensor.to(dtype) + : tensor; +} + +template +at::Scalar MakeIntScalar(T value) { + return at::Scalar(static_cast(value)); +} + +// Routing values to device data maximizes the changes for compilation cache +// hits, but it can prevent the compiler to perform optimizations. So tensor +// values which are within a given set, are routed to constant scalars if this +// API returns true. +TORCH_API bool IsSpecialScalar(const at::Scalar& value); + +// Note: returns a reference instead of a fresh tensor to avoid refcount bumps. +inline const at::Tensor& maybe_unwrap_functional(const at::Tensor& tensor) { + if (at::functionalization::impl::isFunctionalTensor(tensor)) { + return at::functionalization::impl::unsafeGetFunctionalWrapper(tensor) + ->value(); + } else { + return tensor; + } +} + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/thread_pool.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/thread_pool.h new file mode 100644 index 0000000000000000000000000000000000000000..ac54c00f81a1bc0b7d47ce5d6402b98f1007f104 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/thread_pool.h @@ -0,0 +1,41 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +/** + * This file is adapted from PyTorch/XLA + * https://github.com/pytorch/xla/blob/e0e5f937a0ba8d904f9608137dc8c51ba439df2d/third_party/xla_client/metrics.h + */ + +#pragma once + +#include +#include +#include + +#include + +namespace torch::lazy { + +// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) +class TORCH_API Completion { + public: + class Data; + + explicit Completion(std::shared_ptr data); + + ~Completion(); + + void Wait(); + + private: + std::shared_ptr data_; +}; + +// Schedules a closure which might wait for IO or other events/conditions. +TORCH_API void ScheduleIoClosure(std::function closure); +TORCH_API Completion +ScheduleIoClosureWithCompletion(std::function closure); + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/trie.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/trie.h new file mode 100644 index 0000000000000000000000000000000000000000..ca5fc4645c2e69fd3894c382a7fcf47dc64ff398 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/trie.h @@ -0,0 +1,82 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include +#include +#include + +namespace torch::lazy { + +struct TORCH_API TrieNode { + static size_t GetNextUniqueId() { + static thread_local size_t id_generator = 0; + return id_generator++; + } + + size_t unique_id; + size_t hit_counter; + NodePtr ir_node; + std::list> successors; + + TrieNode() : unique_id(GetNextUniqueId()), hit_counter(0), ir_node(nullptr) {} + explicit TrieNode(NodePtr node) + : unique_id(GetNextUniqueId()), + hit_counter(0), + ir_node(std::move(node)) {} +}; + +class TORCH_API TrieCache { + public: + static TrieCache* Get(); + + TrieNode* Current() const; + // Take an iterator as the input because we want to move the corresponding + // node in the successor list to achieve a LRU caching effect + void SetCurrent(std::list>::iterator& iter); + // Used in MarkStep to indicate the end of one tracing + void ResetCurrent(); + + // Create a new TrieNode for ir_node and insert into the TrieCache + void Insert(NodePtr ir_node); + + // Clear all TrieCache nodes + // TODO: Because we don't expect user to explicitly call this function via + // a Python API, we may need to introduce a threshold on the size of the cache + // to avoid holding tensors for too long. + void Clear(); + + void DumpToDotFile(const std::string& file_name); + + private: + TrieCache(); + + std::shared_ptr root_; + TrieNode* current_; +}; + +template +NodePtr LookupNodeFromTrieCache(Args&&... args) { + auto& successors = TrieCache::Get()->Current()->successors; + for (auto it = successors.begin(); it != successors.end(); it++) { + NodePtr ir_node = (*it)->ir_node; + const T* concrete_node = NodeCast(ir_node.get()); + if (concrete_node && + concrete_node->CanBeReused(std::forward(args)...)) { + TORCH_LAZY_COUNTER( + "IrNodeReused_" + c10::demangle((typeid(T).name())), 1); + (*it)->hit_counter++; + TrieCache::Get()->SetCurrent(it); + return ir_node; + } + } + return nullptr; +} + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/unique.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/unique.h new file mode 100644 index 0000000000000000000000000000000000000000..718cac504751dc9b08fc72d69fcf91dbfbe77376 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/unique.h @@ -0,0 +1,59 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +/** + * Unique in this file is adapted from PyTorch/XLA + * https://github.com/pytorch/xla/blob/e0e5f937a0ba8d904f9608137dc8c51ba439df2d/third_party/xla_client/unique.h + */ + +#pragma once + +#include + +#include +#include + +namespace torch::lazy { + +// Helper class to allow tracking zero or more things, which should be forcibly +// be one only thing. +template > +class Unique { + public: + std::pair set(const T& value) { + if (value_) { + TORCH_CHECK(C()(*value_, value), "'", *value_, "' vs '", value); + return std::pair(false, *value_); + } + value_ = value; + return std::pair(true, *value_); + } + + operator bool() const { + return value_.has_value(); + } + operator const T&() const { + return *value_; + } + const T& operator*() const { + return *value_; + } + const T* operator->() const { + return value_.operator->(); + } + + std::set AsSet() const { + std::set vset; + if (value_.has_value()) { + vset.insert(*value_); + } + return vset; + } + + private: + std::optional value_; +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/util.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/util.h new file mode 100644 index 0000000000000000000000000000000000000000..4324148de300340fa58151cc73ee6032f1f530ae --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/core/util.h @@ -0,0 +1,130 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +/** + * Most of the utils in this file is adapted from PyTorch/XLA + * https://github.com/pytorch/xla/blob/e0e5f937a0ba8d904f9608137dc8c51ba439df2d/third_party/xla_client/util.h + */ + +#pragma once + +#include +#include +#include + +#include +#include + +namespace torch::lazy { + +// Similar to c10::scope_exit but with a status. +// TODO(alanwaketan): Consolidate it with c10::scope_exit. +template +class Cleanup { + public: + using StatusType = T; + + explicit Cleanup(std::function&& func) + : func_(std::move(func)) {} + Cleanup(Cleanup&& ref) noexcept + : func_(std::move(ref.func_)), status_(std::move(ref.status_)) {} + Cleanup(const Cleanup&) = delete; + + ~Cleanup() { + if (func_ != nullptr) { + func_(std::move(status_)); + } + } + + Cleanup& operator=(const Cleanup&) = delete; + + Cleanup& operator=(Cleanup&& ref) noexcept { + if (this != &ref) { + func_ = std::move(ref.func_); + status_ = std::move(ref.status_); + } + return *this; + } + + void Release() { + func_ = nullptr; + } + + void SetStatus(StatusType&& status) { + status_ = std::move(status); + } + + const StatusType& GetStatus() const { + return status_; + } + + private: + std::function func_; + StatusType status_; +}; + +using ExceptionCleanup = Cleanup; + +// Allows APIs which might return const references and values, to not be forced +// to return values in the signature. +// TODO(alanwaketan): This is clever, but is there really no std or c10 +// supports? Needs more investigations. +template +class MaybeRef { + public: + /* implicit */ MaybeRef(const T& ref) : ref_(ref) {} + /* implicit */ MaybeRef(T&& value) + : storage_(std::move(value)), ref_(*storage_) {} + + const T& Get() const { + return ref_; + } + const T& operator*() const { + return Get(); + } + operator const T&() const { + return Get(); + } + + bool IsStored() const { + return storage_.has_value(); + } + + private: + std::optional storage_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const T& ref_; +}; + +template +std::vector Iota(size_t size, T init = 0, T incr = 1) { + std::vector result(size); + T value = init; + for (size_t i = 0; i < size; ++i, value += incr) { + result[i] = value; + } + return result; +} + +template +std::vector ToVector(const S& input) { + return std::vector(input.begin(), input.end()); +} + +template +std::optional> ToOptionalVector( + c10::OptionalArrayRef arrayRef) { + if (arrayRef) { + return arrayRef->vec(); + } + return std::nullopt; +} + +template +std::underlying_type_t GetEnumValue(T value) { + return static_cast>(value); +} + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/generated/LazyIr.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/generated/LazyIr.h new file mode 100644 index 0000000000000000000000000000000000000000..dfd6a881958c2d7eb0cbbe5006d4302669450d4d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/generated/LazyIr.h @@ -0,0 +1,10312 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +// This file contains autogenerated LazyTensor IR nodes +#include +#include +#include +#include +#include +#include +#include +#include "torch/csrc/lazy/ts_backend/ts_node.h" + +namespace torch { +namespace lazy { +using at::operator<<; + +// kNullValue is used to contribute a static hash value any time +// a node has an Optional input that is nullopt. It is important +// to differentiate between HASH(std::nullopt, something) and HASH(something, std::nullopt), +// and using kNullValue in the hash function in the order of arguments +// serves this purpose. +static const torch::lazy::Value kNullValue = torch::lazy::Value(); + +class AdaptiveAvgPool2d : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::_adaptive_avg_pool2d); + } + + AdaptiveAvgPool2d(const torch::lazy::Value& self, const ::std::vector& output_size, std::vector&& shapes) + : TsNode( + AdaptiveAvgPool2d::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(output_size)), + output_size(output_size) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", output_size=" << output_size; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::vector& output_size) const { + size_t i = 0; + return (operand(i++) == self && + this->output_size == output_size); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("output_size", output_size); + + torch::lazy::TSOpVector _adaptive_avg_pool2d_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(_adaptive_avg_pool2d_out.size(), 1); + + return _adaptive_avg_pool2d_out; + + } + + + ::std::vector output_size; + + +}; + +class AdaptiveAvgPool2dBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::_adaptive_avg_pool2d_backward); + } + + AdaptiveAvgPool2dBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + AdaptiveAvgPool2dBackward::ClassOpKind(), + OpList{grad_output, self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector _adaptive_avg_pool2d_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(_adaptive_avg_pool2d_backward_out.size(), 1); + + return _adaptive_avg_pool2d_backward_out; + + } + + + + + +}; + +class LogSoftmax : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::_log_softmax); + } + + LogSoftmax(const torch::lazy::Value& self, const int64_t& dim, const bool& half_to_float, std::vector&& shapes) + : TsNode( + LogSoftmax::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim, half_to_float)), + dim(dim), + half_to_float(half_to_float) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + ss << ", half_to_float=" << half_to_float; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& dim, const bool& half_to_float) const { + size_t i = 0; + return (operand(i++) == self && + this->dim == dim && + this->half_to_float == half_to_float); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back("half_to_float", half_to_float); + + torch::lazy::TSOpVector _log_softmax_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(_log_softmax_out.size(), 1); + + return _log_softmax_out; + + } + + + int64_t dim; + bool half_to_float; + + +}; + +class LogSoftmaxBackwardData : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::_log_softmax_backward_data); + } + + LogSoftmaxBackwardData(const torch::lazy::Value& grad_output, const torch::lazy::Value& output, const int64_t& dim, const at::ScalarType& input_dtype, std::vector&& shapes) + : TsNode( + LogSoftmaxBackwardData::ClassOpKind(), + OpList{grad_output, output}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim, input_dtype)), + dim(dim), + input_dtype(input_dtype) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + ss << ", input_dtype=" << input_dtype; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& output, const int64_t& dim, const at::ScalarType& input_dtype) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == output && + this->dim == dim && + this->input_dtype == input_dtype); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back("input_dtype", input_dtype); + + torch::lazy::TSOpVector _log_softmax_backward_data_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(_log_softmax_backward_data_out.size(), 1); + + return _log_softmax_backward_data_out; + + } + + + int64_t dim; + at::ScalarType input_dtype; + + +}; + +class ReshapeAliasCopy : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::_reshape_alias_copy); + } + + ReshapeAliasCopy(const torch::lazy::Value& self, const ::std::vector& size, const ::std::vector& stride, std::vector&& shapes) + : TsNode( + ReshapeAliasCopy::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(size, stride)), + size(size), + stride(stride) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", size=" << size; + ss << ", stride=" << stride; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::vector& size, const ::std::vector& stride) const { + size_t i = 0; + return (operand(i++) == self && + this->size == size && + this->stride == stride); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("size", size); + arguments.emplace_back("stride", stride); + + torch::lazy::TSOpVector _reshape_alias_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(_reshape_alias_copy_out.size(), 1); + + return _reshape_alias_copy_out; + + } + + + ::std::vector size; + ::std::vector stride; + + +}; + +class Softmax : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::_softmax); + } + + Softmax(const torch::lazy::Value& self, const int64_t& dim, const bool& half_to_float, std::vector&& shapes) + : TsNode( + Softmax::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim, half_to_float)), + dim(dim), + half_to_float(half_to_float) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + ss << ", half_to_float=" << half_to_float; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& dim, const bool& half_to_float) const { + size_t i = 0; + return (operand(i++) == self && + this->dim == dim && + this->half_to_float == half_to_float); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back("half_to_float", half_to_float); + + torch::lazy::TSOpVector _softmax_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(_softmax_out.size(), 1); + + return _softmax_out; + + } + + + int64_t dim; + bool half_to_float; + + +}; + +class SoftmaxBackwardData : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::_softmax_backward_data); + } + + SoftmaxBackwardData(const torch::lazy::Value& grad_output, const torch::lazy::Value& output, const int64_t& dim, const at::ScalarType& input_dtype, std::vector&& shapes) + : TsNode( + SoftmaxBackwardData::ClassOpKind(), + OpList{grad_output, output}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim, input_dtype)), + dim(dim), + input_dtype(input_dtype) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + ss << ", input_dtype=" << input_dtype; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& output, const int64_t& dim, const at::ScalarType& input_dtype) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == output && + this->dim == dim && + this->input_dtype == input_dtype); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back("input_dtype", input_dtype); + + torch::lazy::TSOpVector _softmax_backward_data_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(_softmax_backward_data_out.size(), 1); + + return _softmax_backward_data_out; + + } + + + int64_t dim; + at::ScalarType input_dtype; + + +}; + +class Abs : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::abs); + } + + Abs(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Abs::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector abs_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(abs_out.size(), 1); + + return abs_out; + + } + + + + + +}; + +class AddTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::add); + } + + AddTensor(const torch::lazy::Value& self, const torch::lazy::Value& other, const torch::lazy::Value& alpha, std::vector&& shapes) + : TsNode( + AddTensor::ClassOpKind(), + OpList{self, other, alpha}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other, const torch::lazy::Value& alpha) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other && + operand(i++) == alpha); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("alpha", loctx->GetOutputOp(operand(i++))); + torch::lazy::TSOpVector add_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(add_out.size(), 1); + + return add_out; + + } + + + + + +}; + +class Addcdiv : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::addcdiv); + } + + Addcdiv(const torch::lazy::Value& self, const torch::lazy::Value& tensor1, const torch::lazy::Value& tensor2, const torch::lazy::Value& value, std::vector&& shapes) + : TsNode( + Addcdiv::ClassOpKind(), + OpList{self, tensor1, tensor2, value}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& tensor1, const torch::lazy::Value& tensor2, const torch::lazy::Value& value) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == tensor1 && + operand(i++) == tensor2 && + operand(i++) == value); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("value", loctx->GetOutputOp(operand(i++))); + torch::lazy::TSOpVector addcdiv_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(addcdiv_out.size(), 1); + + return addcdiv_out; + + } + + + + + +}; + +class Addcmul : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::addcmul); + } + + Addcmul(const torch::lazy::Value& self, const torch::lazy::Value& tensor1, const torch::lazy::Value& tensor2, const torch::lazy::Value& value, std::vector&& shapes) + : TsNode( + Addcmul::ClassOpKind(), + OpList{self, tensor1, tensor2, value}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& tensor1, const torch::lazy::Value& tensor2, const torch::lazy::Value& value) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == tensor1 && + operand(i++) == tensor2 && + operand(i++) == value); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("value", loctx->GetOutputOp(operand(i++))); + torch::lazy::TSOpVector addcmul_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(addcmul_out.size(), 1); + + return addcmul_out; + + } + + + + + +}; + +class Addmm : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::addmm); + } + + Addmm(const torch::lazy::Value& self, const torch::lazy::Value& mat1, const torch::lazy::Value& mat2, const torch::lazy::Value& beta, const torch::lazy::Value& alpha, std::vector&& shapes) + : TsNode( + Addmm::ClassOpKind(), + OpList{self, mat1, mat2, beta, alpha}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& mat1, const torch::lazy::Value& mat2, const torch::lazy::Value& beta, const torch::lazy::Value& alpha) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == mat1 && + operand(i++) == mat2 && + operand(i++) == beta && + operand(i++) == alpha); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(2); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("beta", loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("alpha", loctx->GetOutputOp(operand(i++))); + torch::lazy::TSOpVector addmm_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(addmm_out.size(), 1); + + return addmm_out; + + } + + + + + +}; + +class AliasCopy : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::alias_copy); + } + + AliasCopy(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + AliasCopy::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector alias_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(alias_copy_out.size(), 1); + + return alias_copy_out; + + } + + + + + +}; + +class All : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::all); + } + + All(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + All::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector all_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(all_out.size(), 1); + + return all_out; + + } + + + + + +}; + +class Any : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::any); + } + + Any(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Any::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector any_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(any_out.size(), 1); + + return any_out; + + } + + + + + +}; + +class ArangeStartOut : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::arange); + } + + ArangeStartOut(const torch::lazy::Value& start, const torch::lazy::Value& end, const torch::lazy::Value& step, const torch::lazy::Value& out, std::vector&& shapes) + : TsNode( + ArangeStartOut::ClassOpKind(), + OpList{start, end, step, out}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& start, const torch::lazy::Value& end, const torch::lazy::Value& step, const torch::lazy::Value& out) const { + size_t i = 0; + return (operand(i++) == start && + operand(i++) == end && + operand(i++) == step && + operand(i++) == out); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("out", loctx->GetOutputOp(operand(i++))); + torch::lazy::TSOpVector arange_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(arange_out.size(), 1); + + return arange_out; + + } + + + + + +}; + +class AsStridedCopy : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::as_strided_copy); + } + + AsStridedCopy(const torch::lazy::Value& self, const ::std::vector& size, const ::std::vector& stride, const ::std::optional& storage_offset, std::vector&& shapes) + : TsNode( + AsStridedCopy::ClassOpKind(), + OpList{self, storage_offset.value_or(kNullValue)}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(size, stride)), + size(size), + stride(stride) + { + has_storage_offset = !!storage_offset; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", size=" << size; + ss << ", stride=" << stride; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::vector& size, const ::std::vector& stride, const ::std::optional& storage_offset) const { + size_t i = 0; + return (operand(i++) == self && + nullable_operand(i++) == storage_offset.value_or(kNullValue) && + this->size == size && + this->stride == stride); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("size", size); + arguments.emplace_back("stride", stride); + arguments.emplace_back(has_storage_offset ? loctx->GetOutputOp(operand(i++)) : nullptr); + + torch::lazy::TSOpVector as_strided_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(as_strided_copy_out.size(), 1); + + return as_strided_copy_out; + + } + + + ::std::vector size; + ::std::vector stride; + bool has_storage_offset: 1; + +}; + +class AsStridedScatter : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::as_strided_scatter); + } + + AsStridedScatter(const torch::lazy::Value& self, const torch::lazy::Value& src, const ::std::vector& size, const ::std::vector& stride, const ::std::optional& storage_offset, std::vector&& shapes) + : TsNode( + AsStridedScatter::ClassOpKind(), + OpList{self, src, storage_offset.value_or(kNullValue)}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(size, stride)), + size(size), + stride(stride) + { + has_storage_offset = !!storage_offset; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", size=" << size; + ss << ", stride=" << stride; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& src, const ::std::vector& size, const ::std::vector& stride, const ::std::optional& storage_offset) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == src && + nullable_operand(i++) == storage_offset.value_or(kNullValue) && + this->size == size && + this->stride == stride); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(5); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("size", size); + arguments.emplace_back("stride", stride); + arguments.emplace_back(has_storage_offset ? loctx->GetOutputOp(operand(i++)) : nullptr); + + torch::lazy::TSOpVector as_strided_scatter_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(as_strided_scatter_out.size(), 1); + + return as_strided_scatter_out; + + } + + + ::std::vector size; + ::std::vector stride; + bool has_storage_offset: 1; + +}; + +class AvgPool2d : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::avg_pool2d); + } + + AvgPool2d(const torch::lazy::Value& self, const ::std::vector& kernel_size, const ::std::vector& stride, const ::std::vector& padding, const bool& ceil_mode, const bool& count_include_pad, const ::std::optional& divisor_override, std::vector&& shapes) + : TsNode( + AvgPool2d::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(kernel_size, stride, padding, ceil_mode, count_include_pad, divisor_override)), + kernel_size(kernel_size), + stride(stride), + padding(padding), + ceil_mode(ceil_mode), + count_include_pad(count_include_pad), + divisor_override(divisor_override) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", kernel_size=" << kernel_size; + ss << ", stride=" << stride; + ss << ", padding=" << padding; + ss << ", ceil_mode=" << ceil_mode; + ss << ", count_include_pad=" << count_include_pad; + if (divisor_override.has_value()) { + ss << ", divisor_override=" << divisor_override.value(); + } else { + ss << ", divisor_override=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::vector& kernel_size, const ::std::vector& stride, const ::std::vector& padding, const bool& ceil_mode, const bool& count_include_pad, const ::std::optional& divisor_override) const { + size_t i = 0; + return (operand(i++) == self && + this->kernel_size == kernel_size && + this->stride == stride && + this->padding == padding && + this->ceil_mode == ceil_mode && + this->count_include_pad == count_include_pad && + ((!this->divisor_override&&!divisor_override) || (this->divisor_override&&divisor_override && *(this->divisor_override) == *divisor_override))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(7); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("kernel_size", kernel_size); + arguments.emplace_back("stride", stride); + arguments.emplace_back("padding", padding); + arguments.emplace_back("ceil_mode", ceil_mode); + arguments.emplace_back("count_include_pad", count_include_pad); + arguments.emplace_back("divisor_override", divisor_override); + + torch::lazy::TSOpVector avg_pool2d_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(avg_pool2d_out.size(), 1); + + return avg_pool2d_out; + + } + + + ::std::vector kernel_size; + ::std::vector stride; + ::std::vector padding; + bool ceil_mode; + bool count_include_pad; + ::std::optional divisor_override; + + +}; + +class AvgPool2dBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::avg_pool2d_backward); + } + + AvgPool2dBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const ::std::vector& kernel_size, const ::std::vector& stride, const ::std::vector& padding, const bool& ceil_mode, const bool& count_include_pad, const ::std::optional& divisor_override, std::vector&& shapes) + : TsNode( + AvgPool2dBackward::ClassOpKind(), + OpList{grad_output, self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(kernel_size, stride, padding, ceil_mode, count_include_pad, divisor_override)), + kernel_size(kernel_size), + stride(stride), + padding(padding), + ceil_mode(ceil_mode), + count_include_pad(count_include_pad), + divisor_override(divisor_override) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", kernel_size=" << kernel_size; + ss << ", stride=" << stride; + ss << ", padding=" << padding; + ss << ", ceil_mode=" << ceil_mode; + ss << ", count_include_pad=" << count_include_pad; + if (divisor_override.has_value()) { + ss << ", divisor_override=" << divisor_override.value(); + } else { + ss << ", divisor_override=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const ::std::vector& kernel_size, const ::std::vector& stride, const ::std::vector& padding, const bool& ceil_mode, const bool& count_include_pad, const ::std::optional& divisor_override) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == self && + this->kernel_size == kernel_size && + this->stride == stride && + this->padding == padding && + this->ceil_mode == ceil_mode && + this->count_include_pad == count_include_pad && + ((!this->divisor_override&&!divisor_override) || (this->divisor_override&&divisor_override && *(this->divisor_override) == *divisor_override))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(8); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("kernel_size", kernel_size); + arguments.emplace_back("stride", stride); + arguments.emplace_back("padding", padding); + arguments.emplace_back("ceil_mode", ceil_mode); + arguments.emplace_back("count_include_pad", count_include_pad); + arguments.emplace_back("divisor_override", divisor_override); + + torch::lazy::TSOpVector avg_pool2d_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(avg_pool2d_backward_out.size(), 1); + + return avg_pool2d_backward_out; + + } + + + ::std::vector kernel_size; + ::std::vector stride; + ::std::vector padding; + bool ceil_mode; + bool count_include_pad; + ::std::optional divisor_override; + + +}; + +class Baddbmm : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::baddbmm); + } + + Baddbmm(const torch::lazy::Value& self, const torch::lazy::Value& batch1, const torch::lazy::Value& batch2, const torch::lazy::Value& beta, const torch::lazy::Value& alpha, std::vector&& shapes) + : TsNode( + Baddbmm::ClassOpKind(), + OpList{self, batch1, batch2, beta, alpha}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& batch1, const torch::lazy::Value& batch2, const torch::lazy::Value& beta, const torch::lazy::Value& alpha) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == batch1 && + operand(i++) == batch2 && + operand(i++) == beta && + operand(i++) == alpha); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(2); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("beta", loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("alpha", loctx->GetOutputOp(operand(i++))); + torch::lazy::TSOpVector baddbmm_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(baddbmm_out.size(), 1); + + return baddbmm_out; + + } + + + + + +}; + +class Bernoulli : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::bernoulli); + } + + Bernoulli(const torch::lazy::Value& self, const ::std::optional& generator, std::vector&& shapes) + : TsNode( + Bernoulli::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(generator)), + generator(generator) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + if (generator.has_value()) { + ss << ", generator=" << "torch.Generator()"; + } else { + ss << ", generator=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::optional& generator) const { + size_t i = 0; + return (operand(i++) == self && + ((!this->generator&&!generator) || (this->generator&&generator && *(this->generator) == *generator))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("generator", generator); + torch::lazy::TSOpVector bernoulli_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(bernoulli_out.size(), 1); + + return bernoulli_out; + + } + + + ::std::optional generator; + + +}; + +class BernoulliP : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::bernoulli); + } + + BernoulliP(const torch::lazy::Value& self, const double& p, const ::std::optional& generator, std::vector&& shapes) + : TsNode( + BernoulliP::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(p, generator)), + p(p), + generator(generator) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", p=" << p; + if (generator.has_value()) { + ss << ", generator=" << "torch.Generator()"; + } else { + ss << ", generator=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const double& p, const ::std::optional& generator) const { + size_t i = 0; + return (operand(i++) == self && + this->p == p && + ((!this->generator&&!generator) || (this->generator&&generator && *(this->generator) == *generator))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("p", p); + kwarguments.emplace_back("generator", generator); + torch::lazy::TSOpVector bernoulli_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(bernoulli_out.size(), 1); + + return bernoulli_out; + + } + + + double p; + ::std::optional generator; + + +}; + +class BinaryCrossEntropy : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::binary_cross_entropy); + } + + BinaryCrossEntropy(const torch::lazy::Value& self, const torch::lazy::Value& target, const ::std::optional& weight, const int64_t& reduction, std::vector&& shapes) + : TsNode( + BinaryCrossEntropy::ClassOpKind(), + OpList{self, target, weight.value_or(kNullValue)}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(reduction)), + reduction(reduction) + { + has_weight = !!weight; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", reduction=" << reduction; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& target, const ::std::optional& weight, const int64_t& reduction) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == target && + nullable_operand(i++) == weight.value_or(kNullValue) && + this->reduction == reduction); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(has_weight ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back("reduction", reduction); + + torch::lazy::TSOpVector binary_cross_entropy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(binary_cross_entropy_out.size(), 1); + + return binary_cross_entropy_out; + + } + + + int64_t reduction; + bool has_weight: 1; + +}; + +class BinaryCrossEntropyBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::binary_cross_entropy_backward); + } + + BinaryCrossEntropyBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& target, const ::std::optional& weight, const int64_t& reduction, std::vector&& shapes) + : TsNode( + BinaryCrossEntropyBackward::ClassOpKind(), + OpList{grad_output, self, target, weight.value_or(kNullValue)}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(reduction)), + reduction(reduction) + { + has_weight = !!weight; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", reduction=" << reduction; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& target, const ::std::optional& weight, const int64_t& reduction) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == self && + operand(i++) == target && + nullable_operand(i++) == weight.value_or(kNullValue) && + this->reduction == reduction); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(5); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(has_weight ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back("reduction", reduction); + + torch::lazy::TSOpVector binary_cross_entropy_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(binary_cross_entropy_backward_out.size(), 1); + + return binary_cross_entropy_backward_out; + + } + + + int64_t reduction; + bool has_weight: 1; + +}; + +class BitwiseAndTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::bitwise_and); + } + + BitwiseAndTensor(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + BitwiseAndTensor::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector bitwise_and_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(bitwise_and_out.size(), 1); + + return bitwise_and_out; + + } + + + + + +}; + +class BitwiseOrTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::bitwise_or); + } + + BitwiseOrTensor(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + BitwiseOrTensor::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector bitwise_or_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(bitwise_or_out.size(), 1); + + return bitwise_or_out; + + } + + + + + +}; + +class Bmm : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::bmm); + } + + Bmm(const torch::lazy::Value& self, const torch::lazy::Value& mat2, std::vector&& shapes) + : TsNode( + Bmm::ClassOpKind(), + OpList{self, mat2}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& mat2) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == mat2); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector bmm_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(bmm_out.size(), 1); + + return bmm_out; + + } + + + + + +}; + +class Cat : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::cat); + } + + Cat(const torch::lazy::Value& tensors, const int64_t& dim, std::vector&& shapes) + : TsNode( + Cat::ClassOpKind(), + OpList{tensors}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim)), + dim(dim) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& tensors, const int64_t& dim) const { + size_t i = 0; + return (operand(i++) == tensors && + this->dim == dim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + + torch::lazy::TSOpVector cat_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(cat_out.size(), 1); + + return cat_out; + + } + + + int64_t dim; + + +}; + +class Clamp : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::clamp); + } + + Clamp(const torch::lazy::Value& self, const ::std::optional& min, const ::std::optional& max, std::vector&& shapes) + : TsNode( + Clamp::ClassOpKind(), + OpList{self, min.value_or(kNullValue), max.value_or(kNullValue)}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + has_min = !!min; + has_max = !!max; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::optional& min, const ::std::optional& max) const { + size_t i = 0; + return (operand(i++) == self && + nullable_operand(i++) == min.value_or(kNullValue) && + nullable_operand(i++) == max.value_or(kNullValue)); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(has_min ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back(has_max ? loctx->GetOutputOp(operand(i++)) : nullptr); + + torch::lazy::TSOpVector clamp_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(clamp_out.size(), 1); + + return clamp_out; + + } + + + + bool has_min: 1; + bool has_max: 1; + +}; + +class ClampMin : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::clamp_min); + } + + ClampMin(const torch::lazy::Value& self, const torch::lazy::Value& min, std::vector&& shapes) + : TsNode( + ClampMin::ClassOpKind(), + OpList{self, min}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& min) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == min); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector clamp_min_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(clamp_min_out.size(), 1); + + return clamp_min_out; + + } + + + + + +}; + +class ConstantPadNd : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::constant_pad_nd); + } + + ConstantPadNd(const torch::lazy::Value& self, const ::std::vector& pad, const torch::lazy::Value& value, std::vector&& shapes) + : TsNode( + ConstantPadNd::ClassOpKind(), + OpList{self, value}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(pad)), + pad(pad) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", pad=" << pad; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::vector& pad, const torch::lazy::Value& value) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == value && + this->pad == pad); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("pad", pad); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector constant_pad_nd_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(constant_pad_nd_out.size(), 1); + + return constant_pad_nd_out; + + } + + + ::std::vector pad; + + +}; + +class Convolution : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::convolution); + } + + Convolution(const torch::lazy::Value& input, const torch::lazy::Value& weight, const ::std::optional& bias, const ::std::vector& stride, const ::std::vector& padding, const ::std::vector& dilation, const bool& transposed, const ::std::vector& output_padding, const int64_t& groups, std::vector&& shapes) + : TsNode( + Convolution::ClassOpKind(), + OpList{input, weight, bias.value_or(kNullValue)}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(stride, padding, dilation, transposed, output_padding, groups)), + stride(stride), + padding(padding), + dilation(dilation), + transposed(transposed), + output_padding(output_padding), + groups(groups) + { + has_bias = !!bias; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", stride=" << stride; + ss << ", padding=" << padding; + ss << ", dilation=" << dilation; + ss << ", transposed=" << transposed; + ss << ", output_padding=" << output_padding; + ss << ", groups=" << groups; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& input, const torch::lazy::Value& weight, const ::std::optional& bias, const ::std::vector& stride, const ::std::vector& padding, const ::std::vector& dilation, const bool& transposed, const ::std::vector& output_padding, const int64_t& groups) const { + size_t i = 0; + return (operand(i++) == input && + operand(i++) == weight && + nullable_operand(i++) == bias.value_or(kNullValue) && + this->stride == stride && + this->padding == padding && + this->dilation == dilation && + this->transposed == transposed && + this->output_padding == output_padding && + this->groups == groups); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(9); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(has_bias ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back("stride", stride); + arguments.emplace_back("padding", padding); + arguments.emplace_back("dilation", dilation); + arguments.emplace_back("transposed", transposed); + arguments.emplace_back("output_padding", output_padding); + arguments.emplace_back("groups", groups); + + torch::lazy::TSOpVector convolution_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(convolution_out.size(), 1); + + return convolution_out; + + } + + + ::std::vector stride; + ::std::vector padding; + ::std::vector dilation; + bool transposed; + ::std::vector output_padding; + int64_t groups; + bool has_bias: 1; + +}; + +class ConvolutionBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::convolution_backward); + } + + ConvolutionBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& input, const torch::lazy::Value& weight, const ::std::optional<::std::vector>& bias_sizes, const ::std::vector& stride, const ::std::vector& padding, const ::std::vector& dilation, const bool& transposed, const ::std::vector& output_padding, const int64_t& groups, const ::std::vector& output_mask, std::vector&& shapes) + : TsNode( + ConvolutionBackward::ClassOpKind(), + OpList{grad_output, input, weight}, + std::move(shapes), + /* num_outputs */ 3, + torch::lazy::MHash(bias_sizes, stride, padding, dilation, transposed, output_padding, groups, output_mask)), + bias_sizes(bias_sizes), + stride(stride), + padding(padding), + dilation(dilation), + transposed(transposed), + output_padding(output_padding), + groups(groups), + output_mask(output_mask) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + if (bias_sizes.has_value()) { + ss << ", bias_sizes=" << bias_sizes.value(); + } else { + ss << ", bias_sizes=null"; + } + ss << ", stride=" << stride; + ss << ", padding=" << padding; + ss << ", dilation=" << dilation; + ss << ", transposed=" << transposed; + ss << ", output_padding=" << output_padding; + ss << ", groups=" << groups; + ss << ", output_mask=" << output_mask; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& input, const torch::lazy::Value& weight, const ::std::optional<::std::vector>& bias_sizes, const ::std::vector& stride, const ::std::vector& padding, const ::std::vector& dilation, const bool& transposed, const ::std::vector& output_padding, const int64_t& groups, const ::std::vector& output_mask) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == input && + operand(i++) == weight && + ((!this->bias_sizes&&!bias_sizes) || (this->bias_sizes&&bias_sizes && *(this->bias_sizes) == *bias_sizes)) && + this->stride == stride && + this->padding == padding && + this->dilation == dilation && + this->transposed == transposed && + this->output_padding == output_padding && + this->groups == groups && + this->output_mask == output_mask); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(11); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("bias_sizes", bias_sizes); + arguments.emplace_back("stride", stride); + arguments.emplace_back("padding", padding); + arguments.emplace_back("dilation", dilation); + arguments.emplace_back("transposed", transposed); + arguments.emplace_back("output_padding", output_padding); + arguments.emplace_back("groups", groups); + arguments.emplace_back("output_mask", output_mask); + + torch::lazy::TSOpVector convolution_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(convolution_backward_out.size(), 3); + + return convolution_backward_out; + + } + + + ::std::optional<::std::vector> bias_sizes; + ::std::vector stride; + ::std::vector padding; + ::std::vector dilation; + bool transposed; + ::std::vector output_padding; + int64_t groups; + ::std::vector output_mask; + + +}; + +class Cos : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::cos); + } + + Cos(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Cos::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector cos_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(cos_out.size(), 1); + + return cos_out; + + } + + + + + +}; + +class Cumsum : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::cumsum); + } + + Cumsum(const torch::lazy::Value& self, const int64_t& dim, const ::std::optional& dtype, std::vector&& shapes) + : TsNode( + Cumsum::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim, dtype)), + dim(dim), + dtype(dtype) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + if (dtype.has_value()) { + ss << ", dtype=" << dtype.value(); + } else { + ss << ", dtype=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& dim, const ::std::optional& dtype) const { + size_t i = 0; + return (operand(i++) == self && + this->dim == dim && + ((!this->dtype&&!dtype) || (this->dtype&&dtype && *(this->dtype) == *dtype))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + kwarguments.emplace_back("dtype", dtype); + torch::lazy::TSOpVector cumsum_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(cumsum_out.size(), 1); + + return cumsum_out; + + } + + + int64_t dim; + ::std::optional dtype; + + +}; + +class DetachCopy : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::detach_copy); + } + + DetachCopy(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + DetachCopy::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector detach_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(detach_copy_out.size(), 1); + + return detach_copy_out; + + } + + + + + +}; + +class DiagonalCopy : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::diagonal_copy); + } + + DiagonalCopy(const torch::lazy::Value& self, const int64_t& offset, const int64_t& dim1, const int64_t& dim2, std::vector&& shapes) + : TsNode( + DiagonalCopy::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(offset, dim1, dim2)), + offset(offset), + dim1(dim1), + dim2(dim2) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", offset=" << offset; + ss << ", dim1=" << dim1; + ss << ", dim2=" << dim2; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& offset, const int64_t& dim1, const int64_t& dim2) const { + size_t i = 0; + return (operand(i++) == self && + this->offset == offset && + this->dim1 == dim1 && + this->dim2 == dim2); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("offset", offset); + arguments.emplace_back("dim1", dim1); + arguments.emplace_back("dim2", dim2); + + torch::lazy::TSOpVector diagonal_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(diagonal_copy_out.size(), 1); + + return diagonal_copy_out; + + } + + + int64_t offset; + int64_t dim1; + int64_t dim2; + + +}; + +class DiagonalScatter : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::diagonal_scatter); + } + + DiagonalScatter(const torch::lazy::Value& self, const torch::lazy::Value& src, const int64_t& offset, const int64_t& dim1, const int64_t& dim2, std::vector&& shapes) + : TsNode( + DiagonalScatter::ClassOpKind(), + OpList{self, src}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(offset, dim1, dim2)), + offset(offset), + dim1(dim1), + dim2(dim2) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", offset=" << offset; + ss << ", dim1=" << dim1; + ss << ", dim2=" << dim2; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& src, const int64_t& offset, const int64_t& dim1, const int64_t& dim2) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == src && + this->offset == offset && + this->dim1 == dim1 && + this->dim2 == dim2); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(5); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("offset", offset); + arguments.emplace_back("dim1", dim1); + arguments.emplace_back("dim2", dim2); + + torch::lazy::TSOpVector diagonal_scatter_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(diagonal_scatter_out.size(), 1); + + return diagonal_scatter_out; + + } + + + int64_t offset; + int64_t dim1; + int64_t dim2; + + +}; + +class DivTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::div); + } + + DivTensor(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + DivTensor::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector div_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(div_out.size(), 1); + + return div_out; + + } + + + + + +}; + +class DivTensorMode : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::div); + } + + DivTensorMode(const torch::lazy::Value& self, const torch::lazy::Value& other, const ::std::optional& rounding_mode, std::vector&& shapes) + : TsNode( + DivTensorMode::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(rounding_mode)), + rounding_mode(rounding_mode.has_value() ? ::std::make_optional(std::string(*rounding_mode)) : ::std::nullopt) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + if (rounding_mode.has_value()) { + ss << ", rounding_mode=" << rounding_mode.value(); + } else { + ss << ", rounding_mode=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other, const ::std::optional& rounding_mode) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other && + ((!this->rounding_mode&&!rounding_mode) || (this->rounding_mode&&rounding_mode && *(this->rounding_mode) == *rounding_mode))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("rounding_mode", rounding_mode); + torch::lazy::TSOpVector div_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(div_out.size(), 1); + + return div_out; + + } + + + ::std::optional rounding_mode; + + +}; + +class Elu : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::elu); + } + + Elu(const torch::lazy::Value& self, const torch::lazy::Value& alpha, const torch::lazy::Value& scale, const torch::lazy::Value& input_scale, std::vector&& shapes) + : TsNode( + Elu::ClassOpKind(), + OpList{self, alpha, scale, input_scale}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& alpha, const torch::lazy::Value& scale, const torch::lazy::Value& input_scale) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == alpha && + operand(i++) == scale && + operand(i++) == input_scale); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector elu_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(elu_out.size(), 1); + + return elu_out; + + } + + + + + +}; + +class EluBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::elu_backward); + } + + EluBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& alpha, const torch::lazy::Value& scale, const torch::lazy::Value& input_scale, const bool& is_result, const torch::lazy::Value& self_or_result, std::vector&& shapes) + : TsNode( + EluBackward::ClassOpKind(), + OpList{grad_output, alpha, scale, input_scale, self_or_result}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(is_result)), + is_result(is_result) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", is_result=" << is_result; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& alpha, const torch::lazy::Value& scale, const torch::lazy::Value& input_scale, const bool& is_result, const torch::lazy::Value& self_or_result) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == alpha && + operand(i++) == scale && + operand(i++) == input_scale && + operand(i++) == self_or_result && + this->is_result == is_result); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(6); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("is_result", is_result); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector elu_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(elu_backward_out.size(), 1); + + return elu_backward_out; + + } + + + bool is_result; + + +}; + +class Embedding : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::embedding); + } + + Embedding(const torch::lazy::Value& weight, const torch::lazy::Value& indices, const int64_t& padding_idx, const bool& scale_grad_by_freq, const bool& sparse, std::vector&& shapes) + : TsNode( + Embedding::ClassOpKind(), + OpList{weight, indices}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(padding_idx, scale_grad_by_freq, sparse)), + padding_idx(padding_idx), + scale_grad_by_freq(scale_grad_by_freq), + sparse(sparse) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", padding_idx=" << padding_idx; + ss << ", scale_grad_by_freq=" << scale_grad_by_freq; + ss << ", sparse=" << sparse; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& weight, const torch::lazy::Value& indices, const int64_t& padding_idx, const bool& scale_grad_by_freq, const bool& sparse) const { + size_t i = 0; + return (operand(i++) == weight && + operand(i++) == indices && + this->padding_idx == padding_idx && + this->scale_grad_by_freq == scale_grad_by_freq && + this->sparse == sparse); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(5); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("padding_idx", padding_idx); + arguments.emplace_back("scale_grad_by_freq", scale_grad_by_freq); + arguments.emplace_back("sparse", sparse); + + torch::lazy::TSOpVector embedding_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(embedding_out.size(), 1); + + return embedding_out; + + } + + + int64_t padding_idx; + bool scale_grad_by_freq; + bool sparse; + + +}; + +class EmbeddingDenseBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::embedding_dense_backward); + } + + EmbeddingDenseBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& indices, const int64_t& num_weights, const int64_t& padding_idx, const bool& scale_grad_by_freq, std::vector&& shapes) + : TsNode( + EmbeddingDenseBackward::ClassOpKind(), + OpList{grad_output, indices}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(num_weights, padding_idx, scale_grad_by_freq)), + num_weights(num_weights), + padding_idx(padding_idx), + scale_grad_by_freq(scale_grad_by_freq) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", num_weights=" << num_weights; + ss << ", padding_idx=" << padding_idx; + ss << ", scale_grad_by_freq=" << scale_grad_by_freq; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& indices, const int64_t& num_weights, const int64_t& padding_idx, const bool& scale_grad_by_freq) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == indices && + this->num_weights == num_weights && + this->padding_idx == padding_idx && + this->scale_grad_by_freq == scale_grad_by_freq); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(5); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("num_weights", num_weights); + arguments.emplace_back("padding_idx", padding_idx); + arguments.emplace_back("scale_grad_by_freq", scale_grad_by_freq); + + torch::lazy::TSOpVector embedding_dense_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(embedding_dense_backward_out.size(), 1); + + return embedding_dense_backward_out; + + } + + + int64_t num_weights; + int64_t padding_idx; + bool scale_grad_by_freq; + + +}; + +class EqScalar : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::eq); + } + + EqScalar(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + EqScalar::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector eq_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(eq_out.size(), 1); + + return eq_out; + + } + + + + + +}; + +class EqTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::eq); + } + + EqTensor(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + EqTensor::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector eq_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(eq_out.size(), 1); + + return eq_out; + + } + + + + + +}; + +class Exp : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::exp); + } + + Exp(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Exp::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector exp_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(exp_out.size(), 1); + + return exp_out; + + } + + + + + +}; + +class ExpandCopy : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::expand_copy); + } + + ExpandCopy(const torch::lazy::Value& self, const ::std::vector& size, const bool& implicit, std::vector&& shapes) + : TsNode( + ExpandCopy::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(size, implicit)), + size(size), + implicit(implicit) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", size=" << size; + ss << ", implicit=" << implicit; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::vector& size, const bool& implicit) const { + size_t i = 0; + return (operand(i++) == self && + this->size == size && + this->implicit == implicit); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("size", size); + kwarguments.emplace_back("implicit", implicit); + torch::lazy::TSOpVector expand_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(expand_copy_out.size(), 1); + + return expand_copy_out; + + } + + + ::std::vector size; + bool implicit; + + +}; + +class Flip : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::flip); + } + + Flip(const torch::lazy::Value& self, const ::std::vector& dims, std::vector&& shapes) + : TsNode( + Flip::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dims)), + dims(dims) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dims=" << dims; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::vector& dims) const { + size_t i = 0; + return (operand(i++) == self && + this->dims == dims); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dims", dims); + + torch::lazy::TSOpVector flip_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(flip_out.size(), 1); + + return flip_out; + + } + + + ::std::vector dims; + + +}; + +class Floor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::floor); + } + + Floor(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Floor::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector floor_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(floor_out.size(), 1); + + return floor_out; + + } + + + + + +}; + +class Frac : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::frac); + } + + Frac(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Frac::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector frac_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(frac_out.size(), 1); + + return frac_out; + + } + + + + + +}; + +class Gather : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::gather); + } + + Gather(const torch::lazy::Value& self, const int64_t& dim, const torch::lazy::Value& index, const bool& sparse_grad, std::vector&& shapes) + : TsNode( + Gather::ClassOpKind(), + OpList{self, index}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim, sparse_grad)), + dim(dim), + sparse_grad(sparse_grad) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + ss << ", sparse_grad=" << sparse_grad; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& dim, const torch::lazy::Value& index, const bool& sparse_grad) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == index && + this->dim == dim && + this->sparse_grad == sparse_grad); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("sparse_grad", sparse_grad); + torch::lazy::TSOpVector gather_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(gather_out.size(), 1); + + return gather_out; + + } + + + int64_t dim; + bool sparse_grad; + + +}; + +class GeScalar : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::ge); + } + + GeScalar(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + GeScalar::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector ge_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(ge_out.size(), 1); + + return ge_out; + + } + + + + + +}; + +class GeTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::ge); + } + + GeTensor(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + GeTensor::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector ge_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(ge_out.size(), 1); + + return ge_out; + + } + + + + + +}; + +class Gelu : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::gelu); + } + + Gelu(const torch::lazy::Value& self, const c10::string_view& approximate, std::vector&& shapes) + : TsNode( + Gelu::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(approximate)), + approximate(approximate) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", approximate=" << approximate; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const c10::string_view& approximate) const { + size_t i = 0; + return (operand(i++) == self && + this->approximate == approximate); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("approximate", approximate); + torch::lazy::TSOpVector gelu_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(gelu_out.size(), 1); + + return gelu_out; + + } + + + std::string approximate; + + +}; + +class GeluBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::gelu_backward); + } + + GeluBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const c10::string_view& approximate, std::vector&& shapes) + : TsNode( + GeluBackward::ClassOpKind(), + OpList{grad_output, self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(approximate)), + approximate(approximate) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", approximate=" << approximate; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const c10::string_view& approximate) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == self && + this->approximate == approximate); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("approximate", approximate); + torch::lazy::TSOpVector gelu_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(gelu_backward_out.size(), 1); + + return gelu_backward_out; + + } + + + std::string approximate; + + +}; + +class Glu : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::glu); + } + + Glu(const torch::lazy::Value& self, const int64_t& dim, std::vector&& shapes) + : TsNode( + Glu::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim)), + dim(dim) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& dim) const { + size_t i = 0; + return (operand(i++) == self && + this->dim == dim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + + torch::lazy::TSOpVector glu_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(glu_out.size(), 1); + + return glu_out; + + } + + + int64_t dim; + + +}; + +class GluBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::glu_backward); + } + + GluBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const int64_t& dim, std::vector&& shapes) + : TsNode( + GluBackward::ClassOpKind(), + OpList{grad_output, self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim)), + dim(dim) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const int64_t& dim) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == self && + this->dim == dim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + + torch::lazy::TSOpVector glu_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(glu_backward_out.size(), 1); + + return glu_backward_out; + + } + + + int64_t dim; + + +}; + +class GluJvp : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::glu_jvp); + } + + GluJvp(const torch::lazy::Value& glu, const torch::lazy::Value& x, const torch::lazy::Value& dx, const int64_t& dim, std::vector&& shapes) + : TsNode( + GluJvp::ClassOpKind(), + OpList{glu, x, dx}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim)), + dim(dim) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& glu, const torch::lazy::Value& x, const torch::lazy::Value& dx, const int64_t& dim) const { + size_t i = 0; + return (operand(i++) == glu && + operand(i++) == x && + operand(i++) == dx && + this->dim == dim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + + torch::lazy::TSOpVector glu_jvp_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(glu_jvp_out.size(), 1); + + return glu_jvp_out; + + } + + + int64_t dim; + + +}; + +class GridSampler2d : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::grid_sampler_2d); + } + + GridSampler2d(const torch::lazy::Value& input, const torch::lazy::Value& grid, const int64_t& interpolation_mode, const int64_t& padding_mode, const bool& align_corners, std::vector&& shapes) + : TsNode( + GridSampler2d::ClassOpKind(), + OpList{input, grid}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(interpolation_mode, padding_mode, align_corners)), + interpolation_mode(interpolation_mode), + padding_mode(padding_mode), + align_corners(align_corners) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", interpolation_mode=" << interpolation_mode; + ss << ", padding_mode=" << padding_mode; + ss << ", align_corners=" << align_corners; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& input, const torch::lazy::Value& grid, const int64_t& interpolation_mode, const int64_t& padding_mode, const bool& align_corners) const { + size_t i = 0; + return (operand(i++) == input && + operand(i++) == grid && + this->interpolation_mode == interpolation_mode && + this->padding_mode == padding_mode && + this->align_corners == align_corners); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(5); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("interpolation_mode", interpolation_mode); + arguments.emplace_back("padding_mode", padding_mode); + arguments.emplace_back("align_corners", align_corners); + + torch::lazy::TSOpVector grid_sampler_2d_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(grid_sampler_2d_out.size(), 1); + + return grid_sampler_2d_out; + + } + + + int64_t interpolation_mode; + int64_t padding_mode; + bool align_corners; + + +}; + +class GridSampler2dBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::grid_sampler_2d_backward); + } + + GridSampler2dBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& input, const torch::lazy::Value& grid, const int64_t& interpolation_mode, const int64_t& padding_mode, const bool& align_corners, const ::std::vector& output_mask, std::vector&& shapes) + : TsNode( + GridSampler2dBackward::ClassOpKind(), + OpList{grad_output, input, grid}, + std::move(shapes), + /* num_outputs */ 2, + torch::lazy::MHash(interpolation_mode, padding_mode, align_corners, output_mask)), + interpolation_mode(interpolation_mode), + padding_mode(padding_mode), + align_corners(align_corners), + output_mask(output_mask) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", interpolation_mode=" << interpolation_mode; + ss << ", padding_mode=" << padding_mode; + ss << ", align_corners=" << align_corners; + ss << ", output_mask=" << output_mask; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& input, const torch::lazy::Value& grid, const int64_t& interpolation_mode, const int64_t& padding_mode, const bool& align_corners, const ::std::vector& output_mask) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == input && + operand(i++) == grid && + this->interpolation_mode == interpolation_mode && + this->padding_mode == padding_mode && + this->align_corners == align_corners && + this->output_mask == output_mask); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(7); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("interpolation_mode", interpolation_mode); + arguments.emplace_back("padding_mode", padding_mode); + arguments.emplace_back("align_corners", align_corners); + arguments.emplace_back("output_mask", output_mask); + + torch::lazy::TSOpVector grid_sampler_2d_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(grid_sampler_2d_backward_out.size(), 2); + + return grid_sampler_2d_backward_out; + + } + + + int64_t interpolation_mode; + int64_t padding_mode; + bool align_corners; + ::std::vector output_mask; + + +}; + +class GtScalar : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::gt); + } + + GtScalar(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + GtScalar::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector gt_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(gt_out.size(), 1); + + return gt_out; + + } + + + + + +}; + +class GtTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::gt); + } + + GtTensor(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + GtTensor::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector gt_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(gt_out.size(), 1); + + return gt_out; + + } + + + + + +}; + +class Hardsigmoid : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::hardsigmoid); + } + + Hardsigmoid(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Hardsigmoid::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector hardsigmoid_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(hardsigmoid_out.size(), 1); + + return hardsigmoid_out; + + } + + + + + +}; + +class IndexSelect : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::index_select); + } + + IndexSelect(const torch::lazy::Value& self, const int64_t& dim, const torch::lazy::Value& index, std::vector&& shapes) + : TsNode( + IndexSelect::ClassOpKind(), + OpList{self, index}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim)), + dim(dim) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& dim, const torch::lazy::Value& index) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == index && + this->dim == dim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector index_select_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(index_select_out.size(), 1); + + return index_select_out; + + } + + + int64_t dim; + + +}; + +class LeScalar : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::le); + } + + LeScalar(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + LeScalar::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector le_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(le_out.size(), 1); + + return le_out; + + } + + + + + +}; + +class LeTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::le); + } + + LeTensor(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + LeTensor::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector le_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(le_out.size(), 1); + + return le_out; + + } + + + + + +}; + +class LeakyRelu : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::leaky_relu); + } + + LeakyRelu(const torch::lazy::Value& self, const torch::lazy::Value& negative_slope, std::vector&& shapes) + : TsNode( + LeakyRelu::ClassOpKind(), + OpList{self, negative_slope}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& negative_slope) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == negative_slope); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector leaky_relu_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(leaky_relu_out.size(), 1); + + return leaky_relu_out; + + } + + + + + +}; + +class LeakyReluBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::leaky_relu_backward); + } + + LeakyReluBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& negative_slope, const bool& self_is_result, std::vector&& shapes) + : TsNode( + LeakyReluBackward::ClassOpKind(), + OpList{grad_output, self, negative_slope}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(self_is_result)), + self_is_result(self_is_result) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", self_is_result=" << self_is_result; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& negative_slope, const bool& self_is_result) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == self && + operand(i++) == negative_slope && + this->self_is_result == self_is_result); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("self_is_result", self_is_result); + + torch::lazy::TSOpVector leaky_relu_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(leaky_relu_backward_out.size(), 1); + + return leaky_relu_backward_out; + + } + + + bool self_is_result; + + +}; + +class Log : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::log); + } + + Log(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Log::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector log_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(log_out.size(), 1); + + return log_out; + + } + + + + + +}; + +class Log2 : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::log2); + } + + Log2(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Log2::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector log2_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(log2_out.size(), 1); + + return log2_out; + + } + + + + + +}; + +class LogSigmoidBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::log_sigmoid_backward); + } + + LogSigmoidBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& buffer, std::vector&& shapes) + : TsNode( + LogSigmoidBackward::ClassOpKind(), + OpList{grad_output, self, buffer}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& buffer) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == self && + operand(i++) == buffer); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector log_sigmoid_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(log_sigmoid_backward_out.size(), 1); + + return log_sigmoid_backward_out; + + } + + + + + +}; + +class LogSigmoidForward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::log_sigmoid_forward); + } + + LogSigmoidForward(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + LogSigmoidForward::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 2, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector log_sigmoid_forward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(log_sigmoid_forward_out.size(), 2); + + return log_sigmoid_forward_out; + + } + + + + + +}; + +class Logdet : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::logdet); + } + + Logdet(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Logdet::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector logdet_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(logdet_out.size(), 1); + + return logdet_out; + + } + + + + + +}; + +class LtScalar : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::lt); + } + + LtScalar(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + LtScalar::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector lt_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(lt_out.size(), 1); + + return lt_out; + + } + + + + + +}; + +class LtTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::lt); + } + + LtTensor(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + LtTensor::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector lt_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(lt_out.size(), 1); + + return lt_out; + + } + + + + + +}; + +class MaskedFillScalar : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::masked_fill); + } + + MaskedFillScalar(const torch::lazy::Value& self, const torch::lazy::Value& mask, const torch::lazy::Value& value, std::vector&& shapes) + : TsNode( + MaskedFillScalar::ClassOpKind(), + OpList{self, mask, value}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& mask, const torch::lazy::Value& value) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == mask && + operand(i++) == value); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector masked_fill_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(masked_fill_out.size(), 1); + + return masked_fill_out; + + } + + + + + +}; + +class MaskedFillTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::masked_fill); + } + + MaskedFillTensor(const torch::lazy::Value& self, const torch::lazy::Value& mask, const torch::lazy::Value& value, std::vector&& shapes) + : TsNode( + MaskedFillTensor::ClassOpKind(), + OpList{self, mask, value}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& mask, const torch::lazy::Value& value) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == mask && + operand(i++) == value); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector masked_fill_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(masked_fill_out.size(), 1); + + return masked_fill_out; + + } + + + + + +}; + +class MaxDim : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::max); + } + + MaxDim(const torch::lazy::Value& self, const int64_t& dim, const bool& keepdim, std::vector&& shapes) + : TsNode( + MaxDim::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 2, + torch::lazy::MHash(dim, keepdim)), + dim(dim), + keepdim(keepdim) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + ss << ", keepdim=" << keepdim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& dim, const bool& keepdim) const { + size_t i = 0; + return (operand(i++) == self && + this->dim == dim && + this->keepdim == keepdim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back("keepdim", keepdim); + + torch::lazy::TSOpVector max_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(max_out.size(), 2); + + return max_out; + + } + + + int64_t dim; + bool keepdim; + + +}; + +class Max : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::max); + } + + Max(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Max::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector max_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(max_out.size(), 1); + + return max_out; + + } + + + + + +}; + +class MaxPool2dWithIndices : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::max_pool2d_with_indices); + } + + MaxPool2dWithIndices(const torch::lazy::Value& self, const ::std::vector& kernel_size, const ::std::vector& stride, const ::std::vector& padding, const ::std::vector& dilation, const bool& ceil_mode, std::vector&& shapes) + : TsNode( + MaxPool2dWithIndices::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 2, + torch::lazy::MHash(kernel_size, stride, padding, dilation, ceil_mode)), + kernel_size(kernel_size), + stride(stride), + padding(padding), + dilation(dilation), + ceil_mode(ceil_mode) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", kernel_size=" << kernel_size; + ss << ", stride=" << stride; + ss << ", padding=" << padding; + ss << ", dilation=" << dilation; + ss << ", ceil_mode=" << ceil_mode; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::vector& kernel_size, const ::std::vector& stride, const ::std::vector& padding, const ::std::vector& dilation, const bool& ceil_mode) const { + size_t i = 0; + return (operand(i++) == self && + this->kernel_size == kernel_size && + this->stride == stride && + this->padding == padding && + this->dilation == dilation && + this->ceil_mode == ceil_mode); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(6); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("kernel_size", kernel_size); + arguments.emplace_back("stride", stride); + arguments.emplace_back("padding", padding); + arguments.emplace_back("dilation", dilation); + arguments.emplace_back("ceil_mode", ceil_mode); + + torch::lazy::TSOpVector max_pool2d_with_indices_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(max_pool2d_with_indices_out.size(), 2); + + return max_pool2d_with_indices_out; + + } + + + ::std::vector kernel_size; + ::std::vector stride; + ::std::vector padding; + ::std::vector dilation; + bool ceil_mode; + + +}; + +class MaxPool2dWithIndicesBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::max_pool2d_with_indices_backward); + } + + MaxPool2dWithIndicesBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const ::std::vector& kernel_size, const ::std::vector& stride, const ::std::vector& padding, const ::std::vector& dilation, const bool& ceil_mode, const torch::lazy::Value& indices, std::vector&& shapes) + : TsNode( + MaxPool2dWithIndicesBackward::ClassOpKind(), + OpList{grad_output, self, indices}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(kernel_size, stride, padding, dilation, ceil_mode)), + kernel_size(kernel_size), + stride(stride), + padding(padding), + dilation(dilation), + ceil_mode(ceil_mode) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", kernel_size=" << kernel_size; + ss << ", stride=" << stride; + ss << ", padding=" << padding; + ss << ", dilation=" << dilation; + ss << ", ceil_mode=" << ceil_mode; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const ::std::vector& kernel_size, const ::std::vector& stride, const ::std::vector& padding, const ::std::vector& dilation, const bool& ceil_mode, const torch::lazy::Value& indices) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == self && + operand(i++) == indices && + this->kernel_size == kernel_size && + this->stride == stride && + this->padding == padding && + this->dilation == dilation && + this->ceil_mode == ceil_mode); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(8); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("kernel_size", kernel_size); + arguments.emplace_back("stride", stride); + arguments.emplace_back("padding", padding); + arguments.emplace_back("dilation", dilation); + arguments.emplace_back("ceil_mode", ceil_mode); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector max_pool2d_with_indices_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(max_pool2d_with_indices_backward_out.size(), 1); + + return max_pool2d_with_indices_backward_out; + + } + + + ::std::vector kernel_size; + ::std::vector stride; + ::std::vector padding; + ::std::vector dilation; + bool ceil_mode; + + +}; + +class Maximum : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::maximum); + } + + Maximum(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + Maximum::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector maximum_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(maximum_out.size(), 1); + + return maximum_out; + + } + + + + + +}; + +class Mean : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::mean); + } + + Mean(const torch::lazy::Value& self, const ::std::optional& dtype, std::vector&& shapes) + : TsNode( + Mean::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dtype)), + dtype(dtype) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + if (dtype.has_value()) { + ss << ", dtype=" << dtype.value(); + } else { + ss << ", dtype=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::optional& dtype) const { + size_t i = 0; + return (operand(i++) == self && + ((!this->dtype&&!dtype) || (this->dtype&&dtype && *(this->dtype) == *dtype))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("dtype", dtype); + torch::lazy::TSOpVector mean_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(mean_out.size(), 1); + + return mean_out; + + } + + + ::std::optional dtype; + + +}; + +class MeanDim : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::mean); + } + + MeanDim(const torch::lazy::Value& self, const ::std::optional<::std::vector>& dim, const bool& keepdim, const ::std::optional& dtype, std::vector&& shapes) + : TsNode( + MeanDim::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim, keepdim, dtype)), + dim(dim), + keepdim(keepdim), + dtype(dtype) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + if (dim.has_value()) { + ss << ", dim=" << dim.value(); + } else { + ss << ", dim=null"; + } + ss << ", keepdim=" << keepdim; + if (dtype.has_value()) { + ss << ", dtype=" << dtype.value(); + } else { + ss << ", dtype=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::optional<::std::vector>& dim, const bool& keepdim, const ::std::optional& dtype) const { + size_t i = 0; + return (operand(i++) == self && + ((!this->dim&&!dim) || (this->dim&&dim && *(this->dim) == *dim)) && + this->keepdim == keepdim && + ((!this->dtype&&!dtype) || (this->dtype&&dtype && *(this->dtype) == *dtype))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back("keepdim", keepdim); + kwarguments.emplace_back("dtype", dtype); + torch::lazy::TSOpVector mean_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(mean_out.size(), 1); + + return mean_out; + + } + + + ::std::optional<::std::vector> dim; + bool keepdim; + ::std::optional dtype; + + +}; + +class Min : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::min); + } + + Min(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Min::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector min_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(min_out.size(), 1); + + return min_out; + + } + + + + + +}; + +class Minimum : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::minimum); + } + + Minimum(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + Minimum::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector minimum_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(minimum_out.size(), 1); + + return minimum_out; + + } + + + + + +}; + +class Mm : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::mm); + } + + Mm(const torch::lazy::Value& self, const torch::lazy::Value& mat2, std::vector&& shapes) + : TsNode( + Mm::ClassOpKind(), + OpList{self, mat2}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& mat2) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == mat2); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector mm_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(mm_out.size(), 1); + + return mm_out; + + } + + + + + +}; + +class MulTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::mul); + } + + MulTensor(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + MulTensor::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector mul_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(mul_out.size(), 1); + + return mul_out; + + } + + + + + +}; + +class Mv : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::mv); + } + + Mv(const torch::lazy::Value& self, const torch::lazy::Value& vec, std::vector&& shapes) + : TsNode( + Mv::ClassOpKind(), + OpList{self, vec}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& vec) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == vec); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector mv_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(mv_out.size(), 1); + + return mv_out; + + } + + + + + +}; + +class NativeBatchNorm : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::native_batch_norm); + } + + NativeBatchNorm(const torch::lazy::Value& input, const ::std::optional& weight, const ::std::optional& bias, const ::std::optional& running_mean, const ::std::optional& running_var, const bool& training, const double& momentum, const double& eps, std::vector&& shapes) + : TsNode( + NativeBatchNorm::ClassOpKind(), + OpList{input, weight.value_or(kNullValue), bias.value_or(kNullValue), running_mean.value_or(kNullValue), running_var.value_or(kNullValue)}, + std::move(shapes), + /* num_outputs */ 3, + torch::lazy::MHash(training, momentum, eps)), + training(training), + momentum(momentum), + eps(eps) + { + has_weight = !!weight; + has_bias = !!bias; + has_running_mean = !!running_mean; + has_running_var = !!running_var; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", training=" << training; + ss << ", momentum=" << momentum; + ss << ", eps=" << eps; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& input, const ::std::optional& weight, const ::std::optional& bias, const ::std::optional& running_mean, const ::std::optional& running_var, const bool& training, const double& momentum, const double& eps) const { + size_t i = 0; + return (operand(i++) == input && + nullable_operand(i++) == weight.value_or(kNullValue) && + nullable_operand(i++) == bias.value_or(kNullValue) && + nullable_operand(i++) == running_mean.value_or(kNullValue) && + nullable_operand(i++) == running_var.value_or(kNullValue) && + this->training == training && + this->momentum == momentum && + this->eps == eps); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(8); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(has_weight ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back(has_bias ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back(has_running_mean ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back(has_running_var ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back("training", training); + arguments.emplace_back("momentum", momentum); + arguments.emplace_back("eps", eps); + + torch::lazy::TSOpVector native_batch_norm_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(native_batch_norm_out.size(), 3); + + return native_batch_norm_out; + + } + + + bool training; + double momentum; + double eps; + bool has_weight: 1; + bool has_bias: 1; + bool has_running_mean: 1; + bool has_running_var: 1; + +}; + +class NativeBatchNormBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::native_batch_norm_backward); + } + + NativeBatchNormBackward(const torch::lazy::Value& grad_out, const torch::lazy::Value& input, const ::std::optional& weight, const ::std::optional& running_mean, const ::std::optional& running_var, const ::std::optional& save_mean, const ::std::optional& save_invstd, const bool& train, const double& eps, const ::std::vector& output_mask, std::vector&& shapes) + : TsNode( + NativeBatchNormBackward::ClassOpKind(), + OpList{grad_out, input, weight.value_or(kNullValue), running_mean.value_or(kNullValue), running_var.value_or(kNullValue), save_mean.value_or(kNullValue), save_invstd.value_or(kNullValue)}, + std::move(shapes), + /* num_outputs */ 3, + torch::lazy::MHash(train, eps, output_mask)), + train(train), + eps(eps), + output_mask(output_mask) + { + has_weight = !!weight; + has_running_mean = !!running_mean; + has_running_var = !!running_var; + has_save_mean = !!save_mean; + has_save_invstd = !!save_invstd; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", train=" << train; + ss << ", eps=" << eps; + ss << ", output_mask=" << output_mask; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_out, const torch::lazy::Value& input, const ::std::optional& weight, const ::std::optional& running_mean, const ::std::optional& running_var, const ::std::optional& save_mean, const ::std::optional& save_invstd, const bool& train, const double& eps, const ::std::vector& output_mask) const { + size_t i = 0; + return (operand(i++) == grad_out && + operand(i++) == input && + nullable_operand(i++) == weight.value_or(kNullValue) && + nullable_operand(i++) == running_mean.value_or(kNullValue) && + nullable_operand(i++) == running_var.value_or(kNullValue) && + nullable_operand(i++) == save_mean.value_or(kNullValue) && + nullable_operand(i++) == save_invstd.value_or(kNullValue) && + this->train == train && + this->eps == eps && + this->output_mask == output_mask); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(10); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(has_weight ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back(has_running_mean ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back(has_running_var ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back(has_save_mean ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back(has_save_invstd ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back("train", train); + arguments.emplace_back("eps", eps); + arguments.emplace_back("output_mask", output_mask); + + torch::lazy::TSOpVector native_batch_norm_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(native_batch_norm_backward_out.size(), 3); + + return native_batch_norm_backward_out; + + } + + + bool train; + double eps; + ::std::vector output_mask; + bool has_weight: 1; + bool has_running_mean: 1; + bool has_running_var: 1; + bool has_save_mean: 1; + bool has_save_invstd: 1; + +}; + +class NativeDropout : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::native_dropout); + } + + NativeDropout(const torch::lazy::Value& input, const double& p, const ::std::optional& train, std::vector&& shapes) + : TsNode( + NativeDropout::ClassOpKind(), + OpList{input}, + std::move(shapes), + /* num_outputs */ 2, + torch::lazy::MHash(p, train)), + p(p), + train(train) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", p=" << p; + if (train.has_value()) { + ss << ", train=" << train.value(); + } else { + ss << ", train=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& input, const double& p, const ::std::optional& train) const { + size_t i = 0; + return (operand(i++) == input && + this->p == p && + ((!this->train&&!train) || (this->train&&train && *(this->train) == *train))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("p", p); + arguments.emplace_back("train", train); + + torch::lazy::TSOpVector native_dropout_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(native_dropout_out.size(), 2); + + return native_dropout_out; + + } + + + double p; + ::std::optional train; + + +}; + +class NativeDropoutBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::native_dropout_backward); + } + + NativeDropoutBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& mask, const double& scale, std::vector&& shapes) + : TsNode( + NativeDropoutBackward::ClassOpKind(), + OpList{grad_output, mask}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(scale)), + scale(scale) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", scale=" << scale; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& mask, const double& scale) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == mask && + this->scale == scale); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("scale", scale); + + torch::lazy::TSOpVector native_dropout_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(native_dropout_backward_out.size(), 1); + + return native_dropout_backward_out; + + } + + + double scale; + + +}; + +class NativeLayerNorm : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::native_layer_norm); + } + + NativeLayerNorm(const torch::lazy::Value& input, const ::std::vector& normalized_shape, const ::std::optional& weight, const ::std::optional& bias, const double& eps, std::vector&& shapes) + : TsNode( + NativeLayerNorm::ClassOpKind(), + OpList{input, weight.value_or(kNullValue), bias.value_or(kNullValue)}, + std::move(shapes), + /* num_outputs */ 3, + torch::lazy::MHash(normalized_shape, eps)), + normalized_shape(normalized_shape), + eps(eps) + { + has_weight = !!weight; + has_bias = !!bias; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", normalized_shape=" << normalized_shape; + ss << ", eps=" << eps; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& input, const ::std::vector& normalized_shape, const ::std::optional& weight, const ::std::optional& bias, const double& eps) const { + size_t i = 0; + return (operand(i++) == input && + nullable_operand(i++) == weight.value_or(kNullValue) && + nullable_operand(i++) == bias.value_or(kNullValue) && + this->normalized_shape == normalized_shape && + this->eps == eps); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(5); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("normalized_shape", normalized_shape); + arguments.emplace_back(has_weight ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back(has_bias ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back("eps", eps); + + torch::lazy::TSOpVector native_layer_norm_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(native_layer_norm_out.size(), 3); + + return native_layer_norm_out; + + } + + + ::std::vector normalized_shape; + double eps; + bool has_weight: 1; + bool has_bias: 1; + +}; + +class NativeLayerNormBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::native_layer_norm_backward); + } + + NativeLayerNormBackward(const torch::lazy::Value& grad_out, const torch::lazy::Value& input, const ::std::vector& normalized_shape, const torch::lazy::Value& mean, const torch::lazy::Value& rstd, const ::std::optional& weight, const ::std::optional& bias, const ::std::vector& output_mask, std::vector&& shapes) + : TsNode( + NativeLayerNormBackward::ClassOpKind(), + OpList{grad_out, input, mean, rstd, weight.value_or(kNullValue), bias.value_or(kNullValue)}, + std::move(shapes), + /* num_outputs */ 3, + torch::lazy::MHash(normalized_shape, output_mask)), + normalized_shape(normalized_shape), + output_mask(output_mask) + { + has_weight = !!weight; + has_bias = !!bias; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", normalized_shape=" << normalized_shape; + ss << ", output_mask=" << output_mask; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_out, const torch::lazy::Value& input, const ::std::vector& normalized_shape, const torch::lazy::Value& mean, const torch::lazy::Value& rstd, const ::std::optional& weight, const ::std::optional& bias, const ::std::vector& output_mask) const { + size_t i = 0; + return (operand(i++) == grad_out && + operand(i++) == input && + operand(i++) == mean && + operand(i++) == rstd && + nullable_operand(i++) == weight.value_or(kNullValue) && + nullable_operand(i++) == bias.value_or(kNullValue) && + this->normalized_shape == normalized_shape && + this->output_mask == output_mask); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(8); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("normalized_shape", normalized_shape); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(has_weight ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back(has_bias ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back("output_mask", output_mask); + + torch::lazy::TSOpVector native_layer_norm_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(native_layer_norm_backward_out.size(), 3); + + return native_layer_norm_backward_out; + + } + + + ::std::vector normalized_shape; + ::std::vector output_mask; + bool has_weight: 1; + bool has_bias: 1; + +}; + +class NeScalar : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::ne); + } + + NeScalar(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + NeScalar::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector ne_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(ne_out.size(), 1); + + return ne_out; + + } + + + + + +}; + +class NeTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::ne); + } + + NeTensor(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + NeTensor::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector ne_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(ne_out.size(), 1); + + return ne_out; + + } + + + + + +}; + +class Neg : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::neg); + } + + Neg(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Neg::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector neg_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(neg_out.size(), 1); + + return neg_out; + + } + + + + + +}; + +class NllLoss2dBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::nll_loss2d_backward); + } + + NllLoss2dBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& target, const ::std::optional& weight, const int64_t& reduction, const int64_t& ignore_index, const torch::lazy::Value& total_weight, std::vector&& shapes) + : TsNode( + NllLoss2dBackward::ClassOpKind(), + OpList{grad_output, self, target, weight.value_or(kNullValue), total_weight}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(reduction, ignore_index)), + reduction(reduction), + ignore_index(ignore_index) + { + has_weight = !!weight; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", reduction=" << reduction; + ss << ", ignore_index=" << ignore_index; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& target, const ::std::optional& weight, const int64_t& reduction, const int64_t& ignore_index, const torch::lazy::Value& total_weight) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == self && + operand(i++) == target && + nullable_operand(i++) == weight.value_or(kNullValue) && + operand(i++) == total_weight && + this->reduction == reduction && + this->ignore_index == ignore_index); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(7); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(has_weight ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back("reduction", reduction); + arguments.emplace_back("ignore_index", ignore_index); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector nll_loss2d_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(nll_loss2d_backward_out.size(), 1); + + return nll_loss2d_backward_out; + + } + + + int64_t reduction; + int64_t ignore_index; + bool has_weight: 1; + +}; + +class NllLoss2dForward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::nll_loss2d_forward); + } + + NllLoss2dForward(const torch::lazy::Value& self, const torch::lazy::Value& target, const ::std::optional& weight, const int64_t& reduction, const int64_t& ignore_index, std::vector&& shapes) + : TsNode( + NllLoss2dForward::ClassOpKind(), + OpList{self, target, weight.value_or(kNullValue)}, + std::move(shapes), + /* num_outputs */ 2, + torch::lazy::MHash(reduction, ignore_index)), + reduction(reduction), + ignore_index(ignore_index) + { + has_weight = !!weight; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", reduction=" << reduction; + ss << ", ignore_index=" << ignore_index; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& target, const ::std::optional& weight, const int64_t& reduction, const int64_t& ignore_index) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == target && + nullable_operand(i++) == weight.value_or(kNullValue) && + this->reduction == reduction && + this->ignore_index == ignore_index); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(5); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(has_weight ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back("reduction", reduction); + arguments.emplace_back("ignore_index", ignore_index); + + torch::lazy::TSOpVector nll_loss2d_forward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(nll_loss2d_forward_out.size(), 2); + + return nll_loss2d_forward_out; + + } + + + int64_t reduction; + int64_t ignore_index; + bool has_weight: 1; + +}; + +class NllLossBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::nll_loss_backward); + } + + NllLossBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& target, const ::std::optional& weight, const int64_t& reduction, const int64_t& ignore_index, const torch::lazy::Value& total_weight, std::vector&& shapes) + : TsNode( + NllLossBackward::ClassOpKind(), + OpList{grad_output, self, target, weight.value_or(kNullValue), total_weight}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(reduction, ignore_index)), + reduction(reduction), + ignore_index(ignore_index) + { + has_weight = !!weight; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", reduction=" << reduction; + ss << ", ignore_index=" << ignore_index; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& target, const ::std::optional& weight, const int64_t& reduction, const int64_t& ignore_index, const torch::lazy::Value& total_weight) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == self && + operand(i++) == target && + nullable_operand(i++) == weight.value_or(kNullValue) && + operand(i++) == total_weight && + this->reduction == reduction && + this->ignore_index == ignore_index); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(7); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(has_weight ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back("reduction", reduction); + arguments.emplace_back("ignore_index", ignore_index); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector nll_loss_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(nll_loss_backward_out.size(), 1); + + return nll_loss_backward_out; + + } + + + int64_t reduction; + int64_t ignore_index; + bool has_weight: 1; + +}; + +class NllLossForward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::nll_loss_forward); + } + + NllLossForward(const torch::lazy::Value& self, const torch::lazy::Value& target, const ::std::optional& weight, const int64_t& reduction, const int64_t& ignore_index, std::vector&& shapes) + : TsNode( + NllLossForward::ClassOpKind(), + OpList{self, target, weight.value_or(kNullValue)}, + std::move(shapes), + /* num_outputs */ 2, + torch::lazy::MHash(reduction, ignore_index)), + reduction(reduction), + ignore_index(ignore_index) + { + has_weight = !!weight; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", reduction=" << reduction; + ss << ", ignore_index=" << ignore_index; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& target, const ::std::optional& weight, const int64_t& reduction, const int64_t& ignore_index) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == target && + nullable_operand(i++) == weight.value_or(kNullValue) && + this->reduction == reduction && + this->ignore_index == ignore_index); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(5); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(has_weight ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back("reduction", reduction); + arguments.emplace_back("ignore_index", ignore_index); + + torch::lazy::TSOpVector nll_loss_forward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(nll_loss_forward_out.size(), 2); + + return nll_loss_forward_out; + + } + + + int64_t reduction; + int64_t ignore_index; + bool has_weight: 1; + +}; + +class Nonzero : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::nonzero); + } + + Nonzero(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Nonzero::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector nonzero_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(nonzero_out.size(), 1); + + return nonzero_out; + + } + + + + + +}; + +class NormScalaroptDim : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::norm); + } + + NormScalaroptDim(const torch::lazy::Value& self, const ::std::optional& p, const ::std::vector& dim, const bool& keepdim, std::vector&& shapes) + : TsNode( + NormScalaroptDim::ClassOpKind(), + OpList{self, p.value_or(kNullValue)}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim, keepdim)), + dim(dim), + keepdim(keepdim) + { + has_p = !!p; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + ss << ", keepdim=" << keepdim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::optional& p, const ::std::vector& dim, const bool& keepdim) const { + size_t i = 0; + return (operand(i++) == self && + nullable_operand(i++) == p.value_or(kNullValue) && + this->dim == dim && + this->keepdim == keepdim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(has_p ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back("dim", dim); + arguments.emplace_back("keepdim", keepdim); + + torch::lazy::TSOpVector norm_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(norm_out.size(), 1); + + return norm_out; + + } + + + ::std::vector dim; + bool keepdim; + bool has_p: 1; + +}; + +class NormalFunctional : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::normal_functional); + } + + NormalFunctional(const torch::lazy::Value& self, const double& mean, const double& std, const ::std::optional& generator, std::vector&& shapes) + : TsNode( + NormalFunctional::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(mean, std, generator)), + mean(mean), + std(std), + generator(generator) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", mean=" << mean; + ss << ", std=" << std; + if (generator.has_value()) { + ss << ", generator=" << "torch.Generator()"; + } else { + ss << ", generator=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const double& mean, const double& std, const ::std::optional& generator) const { + size_t i = 0; + return (operand(i++) == self && + this->mean == mean && + this->std == std && + ((!this->generator&&!generator) || (this->generator&&generator && *(this->generator) == *generator))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("mean", mean); + arguments.emplace_back("std", std); + kwarguments.emplace_back("generator", generator); + torch::lazy::TSOpVector normal_functional_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(normal_functional_out.size(), 1); + + return normal_functional_out; + + } + + + double mean; + double std; + ::std::optional generator; + + +}; + +class PermuteCopy : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::permute_copy); + } + + PermuteCopy(const torch::lazy::Value& self, const ::std::vector& dims, std::vector&& shapes) + : TsNode( + PermuteCopy::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dims)), + dims(dims) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dims=" << dims; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::vector& dims) const { + size_t i = 0; + return (operand(i++) == self && + this->dims == dims); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dims", dims); + + torch::lazy::TSOpVector permute_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(permute_copy_out.size(), 1); + + return permute_copy_out; + + } + + + ::std::vector dims; + + +}; + +class PowTensorTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::pow); + } + + PowTensorTensor(const torch::lazy::Value& self, const torch::lazy::Value& exponent, std::vector&& shapes) + : TsNode( + PowTensorTensor::ClassOpKind(), + OpList{self, exponent}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& exponent) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == exponent); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector pow_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(pow_out.size(), 1); + + return pow_out; + + } + + + + + +}; + +class PowTensorScalar : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::pow); + } + + PowTensorScalar(const torch::lazy::Value& self, const torch::lazy::Value& exponent, std::vector&& shapes) + : TsNode( + PowTensorScalar::ClassOpKind(), + OpList{self, exponent}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& exponent) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == exponent); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector pow_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(pow_out.size(), 1); + + return pow_out; + + } + + + + + +}; + +class RandomFrom : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::random); + } + + RandomFrom(const torch::lazy::Value& self, const int64_t& from, const ::std::optional& to, const ::std::optional& generator, std::vector&& shapes) + : TsNode( + RandomFrom::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(from, to, generator)), + from(from), + to(to), + generator(generator) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", from=" << from; + if (to.has_value()) { + ss << ", to=" << to.value(); + } else { + ss << ", to=null"; + } + if (generator.has_value()) { + ss << ", generator=" << "torch.Generator()"; + } else { + ss << ", generator=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& from, const ::std::optional& to, const ::std::optional& generator) const { + size_t i = 0; + return (operand(i++) == self && + this->from == from && + ((!this->to&&!to) || (this->to&&to && *(this->to) == *to)) && + ((!this->generator&&!generator) || (this->generator&&generator && *(this->generator) == *generator))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("from", from); + arguments.emplace_back("to", to); + kwarguments.emplace_back("generator", generator); + torch::lazy::TSOpVector random_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(random_out.size(), 1); + + return random_out; + + } + + + int64_t from; + ::std::optional to; + ::std::optional generator; + + +}; + +class RandomTo : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::random); + } + + RandomTo(const torch::lazy::Value& self, const int64_t& to, const ::std::optional& generator, std::vector&& shapes) + : TsNode( + RandomTo::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(to, generator)), + to(to), + generator(generator) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", to=" << to; + if (generator.has_value()) { + ss << ", generator=" << "torch.Generator()"; + } else { + ss << ", generator=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& to, const ::std::optional& generator) const { + size_t i = 0; + return (operand(i++) == self && + this->to == to && + ((!this->generator&&!generator) || (this->generator&&generator && *(this->generator) == *generator))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("to", to); + kwarguments.emplace_back("generator", generator); + torch::lazy::TSOpVector random_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(random_out.size(), 1); + + return random_out; + + } + + + int64_t to; + ::std::optional generator; + + +}; + +class Random : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::random); + } + + Random(const torch::lazy::Value& self, const ::std::optional& generator, std::vector&& shapes) + : TsNode( + Random::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(generator)), + generator(generator) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + if (generator.has_value()) { + ss << ", generator=" << "torch.Generator()"; + } else { + ss << ", generator=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::optional& generator) const { + size_t i = 0; + return (operand(i++) == self && + ((!this->generator&&!generator) || (this->generator&&generator && *(this->generator) == *generator))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("generator", generator); + torch::lazy::TSOpVector random_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(random_out.size(), 1); + + return random_out; + + } + + + ::std::optional generator; + + +}; + +class Reciprocal : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::reciprocal); + } + + Reciprocal(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Reciprocal::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector reciprocal_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(reciprocal_out.size(), 1); + + return reciprocal_out; + + } + + + + + +}; + +class Relu : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::relu); + } + + Relu(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Relu::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector relu_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(relu_out.size(), 1); + + return relu_out; + + } + + + + + +}; + +class RemainderTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::remainder); + } + + RemainderTensor(const torch::lazy::Value& self, const torch::lazy::Value& other, std::vector&& shapes) + : TsNode( + RemainderTensor::ClassOpKind(), + OpList{self, other}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector remainder_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(remainder_out.size(), 1); + + return remainder_out; + + } + + + + + +}; + +class Repeat : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::repeat); + } + + Repeat(const torch::lazy::Value& self, const ::std::vector& repeats, std::vector&& shapes) + : TsNode( + Repeat::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(repeats)), + repeats(repeats) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", repeats=" << repeats; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::vector& repeats) const { + size_t i = 0; + return (operand(i++) == self && + this->repeats == repeats); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("repeats", repeats); + + torch::lazy::TSOpVector repeat_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(repeat_out.size(), 1); + + return repeat_out; + + } + + + ::std::vector repeats; + + +}; + +class Rsqrt : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::rsqrt); + } + + Rsqrt(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Rsqrt::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector rsqrt_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(rsqrt_out.size(), 1); + + return rsqrt_out; + + } + + + + + +}; + +class ScatterAdd : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::scatter_add); + } + + ScatterAdd(const torch::lazy::Value& self, const int64_t& dim, const torch::lazy::Value& index, const torch::lazy::Value& src, std::vector&& shapes) + : TsNode( + ScatterAdd::ClassOpKind(), + OpList{self, index, src}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim)), + dim(dim) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& dim, const torch::lazy::Value& index, const torch::lazy::Value& src) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == index && + operand(i++) == src && + this->dim == dim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector scatter_add_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(scatter_add_out.size(), 1); + + return scatter_add_out; + + } + + + int64_t dim; + + +}; + +class SelectCopyInt : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::select_copy); + } + + SelectCopyInt(const torch::lazy::Value& self, const int64_t& dim, const int64_t& index, std::vector&& shapes) + : TsNode( + SelectCopyInt::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim, index)), + dim(dim), + index(index) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + ss << ", index=" << index; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& dim, const int64_t& index) const { + size_t i = 0; + return (operand(i++) == self && + this->dim == dim && + this->index == index); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back("index", index); + + torch::lazy::TSOpVector select_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(select_copy_out.size(), 1); + + return select_copy_out; + + } + + + int64_t dim; + int64_t index; + + +}; + +class SelectScatter : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::select_scatter); + } + + SelectScatter(const torch::lazy::Value& self, const torch::lazy::Value& src, const int64_t& dim, const int64_t& index, std::vector&& shapes) + : TsNode( + SelectScatter::ClassOpKind(), + OpList{self, src}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim, index)), + dim(dim), + index(index) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + ss << ", index=" << index; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& src, const int64_t& dim, const int64_t& index) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == src && + this->dim == dim && + this->index == index); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back("index", index); + + torch::lazy::TSOpVector select_scatter_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(select_scatter_out.size(), 1); + + return select_scatter_out; + + } + + + int64_t dim; + int64_t index; + + +}; + +class Selu : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::selu); + } + + Selu(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Selu::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector selu_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(selu_out.size(), 1); + + return selu_out; + + } + + + + + +}; + +class Sgn : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::sgn); + } + + Sgn(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Sgn::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector sgn_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(sgn_out.size(), 1); + + return sgn_out; + + } + + + + + +}; + +class Sigmoid : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::sigmoid); + } + + Sigmoid(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Sigmoid::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector sigmoid_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(sigmoid_out.size(), 1); + + return sigmoid_out; + + } + + + + + +}; + +class SigmoidBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(c10::Symbol::fromQualString("aten::sigmoid_backward")); + } + + SigmoidBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& output, std::vector&& shapes) + : TsNode( + SigmoidBackward::ClassOpKind(), + OpList{grad_output, output}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& output) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == output); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector sigmoid_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(sigmoid_backward_out.size(), 1); + + return sigmoid_backward_out; + + } + + + + + +}; + +class Silu : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::silu); + } + + Silu(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Silu::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector silu_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(silu_out.size(), 1); + + return silu_out; + + } + + + + + +}; + +class SliceCopyTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::slice_copy); + } + + SliceCopyTensor(const torch::lazy::Value& self, const int64_t& dim, const ::std::optional& start, const ::std::optional& end, const torch::lazy::Value& step, std::vector&& shapes) + : TsNode( + SliceCopyTensor::ClassOpKind(), + OpList{self, start.value_or(kNullValue), end.value_or(kNullValue), step}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim)), + dim(dim) + { + has_start = !!start; + has_end = !!end; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& dim, const ::std::optional& start, const ::std::optional& end, const torch::lazy::Value& step) const { + size_t i = 0; + return (operand(i++) == self && + nullable_operand(i++) == start.value_or(kNullValue) && + nullable_operand(i++) == end.value_or(kNullValue) && + operand(i++) == step && + this->dim == dim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(5); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back(has_start ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back(has_end ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector slice_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(slice_copy_out.size(), 1); + + return slice_copy_out; + + } + + + int64_t dim; + bool has_start: 1; + bool has_end: 1; + +}; + +class SliceScatter : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::slice_scatter); + } + + SliceScatter(const torch::lazy::Value& self, const torch::lazy::Value& src, const int64_t& dim, const ::std::optional& start, const ::std::optional& end, const torch::lazy::Value& step, std::vector&& shapes) + : TsNode( + SliceScatter::ClassOpKind(), + OpList{self, src, start.value_or(kNullValue), end.value_or(kNullValue), step}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim)), + dim(dim) + { + has_start = !!start; + has_end = !!end; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& src, const int64_t& dim, const ::std::optional& start, const ::std::optional& end, const torch::lazy::Value& step) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == src && + nullable_operand(i++) == start.value_or(kNullValue) && + nullable_operand(i++) == end.value_or(kNullValue) && + operand(i++) == step && + this->dim == dim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(6); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back(has_start ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back(has_end ? loctx->GetOutputOp(operand(i++)) : nullptr); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector slice_scatter_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(slice_scatter_out.size(), 1); + + return slice_scatter_out; + + } + + + int64_t dim; + bool has_start: 1; + bool has_end: 1; + +}; + +class SmoothL1Loss : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::smooth_l1_loss); + } + + SmoothL1Loss(const torch::lazy::Value& self, const torch::lazy::Value& target, const int64_t& reduction, const double& beta, std::vector&& shapes) + : TsNode( + SmoothL1Loss::ClassOpKind(), + OpList{self, target}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(reduction, beta)), + reduction(reduction), + beta(beta) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", reduction=" << reduction; + ss << ", beta=" << beta; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& target, const int64_t& reduction, const double& beta) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == target && + this->reduction == reduction && + this->beta == beta); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("reduction", reduction); + arguments.emplace_back("beta", beta); + + torch::lazy::TSOpVector smooth_l1_loss_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(smooth_l1_loss_out.size(), 1); + + return smooth_l1_loss_out; + + } + + + int64_t reduction; + double beta; + + +}; + +class SmoothL1LossBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::smooth_l1_loss_backward); + } + + SmoothL1LossBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& target, const int64_t& reduction, const double& beta, std::vector&& shapes) + : TsNode( + SmoothL1LossBackward::ClassOpKind(), + OpList{grad_output, self, target}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(reduction, beta)), + reduction(reduction), + beta(beta) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", reduction=" << reduction; + ss << ", beta=" << beta; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& target, const int64_t& reduction, const double& beta) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == self && + operand(i++) == target && + this->reduction == reduction && + this->beta == beta); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(5); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("reduction", reduction); + arguments.emplace_back("beta", beta); + + torch::lazy::TSOpVector smooth_l1_loss_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(smooth_l1_loss_backward_out.size(), 1); + + return smooth_l1_loss_backward_out; + + } + + + int64_t reduction; + double beta; + + +}; + +class Softplus : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::softplus); + } + + Softplus(const torch::lazy::Value& self, const torch::lazy::Value& beta, const torch::lazy::Value& threshold, std::vector&& shapes) + : TsNode( + Softplus::ClassOpKind(), + OpList{self, beta, threshold}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& beta, const torch::lazy::Value& threshold) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == beta && + operand(i++) == threshold); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector softplus_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(softplus_out.size(), 1); + + return softplus_out; + + } + + + + + +}; + +class SoftplusBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::softplus_backward); + } + + SoftplusBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& beta, const torch::lazy::Value& threshold, std::vector&& shapes) + : TsNode( + SoftplusBackward::ClassOpKind(), + OpList{grad_output, self, beta, threshold}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& beta, const torch::lazy::Value& threshold) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == self && + operand(i++) == beta && + operand(i++) == threshold); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector softplus_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(softplus_backward_out.size(), 1); + + return softplus_backward_out; + + } + + + + + +}; + +class Sort : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::sort); + } + + Sort(const torch::lazy::Value& self, const int64_t& dim, const bool& descending, std::vector&& shapes) + : TsNode( + Sort::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 2, + torch::lazy::MHash(dim, descending)), + dim(dim), + descending(descending) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + ss << ", descending=" << descending; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& dim, const bool& descending) const { + size_t i = 0; + return (operand(i++) == self && + this->dim == dim && + this->descending == descending); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back("descending", descending); + + torch::lazy::TSOpVector sort_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(sort_out.size(), 2); + + return sort_out; + + } + + + int64_t dim; + bool descending; + + +}; + +class Sqrt : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::sqrt); + } + + Sqrt(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Sqrt::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector sqrt_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(sqrt_out.size(), 1); + + return sqrt_out; + + } + + + + + +}; + +class SqueezeCopy : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::squeeze_copy); + } + + SqueezeCopy(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + SqueezeCopy::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector squeeze_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(squeeze_copy_out.size(), 1); + + return squeeze_copy_out; + + } + + + + + +}; + +class SqueezeCopyDim : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::squeeze_copy); + } + + SqueezeCopyDim(const torch::lazy::Value& self, const int64_t& dim, std::vector&& shapes) + : TsNode( + SqueezeCopyDim::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim)), + dim(dim) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& dim) const { + size_t i = 0; + return (operand(i++) == self && + this->dim == dim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + + torch::lazy::TSOpVector squeeze_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(squeeze_copy_out.size(), 1); + + return squeeze_copy_out; + + } + + + int64_t dim; + + +}; + +class SqueezeCopyDims : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::squeeze_copy); + } + + SqueezeCopyDims(const torch::lazy::Value& self, const ::std::vector& dim, std::vector&& shapes) + : TsNode( + SqueezeCopyDims::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim)), + dim(dim) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::vector& dim) const { + size_t i = 0; + return (operand(i++) == self && + this->dim == dim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + + torch::lazy::TSOpVector squeeze_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(squeeze_copy_out.size(), 1); + + return squeeze_copy_out; + + } + + + ::std::vector dim; + + +}; + +class Stack : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::stack); + } + + Stack(const torch::lazy::Value& tensors, const int64_t& dim, std::vector&& shapes) + : TsNode( + Stack::ClassOpKind(), + OpList{tensors}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim)), + dim(dim) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& tensors, const int64_t& dim) const { + size_t i = 0; + return (operand(i++) == tensors && + this->dim == dim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + + torch::lazy::TSOpVector stack_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(stack_out.size(), 1); + + return stack_out; + + } + + + int64_t dim; + + +}; + +class Std : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::std); + } + + Std(const torch::lazy::Value& self, const bool& unbiased, std::vector&& shapes) + : TsNode( + Std::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(unbiased)), + unbiased(unbiased) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", unbiased=" << unbiased; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const bool& unbiased) const { + size_t i = 0; + return (operand(i++) == self && + this->unbiased == unbiased); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("unbiased", unbiased); + + torch::lazy::TSOpVector std_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(std_out.size(), 1); + + return std_out; + + } + + + bool unbiased; + + +}; + +class StdDim : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::std); + } + + StdDim(const torch::lazy::Value& self, const ::std::optional<::std::vector>& dim, const bool& unbiased, const bool& keepdim, std::vector&& shapes) + : TsNode( + StdDim::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim, unbiased, keepdim)), + dim(dim), + unbiased(unbiased), + keepdim(keepdim) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + if (dim.has_value()) { + ss << ", dim=" << dim.value(); + } else { + ss << ", dim=null"; + } + ss << ", unbiased=" << unbiased; + ss << ", keepdim=" << keepdim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::optional<::std::vector>& dim, const bool& unbiased, const bool& keepdim) const { + size_t i = 0; + return (operand(i++) == self && + ((!this->dim&&!dim) || (this->dim&&dim && *(this->dim) == *dim)) && + this->unbiased == unbiased && + this->keepdim == keepdim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back("unbiased", unbiased); + arguments.emplace_back("keepdim", keepdim); + + torch::lazy::TSOpVector std_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(std_out.size(), 1); + + return std_out; + + } + + + ::std::optional<::std::vector> dim; + bool unbiased; + bool keepdim; + + +}; + +class StdCorrection : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::std); + } + + StdCorrection(const torch::lazy::Value& self, const ::std::optional<::std::vector>& dim, const ::std::optional& correction, const bool& keepdim, std::vector&& shapes) + : TsNode( + StdCorrection::ClassOpKind(), + OpList{self, correction.value_or(kNullValue)}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim, keepdim)), + dim(dim), + keepdim(keepdim) + { + has_correction = !!correction; + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + if (dim.has_value()) { + ss << ", dim=" << dim.value(); + } else { + ss << ", dim=null"; + } + ss << ", keepdim=" << keepdim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::optional<::std::vector>& dim, const ::std::optional& correction, const bool& keepdim) const { + size_t i = 0; + return (operand(i++) == self && + nullable_operand(i++) == correction.value_or(kNullValue) && + ((!this->dim&&!dim) || (this->dim&&dim && *(this->dim) == *dim)) && + this->keepdim == keepdim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(2); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + kwarguments.emplace_back("correction", has_correction ? loctx->GetOutputOp(operand(i++)) : nullptr); + kwarguments.emplace_back("keepdim", keepdim); + torch::lazy::TSOpVector std_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(std_out.size(), 1); + + return std_out; + + } + + + ::std::optional<::std::vector> dim; + bool keepdim; + bool has_correction: 1; + +}; + +class SubTensor : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::sub); + } + + SubTensor(const torch::lazy::Value& self, const torch::lazy::Value& other, const torch::lazy::Value& alpha, std::vector&& shapes) + : TsNode( + SubTensor::ClassOpKind(), + OpList{self, other, alpha}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& other, const torch::lazy::Value& alpha) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == other && + operand(i++) == alpha); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("alpha", loctx->GetOutputOp(operand(i++))); + torch::lazy::TSOpVector sub_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(sub_out.size(), 1); + + return sub_out; + + } + + + + + +}; + +class Sum : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::sum); + } + + Sum(const torch::lazy::Value& self, const ::std::optional& dtype, std::vector&& shapes) + : TsNode( + Sum::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dtype)), + dtype(dtype) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + if (dtype.has_value()) { + ss << ", dtype=" << dtype.value(); + } else { + ss << ", dtype=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::optional& dtype) const { + size_t i = 0; + return (operand(i++) == self && + ((!this->dtype&&!dtype) || (this->dtype&&dtype && *(this->dtype) == *dtype))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("dtype", dtype); + torch::lazy::TSOpVector sum_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(sum_out.size(), 1); + + return sum_out; + + } + + + ::std::optional dtype; + + +}; + +class SumDimIntlist : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::sum); + } + + SumDimIntlist(const torch::lazy::Value& self, const ::std::optional<::std::vector>& dim, const bool& keepdim, const ::std::optional& dtype, std::vector&& shapes) + : TsNode( + SumDimIntlist::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim, keepdim, dtype)), + dim(dim), + keepdim(keepdim), + dtype(dtype) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + if (dim.has_value()) { + ss << ", dim=" << dim.value(); + } else { + ss << ", dim=null"; + } + ss << ", keepdim=" << keepdim; + if (dtype.has_value()) { + ss << ", dtype=" << dtype.value(); + } else { + ss << ", dtype=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::optional<::std::vector>& dim, const bool& keepdim, const ::std::optional& dtype) const { + size_t i = 0; + return (operand(i++) == self && + ((!this->dim&&!dim) || (this->dim&&dim && *(this->dim) == *dim)) && + this->keepdim == keepdim && + ((!this->dtype&&!dtype) || (this->dtype&&dtype && *(this->dtype) == *dtype))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + arguments.emplace_back("keepdim", keepdim); + kwarguments.emplace_back("dtype", dtype); + torch::lazy::TSOpVector sum_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(sum_out.size(), 1); + + return sum_out; + + } + + + ::std::optional<::std::vector> dim; + bool keepdim; + ::std::optional dtype; + + +}; + +class TCopy : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::t_copy); + } + + TCopy(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + TCopy::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector t_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(t_copy_out.size(), 1); + + return t_copy_out; + + } + + + + + +}; + +class Tanh : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::tanh); + } + + Tanh(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Tanh::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector tanh_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(tanh_out.size(), 1); + + return tanh_out; + + } + + + + + +}; + +class TanhBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::tanh_backward); + } + + TanhBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& output, std::vector&& shapes) + : TsNode( + TanhBackward::ClassOpKind(), + OpList{grad_output, output}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& output) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == output); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector tanh_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(tanh_backward_out.size(), 1); + + return tanh_backward_out; + + } + + + + + +}; + +class Threshold : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::threshold); + } + + Threshold(const torch::lazy::Value& self, const torch::lazy::Value& threshold, const torch::lazy::Value& value, std::vector&& shapes) + : TsNode( + Threshold::ClassOpKind(), + OpList{self, threshold, value}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const torch::lazy::Value& threshold, const torch::lazy::Value& value) const { + size_t i = 0; + return (operand(i++) == self && + operand(i++) == threshold && + operand(i++) == value); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector threshold_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(threshold_out.size(), 1); + + return threshold_out; + + } + + + + + +}; + +class ThresholdBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::threshold_backward); + } + + ThresholdBackward(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& threshold, std::vector&& shapes) + : TsNode( + ThresholdBackward::ClassOpKind(), + OpList{grad_output, self, threshold}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const torch::lazy::Value& self, const torch::lazy::Value& threshold) const { + size_t i = 0; + return (operand(i++) == grad_output && + operand(i++) == self && + operand(i++) == threshold); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector threshold_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(threshold_backward_out.size(), 1); + + return threshold_backward_out; + + } + + + + + +}; + +class Topk : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::topk); + } + + Topk(const torch::lazy::Value& self, const int64_t& k, const int64_t& dim, const bool& largest, const bool& sorted, std::vector&& shapes) + : TsNode( + Topk::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 2, + torch::lazy::MHash(k, dim, largest, sorted)), + k(k), + dim(dim), + largest(largest), + sorted(sorted) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", k=" << k; + ss << ", dim=" << dim; + ss << ", largest=" << largest; + ss << ", sorted=" << sorted; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& k, const int64_t& dim, const bool& largest, const bool& sorted) const { + size_t i = 0; + return (operand(i++) == self && + this->k == k && + this->dim == dim && + this->largest == largest && + this->sorted == sorted); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(5); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("k", k); + arguments.emplace_back("dim", dim); + arguments.emplace_back("largest", largest); + arguments.emplace_back("sorted", sorted); + + torch::lazy::TSOpVector topk_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(topk_out.size(), 2); + + return topk_out; + + } + + + int64_t k; + int64_t dim; + bool largest; + bool sorted; + + +}; + +class Trace : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::trace); + } + + Trace(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Trace::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector trace_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(trace_out.size(), 1); + + return trace_out; + + } + + + + + +}; + +class TransposeCopyInt : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::transpose_copy); + } + + TransposeCopyInt(const torch::lazy::Value& self, const int64_t& dim0, const int64_t& dim1, std::vector&& shapes) + : TsNode( + TransposeCopyInt::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim0, dim1)), + dim0(dim0), + dim1(dim1) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim0=" << dim0; + ss << ", dim1=" << dim1; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& dim0, const int64_t& dim1) const { + size_t i = 0; + return (operand(i++) == self && + this->dim0 == dim0 && + this->dim1 == dim1); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim0", dim0); + arguments.emplace_back("dim1", dim1); + + torch::lazy::TSOpVector transpose_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(transpose_copy_out.size(), 1); + + return transpose_copy_out; + + } + + + int64_t dim0; + int64_t dim1; + + +}; + +class Tril : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::tril); + } + + Tril(const torch::lazy::Value& self, const int64_t& diagonal, std::vector&& shapes) + : TsNode( + Tril::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(diagonal)), + diagonal(diagonal) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", diagonal=" << diagonal; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& diagonal) const { + size_t i = 0; + return (operand(i++) == self && + this->diagonal == diagonal); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("diagonal", diagonal); + + torch::lazy::TSOpVector tril_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(tril_out.size(), 1); + + return tril_out; + + } + + + int64_t diagonal; + + +}; + +class Triu : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::triu); + } + + Triu(const torch::lazy::Value& self, const int64_t& diagonal, std::vector&& shapes) + : TsNode( + Triu::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(diagonal)), + diagonal(diagonal) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", diagonal=" << diagonal; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& diagonal) const { + size_t i = 0; + return (operand(i++) == self && + this->diagonal == diagonal); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("diagonal", diagonal); + + torch::lazy::TSOpVector triu_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(triu_out.size(), 1); + + return triu_out; + + } + + + int64_t diagonal; + + +}; + +class Trunc : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::trunc); + } + + Trunc(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Trunc::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector trunc_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(trunc_out.size(), 1); + + return trunc_out; + + } + + + + + +}; + +class UnfoldCopy : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::unfold_copy); + } + + UnfoldCopy(const torch::lazy::Value& self, const int64_t& dimension, const int64_t& size, const int64_t& step, std::vector&& shapes) + : TsNode( + UnfoldCopy::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dimension, size, step)), + dimension(dimension), + size(size), + step(step) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dimension=" << dimension; + ss << ", size=" << size; + ss << ", step=" << step; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& dimension, const int64_t& size, const int64_t& step) const { + size_t i = 0; + return (operand(i++) == self && + this->dimension == dimension && + this->size == size && + this->step == step); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dimension", dimension); + arguments.emplace_back("size", size); + arguments.emplace_back("step", step); + + torch::lazy::TSOpVector unfold_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(unfold_copy_out.size(), 1); + + return unfold_copy_out; + + } + + + int64_t dimension; + int64_t size; + int64_t step; + + +}; + +class Uniform : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::uniform); + } + + Uniform(const torch::lazy::Value& self, const double& from, const double& to, const ::std::optional& generator, std::vector&& shapes) + : TsNode( + Uniform::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(from, to, generator)), + from(from), + to(to), + generator(generator) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", from=" << from; + ss << ", to=" << to; + if (generator.has_value()) { + ss << ", generator=" << "torch.Generator()"; + } else { + ss << ", generator=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const double& from, const double& to, const ::std::optional& generator) const { + size_t i = 0; + return (operand(i++) == self && + this->from == from && + this->to == to && + ((!this->generator&&!generator) || (this->generator&&generator && *(this->generator) == *generator))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(3); + kwarguments.reserve(1); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("from", from); + arguments.emplace_back("to", to); + kwarguments.emplace_back("generator", generator); + torch::lazy::TSOpVector uniform_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(uniform_out.size(), 1); + + return uniform_out; + + } + + + double from; + double to; + ::std::optional generator; + + +}; + +class UnsqueezeCopy : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::unsqueeze_copy); + } + + UnsqueezeCopy(const torch::lazy::Value& self, const int64_t& dim, std::vector&& shapes) + : TsNode( + UnsqueezeCopy::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dim)), + dim(dim) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dim=" << dim; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const int64_t& dim) const { + size_t i = 0; + return (operand(i++) == self && + this->dim == dim); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dim", dim); + + torch::lazy::TSOpVector unsqueeze_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(unsqueeze_copy_out.size(), 1); + + return unsqueeze_copy_out; + + } + + + int64_t dim; + + +}; + +class UpsampleBilinear2d : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::upsample_bilinear2d); + } + + UpsampleBilinear2d(const torch::lazy::Value& self, const ::std::vector& output_size, const bool& align_corners, const ::std::optional& scales_h, const ::std::optional& scales_w, std::vector&& shapes) + : TsNode( + UpsampleBilinear2d::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(output_size, align_corners, scales_h, scales_w)), + output_size(output_size), + align_corners(align_corners), + scales_h(scales_h), + scales_w(scales_w) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", output_size=" << output_size; + ss << ", align_corners=" << align_corners; + if (scales_h.has_value()) { + ss << ", scales_h=" << scales_h.value(); + } else { + ss << ", scales_h=null"; + } + if (scales_w.has_value()) { + ss << ", scales_w=" << scales_w.value(); + } else { + ss << ", scales_w=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::vector& output_size, const bool& align_corners, const ::std::optional& scales_h, const ::std::optional& scales_w) const { + size_t i = 0; + return (operand(i++) == self && + this->output_size == output_size && + this->align_corners == align_corners && + ((!this->scales_h&&!scales_h) || (this->scales_h&&scales_h && *(this->scales_h) == *scales_h)) && + ((!this->scales_w&&!scales_w) || (this->scales_w&&scales_w && *(this->scales_w) == *scales_w))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(5); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("output_size", output_size); + arguments.emplace_back("align_corners", align_corners); + arguments.emplace_back("scales_h", scales_h); + arguments.emplace_back("scales_w", scales_w); + + torch::lazy::TSOpVector upsample_bilinear2d_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(upsample_bilinear2d_out.size(), 1); + + return upsample_bilinear2d_out; + + } + + + ::std::vector output_size; + bool align_corners; + ::std::optional scales_h; + ::std::optional scales_w; + + +}; + +class UpsampleBilinear2dBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::upsample_bilinear2d_backward); + } + + UpsampleBilinear2dBackward(const torch::lazy::Value& grad_output, const ::std::vector& output_size, const ::std::vector& input_size, const bool& align_corners, const ::std::optional& scales_h, const ::std::optional& scales_w, std::vector&& shapes) + : TsNode( + UpsampleBilinear2dBackward::ClassOpKind(), + OpList{grad_output}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(output_size, input_size, align_corners, scales_h, scales_w)), + output_size(output_size), + input_size(input_size), + align_corners(align_corners), + scales_h(scales_h), + scales_w(scales_w) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", output_size=" << output_size; + ss << ", input_size=" << input_size; + ss << ", align_corners=" << align_corners; + if (scales_h.has_value()) { + ss << ", scales_h=" << scales_h.value(); + } else { + ss << ", scales_h=null"; + } + if (scales_w.has_value()) { + ss << ", scales_w=" << scales_w.value(); + } else { + ss << ", scales_w=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const ::std::vector& output_size, const ::std::vector& input_size, const bool& align_corners, const ::std::optional& scales_h, const ::std::optional& scales_w) const { + size_t i = 0; + return (operand(i++) == grad_output && + this->output_size == output_size && + this->input_size == input_size && + this->align_corners == align_corners && + ((!this->scales_h&&!scales_h) || (this->scales_h&&scales_h && *(this->scales_h) == *scales_h)) && + ((!this->scales_w&&!scales_w) || (this->scales_w&&scales_w && *(this->scales_w) == *scales_w))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(6); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("output_size", output_size); + arguments.emplace_back("input_size", input_size); + arguments.emplace_back("align_corners", align_corners); + arguments.emplace_back("scales_h", scales_h); + arguments.emplace_back("scales_w", scales_w); + + torch::lazy::TSOpVector upsample_bilinear2d_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(upsample_bilinear2d_backward_out.size(), 1); + + return upsample_bilinear2d_backward_out; + + } + + + ::std::vector output_size; + ::std::vector input_size; + bool align_corners; + ::std::optional scales_h; + ::std::optional scales_w; + + +}; + +class UpsampleNearest2d : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::upsample_nearest2d); + } + + UpsampleNearest2d(const torch::lazy::Value& self, const ::std::vector& output_size, const ::std::optional& scales_h, const ::std::optional& scales_w, std::vector&& shapes) + : TsNode( + UpsampleNearest2d::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(output_size, scales_h, scales_w)), + output_size(output_size), + scales_h(scales_h), + scales_w(scales_w) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", output_size=" << output_size; + if (scales_h.has_value()) { + ss << ", scales_h=" << scales_h.value(); + } else { + ss << ", scales_h=null"; + } + if (scales_w.has_value()) { + ss << ", scales_w=" << scales_w.value(); + } else { + ss << ", scales_w=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::vector& output_size, const ::std::optional& scales_h, const ::std::optional& scales_w) const { + size_t i = 0; + return (operand(i++) == self && + this->output_size == output_size && + ((!this->scales_h&&!scales_h) || (this->scales_h&&scales_h && *(this->scales_h) == *scales_h)) && + ((!this->scales_w&&!scales_w) || (this->scales_w&&scales_w && *(this->scales_w) == *scales_w))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(4); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("output_size", output_size); + arguments.emplace_back("scales_h", scales_h); + arguments.emplace_back("scales_w", scales_w); + + torch::lazy::TSOpVector upsample_nearest2d_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(upsample_nearest2d_out.size(), 1); + + return upsample_nearest2d_out; + + } + + + ::std::vector output_size; + ::std::optional scales_h; + ::std::optional scales_w; + + +}; + +class UpsampleNearest2dBackward : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::upsample_nearest2d_backward); + } + + UpsampleNearest2dBackward(const torch::lazy::Value& grad_output, const ::std::vector& output_size, const ::std::vector& input_size, const ::std::optional& scales_h, const ::std::optional& scales_w, std::vector&& shapes) + : TsNode( + UpsampleNearest2dBackward::ClassOpKind(), + OpList{grad_output}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(output_size, input_size, scales_h, scales_w)), + output_size(output_size), + input_size(input_size), + scales_h(scales_h), + scales_w(scales_w) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", output_size=" << output_size; + ss << ", input_size=" << input_size; + if (scales_h.has_value()) { + ss << ", scales_h=" << scales_h.value(); + } else { + ss << ", scales_h=null"; + } + if (scales_w.has_value()) { + ss << ", scales_w=" << scales_w.value(); + } else { + ss << ", scales_w=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& grad_output, const ::std::vector& output_size, const ::std::vector& input_size, const ::std::optional& scales_h, const ::std::optional& scales_w) const { + size_t i = 0; + return (operand(i++) == grad_output && + this->output_size == output_size && + this->input_size == input_size && + ((!this->scales_h&&!scales_h) || (this->scales_h&&scales_h && *(this->scales_h) == *scales_h)) && + ((!this->scales_w&&!scales_w) || (this->scales_w&&scales_w && *(this->scales_w) == *scales_w))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(5); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("output_size", output_size); + arguments.emplace_back("input_size", input_size); + arguments.emplace_back("scales_h", scales_h); + arguments.emplace_back("scales_w", scales_w); + + torch::lazy::TSOpVector upsample_nearest2d_backward_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(upsample_nearest2d_backward_out.size(), 1); + + return upsample_nearest2d_backward_out; + + } + + + ::std::vector output_size; + ::std::vector input_size; + ::std::optional scales_h; + ::std::optional scales_w; + + +}; + +class ViewCopy : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::view_copy); + } + + ViewCopy(const torch::lazy::Value& self, const ::std::vector& size, std::vector&& shapes) + : TsNode( + ViewCopy::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(size)), + size(size) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", size=" << size; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const ::std::vector& size) const { + size_t i = 0; + return (operand(i++) == self && + this->size == size); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("size", size); + + torch::lazy::TSOpVector view_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(view_copy_out.size(), 1); + + return view_copy_out; + + } + + + ::std::vector size; + + +}; + +class ViewCopyDtype : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::view_copy); + } + + ViewCopyDtype(const torch::lazy::Value& self, const at::ScalarType& dtype, std::vector&& shapes) + : TsNode( + ViewCopyDtype::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash(dtype)), + dtype(dtype) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dtype=" << dtype; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self, const at::ScalarType& dtype) const { + size_t i = 0; + return (operand(i++) == self && + this->dtype == dtype); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(2); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + arguments.emplace_back("dtype", dtype); + + torch::lazy::TSOpVector view_copy_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(view_copy_out.size(), 1); + + return view_copy_out; + + } + + + at::ScalarType dtype; + + +}; + +class Zero : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::zero); + } + + Zero(const torch::lazy::Value& self, std::vector&& shapes) + : TsNode( + Zero::ClassOpKind(), + OpList{self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash()) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& self) const { + size_t i = 0; + return (operand(i++) == self); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(0); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + + torch::lazy::TSOpVector zero_out = torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(zero_out.size(), 1); + + return zero_out; + + } + + + + + +}; + +} // namespace lazy +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/generated/LazyNativeFunctions.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/generated/LazyNativeFunctions.h new file mode 100644 index 0000000000000000000000000000000000000000..82f63eb0acc9037329361360459e52f8eda6d55c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/generated/LazyNativeFunctions.h @@ -0,0 +1,216 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +// an external backend might generate file within its code tree +// and check all the source files within the tree with clang-format. +// so, disable it since the backend might have a different config. +// clang-format off + +// Autogenerated file by gen_backend_stubs.py. Do not edit directly! + +#include + +namespace torch { +namespace lazy { + +struct LazyNativeFunctions { + +static ::std::tuple convolution_backward(const at::Tensor & grad_output, const at::Tensor & input, const at::Tensor & weight, at::OptionalIntArrayRef bias_sizes, at::IntArrayRef stride, at::IntArrayRef padding, at::IntArrayRef dilation, bool transposed, at::IntArrayRef output_padding, int64_t groups, ::std::array output_mask); +static ::std::tuple native_batch_norm(const at::Tensor & input, const ::std::optional & weight, const ::std::optional & bias, const ::std::optional & running_mean, const ::std::optional & running_var, bool training, double momentum, double eps); +static ::std::tuple native_batch_norm_backward(const at::Tensor & grad_out, const at::Tensor & input, const ::std::optional & weight, const ::std::optional & running_mean, const ::std::optional & running_var, const ::std::optional & save_mean, const ::std::optional & save_invstd, bool train, double eps, ::std::array output_mask); +static ::std::tuple native_layer_norm(const at::Tensor & input, at::IntArrayRef normalized_shape, const ::std::optional & weight, const ::std::optional & bias, double eps); +static ::std::tuple native_layer_norm_backward(const at::Tensor & grad_out, const at::Tensor & input, at::IntArrayRef normalized_shape, const at::Tensor & mean, const at::Tensor & rstd, const ::std::optional & weight, const ::std::optional & bias, ::std::array output_mask); +static ::std::tuple svd(const at::Tensor & self, bool some, bool compute_uv); +static ::std::tuple grid_sampler_2d_backward(const at::Tensor & grad_output, const at::Tensor & input, const at::Tensor & grid, int64_t interpolation_mode, int64_t padding_mode, bool align_corners, ::std::array output_mask); +static ::std::tuple log_sigmoid_forward(const at::Tensor & self); +static ::std::tuple max(const at::Tensor & self, int64_t dim, bool keepdim); +static ::std::tuple max_pool2d_with_indices(const at::Tensor & self, at::IntArrayRef kernel_size, at::IntArrayRef stride, at::IntArrayRef padding, at::IntArrayRef dilation, bool ceil_mode); +static ::std::tuple max_pool3d_with_indices(const at::Tensor & self, at::IntArrayRef kernel_size, at::IntArrayRef stride, at::IntArrayRef padding, at::IntArrayRef dilation, bool ceil_mode); +static ::std::tuple native_dropout(const at::Tensor & input, double p, ::std::optional train); +static ::std::tuple nll_loss2d_forward(const at::Tensor & self, const at::Tensor & target, const ::std::optional & weight, int64_t reduction, int64_t ignore_index); +static ::std::tuple nll_loss_forward(const at::Tensor & self, const at::Tensor & target, const ::std::optional & weight, int64_t reduction, int64_t ignore_index); +static ::std::tuple sort(const at::Tensor & self, int64_t dim, bool descending); +static ::std::tuple topk(const at::Tensor & self, int64_t k, int64_t dim, bool largest, bool sorted); +static at::Tensor & arange_out(const at::Scalar & start, const at::Scalar & end, const at::Scalar & step, at::Tensor & out); +static at::Tensor & fill_(at::Tensor & self, const at::Scalar & value); +static at::Tensor & logsumexp_out(const at::Tensor & self, at::IntArrayRef dim, bool keepdim, at::Tensor & out); +static at::Tensor _adaptive_avg_pool2d(const at::Tensor & self, at::IntArrayRef output_size); +static at::Tensor _adaptive_avg_pool2d_backward(const at::Tensor & grad_output, const at::Tensor & self); +static at::Tensor _copy_from(const at::Tensor & self, const at::Tensor & dst, bool non_blocking); +static at::Tensor _copy_from_and_resize(const at::Tensor & self, const at::Tensor & dst); +static at::Tensor _log_softmax(const at::Tensor & self, int64_t dim, bool half_to_float); +static at::Tensor _log_softmax_backward_data(const at::Tensor & grad_output, const at::Tensor & output, int64_t dim, at::ScalarType input_dtype); +static at::Tensor _reshape_alias_copy_symint(const at::Tensor & self, c10::SymIntArrayRef size, c10::SymIntArrayRef stride); +static at::Tensor _softmax(const at::Tensor & self, int64_t dim, bool half_to_float); +static at::Tensor _softmax_backward_data(const at::Tensor & grad_output, const at::Tensor & output, int64_t dim, at::ScalarType input_dtype); +static at::Tensor _to_copy(const at::Tensor & self, ::std::optional dtype, ::std::optional layout, ::std::optional device, ::std::optional pin_memory, bool non_blocking, ::std::optional memory_format); +static at::Tensor _trilinear(const at::Tensor & i1, const at::Tensor & i2, const at::Tensor & i3, at::IntArrayRef expand1, at::IntArrayRef expand2, at::IntArrayRef expand3, at::IntArrayRef sumdim, int64_t unroll_dim); +static at::Tensor _unsafe_view(const at::Tensor & self, at::IntArrayRef size); +static at::Tensor abs(const at::Tensor & self); +static at::Tensor add(const at::Tensor & self, const at::Tensor & other, const at::Scalar & alpha); +static at::Tensor addcdiv(const at::Tensor & self, const at::Tensor & tensor1, const at::Tensor & tensor2, const at::Scalar & value); +static at::Tensor addcmul(const at::Tensor & self, const at::Tensor & tensor1, const at::Tensor & tensor2, const at::Scalar & value); +static at::Tensor addmm(const at::Tensor & self, const at::Tensor & mat1, const at::Tensor & mat2, const at::Scalar & beta, const at::Scalar & alpha); +static at::Tensor alias_copy(const at::Tensor & self); +static at::Tensor all(const at::Tensor & self); +static at::Tensor any(const at::Tensor & self); +static at::Tensor as_strided_copy_symint(const at::Tensor & self, c10::SymIntArrayRef size, c10::SymIntArrayRef stride, ::std::optional storage_offset); +static at::Tensor as_strided_scatter_symint(const at::Tensor & self, const at::Tensor & src, c10::SymIntArrayRef size, c10::SymIntArrayRef stride, ::std::optional storage_offset); +static at::Tensor avg_pool2d(const at::Tensor & self, at::IntArrayRef kernel_size, at::IntArrayRef stride, at::IntArrayRef padding, bool ceil_mode, bool count_include_pad, ::std::optional divisor_override); +static at::Tensor avg_pool2d_backward(const at::Tensor & grad_output, const at::Tensor & self, at::IntArrayRef kernel_size, at::IntArrayRef stride, at::IntArrayRef padding, bool ceil_mode, bool count_include_pad, ::std::optional divisor_override); +static at::Tensor baddbmm(const at::Tensor & self, const at::Tensor & batch1, const at::Tensor & batch2, const at::Scalar & beta, const at::Scalar & alpha); +static at::Tensor bernoulli(const at::Tensor & self, ::std::optional generator); +static at::Tensor bernoulli(const at::Tensor & self, double p, ::std::optional generator); +static at::Tensor binary_cross_entropy(const at::Tensor & self, const at::Tensor & target, const ::std::optional & weight, int64_t reduction); +static at::Tensor binary_cross_entropy_backward(const at::Tensor & grad_output, const at::Tensor & self, const at::Tensor & target, const ::std::optional & weight, int64_t reduction); +static at::Tensor bitwise_and(const at::Tensor & self, const at::Tensor & other); +static at::Tensor bitwise_or(const at::Tensor & self, const at::Tensor & other); +static at::Tensor block_diag(at::TensorList tensors); +static at::Tensor bmm(const at::Tensor & self, const at::Tensor & mat2); +static at::Tensor cat(const at::ITensorListRef & tensors, int64_t dim); +static at::Tensor clamp(const at::Tensor & self, const ::std::optional & min, const ::std::optional & max); +static at::Tensor clamp_min(const at::Tensor & self, const at::Scalar & min); +static at::Tensor clone(const at::Tensor & self, ::std::optional memory_format); +static at::Tensor constant_pad_nd(const at::Tensor & self, at::IntArrayRef pad, const at::Scalar & value); +static at::Tensor convolution(const at::Tensor & input, const at::Tensor & weight, const ::std::optional & bias, at::IntArrayRef stride, at::IntArrayRef padding, at::IntArrayRef dilation, bool transposed, at::IntArrayRef output_padding, int64_t groups); +static at::Tensor cos(const at::Tensor & self); +static at::Tensor cumsum(const at::Tensor & self, int64_t dim, ::std::optional dtype); +static at::Tensor detach_copy(const at::Tensor & self); +static at::Tensor diag_embed(const at::Tensor & self, int64_t offset, int64_t dim1, int64_t dim2); +static at::Tensor diagonal_backward_symint(const at::Tensor & grad_output, c10::SymIntArrayRef input_sizes, int64_t offset, int64_t dim1, int64_t dim2); +static at::Tensor diagonal_copy(const at::Tensor & self, int64_t offset, int64_t dim1, int64_t dim2); +static at::Tensor diagonal_scatter(const at::Tensor & self, const at::Tensor & src, int64_t offset, int64_t dim1, int64_t dim2); +static at::Tensor div(const at::Tensor & self, const at::Tensor & other); +static at::Tensor div(const at::Tensor & self, const at::Tensor & other, ::std::optional rounding_mode); +static at::Tensor elu(const at::Tensor & self, const at::Scalar & alpha, const at::Scalar & scale, const at::Scalar & input_scale); +static at::Tensor elu_backward(const at::Tensor & grad_output, const at::Scalar & alpha, const at::Scalar & scale, const at::Scalar & input_scale, bool is_result, const at::Tensor & self_or_result); +static at::Tensor embedding(const at::Tensor & weight, const at::Tensor & indices, int64_t padding_idx, bool scale_grad_by_freq, bool sparse); +static at::Tensor embedding_dense_backward(const at::Tensor & grad_output, const at::Tensor & indices, int64_t num_weights, int64_t padding_idx, bool scale_grad_by_freq); +static at::Tensor empty_strided_symint(c10::SymIntArrayRef size, c10::SymIntArrayRef stride, ::std::optional dtype, ::std::optional layout, ::std::optional device, ::std::optional pin_memory); +static at::Tensor empty_symint(c10::SymIntArrayRef size, ::std::optional dtype, ::std::optional layout, ::std::optional device, ::std::optional pin_memory, ::std::optional memory_format); +static at::Tensor eq(const at::Tensor & self, const at::Scalar & other); +static at::Tensor eq(const at::Tensor & self, const at::Tensor & other); +static at::Tensor exp(const at::Tensor & self); +static at::Tensor expand_copy_symint(const at::Tensor & self, c10::SymIntArrayRef size, bool implicit); +static at::Tensor flip(const at::Tensor & self, at::IntArrayRef dims); +static at::Tensor floor(const at::Tensor & self); +static at::Tensor frac(const at::Tensor & self); +static at::Tensor gather(const at::Tensor & self, int64_t dim, const at::Tensor & index, bool sparse_grad); +static at::Tensor ge(const at::Tensor & self, const at::Scalar & other); +static at::Tensor ge(const at::Tensor & self, const at::Tensor & other); +static at::Tensor gelu(const at::Tensor & self, c10::string_view approximate); +static at::Tensor gelu_backward(const at::Tensor & grad_output, const at::Tensor & self, c10::string_view approximate); +static at::Tensor glu(const at::Tensor & self, int64_t dim); +static at::Tensor glu_backward(const at::Tensor & grad_output, const at::Tensor & self, int64_t dim); +static at::Tensor glu_jvp(const at::Tensor & glu, const at::Tensor & x, const at::Tensor & dx, int64_t dim); +static at::Tensor grid_sampler_2d(const at::Tensor & input, const at::Tensor & grid, int64_t interpolation_mode, int64_t padding_mode, bool align_corners); +static at::Tensor gt(const at::Tensor & self, const at::Scalar & other); +static at::Tensor gt(const at::Tensor & self, const at::Tensor & other); +static at::Tensor hardsigmoid(const at::Tensor & self); +static at::Tensor index_select(const at::Tensor & self, int64_t dim, const at::Tensor & index); +static at::Tensor le(const at::Tensor & self, const at::Scalar & other); +static at::Tensor le(const at::Tensor & self, const at::Tensor & other); +static at::Tensor leaky_relu(const at::Tensor & self, const at::Scalar & negative_slope); +static at::Tensor leaky_relu_backward(const at::Tensor & grad_output, const at::Tensor & self, const at::Scalar & negative_slope, bool self_is_result); +static at::Tensor lift(const at::Tensor & self); +static at::Tensor lift_fresh(const at::Tensor & self); +static at::Tensor linalg_pinv(const at::Tensor & self, const ::std::optional & atol, const ::std::optional & rtol, bool hermitian); +static at::Tensor log(const at::Tensor & self); +static at::Tensor log2(const at::Tensor & self); +static at::Tensor log_sigmoid_backward(const at::Tensor & grad_output, const at::Tensor & self, const at::Tensor & buffer); +static at::Tensor logdet(const at::Tensor & self); +static at::Tensor lt(const at::Tensor & self, const at::Scalar & other); +static at::Tensor lt(const at::Tensor & self, const at::Tensor & other); +static at::Tensor masked_fill(const at::Tensor & self, const at::Tensor & mask, const at::Scalar & value); +static at::Tensor masked_fill(const at::Tensor & self, const at::Tensor & mask, const at::Tensor & value); +static at::Tensor max(const at::Tensor & self); +static at::Tensor max_pool2d_with_indices_backward(const at::Tensor & grad_output, const at::Tensor & self, at::IntArrayRef kernel_size, at::IntArrayRef stride, at::IntArrayRef padding, at::IntArrayRef dilation, bool ceil_mode, const at::Tensor & indices); +static at::Tensor max_pool3d_with_indices_backward(const at::Tensor & grad_output, const at::Tensor & self, at::IntArrayRef kernel_size, at::IntArrayRef stride, at::IntArrayRef padding, at::IntArrayRef dilation, bool ceil_mode, const at::Tensor & indices); +static at::Tensor maximum(const at::Tensor & self, const at::Tensor & other); +static at::Tensor mean(const at::Tensor & self, ::std::optional dtype); +static at::Tensor mean(const at::Tensor & self, at::OptionalIntArrayRef dim, bool keepdim, ::std::optional dtype); +static at::Tensor min(const at::Tensor & self); +static at::Tensor minimum(const at::Tensor & self, const at::Tensor & other); +static at::Tensor mm(const at::Tensor & self, const at::Tensor & mat2); +static at::Tensor mul(const at::Tensor & self, const at::Tensor & other); +static at::Tensor mv(const at::Tensor & self, const at::Tensor & vec); +static at::Tensor narrow_copy_symint(const at::Tensor & self, int64_t dim, c10::SymInt start, c10::SymInt length); +static at::Tensor native_dropout_backward(const at::Tensor & grad_output, const at::Tensor & mask, double scale); +static at::Tensor ne(const at::Tensor & self, const at::Scalar & other); +static at::Tensor ne(const at::Tensor & self, const at::Tensor & other); +static at::Tensor neg(const at::Tensor & self); +static at::Tensor new_empty_strided_symint(const at::Tensor & self, c10::SymIntArrayRef size, c10::SymIntArrayRef stride, ::std::optional dtype, ::std::optional layout, ::std::optional device, ::std::optional pin_memory); +static at::Tensor nll_loss2d_backward(const at::Tensor & grad_output, const at::Tensor & self, const at::Tensor & target, const ::std::optional & weight, int64_t reduction, int64_t ignore_index, const at::Tensor & total_weight); +static at::Tensor nll_loss_backward(const at::Tensor & grad_output, const at::Tensor & self, const at::Tensor & target, const ::std::optional & weight, int64_t reduction, int64_t ignore_index, const at::Tensor & total_weight); +static at::Tensor nonzero(const at::Tensor & self); +static at::Tensor norm(const at::Tensor & self, const ::std::optional & p, at::IntArrayRef dim, bool keepdim); +static at::Tensor normal_functional(const at::Tensor & self, double mean, double std, ::std::optional generator); +static at::Tensor permute_copy(const at::Tensor & self, at::IntArrayRef dims); +static at::Tensor pixel_shuffle(const at::Tensor & self, int64_t upscale_factor); +static at::Tensor pixel_unshuffle(const at::Tensor & self, int64_t downscale_factor); +static at::Tensor pow(const at::Tensor & self, const at::Scalar & exponent); +static at::Tensor pow(const at::Tensor & self, const at::Tensor & exponent); +static at::Tensor random(const at::Tensor & self, ::std::optional generator); +static at::Tensor random(const at::Tensor & self, int64_t from, ::std::optional to, ::std::optional generator); +static at::Tensor random(const at::Tensor & self, int64_t to, ::std::optional generator); +static at::Tensor reciprocal(const at::Tensor & self); +static at::Tensor relu(const at::Tensor & self); +static at::Tensor remainder(const at::Tensor & self, const at::Tensor & other); +static at::Tensor repeat(const at::Tensor & self, at::IntArrayRef repeats); +static at::Tensor rsqrt(const at::Tensor & self); +static at::Tensor scatter_add(const at::Tensor & self, int64_t dim, const at::Tensor & index, const at::Tensor & src); +static at::Tensor select_backward_symint(const at::Tensor & grad_output, c10::SymIntArrayRef input_sizes, int64_t dim, c10::SymInt index); +static at::Tensor select_copy(const at::Tensor & self, int64_t dim, int64_t index); +static at::Tensor select_scatter(const at::Tensor & self, const at::Tensor & src, int64_t dim, int64_t index); +static at::Tensor sgn(const at::Tensor & self); +static at::Tensor sigmoid(const at::Tensor & self); +static at::Tensor sigmoid_backward(const at::Tensor & grad_output, const at::Tensor & output); +static at::Tensor silu(const at::Tensor & self); +static at::Tensor slice_backward_symint(const at::Tensor & grad_output, c10::SymIntArrayRef input_sizes, int64_t dim, c10::SymInt start, c10::SymInt end, c10::SymInt step); +static at::Tensor slice_copy_symint(const at::Tensor & self, int64_t dim, ::std::optional start, ::std::optional end, c10::SymInt step); +static at::Tensor slice_scatter_symint(const at::Tensor & self, const at::Tensor & src, int64_t dim, ::std::optional start, ::std::optional end, c10::SymInt step); +static at::Tensor smooth_l1_loss(const at::Tensor & self, const at::Tensor & target, int64_t reduction, double beta); +static at::Tensor smooth_l1_loss_backward(const at::Tensor & grad_output, const at::Tensor & self, const at::Tensor & target, int64_t reduction, double beta); +static at::Tensor softplus(const at::Tensor & self, const at::Scalar & beta, const at::Scalar & threshold); +static at::Tensor softplus_backward(const at::Tensor & grad_output, const at::Tensor & self, const at::Scalar & beta, const at::Scalar & threshold); +static at::Tensor sqrt(const at::Tensor & self); +static at::Tensor squeeze_copy(const at::Tensor & self); +static at::Tensor squeeze_copy(const at::Tensor & self, at::IntArrayRef dim); +static at::Tensor squeeze_copy(const at::Tensor & self, int64_t dim); +static at::Tensor stack(at::TensorList tensors, int64_t dim); +static at::Tensor std(const at::Tensor & self, at::OptionalIntArrayRef dim, bool unbiased, bool keepdim); +static at::Tensor std(const at::Tensor & self, at::OptionalIntArrayRef dim, const ::std::optional & correction, bool keepdim); +static at::Tensor std(const at::Tensor & self, bool unbiased); +static at::Tensor sub(const at::Tensor & self, const at::Tensor & other, const at::Scalar & alpha); +static at::Tensor sum(const at::Tensor & self, ::std::optional dtype); +static at::Tensor sum(const at::Tensor & self, at::OptionalIntArrayRef dim, bool keepdim, ::std::optional dtype); +static at::Tensor t_copy(const at::Tensor & self); +static at::Tensor tanh(const at::Tensor & self); +static at::Tensor tanh_backward(const at::Tensor & grad_output, const at::Tensor & output); +static at::Tensor threshold(const at::Tensor & self, const at::Scalar & threshold, const at::Scalar & value); +static at::Tensor threshold_backward(const at::Tensor & grad_output, const at::Tensor & self, const at::Scalar & threshold); +static at::Tensor trace(const at::Tensor & self); +static at::Tensor transpose_copy(const at::Tensor & self, int64_t dim0, int64_t dim1); +static at::Tensor tril(const at::Tensor & self, int64_t diagonal); +static at::Tensor triu(const at::Tensor & self, int64_t diagonal); +static at::Tensor trunc(const at::Tensor & self); +static at::Tensor unfold_copy(const at::Tensor & self, int64_t dimension, int64_t size, int64_t step); +static at::Tensor uniform(const at::Tensor & self, double from, double to, ::std::optional generator); +static at::Tensor unsqueeze_copy(const at::Tensor & self, int64_t dim); +static at::Tensor upsample_bilinear2d(const at::Tensor & self, at::IntArrayRef output_size, bool align_corners, ::std::optional scales_h, ::std::optional scales_w); +static at::Tensor upsample_bilinear2d_backward(const at::Tensor & grad_output, at::IntArrayRef output_size, at::IntArrayRef input_size, bool align_corners, ::std::optional scales_h, ::std::optional scales_w); +static at::Tensor upsample_nearest2d(const at::Tensor & self, at::IntArrayRef output_size, ::std::optional scales_h, ::std::optional scales_w); +static at::Tensor upsample_nearest2d_backward(const at::Tensor & grad_output, at::IntArrayRef output_size, at::IntArrayRef input_size, ::std::optional scales_h, ::std::optional scales_w); +static at::Tensor view_copy(const at::Tensor & self, at::ScalarType dtype); +static at::Tensor view_copy_symint(const at::Tensor & self, c10::SymIntArrayRef size); +static at::Tensor zero(const at::Tensor & self); +static ::std::tuple native_group_norm(const at::Tensor & input, const ::std::optional & weight, const ::std::optional & bias, int64_t N, int64_t C, int64_t HxW, int64_t group, double eps); +static at::Tensor max_pool3d(const at::Tensor & self, at::IntArrayRef kernel_size, at::IntArrayRef stride, at::IntArrayRef padding, at::IntArrayRef dilation, bool ceil_mode); + +}; +} // namespace lazy +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/generated/LazyNonNativeIr.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/generated/LazyNonNativeIr.h new file mode 100644 index 0000000000000000000000000000000000000000..4cea78933ef5fb0fe8fb8dea61f56825200d92bc --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/generated/LazyNonNativeIr.h @@ -0,0 +1,160 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +// This file contains autogenerated LazyTensor Non Native IR nodes + +namespace torch { +namespace lazy { + +class Scalar : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::prim::Constant); + } + + Scalar(const at::Scalar& value, const at::ScalarType& type) + : TsNode( + Scalar::ClassOpKind(), + OpList{}, + compute_shape_scalar(value, type), + /* num_outputs */ 1, + torch::lazy::MHash(value, type)), + value(value), + type(type) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", value=" << value; + ss << ", type=" << type; + return ss.str(); + } + + + + bool CanBeReused(const at::Scalar& value, const at::ScalarType& type) const; + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override; + + at::Scalar value; + at::ScalarType type; + + +}; + +class Expand : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(at::aten::expand); + } + + Expand(const torch::lazy::Value& input, const ::std::vector& size, const bool& is_scalar_expand) + : TsNode( + Expand::ClassOpKind(), + OpList{input}, + [&](){ return compute_shape_expand(operand(0), size, is_scalar_expand)[0]; }, + /* num_outputs */ 1, + torch::lazy::MHash(size, is_scalar_expand)), + size(size), + is_scalar_expand(is_scalar_expand) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", size=" << size; + ss << ", is_scalar_expand=" << is_scalar_expand; + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& input, const ::std::vector& size, const bool& is_scalar_expand) const { + size_t i = 0; + return (operand(i++) == input && + this->size == size && + this->is_scalar_expand == is_scalar_expand); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override; + + ::std::vector size; + bool is_scalar_expand; + + +}; + +class Cast : public TsNode { + public: + static torch::lazy::OpKind ClassOpKind() { + return torch::lazy::OpKind(ltc_cast); + } + + Cast(const torch::lazy::Value& input, const at::ScalarType& dtype, const ::std::optional& stype) + : TsNode( + Cast::ClassOpKind(), + OpList{input}, + compute_shape_cast(input, dtype, stype), + /* num_outputs */ 1, + torch::lazy::MHash(dtype, stype)), + dtype(dtype), + stype(stype) + { + + } + + std::string ToString() const override { + std::stringstream ss; + ss << TsNode::ToString(); + ss << ", dtype=" << dtype; + if (stype.has_value()) { + ss << ", stype=" << stype.value(); + } else { + ss << ", stype=null"; + } + return ss.str(); + } + + + + bool CanBeReused(const torch::lazy::Value& input, const at::ScalarType& dtype, const ::std::optional& stype) const { + size_t i = 0; + return (operand(i++) == input && + this->dtype == dtype && + ((!this->stype&&!stype) || (this->stype&&stype && *(this->stype) == *stype))); + } + + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override; + + at::ScalarType dtype; + ::std::optional stype; + + +}; + +} // namespace lazy +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/python/init.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/python/init.h new file mode 100644 index 0000000000000000000000000000000000000000..56e5f624fcff53187e799126003008a0d2874429 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/python/init.h @@ -0,0 +1,15 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include + +namespace torch::lazy { + +TORCH_PYTHON_API void initLazyBindings(PyObject* module); + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/python/python_util.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/python/python_util.h new file mode 100644 index 0000000000000000000000000000000000000000..dc5777bb0f45af1f31d11fc08adb7f873f7bfe46 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/python/python_util.h @@ -0,0 +1,18 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include + +namespace torch::lazy { + +std::optional TORCH_PYTHON_API GetPythonFrameTop(); + +std::vector TORCH_PYTHON_API GetPythonFrames(); + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/config.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/config.h new file mode 100644 index 0000000000000000000000000000000000000000..0157b30fc7817ed9a74cca3ceb769db3a31b320b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/config.h @@ -0,0 +1,12 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include + +// TODO(whc) unclear if this is useful, has only been tested as true +TORCH_DECLARE_bool(torch_lazy_ts_tensor_update_sync); + +TORCH_DECLARE_bool(torch_lazy_ts_cuda); + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/dynamic_ir.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/dynamic_ir.h new file mode 100644 index 0000000000000000000000000000000000000000..4c42b0831100df2c145d7d5ddc0933f7c2085460 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/dynamic_ir.h @@ -0,0 +1,82 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +TORCH_DECLARE_bool(ltc_enable_dynamic_shapes); + +namespace torch::lazy { + +/** + * The goal of "dynamic" Nodes is to patch a hole in our tracing. + * Previously, if a user called `sizes` on a Tensor, it would leak out + * of our tracing system, as `sizes` returns a torch.Size or an int. To + * prevent this from happening, we introduce DimensionNode, a new type + * of Node that abstracts the operation of getting the dimensions of a + * Tensor. + * + * Consider the following example: + * ``` + * numel = x.shape()[0] * x.shape()[1] + * ``` + * + * Here, `x.shape()[i]` will be a SizeNode (subclass of DimensionNode), + * and the multiplication of the two SizeNodes will be represented by + * a SizeMul (also a subclass of DimensionNode). Through this, we can + * prevent `numel` from being represented as a Python int and thus + * burned into the Graph. + */ + +// Represents the result of calling `size` on a Tensor +class TORCH_API SizeNode : public TsNode, public DimensionNode { + public: + SizeNode(Value input, size_t dim); + int64_t getStaticValue() const override; + bool isSymbolic() const override; + std::string ToString() const override; + size_t dim_ = 0; + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + TSLoweringContext* loctx) const override; +}; + +class TORCH_API SizeAdd : public TsNode, public DimensionNode { + public: + SizeAdd(Value a, Value b); + int64_t getStaticValue() const override; + bool isSymbolic() const override; + std::string ToString() const override; +}; + +class TORCH_API SizeMul : public TsNode, public DimensionNode { + public: + SizeMul(Value a, Value b); + int64_t getStaticValue() const override; + bool isSymbolic() const override; + std::string ToString() const override; +}; + +class TORCH_API SizeDiv : public TsNode, public DimensionNode { + public: + SizeDiv(Value a, Value b); + int64_t getStaticValue() const override; + bool isSymbolic() const override; + std::string ToString() const override; +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ir_builder.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ir_builder.h new file mode 100644 index 0000000000000000000000000000000000000000..7d8dd8c804cc68910334fc737043c58e90cc4ea0 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ir_builder.h @@ -0,0 +1,74 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace torch::lazy { + +struct TorchScriptIrBuilder : IrBuilder { + NodePtr MakeDeviceData( + const std::shared_ptr& data) const override { + return DeviceData::Create(data); + } + // TODO: Scalar node is not currently used by ts_backend. Enable reusing + // Scalar node later if needed. + NodePtr MakeScalar(const at::Scalar& value, const at::ScalarType& type) + const override { + return MakeNode(value, type); + } + NodePtr MakeExpand( + const Value& input0, + const std::vector& size, + const bool& is_scalar_expand) const override { + return ReuseOrMakeNode(input0, size, is_scalar_expand); + } + NodePtr MakeCast( + const Value& input0, + const at::ScalarType& dtype, + const std::optional& stype = + std::nullopt) const override { + return ReuseOrMakeNode(input0, dtype, stype); + } + NodePtr MakeTensorList(const OpList& inputs) const override { + return ReuseOrMakeNode(inputs); + } + // Generic needs cleanup + NodePtr MakeGeneric( + const OpKind& op, + const OpList& operands, + const Shape& shape, + const size_t& num_outputs = 1, + const hash_t& hash_seed = + static_cast(0x5a2d296e9)) const override { + return MakeNode(op, operands, shape, num_outputs, hash_seed); + } + + // dynamic ir nodes + // TODO: verify if IR node reusing works for Dynamic shape ops + NodePtr MakeSizeNode(const Value& input, size_t dim) const override { + return MakeNode(input, dim); + } + NodePtr MakeSizeAdd(const Value& a, const Value& b) const override { + return MakeNode(a, b); + } + NodePtr MakeSizeMul(const Value& a, const Value& b) const override { + return MakeNode(a, b); + } + NodePtr MakeSizeDiv(const Value& a, const Value& b) const override { + return MakeNode(a, b); + } +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ops/device_data.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ops/device_data.h new file mode 100644 index 0000000000000000000000000000000000000000..f258cf99c580b129f640070fd14839230a6f881f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ops/device_data.h @@ -0,0 +1,55 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include + +namespace torch::lazy { + +class TORCH_API DeviceData : public TsNode { + public: + static OpKind ClassOpKind() { + return ltc_device_data; + } + + explicit DeviceData(std::shared_ptr data); + + // A DeviceData node can be reused if the shape matches, + // but we will substitute the actual data_ pointer under + // the hood. + bool CanBeReused(const std::shared_ptr& data) const { + return data_->shape() == data->shape(); + } + + std::string ToString() const override; + + const std::shared_ptr& data() const { + return data_; + } + + void SetData(std::shared_ptr data) { + data_ = std::move(data); + } + + static const DeviceData* Cast(const Node* node); + + // To reuse IR nodes, use this method to create DeviceData nodes + // instead of calling the constructor directconst ly. + static NodePtr Create(const std::shared_ptr& data); + + TSOpVector Lower( + std::shared_ptr function, + TSLoweringContext* loctx) const override; + + private: + std::shared_ptr data_; +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ops/generic.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ops/generic.h new file mode 100644 index 0000000000000000000000000000000000000000..8334391a593aa80e966f057b94eb47b43834c03e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ops/generic.h @@ -0,0 +1,57 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include + +namespace torch::lazy { + +// Generic IR Node implementation for nodes which can simply be described by a +// specific OpKind and a lowering function. IR nodes carrying +// metadata should not be using this class TORCH_API (and have the metadata +// captured by the LowerFn), but they should instead create a dedicated IR node. +// Doing the former would limit IR introspection. +class TORCH_API Generic : public TsNode { + public: + Generic( + OpKind op, + OpList operands, + Shape shape, + size_t num_outputs = 1, + hash_t hash_seed = static_cast(0x5a2d296e9)); + + Generic( + OpKind op, + OpList operands, + const std::function& shape_fn, + size_t num_outputs = 1, + hash_t hash_seed = static_cast(0x5a2d296e9)); + + Generic( + OpKind op, + OpList operands, + size_t num_outputs = 1, + hash_t hash_seed = static_cast(0x5a2d296e9)); + + Generic(OpKind op, Shape shape, size_t num_outputs, hash_t hash_seed); + + private: + hash_t hash_seed_; +}; + +inline NodePtr GenericOp( + OpKind op, + OpList operands, + Shape shape, + size_t num_outputs = 1, + hash_t hash_seed = static_cast(0x5a2d296e9)) { + return MakeNode( + op, operands, std::move(shape), num_outputs, hash_seed); +} + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ops/to_copy.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ops/to_copy.h new file mode 100644 index 0000000000000000000000000000000000000000..121cd0ffcbc99e5680c16e312013059d6dd5e74c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ops/to_copy.h @@ -0,0 +1,130 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::lazy { + +// This IR was copied from code-generated output, but the entire _to_copy +// operator cannot be trivially code generated since it is only desirable to +// capture IR for certain permutations of _to_copy (e.g. dtype), and for the +// others it is difficult to even invoke the aten/eager fallback necessitating +// directly implementing the right to(device) behavior +class ToCopy : public torch::lazy::TsNode { + public: + static OpKind ClassOpKind() { + return OpKind(at::aten::_to_copy); + } + + ToCopy( + const torch::lazy::Value& self, + const std::optional& dtype, + const std::optional& layout, + const std::optional& device, + const std::optional& pin_memory, + const bool& non_blocking, + const std::optional& memory_format, + std::vector&& shapes) + : torch::lazy::TsNode( + ClassOpKind(), + {self}, + std::move(shapes), + /* num_outputs */ 1, + torch::lazy::MHash( + dtype, + layout, + device, + pin_memory, + non_blocking, + memory_format)), + + dtype(dtype), + layout(layout), + device(device), + pin_memory(pin_memory), + non_blocking(non_blocking), + memory_format(memory_format) {} + + bool CanBeReused( + const torch::lazy::Value& self, + const std::optional& dtype, + const std::optional& layout, + const std::optional& device, + const std::optional& pin_memory, + const bool& non_blocking, + const std::optional& memory_format) const { + size_t i = 0; + return ( + operand(i++) == self && this->dtype == dtype && + this->layout == layout && this->device == device && + this->pin_memory == pin_memory && this->non_blocking == non_blocking && + this->memory_format == memory_format); + } + + std::string ToString() const override { + std::stringstream ss; + ss << torch::lazy::TsNode::ToString(); + if (dtype.has_value()) { + ss << ", dtype=" << dtype.value(); + } else { + ss << ", dtype=null"; + } + if (layout.has_value()) { + ss << ", layout=" << layout.value(); + } else { + ss << ", layout=null"; + } + if (device.has_value()) { + ss << ", device=" << device.value(); + } else { + ss << ", device=null"; + } + if (pin_memory.has_value()) { + ss << ", pin_memory=" << pin_memory.value(); + } else { + ss << ", pin_memory=null"; + } + ss << ", non_blocking=" << non_blocking; + if (memory_format.has_value()) { + ss << ", memory_format=" << memory_format.value(); + } else { + ss << ", memory_format=null"; + } + return ss.str(); + } + + torch::lazy::TSOpVector Lower( + std::shared_ptr function, + torch::lazy::TSLoweringContext* loctx) const override { + std::vector arguments; + std::vector kwarguments; + arguments.reserve(1); + kwarguments.reserve(6); + size_t i = 0; + arguments.emplace_back(loctx->GetOutputOp(operand(i++))); + kwarguments.emplace_back("dtype", dtype); + kwarguments.emplace_back("layout", layout); + kwarguments.emplace_back("device", device); + kwarguments.emplace_back("pin_memory", pin_memory); + kwarguments.emplace_back("non_blocking", non_blocking); + kwarguments.emplace_back("memory_format", memory_format); + torch::lazy::TSOpVector _to_copy_out = + torch::lazy::LowerTSBuiltin(function, op().op, arguments, kwarguments); + TORCH_CHECK_EQ(_to_copy_out.size(), 1); + + return _to_copy_out; + } + + std::optional dtype; + std::optional layout; + std::optional device; + std::optional pin_memory; + bool non_blocking; + std::optional memory_format; +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/tensor_aten_ops.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/tensor_aten_ops.h new file mode 100644 index 0000000000000000000000000000000000000000..b6d42fb70a08f6942e1a9c89ea387b0221878cb2 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/tensor_aten_ops.h @@ -0,0 +1,20 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::lazy { + +////////////////////////////////////////////////////////////////////////////// +// ATEN operators follows here, listed in alphabetical order. +////////////////////////////////////////////////////////////////////////////// + +void copy_(torch::lazy::LazyTensorPtr& input, torch::lazy::LazyTensorPtr& src); +// Fills the input with the given value. +void fill_(torch::lazy::LazyTensorPtr& input, const at::Scalar& value); + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_autograd_functions.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_autograd_functions.h new file mode 100644 index 0000000000000000000000000000000000000000..3d7ba8436e4923dac4fe138a1a90cb62b084b546 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_autograd_functions.h @@ -0,0 +1,27 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::lazy { + +struct MaxPool3dAutogradFunctionTS + : public torch::autograd::Function { + static at::Tensor forward( + torch::autograd::AutogradContext* ctx, + const at::Tensor& self, + at::IntArrayRef kernel_size, + at::IntArrayRef stride, + at::IntArrayRef padding, + at::IntArrayRef dilation, + bool ceil_mode); + static torch::autograd::variable_list backward( + torch::autograd::AutogradContext* ctx, + torch::autograd::variable_list grad_output); +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_backend_impl.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_backend_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..d00d8f1812545994e00b2137df9cdc11c1cf20e8 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_backend_impl.h @@ -0,0 +1,57 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include + +namespace torch::lazy { + +class TORCH_API TSData : public torch::lazy::BackendData { + public: + TSData(const at::Scalar& scalar, const torch::lazy::BackendDevice& device) + : torch::lazy::BackendData(device, torch::lazy::Shape(scalar.type(), {})), + scalar(scalar) {} + + TSData( + at::Tensor data, + const torch::lazy::Shape& shape, + const torch::lazy::BackendDevice& device) + : torch::lazy::BackendData(device, shape), data_(std::move(data)) {} + + TSData( + const torch::lazy::Shape& shape, + const torch::lazy::BackendDevice& device) + : torch::lazy::BackendData(device, shape) {} + + Handle GetHandle() override { + return reinterpret_cast(this); + } + + void Assign(const torch::lazy::BackendData& data) override { + data_ = static_cast(data).data_; + } + + bool HasValue() const override { + return data_.defined(); + } + + at::Tensor data() { + return data_; + } + + std::optional scalar; + + private: + at::Tensor data_; +}; + +TORCH_API torch::lazy::BackendImplInterface* GetTSBackendImpl(); + +TORCH_PYTHON_API void InitTorchScriptBackend(); + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_eager_fallback.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_eager_fallback.h new file mode 100644 index 0000000000000000000000000000000000000000..3cbf6f8a37d864acfe1f2be569a1b7cc436801fc --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_eager_fallback.h @@ -0,0 +1,30 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +namespace torch::lazy { + +bool force_eager_fallback(c10::Symbol op); +void ltc_eager_fallback( + const c10::OperatorHandle& op, + torch::jit::Stack* stack); + +void ts_eager_fallback( + const c10::OperatorHandle& op, + torch::jit::Stack* stack, + c10::DeviceType device_type); + +// The TorchScript backend does not register itself with pytorch dispatcher +// until it is explicitly initialized. This function should only be called +// by the main Torchscript backend init function. +void register_ts_ltc_eager_fallback(); + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_lowering_context.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_lowering_context.h new file mode 100644 index 0000000000000000000000000000000000000000..3ab1b3191135cd0ef213962515cc264459f9f28b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_lowering_context.h @@ -0,0 +1,156 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +namespace torch::lazy { + +using TSOpVector = std::vector; + +class TORCH_API TSComputation : public Computation { + public: + TSComputation(const std::shared_ptr& graph) + : graph_(graph), graph_executor_(graph, "") { + for (torch::jit::Value* input : graph_->inputs()) { + parameter_names_.push_back(input->debugName()); + } + } + + int parameters_size() const override { + return static_cast(parameter_names_.size()); + } + + const std::vector& parameter_shapes() const override { + TORCH_CHECK( + false, "TODO(whc) implement TS computation shapes or change interface"); + return parameter_shapes_; + } + + const std::vector& parameter_names() const override { + return parameter_names_; + } + + const Shape& result_shape() const override { + TORCH_CHECK( + false, "TODO(whc) implement TS computation shapes or change interface"); + return result_shape_; + } + + const std::string to_string() const override { + std::ostringstream oss; + oss << *graph_; + return oss.str(); + } + + std::shared_ptr graph() const { + return graph_; + } + + torch::jit::GraphExecutor& graph_executor() { + return graph_executor_; + } + + private: + std::shared_ptr graph_; + torch::jit::GraphExecutor graph_executor_; + std::vector parameter_names_; + std::vector parameter_shapes_; + Shape result_shape_; +}; + +class TORCH_API TSLoweringContext : public LoweringContext { + public: + TSLoweringContext(const std::string& name, const BackendDevice device); + + TSLoweringContext( + const std::string& name, + BackendDevice device, + c10::ArrayRef post_order, + Util::EmissionMap emit_status); + + size_t AddResult(const Output& output) override { + return AddResult(GetOutputOp(output)); + } + + void AddParameter( + const torch::lazy::Output& output, + size_t index, + const Shape& shape, + const std::string& name) override { + TORCH_INTERNAL_ASSERT(false, "not implemented"); + } + + void Lower(const Node* node); + + ComputationPtr Build() override { + for (torch::jit::Value* output : root_tuple_) { + graph_->block()->registerOutput(output); + } + return std::make_shared(graph_); + } + + // Retrieves the lowered operation for an output. If the requested output is + // not available yet, the graph behind the output's Node is lowered, and the + // corresponding TS operation returned. + torch::jit::Value* GetOutputOp(const Output& output) { + auto it = emitted_outputs_.find(output); + if (it == emitted_outputs_.end()) { + auto post_order = Util::ComputePostOrder(output.node, &emit_status_); + for (auto node : post_order) { + Lower(node); + } + // At this point the output better be present, otherwise there is an issue + // with the lowering code. + it = emitted_outputs_.find(output); + TORCH_CHECK( + it != emitted_outputs_.end(), + "No TS operation emitted for output: ", + output.ToString()); + } + return it->second; + } + + // Assigns the given TS operation to the specified output. As outputs are + // lowered in a post-order fashion, later nodes should always find their + // operands among the emitted outputs. + void AssignOutputOp(const Output& output, torch::jit::Value* op); + + // If a parameter associated with data has already been declared, it will be + // returned. Otherwise a new one will be created, associated with the tensor + // held in data. + torch::jit::Value* GetParameter(const BackendDataPtr& data); + + std::shared_ptr graph() const { + return graph_; + } + + private: + struct Parameter { + torch::jit::Value* param{nullptr}; + size_t index = 0; + }; + + size_t AddResult(torch::jit::Value* op) { + root_tuple_.push_back(op); + return root_tuple_.size() - 1; + } + + std::shared_ptr graph_; + std::shared_ptr function_; + std::unordered_map parameters_map_; + std::vector root_tuple_; + OutputMap emitted_outputs_; +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_node.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_node.h new file mode 100644 index 0000000000000000000000000000000000000000..5efd7eed90acd7f260b9f9a64fd86819cc9fb6c3 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_node.h @@ -0,0 +1,109 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace torch::lazy { + +using TSOpVector = std::vector; + +class TORCH_API TsNode : public lazy::Node { + public: + TsNode( + OpKind op, + OpList operands, + std::vector&& shapes, + size_t num_outputs, + hash_t hash_seed = kHashSeed); + + TsNode( + OpKind op, + OpList operands, + const std::function& shape_fn, + size_t num_outputs, + hash_t hash_seed = kHashSeed); + + TsNode( + OpKind op, + OpList operands, + size_t num_outputs, + hash_t hash_seed = kHashSeed); + + TsNode( + OpKind op, + Shape shape, + size_t num_outputs, + hash_t hash_seed = kHashSeed); + + ~TsNode() override = default; + + hash_t hash() const override; + + hash_t shapeHash() const override; + + const std::string getPythonStacktrace() const; + + // Lower is a backend-specific method since it returns a backend specific + // type. hence, it is convenient to define it differently per-backend rather + // than at Node API + virtual TSOpVector Lower( + std::shared_ptr function, + TSLoweringContext* loctx) const; + + private: + // The hash of the dag WITH size info. Used for shape caching + hash_t shape_hash_; + // The hash of the dag used to look up the compiled graph by a hash + // in this case, we will use the dag hash WITHOUT size info if dynamic shape + // is enabled and use the dag hash WITH size info otherwise. + hash_t dag_hash_; +}; + +// Note: this OpKind is separate from ltc_ops.h since it would be a circular +// import otherwise, I like leaving TensorList in this file, and I think most of +// ltc_ops special cases will be deleted anyway +const OpKind tensor_list_opkind = OpKind::Get("lazy_tensors::tensor_list"); + +// TensorList represents an at::TensorList which is a vector[Tensor] but is also +// a first-class IValue and can be fed as a single input to a TS program. It is +// much easier to handle TensorLists in Lazy Tensor code if they are represented +// as a single Node so there can be more than one TensorList and more than one +// Tensor side-by-side as operands to an op. +// +// Note: shape is undefined for TensorList. We assert in some places that +// #shapes matches #outputs and this stems from +// the fact that currently all IR nodes represent tensors (there is no +// type system for this IR). Because of this, TensorList is a bit of a +// hack. +// +// TODO(whc) once Shape() API is moved to Node base, also make it virtual, and +// then implement it as NotImplemented for TensorList, also fixing the assertion +// that would fail. +struct TORCH_API TensorList : public TsNode { + static OpKind ClassOpKind() { + return tensor_list_opkind; + } + + TensorList() = delete; + TensorList(OpList values); + + bool CanBeReused(OpList values) const { + return operands() == std::vector(values.begin(), values.end()); + } + + TSOpVector Lower( + std::shared_ptr function, + TSLoweringContext* loctx) const override; +}; + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_node_lowering.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_node_lowering.h new file mode 100644 index 0000000000000000000000000000000000000000..37a11e964bb5e8e4eeaff374b8a5b7792c3502b0 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/lazy/ts_backend/ts_node_lowering.h @@ -0,0 +1,20 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::lazy { +using TSOpVector = std::vector; + +TORCH_API TSOpVector LowerTSBuiltin( + const std::shared_ptr& function, + c10::Symbol sym, + const std::vector& arguments, + const std::vector& kwarguments = {}); + +} // namespace torch::lazy + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/monitor/counters.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/monitor/counters.h new file mode 100644 index 0000000000000000000000000000000000000000..137c149ed6737e3484f6536a6dba0462c47f33ee --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/monitor/counters.h @@ -0,0 +1,285 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +#include + +#include + +namespace torch::monitor { + +constexpr int NUM_AGGREGATIONS = 7; + +// Aggregation is the list of possible aggregations for Stats. +// These use bitwise flags so they can be efficiently stored. +enum class C10_API_ENUM Aggregation { + // NONE means no aggregations are set. + NONE = 0, + // VALUE exports the most recently set value. + VALUE = 1, + // MEAN computes the mean of the set values within the window. Zero if no + // values. + MEAN = 2, + // COUNT tracks the number of times a value is set within the window. + COUNT = 3, + // SUM computes the sum of the values set within the window. + SUM = 4, + // MIN computes the minimum of the values set within the window. Zero if no + // values. + MAX = 5, + // MAX computes the maximum of the values set within the window. Zero if no + // values. + MIN = 6, +}; + +struct TORCH_API AggregationHash{template std::size_t operator()( + T t) const {return static_cast(t); +} // namespace torch::monitor +} +; + +// aggregationName returns the human readable name corresponding to the +// aggregation. +TORCH_API const char* aggregationName(Aggregation agg); + +template +class Stat; + +namespace { +template +inline std::bitset merge(T& list) { + std::bitset a; + for (Aggregation b : list) { + a.set(static_cast(b)); + } + return a; +} +} // namespace + +namespace detail { +void TORCH_API registerStat(Stat* stat); +void TORCH_API registerStat(Stat* stat); +void TORCH_API unregisterStat(Stat* stat); +void TORCH_API unregisterStat(Stat* stat); +} // namespace detail + +// Stat is used to compute summary statistics in a performant way over fixed +// intervals. Stat logs the statistics as an Event once every `windowSize` +// duration. When the window closes the stats are logged via the event handlers +// as a `torch.monitor.Stat` event. +// +// `windowSize` should be set to something relatively high to avoid a huge +// number of events being logged. Ex: 60s. Stat uses millisecond precision. +// +// If maxSamples is set, the stat will cap the number of samples per window by +// discarding `add` calls once `maxSamples` adds have occurred. If it's not set, +// all `add` calls during the window will be included. +// This is an optional field to make aggregations more directly comparable +// across windows when the number of samples might vary. +// +// Stats support double and int64_t data types depending on what needs to be +// logged and needs to be templatized with one of them. +// +// When the Stat is destructed it will log any remaining data even if the window +// hasn't elapsed. +template +class Stat { + private: + struct Values { + T value{0}; + T sum{0}; + T min{0}; + T max{0}; + int64_t count{0}; + }; + + public: + Stat( + std::string name, + std::initializer_list aggregations, + std::chrono::milliseconds windowSize, + int64_t maxSamples = std::numeric_limits::max()) + : name_(std::move(name)), + aggregations_(merge(aggregations)), + windowSize_(windowSize), + maxSamples_(maxSamples) { + detail::registerStat(this); + } + + Stat( + std::string name, + std::vector aggregations, + std::chrono::milliseconds windowSize, + int64_t maxSamples = std::numeric_limits::max()) + : name_(std::move(name)), + aggregations_(merge(aggregations)), + windowSize_(windowSize), + maxSamples_(maxSamples) { + detail::registerStat(this); + } + Stat(const Stat&) = delete; + Stat(Stat&&) = delete; + Stat& operator=(const Stat&) = delete; + Stat& operator=(Stat&&) = delete; + + virtual ~Stat() { + { + // on destruction log if there's unlogged data + std::lock_guard guard(mu_); + logLocked(); + } + detail::unregisterStat(this); + } + + // add adds the value v to the current window. + void add(T v) { + std::lock_guard guard(mu_); + maybeLogLocked(); + + if (alreadyLogged()) { + return; + } + + if (aggregations_.test(static_cast(Aggregation::VALUE))) { + current_.value = v; + } + if (aggregations_.test(static_cast(Aggregation::MEAN)) || + aggregations_.test(static_cast(Aggregation::SUM))) { + current_.sum += v; + } + + if (aggregations_.test(static_cast(Aggregation::MAX))) { + if (current_.max < v || current_.count == 0) { + current_.max = v; + } + } + if (aggregations_.test(static_cast(Aggregation::MIN))) { + if (current_.min > v || current_.count == 0) { + current_.min = v; + } + } + + current_.count += 1; + maybeLogLocked(); + } + + const std::string& name() const noexcept { + return name_; + } + + // count returns the number of items in the current open window. + int64_t count() noexcept { + std::lock_guard guard(mu_); + + return current_.count; + } + + std::unordered_map get() noexcept { + std::lock_guard guard(mu_); + return getLocked(); + } + + protected: + virtual uint64_t currentWindowId() const { + std::chrono::milliseconds now = + std::chrono::duration_cast( + std::chrono::steady_clock::now().time_since_epoch()); + + // always returns a currentWindowId of at least 1 to avoid 0 window issues + return (now / windowSize_) + 1; + } + + private: + bool alreadyLogged() { + return lastLoggedWindowId_ == currentWindowId(); + } + + void maybeLogLocked() { + auto windowId = currentWindowId(); + bool shouldLog = windowId_ != windowId || current_.count >= maxSamples_; + if (shouldLog && !alreadyLogged()) { + logLocked(); + lastLoggedWindowId_ = windowId_; + windowId_ = windowId; + } + } + + void logLocked() { + prev_ = current_; + current_ = Values(); + + // don't log event if there's no data + if (prev_.count == 0) { + return; + } + + Event e; + e.name = "torch.monitor.Stat"; + e.timestamp = std::chrono::system_clock::now(); + + auto stats = getLocked(); + e.data.reserve(stats.size()); + for (auto& kv : stats) { + std::stringstream key; + key << name_; + key << '.'; + key << aggregationName(kv.first); + e.data[key.str()] = kv.second; + } + + logEvent(e); + } + + std::unordered_map getLocked() + const noexcept { + std::unordered_map out; + out.reserve(aggregations_.count()); + + if (aggregations_.test(static_cast(Aggregation::VALUE))) { + out.emplace(Aggregation::VALUE, prev_.value); + } + if (aggregations_.test(static_cast(Aggregation::MEAN))) { + if (prev_.count == 0) { + out.emplace(Aggregation::MEAN, 0); + } else { + out.emplace(Aggregation::MEAN, prev_.sum / prev_.count); + } + } + if (aggregations_.test(static_cast(Aggregation::COUNT))) { + out.emplace(Aggregation::COUNT, prev_.count); + } + if (aggregations_.test(static_cast(Aggregation::SUM))) { + out.emplace(Aggregation::SUM, prev_.sum); + } + if (aggregations_.test(static_cast(Aggregation::MAX))) { + out.emplace(Aggregation::MAX, prev_.max); + } + if (aggregations_.test(static_cast(Aggregation::MIN))) { + out.emplace(Aggregation::MIN, prev_.min); + } + + return out; + } + + const std::string name_; + const std::bitset aggregations_; + + std::mutex mu_; + Values current_; + Values prev_; + + uint64_t windowId_{0}; + uint64_t lastLoggedWindowId_{0}; + const std::chrono::milliseconds windowSize_; + const int64_t maxSamples_; +}; +} // namespace torch::monitor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/monitor/events.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/monitor/events.h new file mode 100644 index 0000000000000000000000000000000000000000..320d63457f91c46c501bfc9c62d1e3aeb8624676 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/monitor/events.h @@ -0,0 +1,76 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace torch::monitor { + +// data_value_t is the type for Event data values. +using data_value_t = std::variant; + +// Event represents a single event that can be logged out to an external +// tracker. This does acquire a lock on logging so should be used relatively +// infrequently to avoid performance issues. +struct TORCH_API Event { + // name is the name of the event. This is a static string that's used to + // differentiate between event types for programmatic access. The type should + // be in the format of a fully qualified Python-style class name. + // Ex: torch.monitor.MonitorEvent + std::string name; + + // timestamp is a timestamp relative to the Unix epoch time. + std::chrono::system_clock::time_point timestamp; + + // data contains rich information about the event. The contents are event + // specific so you should check the type to ensure it's what you expect before + // accessing the data. + // + // NOTE: these events are not versioned and it's up to the consumer of the + // events to check the fields to ensure backwards compatibility. + std::unordered_map data; +}; + +inline bool operator==(const Event& lhs, const Event& rhs) { + return lhs.name == rhs.name && lhs.timestamp == rhs.timestamp && + lhs.data == rhs.data; +} + +// EventHandler represents an abstract event handler that can be registered to +// capture events. Every time an event is logged every handler will be called +// with the events contents. +// +// NOTE: The handlers should avoid any IO, blocking calls or heavy computation +// as this may block the main thread and cause performance issues. +class TORCH_API EventHandler { + public: + virtual ~EventHandler() = default; + + // handle needs to be implemented to handle the events. This may be called + // from multiple threads so needs to be thread safe. + virtual void handle(const Event& e) = 0; +}; + +// logEvent calls each registered event handler with the event. This method can +// be called from concurrently from multiple threads. +TORCH_API void logEvent(const Event& e); + +// registerEventHandler registers an EventHandler so it receives any logged +// events. Typically an EventHandler will be registered during program +// setup and unregistered at the end. +TORCH_API void registerEventHandler(std::shared_ptr p); + +// unregisterEventHandler unregisters the event handler pointed to by the +// shared_ptr. +TORCH_API void unregisterEventHandler(const std::shared_ptr& p); + +} // namespace torch::monitor + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/monitor/python_init.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/monitor/python_init.h new file mode 100644 index 0000000000000000000000000000000000000000..bfe66eacb1ec44f7734a1ac71bfba64614e1d6a8 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/monitor/python_init.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::monitor { + +void initMonitorBindings(PyObject* module); + +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/mps/Module.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/mps/Module.h new file mode 100644 index 0000000000000000000000000000000000000000..f636e580b673f35d4e0fbbc7308c79f020d72bc5 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/mps/Module.h @@ -0,0 +1,15 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::mps { + +PyMethodDef* python_functions(); +void initModule(PyObject* module); + +} // namespace torch::mps + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/mtia/Module.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/mtia/Module.h new file mode 100644 index 0000000000000000000000000000000000000000..84259c7651ebceace7f29d7429e5e3217eba57a4 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/mtia/Module.h @@ -0,0 +1,15 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::mtia { + +// PyMethodDef* python_functions(); +void initModule(PyObject* module); + +} // namespace torch::mtia + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/mtia/profiler/MTIAMemoryProfiler.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/mtia/profiler/MTIAMemoryProfiler.h new file mode 100644 index 0000000000000000000000000000000000000000..b50d495618218335dd644f3da308eb59f28a9eac --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/mtia/profiler/MTIAMemoryProfiler.h @@ -0,0 +1,25 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include + +namespace torch::mtia { +using namespace torch::profiler::impl::python_tracer; + +void initMemoryProfiler(); + +std::unique_ptr getMemoryTracer(); + +class MTIAMemoryProfiler final : public PythonMemoryTracerBase { + public: + explicit MTIAMemoryProfiler() = default; + ~MTIAMemoryProfiler() override = default; + void start() override; + void stop() override; + void export_memory_history(const std::string& path) override; +}; + +} // namespace torch::mtia + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/multiprocessing/init.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/multiprocessing/init.h new file mode 100644 index 0000000000000000000000000000000000000000..1800ffa2ce1dd605a0daae7e707516920537060f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/multiprocessing/init.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::multiprocessing { + +const PyMethodDef* python_functions(); + +} // namespace torch::multiprocessing + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/onnx/back_compat.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/onnx/back_compat.h new file mode 100644 index 0000000000000000000000000000000000000000..5132fe262ac095863a64efb85bf0358dbde14e35 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/onnx/back_compat.h @@ -0,0 +1,30 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::onnx { + +// The following constants are defined here to avoid breaking Meta's internal +// usage of ONNX which pre-dates ONNX 1.14 and thus does not support FLOAT8: +// cf. https://github.com/pytorch/pytorch/pull/106379#issuecomment-1675189340 +// -abock, 2023-08-25 +// +// ::ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E4M3FN +constexpr auto TensorProto_DataType_FLOAT8E4M3FN = + static_cast<::ONNX_NAMESPACE::TensorProto_DataType>(17); +// ::ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E4M3FNUZ +constexpr auto TensorProto_DataType_FLOAT8E4M3FNUZ = + static_cast<::ONNX_NAMESPACE::TensorProto_DataType>(18); +// ::ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E5M2 +constexpr auto TensorProto_DataType_FLOAT8E5M2 = + static_cast<::ONNX_NAMESPACE::TensorProto_DataType>(19); +// ::ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E5M2FNUZ +constexpr auto TensorProto_DataType_FLOAT8E5M2FNUZ = + static_cast<::ONNX_NAMESPACE::TensorProto_DataType>(20); + +} // namespace torch::onnx + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/onnx/init.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/onnx/init.h new file mode 100644 index 0000000000000000000000000000000000000000..4c451df8c9e5f9af3b5ece63f82e9c93cdd785ee --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/onnx/init.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::onnx { + +void initONNXBindings(PyObject* module); + +} // namespace torch::onnx + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/onnx/onnx.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/onnx/onnx.h new file mode 100644 index 0000000000000000000000000000000000000000..6a5eb189134d0eaac3e056b939ef8cf539edb8d9 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/onnx/onnx.h @@ -0,0 +1,25 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +namespace torch::onnx { + +enum class OperatorExportTypes { + ONNX, // Strict ONNX export + ONNX_ATEN, // ONNX With ATen op everywhere + ONNX_ATEN_FALLBACK, // ONNX export with ATen fallback + ONNX_FALLTHROUGH, // Export supported ONNX ops. Pass through unsupported ops. +}; + +enum class TrainingMode { + EVAL, // Inference mode + PRESERVE, // Preserve model state (eval/training) + TRAINING, // Training mode +}; + +constexpr auto kOnnxNodeNameAttribute = "onnx_name"; + +} // namespace torch::onnx + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/api.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/api.h new file mode 100644 index 0000000000000000000000000000000000000000..02514ee197c4cacafa6b324da402be8ed4504787 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/api.h @@ -0,0 +1,19 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +// There are some components which use these symbols. Until we migrate them +// we have to mirror them in the old autograd namespace. + +namespace torch::autograd::profiler { +using torch::profiler::impl::ActivityType; +using torch::profiler::impl::getProfilerConfig; +using torch::profiler::impl::ProfilerConfig; +using torch::profiler::impl::profilerEnabled; +using torch::profiler::impl::ProfilerState; +} // namespace torch::autograd::profiler + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/collection.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/collection.h new file mode 100644 index 0000000000000000000000000000000000000000..98fbf924244663974e55609f445efae537ea9a62 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/collection.h @@ -0,0 +1,715 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace torch::profiler::impl { + +enum class EventType : uint8_t { + TorchOp = 0, + Backend, + Vulkan, + Allocation, + OutOfMemory, + PyCall, + PyCCall, + Kineto, + PythonGC +}; + +// ============================================================================ +// == Value (Tensor, Scalar) summary ========================================== +// ============================================================================ +struct TORCH_API RawTensorMetadataBase { + RawTensorMetadataBase() = default; + explicit RawTensorMetadataBase(const at::Tensor& t); + + StorageImplData data_; + c10::ScalarType dtype_{c10::ScalarType::Undefined}; + c10::Layout layout_{c10::Layout::Strided}; + uint32_t size_dim_{0}; +}; + +// Collected during profiling. +struct TORCH_API RawTensorMetadata : RawTensorMetadataBase { + RawTensorMetadata() = default; + RawTensorMetadata(const RawTensorMetadata&) = default; + RawTensorMetadata(RawTensorMetadata&&) noexcept = default; + RawTensorMetadata& operator=(const RawTensorMetadata&) = default; + RawTensorMetadata& operator=(RawTensorMetadata&&) noexcept = default; + ~RawTensorMetadata() = default; + explicit RawTensorMetadata(const at::Tensor& t); + + // Wrap `weak_self_` in `std::optional` and split device into components to + // keep struct default constructable. (which the std::array initializer needs) + std::optional weak_self_; + c10::DeviceType device_type_{c10::DeviceType::CPU}; + c10::DeviceIndex device_index_{-1}; +}; + +// Used during post processing. +struct TORCH_API TensorMetadata : public RawTensorMetadataBase { + TensorMetadata( + const RawTensorMetadata& r, + std::vector sizes, + std::vector strides); + + TensorImplAddress impl() const { + return weak_self_.get(); + } + + WeakTensor weak_self_; + c10::Device device_; + std::vector sizes_; + std::vector strides_; + + // Set during `calculateUniqueTensorIDs`. + std::optional id_; + std::optional allocation_id_; +}; + +// Used during post processing. +struct TORCH_API ProfilerStepInfo { + int64_t start_time_ns; // start time of the profiler step + int64_t end_time_ns; // end time of the profiler step + uint64_t out_idx; // index of the profiler step in the profiler "out" var in + // getRecords + + ProfilerStepInfo(int64_t start, int64_t end, uint64_t out_idx) + : start_time_ns(start), end_time_ns(end), out_idx(out_idx) {} +}; + +using op_input_t = std::variant< + TensorMetadata, + std::vector, + c10::IValue, + std::nullopt_t>; + +// ============================================================================ +// == ExtraFields ============================================================= +// ============================================================================ +template +struct ExtraFields; + +struct TorchOpBasicFields { + int64_t sequence_number_{0}; + uint64_t forward_tid_{0}; + at::RecordScope scope_{}; + bool is_async_{false}; + uint64_t record_function_id_{0}; + int64_t debug_handle_{0}; + std::string name_; + std::string overload_name_; + + // Set in the exit callback. + uint64_t end_tid_{0}; +}; + +using jit_stack_t = std::vector; +using jit_modules_t = std::vector; +using extra_args_t = std::unordered_map; +using extra_meta_t = std::unordered_map; +using kwinputs_t = std::unordered_map; + +// Mirrors `libkineto::GenericTraceActivity::Flow`. Used during post processing +// to embed Kineto events into the broader profiler tree structure. +struct Flow { + uint32_t id{0}; + uint32_t type{0}; + uint32_t start{0}; +}; + +struct FallbackPair { + ProfilerVoidEventStub device_event_start_ = nullptr; + ProfilerVoidEventStub device_event_end_ = nullptr; +}; + +template <> +struct ExtraFields : TorchOpBasicFields { + ExtraFields( + TorchOpBasicFields&& f, + uint64_t correlation_id, + c10::time_t end_time_ns, + std::vector&& inputs, + std::vector&& concrete_inputs, + jit_stack_t&& jit_stack, + jit_modules_t&& jit_modules, + extra_args_t&& extra_args, + extra_meta_t&& extra_meta, + kwinputs_t&& kwinputs, + FallbackPair&& device_fallback, + bool allow_tf32_cublas, + std::unique_ptr&& perf_event_counters) + : TorchOpBasicFields(std::move(f)), + correlation_id_{correlation_id}, + end_time_ns_{end_time_ns}, + inputs_{std::move(inputs)}, + concrete_inputs_{std::move(concrete_inputs)}, + jit_stack_{std::move(jit_stack)}, + jit_modules_{std::move(jit_modules)}, + extra_args_{std::move(extra_args)}, + extra_meta_{std::move(extra_meta)}, + kwinputs_{std::move(kwinputs)}, + device_fallback_{std::move(device_fallback)}, + allow_tf32_cublas_{allow_tf32_cublas}, + perf_event_counters_{std::move(perf_event_counters)} {} + uint64_t correlation_id_; + c10::time_t end_time_ns_; + std::vector inputs_; + std::vector concrete_inputs_; + jit_stack_t jit_stack_; + jit_modules_t jit_modules_; + extra_args_t extra_args_; + extra_meta_t extra_meta_; + kwinputs_t kwinputs_; + FallbackPair device_fallback_; + bool allow_tf32_cublas_; + std::unique_ptr perf_event_counters_; + std::string metadata_json_; + Flow flow; +}; + +template <> +struct ExtraFields { + int64_t start_time_us_; + int64_t end_time_us_; + int64_t debug_handle_; + at::RecordScope scope_; + std::string name_; + std::string backend_; + jit_stack_t jit_stack_; + jit_modules_t jit_modules_; +}; + +template <> +struct ExtraFields { + std::string phase; + int64_t duration_ns_; +}; + +template <> +struct ExtraFields { + using raw_event_t = std::pair; + std::string name_; + int64_t duration_ns_{0}; + // While building the event tree, we want to report a vulkan event's duration + // as 0 so that its end time doesn't exceed that of its parent cpu op + bool in_tree_building_{false}; +}; + +struct RawAllocation { + c10::approx_time_t start_time_; + void* ptr_; + int64_t alloc_size_; + size_t total_allocated_; + size_t total_reserved_; + c10::DeviceType device_type_; + c10::DeviceIndex device_index_; +}; + +// For performance. +static_assert( + std::is_trivial_v, + "Non-Trivial member of RawAllocation."); + +template <> +struct ExtraFields : RawAllocation { + ExtraFields(const RawAllocation& allocation) : RawAllocation(allocation) {} + + c10::Device device() const { + return {device_type_, device_index_}; + } + + std::optional id_; + std::optional allocation_id_; +}; + +template <> +struct ExtraFields { + c10::approx_time_t start_time_; + int64_t alloc_size_; + size_t total_allocated_; + size_t total_reserved_; + c10::DeviceType device_type_; + c10::DeviceIndex device_index_; +}; + +// For performance. +static_assert( + std::is_trivial_v>, + "Non-Trivial member of ExtraFields."); + +struct PyFrameState { + int line_no_; + at::StringView filename_; + at::StringView funcname_; +}; + +template +using strong_t = strong:: + type, strong::hashable>; + +using PyModuleSelf = strong_t; +using PyModuleCls = strong_t; +using PyMethod = strong_t; +using PyOptimizerSelf = strong_t; +using PyOptimizerCls = strong_t; + +struct NNModuleInfo { + struct ParameterInfo { + std::string name_; + TensorMetadata metadata_; + std::optional grad_metadata_; + }; + + PyModuleSelf self_; + PyModuleCls cls_; + at::StringView cls_name_; + + std::vector parameters_; + // Indicates that `self_` is the kth instance of `cls_` observed. + size_t id_{std::numeric_limits::max()}; +}; + +struct OptimizerInfo { + struct ParameterInfo { + TensorMetadata metadata_; + std::optional grad_metadata_; + std::vector> state_; + }; + + PyOptimizerSelf self_; + PyOptimizerCls cls_; + at::StringView cls_name_; + + std::vector parameters_; +}; + +struct PyExtraFieldsBase { + PyExtraFieldsBase( + c10::time_t end_time_ns, + size_t python_tid, + PyFrameState caller) + : end_time_ns_{end_time_ns}, + python_tid_{python_tid}, + caller_{std::move(caller)} {} + + c10::time_t end_time_ns_; + size_t python_tid_; + PyFrameState caller_; + + // kth python event observed. (Used by TensorBoard) + size_t id_{std::numeric_limits::max()}; +}; + +template <> +struct ExtraFields : public PyExtraFieldsBase { + struct args_t { + PyFrameState frame_state_; + std::optional module_info_; + std::optional optimizer_info_; + }; + + ExtraFields( + c10::time_t end_time_ns, + size_t python_tid, + PyFrameState caller, + args_t args) + : PyExtraFieldsBase(end_time_ns, python_tid, std::move(caller)), + callsite_{std::move(args.frame_state_)}, + module_{std::move(args.module_info_)}, + optimizer_{std::move(args.optimizer_info_)} {} + + PyFrameState callsite_; + std::optional module_; + std::optional optimizer_; +}; + +template <> +struct ExtraFields : public PyExtraFieldsBase { + using args_t = at::StringView; + + ExtraFields( + c10::time_t end_time_ns, + size_t python_tid, + PyFrameState caller, + args_t args) + : PyExtraFieldsBase(end_time_ns, python_tid, std::move(caller)), + function_name_{std::move(args)} {} + + at::StringView function_name_; +}; + +template <> +struct ExtraFields { + std::string name_; + int64_t duration_ns_{0}; + uint64_t correlation_id_{0}; + libkineto::ActivityType activity_type_; + Flow flow; + std::weak_ptr linked_activity_; + std::string metadata_json_; + extra_meta_t extra_meta_; +}; + +struct TORCH_API Result : public std::enable_shared_from_this { + template + [[nodiscard]] static std::shared_ptr create(Args... args) { + return std::shared_ptr(new Result(std::forward(args)...)); + } + + template + auto visit(T&& visitor) { + return std::visit(std::forward(visitor), extra_fields_); + } + + template + auto visit(T&& visitor) const { + return std::visit(std::forward(visitor), extra_fields_); + } + + template + void visit_if_base(const Fn& fn) const { + visit([&](const auto& extra_fields) { + using extra_fields_t = typename std::remove_cv_t< + typename std::remove_reference_t>; + + if constexpr (std::is_base_of_v) { + fn(extra_fields); + } + }); + } + + EventType tag() const { + return visit([](const auto& i) { return deduceTag(i); }); + } + + std::string name() const; + std::string overload_name() const; + libkineto::ActivityType kinetoType() const; + uint64_t correlationID() const; + int64_t endTimeNS() const; + uint64_t endTID() const; + c10::DeviceType deviceType() const; + + int64_t start_time_ns_; + uint64_t start_tid_; + kineto::DeviceAndResource kineto_info_; + std::variant< + ExtraFields, + ExtraFields, + ExtraFields, + ExtraFields, + ExtraFields, + ExtraFields, + ExtraFields, + ExtraFields, + ExtraFields> + extra_fields_; + + std::weak_ptr parent_; + std::vector> children_; + bool finished_{false}; + bool hidden_{false}; + const torch::profiler::impl::kineto::activity_t* kineto_activity_{nullptr}; + + private: + template + Result( + int64_t start_time_ns, + uint64_t start_tid, + kineto::DeviceAndResource kineto_info, + ExtraFields&& extra_fields) + : start_time_ns_{start_time_ns}, + start_tid_{start_tid}, + kineto_info_{kineto_info}, + extra_fields_{std::move(extra_fields)} {} + + template + static EventType deduceTag(const ExtraFields& /*unused*/) { + return E; + } +}; + +struct KinetoObserverContext : public at::ObserverContext { + struct Event { + TorchOpBasicFields basic_fields_; + c10::approx_time_t start_time_; + + // Set in the exit callback. + c10::approx_time_t end_time_{ + std::numeric_limits::min()}; + + bool allow_tf32_cublas_; + std::unique_ptr counters_; + extra_meta_t* extra_nccl_meta_{}; + }; + + explicit KinetoObserverContext(Event* event) : event_{event} {} + + Event* event_; + FallbackPair* fallback_{nullptr}; +}; + +constexpr int IO_ENCODER_DEFAULT_BLOCK_SIZE = 1024; + +constexpr int SCALAR_LIST_LENGTH_LIMIT = 30; + +// InputOutputEncoder +// Stores each op_events' shapes and dtypes, and concrete values into a +// contiguous AppendOnlyList so that we no longer create vectors for shapes +// and dtypes on every op. Those vectors can be created during +// post-processing. +// It splits the data into two categories: input shapes and concrete inputs. +class InputOutputEncoder final { + public: + void push(c10::ArrayRef values); + + // Used during post-processing to unpack the encoded data. + // Each method returns a "supplier" lambda which takes no arguments; + // invoking the lambda once will return a list of args that represent + // the inputs for one op. + // The data is split into two streams: "input shapes" and "concrete inputs". + // Note: "auto" only works because these are only used in collection.cpp, + // where they are implemented. + auto getInputShapeGenerator(); + auto getConcreteInputGenerator(); + + bool isSupportedScalarList(const c10::IValue& list_candidate); + + void clear(); + + enum class Tag { + Tensor = 0, + UndefinedTensor, + TensorListBegin, // TODO: generalize to other lists. + ScalarList, + Scalar, + Other, + TERMINATOR + }; + + enum class IOType { Shapes, ConcreteInputs, None }; + + private: + void push(const at::Tensor& t); + + // Implementation detail for getInputShapeGenerator and + // getConcreteInputGenerator + auto getIValueGenerator(const IOType& io_type); + + AppendOnlyList tags_; + AppendOnlyList + tensor_metadata_; + AppendOnlyList tensor_sizes_strides_; + AppendOnlyList ivalues_; +}; + +using perf_profiler_t = torch::profiler::impl::linux_perf::PerfProfiler; + +class TORCH_API ThreadLocalSubqueue { + public: + ThreadLocalSubqueue(const uint64_t tid, ProfilerConfig config); + + std::unique_ptr begin_op(const at::RecordFunction& fn); + + template + void emplace_backend_event(Args&&... args) { + backend_events_.emplace_back(std::forward(args)...); + } + + template + void emplace_vulkan_event(Args&&... args) { + vulkan_events_.emplace_back(std::forward(args)...); + } + + template + void emplace_allocation_event(Args&&... args) { + allocations_.emplace_back(std::forward(args)...); + } + + template + void emplace_ooms_event(Args&&... args) { + ooms_.emplace_back(std::forward(args)...); + } + + template + void emplace_py_call(Args&&... args) { + py_calls_.emplace_back(std::forward(args)...); + } + + template + void emplace_gc_call(Args&&... args) { + pythongc_.emplace_back(std::forward(args)...); + } + + uint64_t tid() const { + return tid_; + } + + const kineto::DeviceAndResource& kineto_info() const { + return kineto_info_; + } + + inline void disable_perf_profiler(perf_counters_t& counters) const { + perf_profiler_->Disable(counters); + } + + private: + uint64_t tid_; + ProfilerConfig config_; + kineto::DeviceAndResource kineto_info_; + std::unique_ptr perf_profiler_; + + friend class RecordQueue; + // See `containers.h` for block size benchmarks. + static constexpr size_t BlockSize = 512; + + struct TorchOpStorage { + // NB: This is a destructive operation. + void materialize( + std::vector>& out, + std::vector& step_info, + const std::function& time_converter, + const uint64_t tid, + const kineto::DeviceAndResource& kineto_info); + + template + class EventBlock : public std::array { + public: + EventBlock(); + uint64_t correlation_id(const T* ptr) const; + + private: + uint64_t id_start_; + }; + + using event_t = KinetoObserverContext::Event; + class OpList : public AppendOnlyList { + public: + template + std::pair emplace_back(Args&&... args); + static uint64_t correlationID(const OpList::Iterator& e); + } op_events_; + + // report_input_shapes + InputOutputEncoder inputs_outputs_; + + // with_stack (JIT) + AppendOnlyList jit_stack_; + + // with_modules + AppendOnlyList jit_modules_; + + // with_flops + AppendOnlyList extra_args_; + + // report extra metadata, i.e. collective communication meta + AppendOnlyList extra_meta_; + + // report kwinputs + AppendOnlyList kwinputs_; + + // ProfilerState::KINETO_GPU_FALLBACK or + // ProfilerState::KINETO_PRIVATEUSE1_FALLBACK + AppendOnlyList device_fallback_; + } torch_ops_; + + // reportBackendEventToActiveKinetoProfiler + AppendOnlyList, BlockSize> backend_events_; + + // _reportVulkanEventToProfiler + AppendOnlyList::raw_event_t, BlockSize> + vulkan_events_; + + // reportMemoryUsage + AppendOnlyList allocations_; + + // reportOOMs + AppendOnlyList, BlockSize> ooms_; + + // with_stack (Python) + AppendOnlyList< + std::pair, + BlockSize> + py_calls_; + // gc with_stack (Python) + AppendOnlyList, BlockSize> + pythongc_; +}; + +class TORCH_API RecordQueue { + public: + RecordQueue(ProfilerConfig config, std::set activities); + + bool tracePython() const; + bool getPythonGcEvents() const; + ThreadLocalSubqueue* getSubqueue(); + void stop(); + void restart(); + + // NB: This is a destructive operation. + std::pair< + std::vector>, + std::unique_ptr> + getRecords( + std::function time_converter, + uint64_t start_time_ns, + uint64_t end_time_ns); + + private: + uint32_t id_; + ProfilerConfig config_; + std::set activities_; + ska::flat_hash_map> + sub_queues_; + std::mutex sub_queue_mutex_; + std::unique_ptr python_tracer_; +}; + +TORCH_API bool get_record_concrete_inputs_enabled(); +TORCH_API void set_record_concrete_inputs_enabled_fn( + std::function /*fn*/); +TORCH_API void set_record_concrete_inputs_enabled_val(bool /*val*/); + +TORCH_API bool get_fwd_bwd_enabled(); +TORCH_API void set_fwd_bwd_enabled_fn(std::function /*fn*/); +TORCH_API void set_fwd_bwd_enabled_val(bool /*val*/); + +TORCH_API bool get_cuda_sync_enabled(); +TORCH_API void set_cuda_sync_enabled_fn(std::function /*fn*/); +TORCH_API void set_cuda_sync_enabled_val(bool /*val*/); + +// Comms related RecordFunctions will record information about tensor storage +// locations. +TORCH_API bool get_record_tensor_addrs_enabled(); +TORCH_API void set_record_tensor_addrs_enabled_fn(std::function /*fn*/); +TORCH_API void set_record_tensor_addrs_enabled_val(bool /*val*/); + +} // namespace torch::profiler::impl + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/combined_traceback.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/combined_traceback.h new file mode 100644 index 0000000000000000000000000000000000000000..1553cdc2727203cdaf7d4e16f4731b336dbd6a2d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/combined_traceback.h @@ -0,0 +1,119 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include +#include +#include + +namespace torch { + +// struct that holds the result of symbolizing multiple tracebacks +// each traceback is a list of indices into all_frames +// (lots of Frames get duplicated across traces) +struct TORCH_API SymbolizedTracebacks { + std::vector all_frames; + // index into all_frames, so that + // it is possible to dedupe frame objects in + // construction of python objects + std::vector> tracebacks; +}; + +struct TORCH_API CapturedTraceback : public c10::GatheredContext { + struct PyFrame { + void* code; // PyCodeObject*, but python headers not present + int lasti; + }; + + static std::shared_ptr gather( + bool python, + bool script, + bool cpp); + CapturedTraceback() = default; + CapturedTraceback(const CapturedTraceback&) = delete; + CapturedTraceback& operator=(const CapturedTraceback&) = delete; + CapturedTraceback(CapturedTraceback&&) noexcept = default; + CapturedTraceback& operator=(CapturedTraceback&&) noexcept = delete; + ~CapturedTraceback() override; + + using visitproc = int (*)(void* self, void* arg); + + struct Python { + // Check if it's safe to gather Python frames from the current thread. + // Returns false for pure C++ threads that cannot acquire the GIL. + virtual bool canGather() = 0; + virtual std::vector gather() = 0; + virtual void release(std::vector& frames) = 0; + virtual void appendSymbolized( + const std::vector& to_symbolize, + SymbolizedTracebacks& st) = 0; + // tp_traverse/tp_clear implementations + virtual int traverse( + std::vector& frames, + visitproc visit, + void* arg) = 0; + virtual int clear(std::vector& frames) = 0; + // Gather forward traceback from the current autograd node's anomaly + // metadata. Returns a vector of strings representing the forward stack + // trace, or empty if not available. + virtual std::vector gatherForwardTraceback() { + return {}; + } + virtual ~Python() = default; + Python* next_ = nullptr; + }; + // called once by each python interpreter to + // register python stack recording functionality + // p cannot be deleted once added. + static void addPythonUnwinder(Python* p); + + int traversePython(visitproc visit, void* arg); + int clearPython(); + + private: + std::vector frames_; + std::vector cpp_frames_; + std::vector script_frames_; + friend TORCH_API SymbolizedTracebacks + symbolize(const std::vector& to_symbolize); + + // non-owning reference to one of the immortal Python* objects + // registered above. + Python* python_ = nullptr; + + // Optional forward traceback from anomaly mode. + // This is a list of Python strings representing the forward stack trace + // when the autograd Node was created. Used to correlate backward allocations + // with forward operations. + std::optional> forward_traceback_; + + public: + // Set the forward traceback from anomaly mode metadata + void set_forward_traceback(std::vector traceback) { + forward_traceback_ = std::move(traceback); + } + + // Get the forward traceback if available + const std::optional>& forward_traceback() const { + return forward_traceback_; + } +}; + +TORCH_API SymbolizedTracebacks +symbolize(const std::vector& to_symbolize); + +inline CapturedTraceback* getCapturedTracebackFromContext( + const std::shared_ptr& x) { + auto* traceback = dynamic_cast(x.get()); + TORCH_CHECK( + traceback, "attempting to gather stack context from the wrong type."); + return traceback; +} + +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/containers.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/containers.h new file mode 100644 index 0000000000000000000000000000000000000000..49c872babfc71e7edd119d15c359877962304717 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/containers.h @@ -0,0 +1,208 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace torch::profiler::impl { + +// ============================================================================ +// == AppendOnlyList ========================================================== +// ============================================================================ +// During profiling, we have a very predictable access pattern: we only +// append to the end of the container. We can specialize and outperform both +// std::vector (which must realloc) and std::deque (which performs a double +// indirection), and this class of operation is sufficiently important to the +// profiling hot path to warrant specializing: +// https://godbolt.org/z/rTjozf1c4 +// https://quick-bench.com/q/mmfuu71ogwaiULDCJyHdKnHZms4 (Prototype #1, +// int) https://quick-bench.com/q/5vWDW6jjdXVdoffev2zst8D09no (Prototype +// #1, int pair) https://quick-bench.com/q/IfEkfAQMeJSNBA52xtMP6Agcl-Q +// (Prototype #2, int pair) +// https://quick-bench.com/q/wJV2lKmuXL4XyGJzcI5hs4gEHFg (Prototype #3, int +// pair) https://quick-bench.com/q/xiO8ZaBEkYRYUA9dFrMuPLlW9fo (Full impl, +// int pair) +// AppendOnlyList has 2x lower emplace overhead compared to more generic STL +// containers. +// +// The optimal value of `ChunkSize` will vary by use case, but testing shows +// that a value of 1024 does a good job amortizing the `malloc` cost of growth. +// Performance drops off for larger values, so testing on a case-by-case basis +// is recommended if performance is absolutely critical. + +template < + typename T, + size_t ChunkSize, + template class block_t = std::array> +class AppendOnlyList { + public: + using array_t = block_t; + static_assert( + std::is_base_of_v, array_t>, + "AppendOnlyList expects raw low level pointer storage."); + static_assert(ChunkSize > 0, "Block cannot be empty."); + + AppendOnlyList() : buffer_last_{buffer_.before_begin()} {} + AppendOnlyList(const AppendOnlyList&) = delete; + AppendOnlyList(AppendOnlyList&&) = delete; + AppendOnlyList& operator=(const AppendOnlyList&) = delete; + AppendOnlyList& operator=(AppendOnlyList&&) = delete; + ~AppendOnlyList() = default; + + size_t size() const { + return n_blocks_ * ChunkSize - (size_t)(end_ - next_); + } + + template + T* emplace_back(Args&&... args) { + maybe_grow(); + if constexpr ( + std::is_trivially_destructible_v && + std::is_trivially_destructible_v) { + ::new ((void*)next_) T{std::forward(args)...}; + } else { + *next_ = T{std::forward(args)...}; + } + return next_++; + } + + template + std::enable_if_t && std::is_trivially_copyable_v> + copy(c10::ArrayRef src) { + size_t n = src.size(); + if (C10_UNLIKELY(n == 0)) { + return; + } + maybe_grow(); + if (C10_LIKELY(next_ && (next_ + n <= end_))) { + std::memcpy((void*)next_, (void*)src.begin(), n * sizeof(T0)); + next_ += n; + } else { + // We could chunk this into several `memcpy`s, but because we expect this + // fallback to be infrequent (n << ChunkSize) the performance impact is + // negligible. + for (auto i : src) { + emplace_back(i); + } + } + } + + void clear() { + buffer_.clear(); + buffer_last_ = buffer_.before_begin(); + n_blocks_ = 0; + next_ = nullptr; + end_ = nullptr; + } + + struct Iterator { + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = T; + using pointer = T*; + using reference = T&; + + Iterator(std::forward_list& buffer, const size_t size) + : block_{buffer.begin()}, size_{size} {} + + // End iterator. + Iterator() = default; + + bool exhausted() const { + return current_ >= size_; + } + + reference operator*() const { + return *current_ptr(/*checked=*/true); + } + pointer operator->() { + return current_ptr(/*checked=*/true); + } + + // Prefix increment + Iterator& operator++() { + if (!(++current_ % ChunkSize)) { + block_++; + } + return *this; + } + + // Postfix increment + Iterator operator++(int) { + Iterator tmp = *this; + ++(*this); + return tmp; + } + + friend bool operator==(const Iterator& a, const Iterator& b) { + return a.current_ptr() == b.current_ptr(); + } + friend bool operator!=(const Iterator& a, const Iterator& b) { + return a.current_ptr() != b.current_ptr(); + } + + std::pair address() const { + if (current_ >= size_) { + return {nullptr, 0}; + } + return {&(*block_), current_ % ChunkSize}; + } + + private: + T* current_ptr(bool checked = false) const { + auto a = address(); + if (a.first == nullptr) { + TORCH_INTERNAL_ASSERT(!checked, "Invalid access on AppendOnlyList."); + return nullptr; + } + return a.first->data() + a.second; + } + + typename std::forward_list::iterator block_; + size_t current_{0}; + size_t size_{0}; + }; + + Iterator begin() { + return Iterator(buffer_, size()); + } + Iterator end() { + return Iterator(); + } + // TODO: cbegin and cend() + + private: + void maybe_grow() { + if (C10_UNLIKELY(next_ == end_)) { + buffer_last_ = buffer_.emplace_after(buffer_last_); + n_blocks_++; + next_ = buffer_last_->data(); + end_ = next_ + ChunkSize; + } + } + + std::forward_list buffer_; + + // We maintain a pointer to the last element of `buffer_` so that we can + // insert at the end in O(1) time. + size_t n_blocks_{0}; + T* next_{nullptr}; + T* end_{nullptr}; + + protected: + typename std::forward_list::iterator buffer_last_; +}; + +} // namespace torch::profiler::impl + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/data_flow.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/data_flow.h new file mode 100644 index 0000000000000000000000000000000000000000..115bd72209f71641b412d124643e5a9242b1b6ab --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/data_flow.h @@ -0,0 +1,95 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include +#include +#include +#include + +namespace torch::profiler::impl { + +// Identity is a complex concept in PyTorch. A Tensor might not have a +// an associated storage, multiple Tensors might share the same underlying +// storage, the storage of a Tensor might change over time, etc. +// +// For the purpose of profiling we're mostly interested in data flow +// analysis. As a result, we can take an expansive view of identity: +// Tensors share an ID if they share a TensorImpl or storage data. +// +// This identity equality is transitive; If Tensors T0 and T1 share a storage +// S0 and T1 later points to a different storage S1 then all Tensors which +// point to either S0 or S1 are considered to have the same identity. (Since +// profiler cannot reason beyond that.) +// +// The profiler will handle lifetime analysis to ensure that identities do +// not run afoul of the ABA problem. This does, however, mean that identities +// can only be assigned when memory profiling is enabled. +using TensorID = strong::type; + +// Uniquely identifies an allocation. (Generally a StorageImpl's data ptr.) +using AllocationID = strong::type< + size_t, + struct StorageID_, + strong::ordered, + strong::regular, + strong::hashable>; + +// We use a Tensor's TensorImpl address and StorageImpl data start to build the +// data flow graph. We do not hold an owning reference so we wrap them in strong +// types to prevent direct access. +using TensorImplAddress = strong::type< + const c10::TensorImpl*, + struct TensorImplAddress_, + strong::regular, + strong::hashable, + strong::boolean>; + +using StorageImplData = strong::type< + const void*, + struct StorageImplData_, + strong::regular, + strong::hashable, + strong::boolean>; + +// ============================================================================ +// == weak_intrusive_ptr and the ABA problem for TensorImpl* ================== +// ============================================================================ +// Tracking `TensorImpl`s is an important part of identity tracking, because +// a Tensor might change storage; however when it does we want to retain the +// fact that the old and new storage belong to the same logical Tensor. We +// cannot take an owning reference to the Tensor because that would change +// program semantics by extending the lifetime of the Tensor. However if we +// store a raw TensorImpl* pointer the TensorImpl might be deleted and a new +// TensorImpl might be created that reuses the address. (ABA problem) +// +// Fortunately, there is a feature of `c10::intrusive_ptr` that we can use to +// prevent address reuse for the duration of profiling: the weak intrusive ptr. +// When a Tensor's refcount reaches zero but there are outstanding weak +// references (`weakcount_ > 0`) it will free the underlying managed resources +// by calling `target_->release_resources()`, but it will not call `delete`. +// (Instead, `delete` is called when the last weak reference is destroyed.) +// This means that we can safely use address identity to track `TensorImpls`. +class WeakTensor { + public: + explicit WeakTensor(const at::Tensor& t) : weak_self_(t.getIntrusivePtr()) {} + + auto get() const { + return TensorImplAddress{weak_self_._unsafe_get_target()}; + } + + private: + c10::weak_intrusive_ptr weak_self_; +}; + +struct Result; + +void calculateUniqueTensorIDs( + std::vector>& sorted_results); + +} // namespace torch::profiler::impl + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/events.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/events.h new file mode 100644 index 0000000000000000000000000000000000000000..83cc186e15f19dc61fb6d0123593631c5d5961d0 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/events.h @@ -0,0 +1,34 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +namespace torch::profiler { + +/* A vector type to hold a list of performance counters */ +using perf_counters_t = std::vector; + +/* Standard list of performance events independent of hardware or backend */ +constexpr std::array ProfilerPerfEvents = { + /* + * Number of Processing Element (PE) cycles between two points of interest + * in time. This should correlate positively with wall-time. Measured in + * uint64_t. PE can be non cpu. TBD reporting behavior for multiple PEs + * participating (i.e. threadpool). + */ + "cycles", + + /* Number of PE instructions between two points of interest in time. This + * should correlate positively with wall time and the amount of computation + * (i.e. work). Across repeat executions, the number of instructions should + * be more or less invariant. Measured in uint64_t. PE can be non cpu. + */ + "instructions"}; +} // namespace torch::profiler + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/kineto_client_interface.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/kineto_client_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..12b936c44d1fd363c8c53942f3d2e99a7bbb8f04 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/kineto_client_interface.h @@ -0,0 +1,16 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch { + +// declare global_kineto_init for libtorch_cpu.so to call +TORCH_API void global_kineto_init(); + +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/kineto_shim.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/kineto_shim.h new file mode 100644 index 0000000000000000000000000000000000000000..2349701c533b6d0a09039bf018d3a780b05836ad --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/kineto_shim.h @@ -0,0 +1,157 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +// Skip Kineto dependency on mobile unless explicitly asked for. +// When is it explicitly asked for? +// KinetoEdgeCPUProfiler uses KinetoProfiler for cpu +// event profiling. This has a dependency on cpu only libkineto +#if defined(USE_KINETO) && defined(C10_MOBILE) && \ + !defined(EDGE_PROFILER_USE_KINETO) +#undef USE_KINETO +#endif + +#include + +#include +#include + +#ifdef USE_KINETO +// Forward declarations so we don't have to include `libkineto.h` in a header. +namespace libkineto { +class GenericTraceActivity; +struct CpuTraceBuffer; +class ActivityTraceInterface; +} // namespace libkineto +#endif + +namespace torch { +namespace profiler { + +#ifdef USE_KINETO +constexpr bool kKinetoAvailable{true}; +#else +constexpr bool kKinetoAvailable{false}; +#endif + +namespace impl::kineto { + +// ---------------------------------------------------------------------------- +// -- Interface (Does not require Kineto) ------------------------------------- +// ---------------------------------------------------------------------------- +struct DeviceAndResource { + int32_t device; + int32_t resource; +}; +const DeviceAndResource kineto_ids(); + +#ifdef USE_KINETO +using trace_t = libkineto::CpuTraceBuffer; +using interface_trace_t = libkineto::ActivityTraceInterface; +using activity_t = libkineto::GenericTraceActivity; +#else +struct DummyTraceBuffer {}; +struct DummyTraceInterface {}; + +using trace_t = DummyTraceBuffer; +using interface_trace_t = DummyTraceBuffer; +struct activity_t; +#endif // USE_KINETO + +void addMetadata( + activity_t* activity, + const std::string& key, + const std::string& value); + +// Wraps: libkineto::CpuTraceBuffer +struct TraceWrapper { + TraceWrapper(const int64_t start_time, const std::string& name); + + // The caller is expected to hold a mutex when calling `addCPUActivity`. + activity_t* addCPUActivity( + const std::string& name, + const libkineto::ActivityType type, + const DeviceAndResource device_and_resource, + const uint64_t correlation_id, + const int64_t start_time, + const int64_t end_time); + + void transferCpuTrace(int64_t end_time); + + explicit operator bool() const; + + std::unique_ptr& get() { + return cpu_trace_; + } + + private: + std::unique_ptr cpu_trace_; +}; + +// Wraps libkineto::ActivityTraceInterface +struct ActivityTraceWrapper { + explicit ActivityTraceWrapper(std::unique_ptr&& trace); + ActivityTraceWrapper() = default; + explicit operator bool() const; + void save(const std::string& path); + + const std::unique_ptr& get() { + return trace_; + } + + private: + std::unique_ptr trace_; +#ifdef USE_KINETO + bool saved_ = false; // Kineto's save is destructive +#endif +}; + +using ActivitySet = std::set; +using ActivityFilter = std::unordered_map< + torch::autograd::profiler::ActivityType, + std::unordered_set>; +void prepareTrace( + const bool cpuOnly, + const ActivitySet& activities, + const torch::profiler::impl::ExperimentalConfig& config, + const std::string& trace_id = "", + const ActivityFilter& activity_filter = {}); + +void toggleCollectionDynamic(const bool enable); +void startTrace(); +ActivityTraceWrapper stopTrace(); +void pushCorrelationId(uint64_t correlation_id); +void pushUserCorrelationId(uint64_t correlation_id); +void popCorrelationId(); +void popUserCorrelationId(); +void recordThreadInfo(); +bool collectivesProfilerExists(); + +void logInvariantViolation( + const std::string& assertion, + const std::string& error, + const std::string& profile_id, + const std::string& group_profile_id); + +} // namespace impl::kineto + +} // namespace profiler + +namespace autograd::profiler { +c10::DeviceType deviceTypeFromActivity(libkineto::ActivityType activity_type); + +TORCH_API void addMetadataJson( + const std::string& key, + const std::string& value); + +TORCH_API void profilerStep(); + +} // namespace autograd::profiler + +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/orchestration/observer.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/orchestration/observer.h new file mode 100644 index 0000000000000000000000000000000000000000..6ed82f18a2e5b8f545163f4e504b9e3291a40861 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/orchestration/observer.h @@ -0,0 +1,223 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include + +namespace torch::profiler::impl { + +// ---------------------------------------------------------------------------- +// -- Profiler Config --------------------------------------------------------- +// ---------------------------------------------------------------------------- +enum class C10_API_ENUM ActivityType { + CPU = 0, + XPU, // XPU kernels, runtime + CUDA, // CUDA kernels, runtime + HPU, // HPU kernels, runtime + MTIA, // MTIA kernels, runtime + PrivateUse1, // PrivateUse1 kernels, runtime + NUM_KINETO_ACTIVITIES, // must be the last one +}; + +inline std::string actToString(ActivityType t) { + const std::array< + std::string, + static_cast(ActivityType::NUM_KINETO_ACTIVITIES)> + ActivityTypeNames = {"CPU", "XPU", "CUDA", "MTIA", "PrivateUse1"}; + return ActivityTypeNames[static_cast(t)]; +} + +enum class C10_API_ENUM ProfilerState { + Disabled = 0, + CPU, // CPU-only profiling + CUDA, // CPU + CUDA events + NVTX, // only emit NVTX markers + ITT, // only emit ITT markers + PRIVATEUSE1, // only emit PRIVATEUSE1 markers + KINETO, // use libkineto + KINETO_GPU_FALLBACK, // use CUDA events when CUPTI is not available + KINETO_PRIVATEUSE1_FALLBACK, // use PrivateUse1 events + KINETO_PRIVATEUSE1, // use Kineto with registered IActivityProfiler + KINETO_ONDEMAND, // run the profiler in on-demand mode + NUM_PROFILER_STATES, // must be the last one +}; + +enum class C10_API_ENUM ActiveProfilerType { + NONE = 0, + LEGACY, + KINETO, + NVTX, + ITT, + PRIVATEUSE1 +}; + +struct TORCH_API ExperimentalConfig { + ExperimentalConfig( + std::vector profiler_metrics = {}, + bool profiler_measure_per_kernel = false, + bool verbose = false, + std::vector performance_events = {}, + bool enable_cuda_sync_events = false, + bool adjust_profiler_step = false, + bool disable_external_correlation = false, + bool profile_all_threads = false, + bool capture_overload_names = false, + bool record_python_gc_info = false, + bool expose_kineto_event_metadata = false, + std::string custom_profiler_config = "", + bool adjust_timestamps = false); + explicit operator bool() const; + + std::vector profiler_metrics; + bool profiler_measure_per_kernel; + bool verbose; + /* + * List of performance events to be profiled. + * An empty list will disable performance event based profiling altogether. + */ + std::vector performance_events; + /* + * For CUDA profiling mode, enable adding CUDA synchronization events + * that expose CUDA device, stream and event synchronization activities. + * This feature is new and currently disabled by default. + */ + bool enable_cuda_sync_events; + /* + * Controls whether or not timestamp adjustment for ProfilerStep and parent + * Python events occurs after profiling. This occurs at an O(n) cost and + * affects only the start of profiler step events. + */ + bool adjust_profiler_step; + /* + * Controls whether or not external correlation is disabled. This is used to + * lower the amount of events received by CUPTI as correlation events are + * paired with runtime/gpu events for each kind of correlation + */ + bool disable_external_correlation; + + /* controls whether profiler records cpu events on threads + * that are not spawned from the main thread on which the + * profiler was enabled, similar to on_demand mode */ + bool profile_all_threads; + + /* controls whether overload names are queried from an ATen + * function schema and stored in the profile */ + bool capture_overload_names; + + /* + * Controls whether or not python gc info is recorded. This is used to + * determine if gc collect is slowing down your profile. + */ + bool record_python_gc_info; + + /* controls whether KinetoEvent metadata is exposed to FunctionEvent + * in the PyTorch Profiler as a JSON string */ + bool expose_kineto_event_metadata; + + /* + * A custom_profiler_config option is introduced to allow custom backends + * to apply custom configurations as needed. + */ + std::string custom_profiler_config; + + /* + * Controls whether or not timestamp adjustment occurs after profiling. + * The purpose of this is to adjust Vulkan event timelines to align with those + * of their parent CPU events. + * This sometimes requires increasing CPU event durations (to fully contain + * their child events) and delaying CPU event start times (to + * prevent overlaps), so this should not be used unless Vulkan events are + * being profiled and it is ok to use this modified timestamp/duration + * information instead of the original information. + */ + bool adjust_timestamps; +}; + +struct TORCH_API ProfilerConfig { + explicit ProfilerConfig( + ProfilerState state, + bool report_input_shapes = false, + bool profile_memory = false, + bool with_stack = false, + bool with_flops = false, + bool with_modules = false, + ExperimentalConfig experimental_config = ExperimentalConfig(), + std::string trace_id = ""); + + bool disabled() const; + bool global() const; + bool pushGlobalCallbacks() const; + + ProfilerState state; + ExperimentalConfig experimental_config; + bool report_input_shapes; + bool profile_memory; + bool with_stack; + bool with_flops; + bool with_modules; + std::string trace_id; + + // For serialization + at::IValue toIValue() const; + static ProfilerConfig fromIValue(const at::IValue& profilerConfigIValue); +}; + +// ---------------------------------------------------------------------------- +// -- Profiler base class ----------------------------------------------------- +// ---------------------------------------------------------------------------- +struct TORCH_API ProfilerStateBase : public c10::MemoryReportingInfoBase { + explicit ProfilerStateBase(ProfilerConfig config); + ProfilerStateBase(const ProfilerStateBase&) = delete; + ProfilerStateBase(ProfilerStateBase&&) = delete; + ProfilerStateBase& operator=(const ProfilerStateBase&) = delete; + ProfilerStateBase& operator=(ProfilerStateBase&&) = delete; + ~ProfilerStateBase() override; + + static ProfilerStateBase* get(bool global); + static ProfilerStateBase* get() { + auto* out = get(/*global=*/true); + return out ? out : get(/*global=*/false); + } + + static void push(std::shared_ptr&& state); + + static std::shared_ptr pop(bool global); + static std::shared_ptr pop() { + auto out = pop(/*global=*/true); + return out ? std::move(out) : pop(/*global=*/false); + } + + const ProfilerConfig& config() const { + return config_; + } + + void setCallbackHandle(at::CallbackHandle handle); + void removeCallback(); + + bool memoryProfilingEnabled() const override { + return config_.profile_memory; + } + + virtual ActiveProfilerType profilerType() = 0; + + protected: + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + std::mutex state_mutex_; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + ProfilerConfig config_ = ProfilerConfig(ProfilerState::Disabled); + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + at::CallbackHandle handle_ = 0; +}; + +// Note: The following are only for the active *thread local* profiler. +TORCH_API bool profilerEnabled(); +TORCH_API ActiveProfilerType profilerType(); +TORCH_API ProfilerConfig getProfilerConfig(); + +} // namespace torch::profiler::impl + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/orchestration/python_tracer.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/orchestration/python_tracer.h new file mode 100644 index 0000000000000000000000000000000000000000..3cfd6d54b173ddb17adf295d33aab4636c3638a2 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/orchestration/python_tracer.h @@ -0,0 +1,82 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace torch::profiler::impl { + +class RecordQueue; +struct Result; +namespace python_tracer { + +using TraceKey = strong::type< + uint64_t, + struct TraceKey_, + strong::regular, + strong::hashable, + strong::ostreamable>; + +struct CompressedEvent { + TraceKey key_; + uint64_t system_tid_{}; + kineto::DeviceAndResource kineto_info_{}; + c10::time_t enter_t_{}; +}; + +/* +Libtorch does not depend on Python (e.g. cannot #include ); however +when we call the profiler from libtorch_python we need the profiler to be able +to ingest the data that we collect from the Python tracer. (`PyEval_SetProfile`) + +In order to solve this dependency issue we define a virtual base and a function +to register a getter. The python tracer then implements these functions and +exposes itself by calling `registerTracer` from `torch/csrc/autograd/init.cpp`. +This pattern of registration for faux python dependencies in libtorch is common +in the PyTorch codebase. +*/ +struct TORCH_API PythonTracerBase { + static std::unique_ptr make(RecordQueue* queue); + virtual ~PythonTracerBase() = default; + + virtual void stop() = 0; + virtual void restart() = 0; + virtual void register_gc_callback() = 0; + virtual std::vector> getEvents( + std::function time_converter, + std::vector& enters, + c10::time_t end_time_ns) = 0; +}; + +using MakeFn = std::unique_ptr (*)(RecordQueue*); +TORCH_API void registerTracer(MakeFn make_tracer); + +/** + * Memory Tracer Implementation + */ +struct TORCH_API PythonMemoryTracerBase { + static std::unique_ptr make(); + virtual ~PythonMemoryTracerBase() = default; + + virtual void start() = 0; + virtual void stop() = 0; + virtual void export_memory_history(const std::string& path) = 0; +}; + +using MakeMemoryFn = std::unique_ptr (*)(); +TORCH_API void registerMemoryTracer(MakeMemoryFn make_memory_tracer); + +} // namespace python_tracer +} // namespace torch::profiler::impl + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/orchestration/vulkan.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/orchestration/vulkan.h new file mode 100644 index 0000000000000000000000000000000000000000..577d1299b83600fecfca5ecf03a399c526ed2fd1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/orchestration/vulkan.h @@ -0,0 +1,27 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace torch::profiler::impl::vulkan { + +// Using function pointer i.e. [std::tuple (*)(int64_t)] +// doesn't work because we need to capture the QueryPool in the lambda context +// https://stackoverflow.com/a/28746827 +using GetShaderNameAndDurationNsFn = + std::function(int64_t)>; +TORCH_API void registerGetShaderNameAndDurationNs( + GetShaderNameAndDurationNsFn get_shader_name_and_duration_ns); + +TORCH_API void deregisterGetShaderNameAndDurationNs(); + +std::tuple getShaderNameAndDurationNs( + const vulkan_id_t& vulkan_id); + +} // namespace torch::profiler::impl::vulkan + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/perf-inl.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/perf-inl.h new file mode 100644 index 0000000000000000000000000000000000000000..448e4747807ee871734722b351a58215ad2a4f60 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/perf-inl.h @@ -0,0 +1,73 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#if defined(__ANDROID__) || defined(__linux__) + +#include + +#include +#include + +#include + +#endif /* __ANDROID__ || __linux__ */ + +#include + +#include + +namespace torch::profiler::impl::linux_perf { + +/* + * PerfEvent + * --------- + */ + +inline void PerfEvent::Disable() const { +#if defined(__ANDROID__) || defined(__linux__) + ioctl(fd_, PERF_EVENT_IOC_DISABLE, 0); +#endif /* __ANDROID__ || __linux__ */ +} + +inline void PerfEvent::Enable() const { +#if defined(__ANDROID__) || defined(__linux__) + ioctl(fd_, PERF_EVENT_IOC_ENABLE, 0); +#endif /* __ANDROID__ || __linux__ */ +} + +inline void PerfEvent::Reset() const { +#if defined(__ANDROID__) || defined(__linux__) + ioctl(fd_, PERF_EVENT_IOC_RESET, 0); +#endif /* __ANDROID__ || __linux__ */ +} + +/* + * PerfProfiler + * ------------ + */ + +inline uint64_t PerfProfiler::CalcDelta(uint64_t start, uint64_t end) const { + if (end < start) { // overflow + return end + (std::numeric_limits::max() - start); + } + // not possible to wrap around start for a 64b cycle counter + return end - start; +} + +inline void PerfProfiler::StartCounting() const { + for (auto& e : events_) { + e.Enable(); + } +} + +inline void PerfProfiler::StopCounting() const { + for (auto& e : events_) { + e.Disable(); + } +} + +} // namespace torch::profiler::impl::linux_perf + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/perf.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/perf.h new file mode 100644 index 0000000000000000000000000000000000000000..70ea26a46330fdeb556b76a511add5253b0b2314 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/perf.h @@ -0,0 +1,106 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace torch::profiler::impl::linux_perf { + +/* + * Maximum number of events supported + * This stems from the hardware limitation on CPU performance counters, and the + * fact that we don't support time multiplexing just yet. + * Time multiplexing involves scaling the counter values proportional to + * the enabled and running time or running the workload multiple times. + */ +constexpr uint8_t MAX_EVENTS = 4; + +struct PerfCounter { + uint64_t value; /* The value of the event */ + uint64_t time_enabled; /* for TIME_ENABLED */ + uint64_t time_running; /* for TIME_RUNNING */ +}; + +/* + * Basic perf event handler for Android and Linux + */ +class PerfEvent { + public: + explicit PerfEvent(std::string& name) : name_(name) {} + + PerfEvent(const PerfEvent& other) = delete; + PerfEvent& operator=(const PerfEvent&) = delete; + PerfEvent& operator=(PerfEvent&& other) noexcept { + if (this != &other) { + fd_ = other.fd_; + other.fd_ = -1; + name_ = std::move(other.name_); + } + return *this; + } + + PerfEvent(PerfEvent&& other) noexcept { + *this = std::move(other); + } + + ~PerfEvent(); + + /* Setup perf events with the Linux Kernel, attaches perf to this process + * using perf_event_open(2) */ + void Init(); + + /* Stop incrementing hardware counters for this event */ + void Disable() const; + + /* Start counting hardware event from this point on */ + void Enable() const; + + /* Zero out the counts for this event */ + void Reset() const; + + /* Returns PerfCounter values for this event from kernel, on non supported + * platforms this always returns zero */ + uint64_t ReadCounter() const; + + private: + /* Name of the event */ + std::string name_; + + int fd_ = -1; +}; + +class PerfProfiler { + public: + /* Configure all the events and track them as individual PerfEvent */ + void Configure(std::vector& event_names); + + /* Enable events counting from here */ + void Enable(); + + /* Disable counting and fill in the caller supplied container with delta + * calculated from the start count values since last Enable() */ + void Disable(perf_counters_t& /*vals*/); + + private: + uint64_t CalcDelta(uint64_t start, uint64_t end) const; + void StartCounting() const; + void StopCounting() const; + + std::vector events_; + std::stack start_values_; +}; +} // namespace torch::profiler::impl::linux_perf + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/python/combined_traceback.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/python/combined_traceback.h new file mode 100644 index 0000000000000000000000000000000000000000..0cdb2e1737d860f40c91814405a39ef310cee5b1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/python/combined_traceback.h @@ -0,0 +1,32 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include + +#include +#include +#include + +namespace torch { + +// symbolize combined traceback objects, converting them into lists of +// dictionaries that are easily consumed in python. + +// returns std::vector because one use is to call it with a batch of +// tracebacks that come from a larger datastructure (e.g. a memory snapshot) +// and then have more c++ code to put those objects in the right place. +TORCH_API std::vector py_symbolize( + std::vector& to_symbolize); + +// Return the callback in json format so that it can be used within cpp +TORCH_API std::vector json_symbolize( + std::vector& to_symbolize); + +// requires GIL to be held, frees any pending free frames +TORCH_PYTHON_API void freeDeadCapturedTracebackFrames(); + +TORCH_PYTHON_API void installCapturedTracebackPython(); + +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/python/init.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/python/init.h new file mode 100644 index 0000000000000000000000000000000000000000..8f5f25ddaf5cb6b647d99e53c45ed81630ce3213 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/python/init.h @@ -0,0 +1,36 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include +#include + +namespace pybind11::detail { +using torch::profiler::impl::TensorID; + +#define STRONG_POINTER_TYPE_CASTER(T) \ + template <> \ + struct type_caster : public strong_pointer_type_caster {}; + +STRONG_POINTER_TYPE_CASTER(torch::profiler::impl::StorageImplData) +STRONG_POINTER_TYPE_CASTER(torch::profiler::impl::AllocationID) +STRONG_POINTER_TYPE_CASTER(torch::profiler::impl::TensorImplAddress) +STRONG_POINTER_TYPE_CASTER(torch::profiler::impl::PyModuleSelf) +STRONG_POINTER_TYPE_CASTER(torch::profiler::impl::PyModuleCls) +STRONG_POINTER_TYPE_CASTER(torch::profiler::impl::PyOptimizerSelf) +#undef STRONG_POINTER_TYPE_CASTER + +template <> +struct type_caster : public strong_uint_type_caster {}; +} // namespace pybind11::detail + +namespace torch::profiler { + +void initPythonBindings(PyObject* module); + +} // namespace torch::profiler + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/python/pybind.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/python/pybind.h new file mode 100644 index 0000000000000000000000000000000000000000..39c63a85349c7493d1d06e922941ff6205cb1770 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/python/pybind.h @@ -0,0 +1,53 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#include +#include +#include + +namespace pybind11::detail { +// Strong typedefs don't make much sense in Python since everything is duck +// typed. So instead we simply extract the underlying value and let the caller +// handle correctness. +template +struct strong_pointer_type_caster { + template + static handle cast( + const T_& src, + return_value_policy /*policy*/, + handle /*parent*/) { + const auto* ptr = reinterpret_cast(src.value_of()); + return ptr ? handle(THPUtils_packUInt64(reinterpret_cast(ptr))) + : none(); + } + + bool load(handle /*src*/, bool /*convert*/) { + return false; + } + + PYBIND11_TYPE_CASTER(T, _("strong_pointer")); +}; + +template +struct strong_uint_type_caster { + template + static handle cast( + const T_& src, + return_value_policy /*policy*/, + handle /*parent*/) { + return handle(THPUtils_packUInt64(src.value_of())); + } + + bool load(handle /*src*/, bool /*convert*/) { + return false; + } + + PYBIND11_TYPE_CASTER(T, _("strong_uint")); +}; +} // namespace pybind11::detail + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/standalone/execution_trace_observer.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/standalone/execution_trace_observer.h new file mode 100644 index 0000000000000000000000000000000000000000..cd5a3addd9cc27717340a29fa268b7f96ae561ba --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/standalone/execution_trace_observer.h @@ -0,0 +1,26 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::profiler::impl { + +// Adds the execution trace observer as a global callback function, the data +// will be written to output file path. +TORCH_API bool addExecutionTraceObserver(const std::string& output_file_path); + +// Remove the execution trace observer from the global callback functions. +TORCH_API void removeExecutionTraceObserver(); + +// Enables execution trace observer. +TORCH_API void enableExecutionTraceObserver(); + +// Disables execution trace observer. +TORCH_API void disableExecutionTraceObserver(); + +} // namespace torch::profiler::impl + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/standalone/itt_observer.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/standalone/itt_observer.h new file mode 100644 index 0000000000000000000000000000000000000000..e1d340daf8b2917d3b3a4de59f254deb68aefeea --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/standalone/itt_observer.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include + +namespace torch::profiler::impl { + +void pushITTCallbacks( + const ProfilerConfig& config, + const std::unordered_set& scopes); + +} // namespace torch::profiler::impl + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/standalone/nvtx_observer.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/standalone/nvtx_observer.h new file mode 100644 index 0000000000000000000000000000000000000000..75214a0fbd6b9b776bc8788061461057a9843c2a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/standalone/nvtx_observer.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include + +namespace torch::profiler::impl { + +void pushNVTXCallbacks( + const ProfilerConfig& config, + const std::unordered_set& scopes); + +} // namespace torch::profiler::impl + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/standalone/privateuse1_observer.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/standalone/privateuse1_observer.h new file mode 100644 index 0000000000000000000000000000000000000000..09e3f63d535eb7fba56dabd71aaca0ed85e7b968 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/standalone/privateuse1_observer.h @@ -0,0 +1,49 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include + +namespace torch::profiler::impl { + +using CallBackFnPtr = void (*)( + const ProfilerConfig& config, + const std::unordered_set& scopes); + +struct PushPRIVATEUSE1CallbacksStub { + PushPRIVATEUSE1CallbacksStub() = default; + PushPRIVATEUSE1CallbacksStub(const PushPRIVATEUSE1CallbacksStub&) = delete; + PushPRIVATEUSE1CallbacksStub& operator=(const PushPRIVATEUSE1CallbacksStub&) = + delete; + PushPRIVATEUSE1CallbacksStub(PushPRIVATEUSE1CallbacksStub&&) = default; + PushPRIVATEUSE1CallbacksStub& operator=(PushPRIVATEUSE1CallbacksStub&&) = + default; + ~PushPRIVATEUSE1CallbacksStub() = default; + + template + void operator()(ArgTypes&&... args) { + return (*push_privateuse1_callbacks_fn)(std::forward(args)...); + } + + void set_privateuse1_dispatch_ptr(CallBackFnPtr fn_ptr) { + push_privateuse1_callbacks_fn = fn_ptr; + } + + private: + CallBackFnPtr push_privateuse1_callbacks_fn = nullptr; +}; + +extern TORCH_API struct PushPRIVATEUSE1CallbacksStub + pushPRIVATEUSE1CallbacksStub; + +struct RegisterPRIVATEUSE1Observer { + RegisterPRIVATEUSE1Observer(CallBackFnPtr cb) { + pushPRIVATEUSE1CallbacksStub.set_privateuse1_dispatch_ptr(cb); + } +}; + +#define REGISTER_PRIVATEUSE1_OBSERVER(cb) \ + static RegisterPRIVATEUSE1Observer privateuse1_callbacks_stub_register(cb); +} // namespace torch::profiler::impl + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/standalone/privateuse1_profiler.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/standalone/privateuse1_profiler.h new file mode 100644 index 0000000000000000000000000000000000000000..955bcc6c6623a84c43fe257abe6d55faaa88634a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/standalone/privateuse1_profiler.h @@ -0,0 +1,118 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#ifdef USE_KINETO + +#include +#include +#include +#include + +#include + +#include + +namespace torch::profiler::impl { + +// Factory function type that creates an IActivityProfiler instance +using PrivateUse1ProfilerFactory = + std::function()>; + +// Registry for PrivateUse1 activity profiler factories. +// +// This registry allows custom accelerator backends to register their +// IActivityProfiler implementation with Kineto, enabling full profiling +// integration without modifying Kineto code. +// +// Usage: +// 1. Backend implements libkineto::IActivityProfiler +// 2. Backend uses REGISTER_PRIVATEUSE1_PROFILER macro to register +// 3. PyTorch forwards the factory to Kineto during initialization +// +// Example: +// class MyAcceleratorProfiler : public libkineto::IActivityProfiler { +// const std::string& name() const override { return name_; } +// const std::set& availableActivities() const +// override; std::unique_ptr +// configure(...) override; +// private: +// std::string name_{"my_accelerator"}; +// }; +// +// REGISTER_PRIVATEUSE1_PROFILER(MyAcceleratorProfiler) +// +class TORCH_API PrivateUse1ProfilerRegistry { + public: + static PrivateUse1ProfilerRegistry& instance(); + + // Register a factory function for creating the PrivateUse1 profiler. + // This should be called during static initialization. + void registerFactory(PrivateUse1ProfilerFactory factory); + + // Check if a factory has been registered. + bool hasFactory() const; + + // Check if the factory has been registered with Kineto. + // Useful for testing to verify the registration logic. + bool isRegisteredWithKineto() const; + + // Register the factory with Kineto's activity profiler. + // This is called internally when Kineto is ready. + // Safe to call multiple times - will only register once. + void registerWithKineto(); + + // Mark that Kineto has been initialized. + // If a factory was registered before Kineto init, it will be forwarded. + void onKinetoInit(); + + private: + PrivateUse1ProfilerRegistry() = default; + + mutable std::mutex mutex_; + PrivateUse1ProfilerFactory factory_; + bool registered_with_kineto_ = false; + bool kineto_initialized_ = false; +}; + +// Helper struct for static registration via macro. +// Enforces at compile-time that ProfilerClass inherits from +// libkineto::IActivityProfiler. +template +struct RegisterPrivateUse1Profiler { + static_assert( + std::is_base_of_v, + "ProfilerClass must inherit from libkineto::IActivityProfiler. " + "Please ensure your profiler class implements the IActivityProfiler interface."); + + RegisterPrivateUse1Profiler() { + PrivateUse1ProfilerRegistry::instance().registerFactory( + []() -> std::unique_ptr { + return std::make_unique(); + }); + } +}; + +// Macro for registering a PrivateUse1 activity profiler. +// The profiler class must implement libkineto::IActivityProfiler. +// +// Usage: +// REGISTER_PRIVATEUSE1_PROFILER(MyAcceleratorProfiler) +#define REGISTER_PRIVATEUSE1_PROFILER(ProfilerClass) \ + static ::torch::profiler::impl::RegisterPrivateUse1Profiler \ + privateuse1_profiler_register_##ProfilerClass + +} // namespace torch::profiler::impl + +#endif // USE_KINETO + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/stubs/base.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/stubs/base.h new file mode 100644 index 0000000000000000000000000000000000000000..fad34ad6b9daae1c143e9b365ae59a85156a832e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/stubs/base.h @@ -0,0 +1,58 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include +#include +#include + +struct CUevent_st; + +namespace torch::profiler::impl { + +// ---------------------------------------------------------------------------- +// -- Annotation -------------------------------------------------------------- +// ---------------------------------------------------------------------------- +using ProfilerEventStub = std::shared_ptr; +using ProfilerVoidEventStub = std::shared_ptr; + +struct TORCH_API ProfilerStubs { + virtual void record( + c10::DeviceIndex* device, + ProfilerVoidEventStub* event, + int64_t* cpu_ns) const = 0; + virtual float elapsed( + const ProfilerVoidEventStub* event, + const ProfilerVoidEventStub* event2) const = 0; + virtual void mark(const char* name) const = 0; + virtual void rangePush(const char* name) const = 0; + virtual void rangePop() const = 0; + virtual bool enabled() const { + return false; + } + virtual void onEachDevice(std::function op) const = 0; + virtual void synchronize() const = 0; + virtual ~ProfilerStubs() = default; +}; + +TORCH_API void registerCUDAMethods(ProfilerStubs* stubs); +TORCH_API const ProfilerStubs* cudaStubs(); +TORCH_API void registerITTMethods(ProfilerStubs* stubs); +TORCH_API const ProfilerStubs* ittStubs(); +TORCH_API void registerPrivateUse1Methods(ProfilerStubs* stubs); +TORCH_API const ProfilerStubs* privateuse1Stubs(); + +using vulkan_id_t = strong::type< + int64_t, + struct _VulkanID, + strong::regular, + strong::convertible_to, + strong::hashable>; + +} // namespace torch::profiler::impl + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/action.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/action.h new file mode 100644 index 0000000000000000000000000000000000000000..b26be822168f491a116db3400e9ad44b78334c5f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/action.h @@ -0,0 +1,87 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include + +namespace torch::unwind { + +enum { + A_UNDEFINED = 0x0, + A_REG_PLUS_DATA = 0x1, // exp = REG[reg] + data0 + A_LOAD_CFA_OFFSET = 0x2, // exp = *(cfa + data0) + A_REG_PLUS_DATA_DEREF = 0x3 // exp = *(REG[reg] + data0) +}; + +// DWARF register numbers — architecture-specific +#if defined(__x86_64__) +enum { + D_UNDEFINED = -1, + D_RBP = 6, + D_RSP = 7, + D_RIP = 16, + D_REG_SIZE = 17, +}; +static constexpr int D_FRAME_PTR = D_RBP; +static constexpr int D_STACK_PTR = D_RSP; +static constexpr int D_RET_ADDR = D_RIP; +static constexpr int D_EXPECTED_RA_REG = 16; +#elif defined(__aarch64__) +enum { + D_UNDEFINED = -1, + D_FP = 29, + D_LR = 30, + D_SP = 31, + D_REG_SIZE = 32, +}; +static constexpr int D_FRAME_PTR = D_FP; +static constexpr int D_STACK_PTR = D_SP; +static constexpr int D_RET_ADDR = D_LR; +static constexpr int D_EXPECTED_RA_REG = 30; +#else +enum { + D_UNDEFINED = -1, + D_REG_SIZE = 1, +}; +#endif + +struct Action { + uint8_t kind = A_UNDEFINED; + int32_t reg = -1; + int64_t data = 0; + static Action undefined() { + return Action{A_UNDEFINED}; + } + static Action regPlusData(int32_t reg, int64_t offset) { + return Action{A_REG_PLUS_DATA, reg, offset}; + } + static Action regPlusDataDeref(int32_t reg, int64_t offset) { + return Action{A_REG_PLUS_DATA_DEREF, reg, offset}; + } + static Action loadCfaOffset(int64_t offset) { + return Action{A_LOAD_CFA_OFFSET, D_UNDEFINED, offset}; + } + + friend std::ostream& operator<<(std::ostream& out, const Action& self) { + switch (self.kind) { + case A_UNDEFINED: + out << 'u'; + break; + case A_REG_PLUS_DATA: + out << 'r' << (int)self.reg << " + " << self.data; + break; + case A_REG_PLUS_DATA_DEREF: + out << "*(r" << (int)self.reg << " + " << self.data << ')'; + break; + case A_LOAD_CFA_OFFSET: + out << "*(cfa + " << self.data << ')'; + break; + } + return out; + } +}; + +} // namespace torch::unwind + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/communicate.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/communicate.h new file mode 100644 index 0000000000000000000000000000000000000000..a5b2281067ca256e2db7c687c313f29525d556ba --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/communicate.h @@ -0,0 +1,78 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include +#include + +namespace torch::unwind { +// helper to open a process with stdin/stdout/stderr streams. +struct Communicate { + Communicate(const char* command, const char** args) { + if (pipe(inpipe_.data()) < 0 || pipe(outpipe_.data()) < 0 || + pipe(errpipe_.data()) < 0) { + throw UnwindError("pipe() failed"); + } + pid_t pid = fork(); + if (pid < 0) { + throw UnwindError("fork() failed"); + } else if (pid == 0) { // child process + close(inpipe_[1]); + close(outpipe_[0]); + close(errpipe_[0]); + + dup2(inpipe_[0], STDIN_FILENO); + dup2(outpipe_[1], STDOUT_FILENO); + dup2(errpipe_[1], STDERR_FILENO); + execvp(command, (char* const*)args); + throw UnwindError("failed execvp"); + } else { // parent process + close(inpipe_[0]); + close(outpipe_[1]); + close(errpipe_[1]); + outbuf_ = std::make_unique<__gnu_cxx::stdio_filebuf>( + inpipe_[1], std::ios::out); + inbuf_ = std::make_unique<__gnu_cxx::stdio_filebuf>( + outpipe_[0], std::ios::in); + errbuf_ = std::make_unique<__gnu_cxx::stdio_filebuf>( + errpipe_[0], std::ios::in); + in_ = std::make_unique(inbuf_.get()); + out_ = std::make_unique(outbuf_.get()); + err_ = std::make_unique(errbuf_.get()); + } + } + Communicate(const Communicate&) = delete; + Communicate(Communicate&&) = delete; + Communicate& operator=(const Communicate&) = delete; + Communicate& operator=(Communicate&&) = delete; + ~Communicate() { + close(inpipe_[1]); + close(outpipe_[0]); + close(errpipe_[0]); + } + std::ostream& out() { + return *out_; + } + std::ostream& err() { + return *err_; + } + std::istream& in() { + return *in_; + } + + private: + std::array inpipe_{-1, -1}; + std::array outpipe_{-1, -1}; + std::array errpipe_{-1, -1}; + std::unique_ptr<__gnu_cxx::stdio_filebuf> outbuf_, inbuf_, errbuf_; + std::unique_ptr in_; + std::unique_ptr out_; + std::unique_ptr err_; +}; + +} // namespace torch::unwind + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/debug_info.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/debug_info.h new file mode 100644 index 0000000000000000000000000000000000000000..9f4d0fe227613489847733783a13872df1015b1f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/debug_info.h @@ -0,0 +1,285 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include +#include +#include +#include + +namespace torch::unwind { + +struct DebugInfo { + DebugInfo(Sections& s) : s_(s) {} + + void parse(uint64_t offset) { + auto L = parseHeader(offset); + parseCompileUnit(L); + } + std::optional lineNumberProgramOffset() { + return line_number_program_offset_; + } + uint64_t nextOffset() { + return end_ - s_.debug_info.data; + } + std::vector> ranges() { + if (range_ptr_) { + auto offset = range_ptr_->first; + if (range_ptr_->second == DW_FORM_rnglistx) { + UNWIND_CHECK(rnglists_base_, "rnglistx but not rnglists_base_ set"); + LOG_INFO("index for rnglistx {:x} + {:x}\n", *rnglists_base_, offset); + CheckedLexer L = s_.debug_rnglists.lexer( + *rnglists_base_ + offset * sec_offset_size_); + auto read = readSegmentOffset(L); + offset = *rnglists_base_ + read; + } + return version_ == 4 ? readRanges4(offset) : readRanges5(offset); + } + if (!highpc_) { + return {}; + } + return {{lowpc_, lowpc_ + *highpc_}}; + } + + bool is64bit() { + return is_64bit_; + } + + private: + CheckedLexer parseHeader(uint64_t offset) { + offset_ = offset; + CheckedLexer L = s_.debug_info.lexer(offset_); + std::tie(length_, is_64bit_) = L.readSectionLength(); + sec_offset_size_ = is_64bit_ ? 8 : 4; + end_ = (const char*)L.loc() + length_; + version_ = L.read(); + UNWIND_CHECK( + version_ == 5 || version_ == 4, + "unexpected dwarf version {}", + version_); + uint8_t address_size = 0; + if (version_ == 5) { + auto unit_type = L.read(); + UNWIND_CHECK(unit_type == 0x1, "unexpected unit type {}", unit_type); + address_size = L.read(); + debug_abbrev_offset_ = + is_64bit_ ? L.read() : L.read(); + } else { + debug_abbrev_offset_ = + is_64bit_ ? L.read() : L.read(); + address_size = L.read(); + } + LOG_INFO( + "compilation unit at offset {:x} with length {:x} and debug_abbrev_offset {:x}\n", + offset, + length_, + debug_abbrev_offset_); + UNWIND_CHECK( + address_size == 8, + "expected 64-bit dwarf but found address size {}", + address_size); + return L; + } + + uint64_t readSegmentOffset(CheckedLexer& L) { + return s_.readSegmentOffset(L, is_64bit_); + } + + uint64_t readEncoded(CheckedLexer& L, uint64_t encoding) { + switch (encoding) { + case DW_FORM_data8: + case DW_FORM_addr: + return L.read(); + case DW_FORM_data4: + return L.read(); + case DW_FORM_addrx: { + auto idx = L.readULEB128(); + return s_.debug_addr.lexer(address_base_ + sizeof(uint64_t) * idx) + .read(); + } + case DW_FORM_sec_offset: + return readSegmentOffset(L); + case DW_FORM_rnglistx: { + return L.readULEB128(); + } + default: + UNWIND_CHECK(false, "unexpected encoding"); + } + } + + void parseCompileUnit(CheckedLexer& L) { + auto entry = L.readULEB128(); + auto A = findAbbrev(debug_abbrev_offset_, entry); + while (true) { + auto attr = A.readULEB128(); + auto form = A.readULEB128(); + if (attr == 0 && form == 0) { + break; + } + if (form == DW_FORM_implicit_const) { + A.readSLEB128(); + } + if (attr == DW_AT_low_pc) { + lowpc_ = readEncoded(L, form); + LOG_INFO(" lowpc {:x}\n", lowpc_); + } else if (attr == DW_AT_high_pc) { + highpc_ = readEncoded(L, form); + range_ptr_ = std::nullopt; + LOG_INFO(" highpc {:x}\n", *highpc_); + } else if (attr == DW_AT_addr_base) { + UNWIND_CHECK(form == DW_FORM_sec_offset, "unexpected addr_base form"); + address_base_ = readSegmentOffset(L); + LOG_INFO(" address base {:x}\n", address_base_); + } else if (attr == DW_AT_rnglists_base) { + UNWIND_CHECK( + form == DW_FORM_sec_offset, "unexpected rnglists_base form"); + rnglists_base_ = readSegmentOffset(L); + LOG_INFO(" range base {:x}\n", *rnglists_base_); + } else if (form == DW_FORM_string) { + L.readCString(); + } else if (attr == DW_AT_stmt_list) { + UNWIND_CHECK(form == DW_FORM_sec_offset, "unexpected stmt_list form"); + LOG_INFO(" program table offset {:x}\n", *line_number_program_offset_); + line_number_program_offset_ = readSegmentOffset(L); + } else if (form == DW_FORM_exprloc) { + auto sz = L.readULEB128(); + L.skip(int64_t(sz)); + } else if (form == DW_FORM_block1) { + auto sz = L.read(); + L.skip(int64_t(sz)); + } else if (attr == DW_AT_ranges) { + auto range_offset = readEncoded(L, form); + LOG_INFO("setting range_ptr to {:x} {:x}\n", range_offset, form); + range_ptr_.emplace(range_offset, form); + } else if ( + form == DW_FORM_udata || form == DW_FORM_rnglistx || + form == DW_FORM_strx || form == DW_FORM_loclistx || + form == DW_FORM_addrx) { + L.readULEB128(); + } else if (form == DW_FORM_sdata) { + L.readSLEB128(); + } else { + auto sz = formSize(form, sec_offset_size_); + UNWIND_CHECK(sz, "unsupported form in compilation unit {:x}", form); + L.skip(int64_t(*sz)); + } + } + } + + std::vector> readRanges4(uint64_t offset) { + CheckedLexer L = s_.debug_ranges.lexer(offset); + std::vector> ranges; + uint64_t base = lowpc_; + while (true) { + auto start = L.read(); + auto end = L.read(); + if (start == 0 && end == 0) { + break; + } + if (start == std::numeric_limits::max()) { + base = end; + } else { + ranges.emplace_back(base + start, base + end); + } + } + return ranges; + } + + std::vector> readRanges5(uint64_t offset) { + CheckedLexer L = s_.debug_rnglists.lexer(offset); + uint64_t base = 0; + LOG_INFO("BEGIN RANGES {:x}\n", offset); + std::vector> ranges; + while (true) { + auto op = L.read(); + switch (op) { + case DW_RLE_end_of_list: + LOG_INFO("END RANGES\n"); + return ranges; + case DW_RLE_base_addressx: { + base = readEncoded(L, DW_FORM_addrx); + LOG_INFO("BASE ADDRX {:x}\n", base); + } break; + case DW_RLE_startx_length: { + auto s = readEncoded(L, DW_FORM_addrx); + auto e = L.readULEB128(); + LOG_INFO("startx_length {:x} {:x}\n", s, e); + ranges.emplace_back(s, s + e); + } break; + case DW_RLE_base_address: + base = L.read(); + LOG_INFO("BASE ADDR {:x}\n", base); + break; + case DW_RLE_offset_pair: { + auto s = L.readULEB128(); + auto e = L.readULEB128(); + LOG_INFO("offset_pair {:x} {:x}\n", s, e); + ranges.emplace_back(base + s, base + e); + } break; + case DW_RLE_start_length: { + auto s = L.read(); + auto e = L.readULEB128(); + LOG_INFO("start_length {:x} {:x}\n", s, e); + ranges.emplace_back(s, s + e); + } break; + default: + UNWIND_CHECK(false, "unknown range op: {}", op); + } + } + } + + CheckedLexer findAbbrev(uint64_t offset, uint64_t entry) { + CheckedLexer L = s_.debug_abbrev.lexer(offset); + while (true) { + auto abbrev_code = L.readULEB128(); + UNWIND_CHECK( + abbrev_code != 0, + "could not find entry {} at offset {:x}", + entry, + offset); + auto tag = L.readULEB128(); + L.read(); // has children + if (abbrev_code == entry) { + UNWIND_CHECK( + tag == DW_TAG_compile_unit, + "first entry was not a compile unit but {}", + tag); + return L; + } + while (true) { + auto attr = L.readULEB128(); + auto form = L.readULEB128(); + if (attr == 0 && form == 0) { + break; + } + if (form == DW_FORM_implicit_const) { + L.readSLEB128(); + } + } + } + } + + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + Sections& s_; + std::optional line_number_program_offset_; + uint64_t offset_ = 0; + uint8_t sec_offset_size_ = 0; + uint64_t length_ = 0; + const char* end_ = nullptr; + uint64_t debug_abbrev_offset_ = 0; + bool is_64bit_ = false; + + std::optional> range_ptr_; + uint64_t lowpc_ = 0; + std::optional highpc_; + uint16_t version_ = 0; + uint64_t address_base_ = 0; + std::optional rnglists_base_; +}; + +} // namespace torch::unwind + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/dwarf_enums.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/dwarf_enums.h new file mode 100644 index 0000000000000000000000000000000000000000..7254057ca61305f1f12a7b4bf6d94d9eb67ed6a6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/dwarf_enums.h @@ -0,0 +1,52 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +enum { + DW_EH_PE_absptr = 0x00, + DW_EH_PE_omit = 0xff, + /* FDE data encoding. */ + DW_EH_PE_uleb128 = 0x01, + DW_EH_PE_udata2 = 0x02, + DW_EH_PE_udata4 = 0x03, + DW_EH_PE_udata8 = 0x04, + DW_EH_PE_sleb128 = 0x09, + DW_EH_PE_sdata2 = 0x0a, + DW_EH_PE_sdata4 = 0x0b, + DW_EH_PE_sdata8 = 0x0c, + DW_EH_PE_signed = 0x08, + /* FDE flags. */ + DW_EH_PE_pcrel = 0x10, + DW_EH_PE_textrel = 0x20, + DW_EH_PE_datarel = 0x30, + DW_EH_PE_funcrel = 0x40, + DW_EH_PE_aligned = 0x50, + DW_EH_PE_indirect = 0x80, +}; + +enum { + DW_CFA_nop = 0x0, + DW_CFA_advance_loc = 0x01, + DW_CFA_offset = 0x02, + DW_CFA_restore = 0x03, + DW_CFA_advance_loc1 = 0x02, + DW_CFA_advance_loc2 = 0x03, + DW_CFA_advance_loc4 = 0x04, + DW_CFA_offset_extended = 0x05, + DW_CFA_restore_extended = 0x06, + DW_CFA_undefined = 0x07, + DW_CFA_register = 0x09, + DW_CFA_remember_state = 0x0a, + DW_CFA_restore_state = 0x0b, + DW_CFA_def_cfa = 0x0c, + DW_CFA_def_cfa_register = 0x0d, + DW_CFA_def_cfa_offset = 0x0e, + DW_CFA_def_cfa_expression = 0xf, + DW_CFA_expression = 0x10, + DW_CFA_offset_extended_sf = 0x11, + DW_CFA_GNU_args_size = 0x2e, + DW_OP_deref = 0x6, +}; + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/dwarf_symbolize_enums.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/dwarf_symbolize_enums.h new file mode 100644 index 0000000000000000000000000000000000000000..d14a1dfd1d01bcd9ef6e06d63605bb91a8a83ba1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/dwarf_symbolize_enums.h @@ -0,0 +1,184 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include + +enum { + DW_TAG_subprogram = 0x2e, + DW_TAG_inlined_subroutine = 0x1d, + DW_TAG_compile_unit = 0x11, + DW_AT_sibling = 0x1, // reference + DW_AT_name = 0x3, // string + DW_AT_stmt_list = 0x10, // lineptr + DW_AT_addr_base = 0x73, // sec_offset + DW_AT_rnglists_base = 0x74, // sec_offset + DW_AT_low_pc = 0x11, // address + DW_AT_high_pc = 0x12, // address + DW_AT_specification = 0x47, // reference + DW_AT_abstract_origin = 0x31, // reference + DW_AT_linkage_name = 0x6e, // string + DW_AT_ranges = 0x55, // rnglist + DW_AT_str_offsets_base = 0x72, // sec_offset + DW_FORM_addr = 0x01, + DW_FORM_block2 = 0x03, + DW_FORM_block4 = 0x04, + DW_FORM_data2 = 0x05, + DW_FORM_data4 = 0x06, + DW_FORM_data8 = 0x07, + DW_FORM_string = 0x08, + DW_FORM_block = 0x09, + DW_FORM_block1 = 0x0a, + DW_FORM_data1 = 0x0b, + DW_FORM_flag = 0x0c, + DW_FORM_sdata = 0x0d, + DW_FORM_strp = 0x0e, + DW_FORM_udata = 0x0f, + DW_FORM_ref_addr = 0x10, + DW_FORM_ref1 = 0x11, + DW_FORM_ref2 = 0x12, + DW_FORM_ref4 = 0x13, + DW_FORM_ref8 = 0x14, + DW_FORM_ref_udata = 0x15, + DW_FORM_indirect = 0x16, + DW_FORM_sec_offset = 0x17, + DW_FORM_exprloc = 0x18, + DW_FORM_flag_present = 0x19, + DW_FORM_strx = 0x1a, + DW_FORM_addrx = 0x1b, + DW_FORM_ref_sup4 = 0x1c, + DW_FORM_strp_sup = 0x1d, + DW_FORM_data16 = 0x1e, + DW_FORM_line_strp = 0x1f, + DW_FORM_ref_sig8 = 0x20, + DW_FORM_implicit_const = 0x21, + DW_FORM_loclistx = 0x22, + DW_FORM_rnglistx = 0x23, + DW_FORM_ref_sup8 = 0x24, + DW_FORM_strx1 = 0x25, + DW_FORM_strx2 = 0x26, + DW_FORM_strx3 = 0x27, + DW_FORM_strx4 = 0x28, + DW_FORM_addrx1 = 0x29, + DW_FORM_addrx2 = 0x2a, + DW_FORM_addrx3 = 0x2b, + DW_FORM_addrx4 = 0x2c, + /* GNU Debug Fission extensions. */ + DW_FORM_GNU_addr_index = 0x1f01, + DW_FORM_GNU_str_index = 0x1f02, + DW_FORM_GNU_ref_alt = 0x1f20, /* offset in alternate .debuginfo. */ + DW_FORM_GNU_strp_alt = 0x1f21, /* offset in alternate .debug_str. */ + DW_LNCT_path = 0x1, + DW_LNCT_directory_index = 0x2, + DW_LNS_extended_op = 0x00, + DW_LNE_end_sequence = 0x01, + DW_LNE_set_address = 0x02, + DW_LNS_copy = 0x01, + DW_LNS_advance_pc = 0x02, + DW_LNS_advance_line = 0x03, + DW_LNS_set_file = 0x04, + DW_LNS_const_add_pc = 0x08, + DW_LNS_fixed_advance_pc = 0x09, + DW_RLE_end_of_list = 0x0, + DW_RLE_base_addressx = 0x1, + DW_RLE_startx_endx = 0x2, + DW_RLE_startx_length = 0x3, + DW_RLE_offset_pair = 0x4, + DW_RLE_base_address = 0x5, + DW_RLE_start_end = 0x6, + DW_RLE_start_length = 0x7 +}; + +static std::optional formSize(uint64_t form, uint8_t sec_offset_size) { + switch (form) { + case DW_FORM_addr: + return sizeof(void*); + case DW_FORM_block2: + case DW_FORM_block4: + return std::nullopt; + case DW_FORM_data2: + return 2; + case DW_FORM_data4: + return 4; + case DW_FORM_data8: + return 8; + case DW_FORM_string: + case DW_FORM_block: + case DW_FORM_block1: + return std::nullopt; + case DW_FORM_data1: + case DW_FORM_flag: + return 1; + case DW_FORM_sdata: + return std::nullopt; + case DW_FORM_strp: + return sec_offset_size; + case DW_FORM_udata: + return std::nullopt; + case DW_FORM_ref_addr: + return sec_offset_size; + case DW_FORM_ref1: + return 1; + case DW_FORM_ref2: + return 2; + case DW_FORM_ref4: + return 4; + case DW_FORM_ref8: + return 8; + case DW_FORM_ref_udata: + case DW_FORM_indirect: + return std::nullopt; + case DW_FORM_sec_offset: + return sec_offset_size; + case DW_FORM_exprloc: + return std::nullopt; + case DW_FORM_flag_present: + return 0; + case DW_FORM_strx: + case DW_FORM_addrx: + return std::nullopt; + case DW_FORM_ref_sup4: + return 4; + case DW_FORM_strp_sup: + return sec_offset_size; + case DW_FORM_data16: + return 16; + case DW_FORM_line_strp: + return sec_offset_size; + case DW_FORM_ref_sig8: + return 8; + case DW_FORM_implicit_const: + return 0; + case DW_FORM_loclistx: + case DW_FORM_rnglistx: + return std::nullopt; + case DW_FORM_ref_sup8: + return 8; + case DW_FORM_strx1: + return 1; + case DW_FORM_strx2: + return 2; + case DW_FORM_strx3: + return 3; + case DW_FORM_strx4: + return 4; + case DW_FORM_addrx1: + return 1; + case DW_FORM_addrx2: + return 2; + case DW_FORM_addrx3: + return 3; + case DW_FORM_addrx4: + return 4; + case DW_FORM_GNU_addr_index: + case DW_FORM_GNU_str_index: + case DW_FORM_GNU_ref_alt: + case DW_FORM_GNU_strp_alt: + default: + return std::nullopt; + } +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/eh_frame_hdr.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/eh_frame_hdr.h new file mode 100644 index 0000000000000000000000000000000000000000..865ddaecbacc94de1b0995effefbe628f3aefaa8 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/eh_frame_hdr.h @@ -0,0 +1,105 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include + +#include +#include + +// Overview of the format described in +// https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html +namespace torch::unwind { + +struct EHFrameHdr { + EHFrameHdr(void* base) : base_(base) { + Lexer L(base, base); + version_ = L.read(); + eh_frame_ptr_enc_ = L.read(); + fde_count_enc_ = L.read(); + table_enc_ = L.read(); + if (table_enc_ == DW_EH_PE_omit) { + table_size_ = 0; + } else { + switch (table_enc_ & 0xF) { + case DW_EH_PE_udata2: + case DW_EH_PE_sdata2: + table_size_ = 2; + break; + case DW_EH_PE_udata4: + case DW_EH_PE_sdata4: + table_size_ = 4; + break; + case DW_EH_PE_udata8: + case DW_EH_PE_sdata8: + table_size_ = 8; + break; + case DW_EH_PE_uleb128: + case DW_EH_PE_sleb128: + throw UnwindError("uleb/sleb table encoding not supported"); + break; + default: + throw UnwindError("unknown table encoding"); + } + } + // NOLINTNEXTLINE(performance-no-int-to-ptr) + eh_frame_ = (void*)L.readEncodedOr(eh_frame_ptr_enc_, 0); + fde_count_ = L.readEncodedOr(fde_count_enc_, 0); + table_start_ = L.loc(); + } + size_t nentries() const { + return fde_count_; + } + + uint64_t lowpc(size_t i) const { + return Lexer(table_start_, base_) + .skip(2 * i * table_size_) + .readEncoded(table_enc_); + } + void* fde(size_t i) const { + // NOLINTNEXTLINE(performance-no-int-to-ptr) + return (void*)Lexer(table_start_, base_) + .skip((2 * i + 1) * table_size_) + .readEncoded(table_enc_); + } + + void* entryForAddr(uint64_t addr) const { + if (!table_size_ || !nentries()) { + throw UnwindError("search table not present"); + } + uint64_t low = 0; + uint64_t high = nentries(); + while (low + 1 < high) { + auto mid = (low + high) / 2; + if (addr < lowpc(mid)) { + high = mid; + } else { + low = mid; + } + } + return fde(low); + } + + friend std::ostream& operator<<(std::ostream& out, const EHFrameHdr& self) { + out << "EHFrameHeader(version=" << self.version_ + << ",table_size=" << self.table_size_ + << ",fde_count=" << self.fde_count_ << ')'; + return out; + } + + private: + void* base_; + void* table_start_; + uint8_t version_; + uint8_t eh_frame_ptr_enc_; + uint8_t fde_count_enc_; + uint8_t table_enc_; + void* eh_frame_ = nullptr; + int64_t fde_count_; + uint32_t table_size_; +}; + +} // namespace torch::unwind + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/fast_symbolizer.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/fast_symbolizer.h new file mode 100644 index 0000000000000000000000000000000000000000..2740c50054b41a55ff7190aacc9e7258464f5fa7 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/fast_symbolizer.h @@ -0,0 +1,113 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace torch::unwind { + +#define UNWIND_WARN(w, ...) \ + do { \ + w.emplace_back(fmt::format(__VA_ARGS__)); \ + LOG_INFO("WARNING: {}\n", w.back()); \ + } while (0); + +struct FastSymbolizer { + FastSymbolizer() = default; + Frame symbolize(const std::string& library, uint64_t offset) { + LOG_INFO("symbolizing {} + 0x{:x}\n", library, offset); + Frame frame; + frame.funcname = "??"; + frame.filename = library; + frame.lineno = offset; + auto s = getOrCreateSections(library); + if (auto e = s->findSubprogramName(offset)) { + frame.funcname = *e; + } else { + UNWIND_WARN( + warnings_, + "failed to find subprogram name for {} 0x{:x}", + library, + offset); + } + if (auto e = findLine(s, offset)) { + frame.filename = e->first; + frame.lineno = e->second; + } else { + UNWIND_WARN( + warnings_, "failed to find file/line for {} 0x{:x}", library, offset); + } + return frame; + } + const std::vector& warnings() { + return warnings_; + } + + private: + void parseDebugInfo(Sections* s) { + uint64_t offset = 0; + while (offset < s->debug_info.size) { + DebugInfo info(*s); + info.parse(offset); + if (auto lnp_offset = info.lineNumberProgramOffset()) { + for (auto r : info.ranges()) { + s->addDebugInfoRange(r.first, r.second, line_number_programs_.size()); + } + line_number_programs_.emplace_back( + std::make_unique(*s, *lnp_offset)); + } + offset = info.nextOffset(); + } + } + Sections* getOrCreateSections(const std::string& library) { + auto it = libraries_.find(library); + if (it == libraries_.end()) { + it = libraries_.insert({library, std::make_unique()}).first; + try { + Sections* s = it->second.get(); + s->parse(library.c_str()); + parseDebugInfo(s); + } catch (UnwindError& err) { + UNWIND_WARN( + warnings_, "failed to parse library {}: {}", library, err.what()); + } + } + return it->second.get(); + } + std::optional> findLine( + Sections* s, + uint64_t offset) { + if (auto idx = s->findDebugInfoOffset(offset)) { + auto r = line_number_programs_.at(*idx).get(); + try { + r->parse(); + } catch (UnwindError& err) { + UNWIND_WARN( + warnings_, + "failed to read line number program [{:x}] {}", + r->offset(), + err.what()); + } + if (auto e = r->find(offset)) { + return std::make_pair(r->filename(e->file), e->line); + } + } + return std::nullopt; + } + std::unordered_map> libraries_; + std::vector> line_number_programs_; + std::vector warnings_; +}; + +} // namespace torch::unwind + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/fde.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/fde.h new file mode 100644 index 0000000000000000000000000000000000000000..461363707fc46087a34a8d90014786b95a54a92c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/fde.h @@ -0,0 +1,423 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +namespace torch::unwind { + +struct TableState { + Action cfa; + std::array registers; + friend std::ostream& operator<<(std::ostream& out, const TableState& self) { + out << "cfa = " << self.cfa << "; "; + for (auto r : c10::irange(self.registers.size())) { + if (self.registers.at(r).kind != A_UNDEFINED) { + out << 'r' << r << " = " << self.registers.at(r) << "; "; + } + } + return out; + } +}; + +// FDE - Frame Description Entry (Concept in ELF spec) +// This format is explained well by +// https://www.airs.com/blog/archives/460 +// Details of different dwarf actions are explained +// in the spec document: +// https://web.archive.org/web/20221129184704/https://dwarfstd.org/doc/DWARF4.doc +// An overview of how DWARF unwinding works is given in +// https://dl.acm.org/doi/pdf/10.1145/3360572 +// A similar implementation written in rust is: +// https://github.com/mstange/framehop/ + +template +struct FDE { + FDE(void* data, const char* library_name, uint64_t load_bias) + : library_name_(library_name), load_bias_(load_bias) { + Lexer L(data); + auto length = L.read4or8Length(); + void* fde_start = L.loc(); + // NOLINTNEXTLINE(performance-no-int-to-ptr) + void* cie_data = (void*)((int64_t)fde_start - L.read()); + Lexer LC(cie_data); + auto cie_length = LC.read4or8Length(); + void* cie_start = LC.loc(); + auto zero = LC.read(); + TORCH_INTERNAL_ASSERT(zero == 0, "expected 0 for CIE"); + auto version = LC.read(); + TORCH_INTERNAL_ASSERT( + version == 1 || version == 3, "non-1 version for CIE"); + augmentation_string_ = LC.readCString(); + if (hasAugmentation("eh")) { + throw UnwindError("unsupported 'eh' augmentation string"); + } + code_alignment_factor_ = static_cast(LC.readULEB128()); + data_alignment_factor_ = LC.readSLEB128(); + if (version == 1) { + ra_register_ = LC.read(); + } else { + ra_register_ = static_cast(LC.readULEB128()); + } + TORCH_INTERNAL_ASSERT( + ra_register_ == D_EXPECTED_RA_REG, + "unexpected ra register: ", + ra_register_); + if (augmentation_string_ && *augmentation_string_ == 'z') { + augmentation_length_ = static_cast(LC.readULEB128()); + Lexer A(LC.loc()); + for (auto ap = augmentation_string_ + 1; *ap; ap++) { + switch (*ap) { + case 'L': + lsda_enc = A.read(); + break; + case 'R': + fde_enc = A.read(); + break; + case 'P': { + uint8_t personality_enc = A.read(); + A.readEncoded(personality_enc); + } break; + case 'S': { + // signal handler + } break; + default: { + throw UnwindError("unknown augmentation string"); + } break; + } + } + } + LC.skip(augmentation_length_); + low_pc_ = L.readEncoded(fde_enc); + high_pc_ = low_pc_ + L.readEncodedValue(fde_enc); + + if (hasAugmentation("z")) { + augmentation_length_fde_ = static_cast(L.readULEB128()); + } + L.readEncodedOr(lsda_enc, 0); + + cie_begin_ = LC.loc(); + fde_begin_ = L.loc(); + cie_end_ = (void*)((const char*)cie_start + cie_length); + fde_end_ = (void*)((const char*)fde_start + length); + } + + // OP Code implementations + + void advance_raw(int64_t amount) { + auto previous_pc = current_pc_; + current_pc_ += amount; + if (LOG) { + (*out_) << (void*)(previous_pc - load_bias_) << '-' + << (void*)(current_pc_ - load_bias_) << ": " << state() << '\n'; + } + } + + void advance_loc(int64_t amount) { + if (LOG) { + (*out_) << "advance_loc " << amount << '\n'; + } + advance_raw(amount * code_alignment_factor_); + } + + void offset(int64_t reg, int64_t offset) { + if (LOG) { + (*out_) << "offset " << reg << ' ' << offset << '\n'; + } + if (reg > (int64_t)state().registers.size()) { + if (LOG) { + (*out_) << "OFFSET OF BIG REGISTER " << reg << "ignored...\n"; + } + return; + } + state().registers.at(reg) = + Action{A_LOAD_CFA_OFFSET, -1, offset * data_alignment_factor_}; + } + + void restore(int64_t reg) { + if (LOG) { + (*out_) << "restore " << reg << '\n'; + } + if (reg > (int64_t)state().registers.size()) { + if (LOG) { + (*out_) << "RESTORE OF BIG REGISTER " << reg << "ignored...\n"; + } + return; + } + state().registers.at(reg) = initial_state_.registers.at(reg); + } + + void def_cfa(int64_t reg, int64_t off) { + if (LOG) { + (*out_) << "def_cfa " << reg << ' ' << off << '\n'; + } + last_reg_ = reg; + last_offset_ = off; + state().cfa = Action::regPlusData(static_cast(reg), off); + } + void def_cfa_register(int64_t reg) { + def_cfa(reg, last_offset_); + } + void def_cfa_offset(int64_t off) { + def_cfa(last_reg_, off); + } + + void remember_state() { + if (LOG) { + (*out_) << "remember_state\n"; + } + state_stack_.push_back(state()); + } + void restore_state() { + if (LOG) { + (*out_) << "restore_state\n"; + } + state_stack_.pop_back(); + } + + void undefined(int64_t reg) { + if (LOG) { + (*out_) << "undefined " << reg << '\n'; + } + state().registers.at(reg) = Action::undefined(); + } + void register_(int64_t reg, int64_t rhs_reg) { + if (LOG) { + (*out_) << "register " << reg << ' ' << rhs_reg << '\n'; + } + state().registers.at(reg) = + Action::regPlusData(static_cast(reg), 0); + } + + TableState& state() { + return state_stack_.back(); + } + + void dump(std::ostream& out) { + out_ = &out; + out << "FDE(augmentation_string=" << augmentation_string_ + << ", low_pc=" << (void*)(low_pc_ - load_bias_) + << ",high_pc=" << (void*)(high_pc_ - load_bias_) + << ",code_alignment_factor=" << code_alignment_factor_ + << ", data_alignment_factor=" << data_alignment_factor_ + << ", ra_register_=" << ra_register_ << ")\n"; + readUpTo(high_pc_); + out_ = &std::cout; + } + + TableState readUpTo(uint64_t addr) { + if (addr < low_pc_ || addr > high_pc_) { + throw UnwindError("Address not in range"); + } + if (LOG) { + // NOLINTNEXTLINE(performance-no-int-to-ptr) + (*out_) << "readUpTo " << (void*)addr << " for " << library_name_ + << " at " << (void*)load_bias_ << '\n'; + } + state_stack_.emplace_back(); + current_pc_ = low_pc_; + // parse instructions... + Lexer LC(cie_begin_); + while (LC.loc() < cie_end_ && current_pc_ <= addr) { + readInstruction(LC); + } + if (current_pc_ > addr) { + return state(); + } + + initial_state_ = state_stack_.back(); + + if (LOG) { + (*out_) << "--\n"; + } + + Lexer L(fde_begin_); + while (L.loc() < fde_end_ && current_pc_ <= addr) { + readInstruction(L); + } + // so that we print the full range in debugging + if (current_pc_ <= addr) { + advance_raw(addr - current_pc_); + } + return state(); + } + + void dumpAddr2Line() { + std::cout << "addr2line -f -e " << library_name_ << ' ' + << (void*)(low_pc_ - load_bias_) << '\n'; + } + + void readInstruction(Lexer& L) { + uint8_t bc = L.read(); + auto op = bc >> 6; + auto lowbits = bc & 0x3F; + switch (op) { + case 0x0: { + switch (lowbits) { + case DW_CFA_nop: { + return; // nop + } + case DW_CFA_advance_loc1: { + auto delta = L.read(); + return advance_loc(delta); + } + case DW_CFA_advance_loc2: { + auto delta = L.read(); + return advance_loc(delta); + } + case DW_CFA_advance_loc4: { + auto delta = L.read(); + return advance_loc(delta); + } + case DW_CFA_offset_extended: { + auto reg = L.readULEB128(); + auto off = L.readULEB128(); + return offset(reg, off); + } + case DW_CFA_restore_extended: { + auto reg = L.readULEB128(); + return restore(reg); + } + case DW_CFA_undefined: { + auto reg = L.readULEB128(); + return undefined(reg); + } + case DW_CFA_register: { + auto reg = L.readULEB128(); + auto rhs_reg = L.readULEB128(); + return register_(reg, rhs_reg); + } + case DW_CFA_def_cfa: { + auto reg = L.readULEB128(); + auto off = L.readULEB128(); + return def_cfa(reg, off); + } + case DW_CFA_def_cfa_register: { + auto reg = L.readULEB128(); + return def_cfa_register(reg); + } + case DW_CFA_def_cfa_offset: { + auto off = L.readULEB128(); + return def_cfa_offset(off); + } + case DW_CFA_offset_extended_sf: { + auto reg = L.readULEB128(); + auto off = L.readSLEB128(); + return offset(reg, off); + } + case DW_CFA_remember_state: { + return remember_state(); + } + case DW_CFA_restore_state: { + return restore_state(); + } + case DW_CFA_GNU_args_size: { + // GNU_args_size, we do not need to know it.. + L.readULEB128(); + return; + } + case DW_CFA_expression: { + auto reg = L.readULEB128(); + auto len = L.readULEB128(); + // NOLINTNEXTLINE(performance-no-int-to-ptr) + auto end = (void*)((uint64_t)L.loc() + len); + auto op = L.read(); + if ((op & 0xF0) == 0x70) { // DW_bregX + auto rhs_reg = (op & 0xF); + auto addend = L.readSLEB128(); + if (L.loc() == end) { + state().registers.at(reg) = + Action::regPlusDataDeref(rhs_reg, addend); + return; + } + } + throw UnwindError("Unsupported dwarf expression"); + } + case DW_CFA_def_cfa_expression: { + auto len = L.readULEB128(); + // NOLINTNEXTLINE(performance-no-int-to-ptr) + auto end = (void*)((uint64_t)L.loc() + len); + auto op = L.read(); + if ((op & 0xF0) == 0x70) { // DW_bregX + auto rhs_reg = (op & 0xF); + auto addend = L.readSLEB128(); + if (L.loc() != end) { + auto op2 = L.read(); + if (op2 == DW_OP_deref && L.loc() == end) { // deref + state().cfa = Action::regPlusDataDeref(rhs_reg, addend); + return; + } + } + } + throw UnwindError("Unsupported def_cfa dwarf expression"); + } + default: { + std::stringstream ss; + // NOLINTNEXTLINE(performance-no-int-to-ptr) + ss << "unknown op code " << (void*)(uint64_t)lowbits; + throw UnwindError(ss.str()); + } + } + } + case DW_CFA_advance_loc: { + return advance_loc(lowbits); + } + case DW_CFA_offset: { + auto off = L.readULEB128(); + return offset(lowbits, off); + } + case DW_CFA_restore: { + return restore(lowbits); + } + } + } + // used for debug printing + const char* library_name_; + uint64_t load_bias_; + + // parsed from the eh_string data structures: + const char* augmentation_string_ = nullptr; + int64_t augmentation_length_ = 0; + int64_t augmentation_length_fde_ = 0; + + int64_t code_alignment_factor_; + int64_t data_alignment_factor_; + void* cie_data_{nullptr}; + + int64_t ra_register_; + uint8_t lsda_enc = DW_EH_PE_omit; + uint8_t fde_enc = DW_EH_PE_absptr; + uint64_t low_pc_ = UINT64_MAX; + uint64_t high_pc_ = UINT64_MAX; + + void* cie_begin_; + void* fde_begin_; + void* cie_end_; + void* fde_end_; + + // state accumulated while parsing instructions + int64_t last_reg_ = 0; + int64_t last_offset_ = 0; + uint64_t current_pc_ = 0; + + TableState + initial_state_; // state after the initial instructions, used by restore + std::vector state_stack_; + + std::ostream* out_ = &std::cout; // for debug dumping + private: + bool hasAugmentation(const char* s) { + return strstr(augmentation_string_, s) != nullptr; + } +}; + +} // namespace torch::unwind + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/lexer.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/lexer.h new file mode 100644 index 0000000000000000000000000000000000000000..f9580a88c4574ba9d74464bd61b7d4e0ec527730 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/lexer.h @@ -0,0 +1,164 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include + +#include +#include + +namespace torch::unwind { + +template +struct LexerImpl { + LexerImpl(void* data, void* base = nullptr, void* end = nullptr) + : next_((const char*)data), + base_((int64_t)base), + end_((const char*)end) {} + + template + T read() { + T result; + auto end = next_ + sizeof(T); + UNWIND_CHECK( + !checked || end <= end_, + "read out of bounds {} >= {}", + (void*)end, + (void*)end_); + memcpy(&result, next_, sizeof(T)); + next_ = end; + return result; + } + + // SLEB/ULEB code adapted from LLVM equivalents + int64_t readSLEB128() { + int64_t Value = 0; + unsigned Shift = 0; + uint8_t Byte = 0; + do { + Byte = read(); + uint64_t Slice = Byte & 0x7f; + if ((Shift >= 64 && Slice != (Value < 0 ? 0x7f : 0x00)) || + (Shift == 63 && Slice != 0 && Slice != 0x7f)) { + throw UnwindError("sleb128 too big for int64"); + } + Value |= int64_t(Slice << Shift); + Shift += 7; + } while (Byte >= 128); + // Sign extend negative numbers if needed. + if (Shift < 64 && (Byte & 0x40)) { + Value |= int64_t((-1ULL) << Shift); + } + return Value; + } + + uint64_t readULEB128() { + uint64_t Value = 0; + unsigned Shift = 0; + uint8_t p = 0; + do { + p = read(); + uint64_t Slice = p & 0x7f; + if ((Shift >= 64 && Slice != 0) || Slice << Shift >> Shift != Slice) { + throw UnwindError("uleb128 too big for uint64"); + } + Value += Slice << Shift; + Shift += 7; + } while (p >= 128); + return Value; + } + const char* readCString() { + auto result = next_; + if (!checked) { + next_ += strlen(next_) + 1; + return result; + } + while (next_ < end_) { + if (*next_++ == '\0') { + return result; + } + } + UNWIND_CHECK( + false, "string is out of bounds {} >= {}", (void*)next_, (void*)end_); + } + int64_t readEncoded(uint8_t enc) { + int64_t r = 0; + switch (enc & (~DW_EH_PE_indirect & 0xF0)) { + case DW_EH_PE_absptr: + break; + case DW_EH_PE_pcrel: + r = (int64_t)next_; + break; + case DW_EH_PE_datarel: + r = base_; + break; + default: + throw UnwindError("unknown encoding"); + } + return r + readEncodedValue(enc); + } + int64_t readEncodedOr(uint8_t enc, int64_t orelse) { + if (enc == DW_EH_PE_omit) { + return orelse; + } + return readEncoded(enc); + } + + int64_t read4or8Length() { + return readSectionLength().first; + } + + std::pair readSectionLength() { + int64_t length = read(); + if (length == 0xFFFFFFFF) { + return std::make_pair(read(), true); + } + return std::make_pair(length, false); + } + + void* loc() const { + return (void*)next_; + } + LexerImpl& skip(size_t bytes) { + next_ += bytes; + return *this; + } + + int64_t readEncodedValue(uint8_t enc) { + switch (enc & 0xF) { + case DW_EH_PE_udata2: + return read(); + case DW_EH_PE_sdata2: + return read(); + case DW_EH_PE_udata4: + return read(); + case DW_EH_PE_sdata4: + return read(); + case DW_EH_PE_udata8: + return read(); + case DW_EH_PE_sdata8: + return read(); + case DW_EH_PE_uleb128: + return readULEB128(); + case DW_EH_PE_sleb128: + return readSLEB128(); + default: + throw UnwindError("not implemented"); + } + } + + private: + const char* next_; + int64_t base_; + const char* end_; +}; + +// using Lexer = LexerImpl; +using CheckedLexer = LexerImpl; +using Lexer = LexerImpl; + +} // namespace torch::unwind + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/line_number_program.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/line_number_program.h new file mode 100644 index 0000000000000000000000000000000000000000..32fbc59c4655a7d99c2c795c04c88b125b12193c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/line_number_program.h @@ -0,0 +1,333 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include +#include +#include +#include +#include +#include +#include +#include + +namespace torch::unwind { + +struct LineNumberProgram { + LineNumberProgram(Sections& s, uint64_t offset) : s_(s), offset_(offset) {} + + uint64_t offset() { + return offset_; + } + void parse() { + if (parsed_) { + return; + } + parsed_ = true; + CheckedLexer L = s_.debug_line.lexer(offset_); + std::tie(length_, is_64bit_) = L.readSectionLength(); + program_end_ = (char*)L.loc() + length_; + auto version = L.read(); + UNWIND_CHECK( + version == 5 || version == 4, + "expected version 4 or 5 but found {}", + version); + if (version == 5) { + auto address_size = L.read(); + UNWIND_CHECK( + address_size == 8, + "expected 64-bit dwarf but found address size {}", + address_size); + segment_selector_size_ = L.read(); + } + header_length_ = is_64bit_ ? L.read() : L.read(); + program_ = L; + program_.skip(int64_t(header_length_)); + minimum_instruction_length_ = L.read(); + maximum_operations_per_instruction_ = L.read(); + default_is_stmt_ = L.read(); + line_base_ = L.read(); + line_range_ = L.read(); + opcode_base_ = L.read(); + UNWIND_CHECK(line_range_ != 0, "line_range_ must be non-zero"); + standard_opcode_lengths_.resize(opcode_base_); + for (size_t i = 1; i < opcode_base_; i++) { + standard_opcode_lengths_[i] = L.read(); + } + // fmt::print("{:x} {:x} {} {} {} {} {}\n", offset_, header_length_, + // minimum_instruction_length_, maximum_operations_per_instruction_, + // line_base_, line_range_, opcode_base_); + uint8_t directory_entry_format_count = L.read(); + + if (version == 5) { + struct Member { + uint64_t content_type; + uint64_t form; + }; + std::vector directory_members; + directory_members.reserve(directory_entry_format_count); + for (size_t i = 0; i < directory_entry_format_count; i++) { + directory_members.push_back({L.readULEB128(), L.readULEB128()}); + } + uint64_t directories_count = L.readULEB128(); + for (size_t i = 0; i < directories_count; i++) { + for (auto& member : directory_members) { + switch (member.content_type) { + case DW_LNCT_path: { + include_directories_.emplace_back( + s_.readString(L, member.form, is_64bit_)); + } break; + default: { + skipForm(L, member.form); + } break; + } + } + } + + for (auto i : c10::irange(directories_count)) { + (void)i; + LOG_INFO("{} {}\n", i, include_directories_[i]); + } + auto file_name_entry_format_count = L.read(); + std::vector file_members; + file_members.reserve(file_name_entry_format_count); + for (size_t i = 0; i < file_name_entry_format_count; i++) { + file_members.push_back({L.readULEB128(), L.readULEB128()}); + } + auto files_count = L.readULEB128(); + for (size_t i = 0; i < files_count; i++) { + for (auto& member : file_members) { + switch (member.content_type) { + case DW_LNCT_path: { + file_names_.emplace_back( + s_.readString(L, member.form, is_64bit_)); + } break; + case DW_LNCT_directory_index: { + file_directory_index_.emplace_back(readData(L, member.form)); + UNWIND_CHECK( + file_directory_index_.back() < include_directories_.size(), + "directory index out of range"); + } break; + default: { + skipForm(L, member.form); + } break; + } + } + } + for (auto i : c10::irange(files_count)) { + (void)i; + LOG_INFO("{} {} {}\n", i, file_names_[i], file_directory_index_[i]); + } + } else { + include_directories_.emplace_back(""); // implicit cwd + while (true) { + auto str = L.readCString(); + if (*str == '\0') { + break; + } + include_directories_.emplace_back(str); + } + file_names_.emplace_back(""); + file_directory_index_.emplace_back(0); + while (true) { + auto str = L.readCString(); + if (*str == '\0') { + break; + } + auto directory_index = L.readULEB128(); + L.readULEB128(); // mod_time + L.readULEB128(); // file_length + file_names_.emplace_back(str); + file_directory_index_.push_back(directory_index); + } + } + UNWIND_CHECK( + maximum_operations_per_instruction_ == 1, + "maximum_operations_per_instruction_ must be 1"); + UNWIND_CHECK( + minimum_instruction_length_ == 1, + "minimum_instruction_length_ must be 1"); + readProgram(); + } + struct Entry { + uint32_t file = 1; + int64_t line = 1; + }; + std::optional find(uint64_t address) { + auto e = program_index_.find(address); + if (!e) { + return std::nullopt; + } + return all_programs_.at(*e).find(address); + } + std::string filename(uint64_t index) { + return fmt::format( + "{}/{}", + include_directories_.at(file_directory_index_.at(index)), + file_names_.at(index)); + } + + private: + void skipForm(CheckedLexer& L, uint64_t form) { + auto sz = formSize(form, is_64bit_ ? 8 : 4); + UNWIND_CHECK(sz, "unsupported form {}", form); + L.skip(int64_t(*sz)); + } + + uint64_t readData(CheckedLexer& L, uint64_t encoding) { + switch (encoding) { + case DW_FORM_data1: + return L.read(); + case DW_FORM_data2: + return L.read(); + case DW_FORM_data4: + return L.read(); + case DW_FORM_data8: + return L.read(); + case DW_FORM_udata: + return L.readULEB128(); + default: + UNWIND_CHECK(false, "unsupported data encoding {}", encoding); + } + } + + void produceEntry() { + if (shadow_) { + return; + } + if (ranges_.size() == 1) { + start_address_ = address_; + } + PRINT_LINE_TABLE( + "{:x}\t{}\t{}\n", address_, filename(entry_.file), entry_.line); + UNWIND_CHECK( + entry_.file < file_names_.size(), + "file index {} > {} entries", + entry_.file, + file_names_.size()); + ranges_.add(address_, entry_, true); + } + void endSequence() { + if (shadow_) { + return; + } + PRINT_LINE_TABLE( + "{:x}\tEND\n", address_, filename(entry_.file), entry_.line); + program_index_.add(start_address_, all_programs_.size(), false); + program_index_.add(address_, std::nullopt, false); + all_programs_.emplace_back(std::move(ranges_)); + ranges_ = RangeTable(); + } + void readProgram() { + while (program_.loc() < program_end_) { + PRINT_INST("{:x}: ", (char*)program_.loc() - (s_.debug_line.data)); + uint8_t op = program_.read(); + if (op >= opcode_base_) { + auto op2 = int64_t(op - opcode_base_); + address_ += op2 / line_range_; + entry_.line += line_base_ + (op2 % line_range_); + PRINT_INST( + "address += {}, line += {}\n", + op2 / line_range_, + line_base_ + (op2 % line_range_)); + produceEntry(); + } else { + switch (op) { + case DW_LNS_extended_op: { + auto len = program_.readULEB128(); + auto extended_op = program_.read(); + switch (extended_op) { + case DW_LNE_end_sequence: { + PRINT_INST("end_sequence\n"); + endSequence(); + entry_ = Entry{}; + } break; + case DW_LNE_set_address: { + address_ = program_.read(); + if (!shadow_) { + PRINT_INST( + "set address {:x} {:x} {:x}\n", + address_, + min_address_, + max_address_); + } + shadow_ = address_ == 0; + } break; + default: { + PRINT_INST("skip extended op {}\n", extended_op); + program_.skip(int64_t(len - 1)); + } break; + } + } break; + case DW_LNS_copy: { + PRINT_INST("copy\n"); + produceEntry(); + } break; + case DW_LNS_advance_pc: { + PRINT_INST("advance pc\n"); + address_ += program_.readULEB128(); + } break; + case DW_LNS_advance_line: { + entry_.line += program_.readSLEB128(); + PRINT_INST("advance line {}\n", entry_.line); + + } break; + case DW_LNS_set_file: { + PRINT_INST("set file\n"); + entry_.file = program_.readULEB128(); + } break; + case DW_LNS_const_add_pc: { + PRINT_INST("const add pc\n"); + address_ += (255 - opcode_base_) / line_range_; + } break; + case DW_LNS_fixed_advance_pc: { + PRINT_INST("fixed advance pc\n"); + address_ += program_.read(); + } break; + default: { + PRINT_INST("other {}\n", op); + auto n = standard_opcode_lengths_[op]; + for (int i = 0; i < n; ++i) { + program_.readULEB128(); + } + } break; + } + } + } + PRINT_INST( + "{:x}: end {:x}\n", + ((char*)program_.loc() - s_.debug_line.data), + program_end_ - s_.debug_line.data); + } + + uint64_t address_ = 0; + bool shadow_ = false; + bool parsed_ = false; + Entry entry_ = {}; + std::vector include_directories_; + std::vector file_names_; + std::vector file_directory_index_; + uint8_t segment_selector_size_ = 0; + uint8_t minimum_instruction_length_ = 0; + uint8_t maximum_operations_per_instruction_ = 0; + int8_t line_base_ = 0; + uint8_t line_range_ = 0; + uint8_t opcode_base_ = 0; + bool default_is_stmt_ = false; + CheckedLexer program_ = {nullptr}; + char* program_end_ = nullptr; + uint64_t header_length_ = 0; + uint64_t length_ = 0; + bool is_64bit_ = false; + std::vector standard_opcode_lengths_; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + Sections& s_; + uint64_t offset_; + uint64_t start_address_ = 0; + RangeTable program_index_; + std::vector> all_programs_; + RangeTable ranges_; +}; + +} // namespace torch::unwind + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/mem_file.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/mem_file.h new file mode 100644 index 0000000000000000000000000000000000000000..15f6821012f0306007a061499867a8d1d97b7ec2 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/mem_file.h @@ -0,0 +1,164 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// Copyright (c) Meta Platforms, Inc. and affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace torch::unwind { + +struct Section { + char* data = nullptr; + size_t size = 0; + const char* string(size_t offset) { + return lexer(offset).readCString(); + } + CheckedLexer lexer(size_t offset) { + return CheckedLexer(data + offset, data, data + size); + } +}; + +/// Memory maps a file into the address space read-only, and manages the +/// lifetime of the mapping. Here are a few use cases: +/// 1. Used in the loader to read in initial image, and to inspect +// ELF files for dependencies before calling dlopen. +/// +/// 2. Used in unity to load the elf file. +struct MemFile { + explicit MemFile(const char* filename_) + : fd_(open(filename_, O_RDONLY)), name_(filename_) { + UNWIND_CHECK( + fd_ != -1, + "failed to open {}: {}", + filename_, + c10::utils::str_error(errno)); + struct stat s{}; + if (-1 == fstat(fd_, &s)) { + close(fd_); // destructors don't run during exceptions + UNWIND_CHECK( + false, + "failed to stat {}: {}", + filename_, + c10::utils::str_error(errno)); + } + n_bytes_ = s.st_size; + UNWIND_CHECK( + n_bytes_ > sizeof(Elf64_Ehdr), "empty shared library: {}", filename_); + mem_ = (char*)mmap(nullptr, n_bytes_, PROT_READ, MAP_SHARED, fd_, 0); + if (MAP_FAILED == mem_) { + close(fd_); + UNWIND_CHECK( + false, + "failed to mmap {}: {}", + filename_, + c10::utils::str_error(errno)); + } + ehdr_ = (Elf64_Ehdr*)mem_; +#define ELF_CHECK(cond) UNWIND_CHECK(cond, "not an ELF file: {}", filename_) + ELF_CHECK(ehdr_->e_ident[EI_MAG0] == ELFMAG0); + ELF_CHECK(ehdr_->e_ident[EI_MAG1] == ELFMAG1); + ELF_CHECK(ehdr_->e_ident[EI_MAG2] == ELFMAG2); + ELF_CHECK(ehdr_->e_ident[EI_MAG3] == ELFMAG3); + ELF_CHECK(ehdr_->e_ident[EI_CLASS] == ELFCLASS64); + ELF_CHECK(ehdr_->e_ident[EI_VERSION] == EV_CURRENT); + ELF_CHECK(ehdr_->e_version == EV_CURRENT); + ELF_CHECK(ehdr_->e_machine == EM_X86_64); +#undef ELF_CHECK + UNWIND_CHECK( + ehdr_->e_shoff + sizeof(Elf64_Shdr) * ehdr_->e_shnum <= n_bytes_, + "invalid section header table {} {} {}", + ehdr_->e_shoff + sizeof(Elf64_Shdr) * ehdr_->e_shnum, + n_bytes_, + ehdr_->e_shnum); + shdr_ = (Elf64_Shdr*)(mem_ + ehdr_->e_shoff); + UNWIND_CHECK( + ehdr_->e_shstrndx < ehdr_->e_shnum, "invalid strtab section offset"); + auto& strtab_hdr = shdr_[ehdr_->e_shstrndx]; + strtab_ = getSection(strtab_hdr); + } + + MemFile(const MemFile&) = delete; + MemFile(MemFile&&) = delete; + MemFile& operator=(const MemFile&) = delete; + MemFile& operator=(MemFile&&) = delete; + [[nodiscard]] const char* data() const { + return (const char*)mem_; + } + + /// Returns whether or not the file descriptor + /// of the underlying file is valid. + int valid() { + return fcntl(fd_, F_GETFD) != -1 || errno != EBADF; + } + + ~MemFile() { + if (mem_) { + munmap((void*)mem_, n_bytes_); + } + if (fd_ >= 0) { + close(fd_); + } + } + + /// Returns the size of the underlying file defined by the `MemFile` + size_t size() { + return n_bytes_; + } + [[nodiscard]] int fd() const { + return fd_; + } + + Section getSection(const Elf64_Shdr& shdr) { + UNWIND_CHECK(shdr.sh_offset + shdr.sh_size <= n_bytes_, "invalid section"); + return Section{mem_ + shdr.sh_offset, shdr.sh_size}; + } + + Section getSection(const char* name, bool optional) { + for (int i = 0; i < ehdr_->e_shnum; i++) { + if (strcmp(strtab_.string(shdr_[i].sh_name), name) == 0) { + return getSection(shdr_[i]); + } + } + UNWIND_CHECK(optional, "{} has no section {}", name_, name); + return Section{nullptr, 0}; + } + + Section strtab() { + return strtab_; + } + + private: + template + T* load(size_t offset) { + UNWIND_CHECK(offset < n_bytes_, "out of range"); + return (T*)(mem_ + offset); + } + int fd_; + char* mem_{nullptr}; + size_t n_bytes_{0}; + std::string name_; + Elf64_Ehdr* ehdr_; + Elf64_Shdr* shdr_; + Section strtab_ = {nullptr, 0}; +}; + +} // namespace torch::unwind + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/range_table.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/range_table.h new file mode 100644 index 0000000000000000000000000000000000000000..a08bf00133fe6c4aa5f9fa7ef528b99d1c6b547b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/range_table.h @@ -0,0 +1,78 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include +#include + +namespace torch::unwind { +template +struct RangeTable { + RangeTable() { + // guarantee that lower_bound[-1] is always valid + addresses_.push_back(0); + payloads_.emplace_back(std::nullopt); + } + void add(uint64_t address, std::optional payload, bool sorted) { + if (addresses_.back() > address) { + UNWIND_CHECK(!sorted, "expected addresses to be sorted"); + sorted_ = false; + } + addresses_.push_back(address); + payloads_.emplace_back(std::move(payload)); + } + std::optional find(uint64_t address) { + maybeSort(); + auto it = std::upper_bound(addresses_.begin(), addresses_.end(), address); + return payloads_.at(it - addresses_.begin() - 1); + } + void dump() { + for (size_t i = 0; i < addresses_.size(); i++) { + fmt::print("{} {:x}: {}\n", i, addresses_[i], payloads_[i] ? "" : "END"); + } + } + size_t size() const { + return addresses_.size(); + } + uint64_t back() { + maybeSort(); + return addresses_.back(); + } + + private: + void maybeSort() { + if (sorted_) { + return; + } + std::vector indices; + indices.reserve(addresses_.size()); + for (size_t i = 0; i < addresses_.size(); i++) { + indices.push_back(i); + } + std::sort(indices.begin(), indices.end(), [&](uint64_t a, uint64_t b) { + return addresses_[a] < addresses_[b] || + (addresses_[a] == addresses_[b] && + bool(payloads_[a]) < bool(payloads_[b])); + }); + std::vector addresses; + std::vector> payloads; + addresses.reserve(addresses_.size()); + payloads.reserve(addresses_.size()); + for (auto i : indices) { + addresses.push_back(addresses_[i]); + payloads.push_back(payloads_[i]); + } + addresses_ = std::move(addresses); + payloads_ = std::move(payloads); + sorted_ = true; + } + bool sorted_ = true; + std::vector addresses_; + std::vector> payloads_; +}; +} // namespace torch::unwind + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/sections.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/sections.h new file mode 100644 index 0000000000000000000000000000000000000000..f3f4f63b2d4e92d14ff361c722df2b66f0009d73 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/sections.h @@ -0,0 +1,125 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +namespace torch::unwind { + +static std::string demangle(const std::string& mangled_name) { + int status = 0; + char* realname = + abi::__cxa_demangle(mangled_name.c_str(), nullptr, nullptr, &status); + if (status == 0) { + std::string demangled_name(realname); + // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) + free(realname); + return demangled_name; + } else { + return mangled_name; + } +} + +struct Sections { + Sections() = default; + void parse(const char* name) { + library_ = std::make_unique(name); + strtab = library_->getSection(".strtab", false); + + symtab = library_->getSection(".symtab", true); + debug_info = library_->getSection(".debug_info", true); + if (debug_info.size > 0) { + debug_abbrev = library_->getSection(".debug_abbrev", false); + debug_str = library_->getSection(".debug_str", false); + debug_line = library_->getSection(".debug_line", false); + // dwarf 5 + debug_line_str = library_->getSection(".debug_line_str", true); + debug_rnglists = library_->getSection(".debug_rnglists", true); + debug_addr = library_->getSection(".debug_addr", true); + // dwarf 4 + debug_ranges = library_->getSection(".debug_ranges", true); + } + parseSymtab(); + } + + Section debug_info; + Section debug_abbrev; + Section debug_str; + Section debug_line; + Section debug_line_str; + Section debug_rnglists; + Section debug_ranges; + Section debug_addr; + Section symtab; + Section strtab; + + const char* readString(CheckedLexer& data, uint64_t encoding, bool is_64bit) { + switch (encoding) { + case DW_FORM_string: { + return data.readCString(); + } + case DW_FORM_strp: { + return debug_str.string(readSegmentOffset(data, is_64bit)); + } + case DW_FORM_line_strp: { + return debug_line_str.string(readSegmentOffset(data, is_64bit)); + } + default: + UNWIND_CHECK(false, "unsupported string encoding {:x}", encoding); + } + } + + uint64_t readSegmentOffset(CheckedLexer& data, bool is_64bit) { + return is_64bit ? data.read() : data.read(); + } + + std::optional findDebugInfoOffset(uint64_t address) { + return debug_info_offsets_.find(address); + } + size_t compilationUnitCount() { + return debug_info_offsets_.size() / 2; + } + void addDebugInfoRange( + uint64_t start, + uint64_t end, + uint64_t debug_info_offset) { + debug_info_offsets_.add(start, debug_info_offset, false); + debug_info_offsets_.add(end, std::nullopt, false); + } + std::optional findSubprogramName(uint64_t address) { + if (auto e = symbol_table_.find(address)) { + return demangle(strtab.string(*e)); + } + return std::nullopt; + } + + private: + void parseSymtab() { + auto L = symtab.lexer(0); + char* end = symtab.data + symtab.size; + while (L.loc() < end) { + auto symbol = L.read(); + if (symbol.st_shndx == SHN_UNDEF || + ELF64_ST_TYPE(symbol.st_info) != STT_FUNC) { + continue; + } + symbol_table_.add(symbol.st_value, symbol.st_name, false); + symbol_table_.add(symbol.st_value + symbol.st_size, std::nullopt, false); + } + } + + std::unique_ptr library_; + RangeTable debug_info_offsets_; + RangeTable symbol_table_; +}; + +} // namespace torch::unwind + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/unwind.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/unwind.h new file mode 100644 index 0000000000000000000000000000000000000000..5dd90ecbbebb016b28fc3c3581a5e3a4c8f36c6a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/unwind.h @@ -0,0 +1,48 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include +#include + +namespace torch::unwind { +// gather current stack, relatively fast. +// gets faster once the cache of program counter locations is warm. +TORCH_API std::vector unwind(); + +struct Frame { + std::string filename; + std::string funcname; + uint64_t lineno; +}; + +enum class Mode { addr2line, fast, dladdr }; + +// note: symbolize is really slow +// it will launch an addr2line process that has to parse dwarf +// information from the libraries that frames point into. +// Callers should first batch up all the unique void* pointers +// across a number of unwind states and make a single call to +// symbolize. +TORCH_API std::vector symbolize( + const std::vector& frames, + Mode mode); + +// returns path to the library, and the offset of the addr inside the library +TORCH_API std::optional> libraryFor( + void* addr); + +struct Stats { + size_t hits = 0; + size_t misses = 0; + size_t unsupported = 0; + size_t resets = 0; +}; +Stats stats(); + +} // namespace torch::unwind + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/unwind_error.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/unwind_error.h new file mode 100644 index 0000000000000000000000000000000000000000..9a468e702c2379d2b25d6bd1c251daa517f1cf1f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/unwind_error.h @@ -0,0 +1,34 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include + +namespace torch::unwind { + +struct UnwindError : public std::runtime_error { + using std::runtime_error::runtime_error; +}; + +#define UNWIND_CHECK(cond, fmtstring, ...) \ + do { \ + if (!(cond)) { \ + throw unwind::UnwindError(fmt::format( \ + "{}:{}: " fmtstring, __FILE__, __LINE__, ##__VA_ARGS__)); \ + } \ + } while (0) + +// #define LOG_INFO(...) fmt::print(__VA_ARGS__) +#define LOG_INFO(...) + +// #define PRINT_INST(...) LOG_INFO(__VA_ARGS__) +#define PRINT_INST(...) + +// #define PRINT_LINE_TABLE(...) LOG_INFO(__VA_ARGS__) +#define PRINT_LINE_TABLE(...) + +} // namespace torch::unwind + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/unwinder.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/unwinder.h new file mode 100644 index 0000000000000000000000000000000000000000..2f284e849fe2721fcc0ddb929281d8c8e8844409 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/unwind/unwinder.h @@ -0,0 +1,88 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include +#include + +namespace torch::unwind { + +// Architecture-neutral names: pc (program counter / return address), +// fp (frame pointer: x86 RBP, aarch64 x29), sp (stack pointer). +struct UnwindState { + int64_t pc, fp, sp; +}; + +struct Unwinder { + Unwinder(Action cfa, Action ret, Action fp) + : kind_(ret.kind == A_UNDEFINED ? END : STANDARD), + reg_(cfa.reg), + off_(cfa.data), + ret_off_(ret.data), + fp_off_( + fp.kind == A_UNDEFINED ? std::numeric_limits::max() + : fp.data), + deref_(cfa.kind == A_REG_PLUS_DATA_DEREF) { + check(cfa.reg == D_STACK_PTR || cfa.reg == D_FRAME_PTR); + check(ret.kind == A_UNDEFINED || ret.kind == A_LOAD_CFA_OFFSET); + if (cfa.kind == A_REG_PLUS_DATA) { + check(fp.kind == A_LOAD_CFA_OFFSET || fp.kind == A_UNDEFINED); + } else if (cfa.kind == A_REG_PLUS_DATA_DEREF) { + if (fp.kind == A_REG_PLUS_DATA_DEREF) { + check(fp.reg == cfa.reg); + fp_off_ -= cfa.data; + } else { + check(fp.kind == A_UNDEFINED); + } + } else { + check(false); + } + } + void check(bool cond) { + if (!cond) { + throw UnwindError("Unwinding actions do not follow supported patterns"); + } + } + bool terminator() const { + return kind_ != STANDARD; + } + bool isUnknown() const { + return kind_ == UNKNOWN; + } + // unwinder representing some pattern unsupported in + // current implementation + static Unwinder unknown() { + return Unwinder(); + } + UnwindState run(const UnwindState& cur) const { + UnwindState r = cur; + r.sp = (reg_ == D_STACK_PTR ? cur.sp : cur.fp) + off_; + r.fp = fp_off_ == std::numeric_limits::max() + ? cur.fp + // NOLINTNEXTLINE(performance-no-int-to-ptr) + : *(int64_t*)(r.sp + fp_off_); + if (deref_) { + // NOLINTNEXTLINE(performance-no-int-to-ptr) + r.sp = *(int64_t*)r.sp; + } + // NOLINTNEXTLINE(performance-no-int-to-ptr) + r.pc = *(int64_t*)(r.sp + ret_off_); + + return r; + } + + private: + Unwinder() : kind_(UNKNOWN), reg_(0), off_(0), ret_off_(0), fp_off_(0) {} + enum Kind { STANDARD, END, UNKNOWN } kind_; + uint32_t reg_; + int64_t off_; + int64_t ret_off_; + int64_t fp_off_; + bool deref_{false}; +}; + +} // namespace torch::unwind + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/util.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/util.h new file mode 100644 index 0000000000000000000000000000000000000000..a8e084ed3fa49bd3606f48a15097ce57b789061b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/profiler/util.h @@ -0,0 +1,215 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// TODO: replace with pytorch/rfcs#43 when it is ready. +#define SOFT_ASSERT(cond, ...) \ + [&]() -> bool { \ + if (C10_UNLIKELY(!(cond))) { \ + torch::profiler::impl::logSoftAssert( \ + __func__, \ + __FILE__, \ + static_cast(__LINE__), \ + #cond, \ + ::c10::str(__VA_ARGS__)); \ + if (torch::profiler::impl::softAssertRaises()) { \ + TORCH_INTERNAL_ASSERT(cond, __VA_ARGS__); \ + } else { \ + TORCH_WARN_ONCE(__VA_ARGS__); \ + } \ + return false; \ + } \ + return true; \ + }() + +namespace torch::profiler::impl { +TORCH_API bool softAssertRaises(); +TORCH_API void setSoftAssertRaises(std::optional value); +TORCH_API void logSoftAssert( + const char* func, + const char* file, + uint32_t line, + const char* cond, + const char* args); +inline void logSoftAssert( + const char* func, + const char* file, + uint32_t line, + const char* cond, + ::c10::detail::CompileTimeEmptyString args) { + logSoftAssert(func, file, line, cond, (const char*)args); +} +TORCH_API void logSoftAssert( + const char* func, + const char* file, + uint32_t line, + const char* cond, + const std::string& args); + +using shape = + std::variant, std::vector>>; +constexpr int TENSOR_LIST_DISPLAY_LENGTH_LIMIT = 30; + +std::string getNvtxStr( + const char* name, + int64_t sequence_nr, + const std::vector>& shapes, + at::RecordFunctionHandle op_id = 0, + const std::list>& input_op_ids = + {}); + +struct TORCH_API FileLineFunc { + std::string filename; + size_t line; + std::string funcname; +}; + +struct TORCH_API SaveNcclMetaConfig { + bool truncate; + bool introspectMetadata; + bool introspectInputs; + bool introspectOutputs; + + // Default constructor with default values + SaveNcclMetaConfig() + : truncate(true), + introspectMetadata(true), + introspectInputs(false), + introspectOutputs(false) {} + + SaveNcclMetaConfig( + bool truncate, + bool introspectMetadata, + bool introspectInputs, + bool introspectOutputs) + : truncate(truncate), + introspectMetadata(introspectMetadata), + introspectInputs(introspectInputs), + introspectOutputs(introspectOutputs) {} +}; + +TORCH_API std::vector prepareCallstack( + const std::vector& cs); +TORCH_API std::vector callstackStr( + const std::vector& cs); +TORCH_API std::string stacksToStr( + const std::vector& stacks, + const char* delim); +TORCH_API std::vector> inputSizes( + const at::RecordFunction& fn, + const bool flatten_list_enabled = false); +TORCH_API std::string variantShapesToStr(const std::vector& shapes); +TORCH_API std::string shapesToStr( + const std::vector>& shapes); +TORCH_API std::string strListToStr(const std::vector& types); +TORCH_API std::string inputOpIdsToStr( + const std::list>& input_op_ids); +TORCH_API std::string ivalueToStr(const c10::IValue& val, bool isString); +TORCH_API std::string ivalueListToStr(const std::vector& list); +TORCH_API std::vector inputTypes(const at::RecordFunction& fn); + +std::unordered_map TORCH_API +saveExtraArgs(const at::RecordFunction& fn); +std::unordered_map TORCH_API saveNcclMeta( + const at::RecordFunction& fn, + const SaveNcclMetaConfig& config = SaveNcclMetaConfig()); +int getTensorStartHint(const at::Tensor& t); +bool checkFunctionOutputsForLogging(const at::RecordFunction& fn); +bool checkFunctionInputsForLogging(const at::RecordFunction& fn); +std::pair>> findStartAddrForTensors( + const c10::IValue& val); +uint64_t TORCH_API computeFlops( + const std::string& op_name, + const std::unordered_map& extra_args); + +std::string shapeToStr(const std::vector& shape); + +template +class TORCH_API GlobalStateManager { + public: + static GlobalStateManager& singleton() { + /* library-local */ static GlobalStateManager singleton_; + return singleton_; + } + + static void push(std::shared_ptr&& state) { + if (singleton().state_) { + LOG(WARNING) << "GlobalStatePtr already exists!"; + } else { + singleton().state_ = std::move(state); + } + } + + static auto* get() { + return singleton().state_.get(); + } + + static std::shared_ptr pop() { + auto out = singleton().state_; + singleton().state_.reset(); + return out; + } + + private: + GlobalStateManager() = default; + + std::shared_ptr state_; +}; + +struct HashCombine { + template + size_t operator()(const std::pair& i) { + return c10::get_hash((*this)(i.first), (*this)(i.second)); + } + + template + size_t operator()(const std::tuple& i) { + return c10::get_hash(i); + } + + template + size_t operator()(const T& i) { + return c10::get_hash(i); + } +}; + +#ifdef USE_DISTRIBUTED +constexpr auto kCommsName = "Collective name"; +constexpr auto kDtype = "dtype"; +constexpr auto kInMsgNelems = "In msg nelems"; +constexpr auto kOutMsgNelems = "Out msg nelems"; +constexpr auto kInSplit = "In split size"; +constexpr auto kOutSplit = "Out split size"; +constexpr auto kGlobalRankStart = "Global rank start"; +constexpr auto kGlobalRankStride = "Global rank stride"; +constexpr auto kGroupSize = "Group size"; +constexpr auto kProcessGroupName = "Process Group Name"; +constexpr auto kProcessGroupDesc = "Process Group Description"; +constexpr auto kGroupRanks = "Process Group Ranks"; +constexpr auto kRank = "Rank"; +constexpr auto kP2pSrc = "Src Rank"; +constexpr auto kP2pDst = "Dst Rank"; +constexpr auto kSeqNum = "Seq"; +constexpr auto kInTensorsStart = "Input Tensors start"; +constexpr auto kOutTensorsStart = "Output Tensors start"; +constexpr auto kIsAsynchronizedOp = "Is asynchronized op"; +#endif // USE_DISTRIBUTED + +} // namespace torch::profiler::impl + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/python_dimname.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/python_dimname.h new file mode 100644 index 0000000000000000000000000000000000000000..34226e53fdfb1dcd5d017c44160b0c1ac8e133db --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/python_dimname.h @@ -0,0 +1,12 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include + +at::Dimname THPDimname_parse(PyObject* obj); +bool THPUtils_checkDimname(PyObject* obj); +bool THPUtils_checkDimnameList(PyObject* obj); + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/python_headers.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/python_headers.h new file mode 100644 index 0000000000000000000000000000000000000000..1b90571fdc027a49d5c9b0828d2d0ec4a96776cc --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/python_headers.h @@ -0,0 +1,30 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +// workaround for https://github.com/python/cpython/pull/23326 +#include +#include +// workaround for Python 2 issue: https://bugs.python.org/issue17120 +// NOTE: It looks like this affects Python 3 as well. +#pragma push_macro("_XOPEN_SOURCE") +#pragma push_macro("_POSIX_C_SOURCE") +#undef _XOPEN_SOURCE +#undef _POSIX_C_SOURCE + +#include +#include +#include + +#pragma pop_macro("_XOPEN_SOURCE") +#pragma pop_macro("_POSIX_C_SOURCE") + +#ifdef copysign +#undef copysign +#endif + +#if PY_MAJOR_VERSION < 3 +#error "Python 2 has reached end-of-life and is no longer supported by PyTorch." +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/serialization.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/serialization.h new file mode 100644 index 0000000000000000000000000000000000000000..7a39f8a320d21183e6a09137e26365ac0d838839 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/serialization.h @@ -0,0 +1,32 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#ifndef THP_SERIALIZATION_INC +#define THP_SERIALIZATION_INC + +#include +#include +template +void doRead(io fildes, void* buf, size_t nbytes); + +template +void doWrite(io fildes, void* buf, size_t nbytes); + +// Note that this takes a mutable storage because it may pass through +// to at::from_blob. +template +void THPStorage_writeFileRaw( + c10::StorageImpl* self, + io fd, + bool save_size, + uint64_t element_size); + +template +c10::intrusive_ptr THPStorage_readFileRaw( + io fd, + c10::intrusive_ptr storage, + uint64_t element_size); + +#endif + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/shim_conversion_utils.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/shim_conversion_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..1ef8f8ac9329b2640f850026c66b847c755a9f56 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/shim_conversion_utils.h @@ -0,0 +1,27 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include + +inline std::vector* list_handle_to_list_pointer( + StableListHandle handle) { + return reinterpret_cast*>(handle); +} + +inline StableListHandle list_pointer_to_list_handle( + std::vector* list_ptr) { + return reinterpret_cast(list_ptr); +} + +inline StableListHandle new_list_handle(std::vector&& list) { + std::vector* new_list = new std::vector(list); + return list_pointer_to_list_handle(new_list); +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/accelerator.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/accelerator.h new file mode 100644 index 0000000000000000000000000000000000000000..d2a35e58982b84057d85bc047b0d1491ade81071 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/accelerator.h @@ -0,0 +1,117 @@ +#pragma once + +#include +#include +#include + +#include + +HIDDEN_NAMESPACE_BEGIN(torch, stable, accelerator) + +using DeleterFnPtr = void (*)(void*); + +namespace { +inline void delete_device_guard(void* ptr) { + TORCH_ERROR_CODE_CHECK( + aoti_torch_delete_device_guard(reinterpret_cast(ptr))); +} + +} // namespace + +// This is bigger than DeviceIndex in c10/core/Device.h but it is the type we +// can converge on in this world as DeviceIndex in libtorch is not stable. +/** + * @brief Device index type for stable ABI. + * + * Minimum compatible version: PyTorch 2.9. + */ +using DeviceIndex = int32_t; + +using StreamId = int64_t; // this is from c10/core/Stream.h + +/** + * @brief A stable ABI version of c10::DeviceGuard. + * + * RAII class that sets the current device to the specified device index + * on construction and restores the previous device on destruction. + * + * Minimum compatible version: PyTorch 2.9. + */ +class DeviceGuard { + public: + /// \private + explicit DeviceGuard() = delete; + + /** + * @brief Constructs a DeviceGuard that sets the current device. + * + * @param device_index The device index to set as the current device. + * + * Minimum compatible version: PyTorch 2.9. + */ + explicit DeviceGuard(DeviceIndex device_index) + : guard_(nullptr, delete_device_guard) { + DeviceGuardHandle ptr = nullptr; + TORCH_ERROR_CODE_CHECK(aoti_torch_create_device_guard(device_index, &ptr)); + guard_.reset(ptr); + } + + /** + * @brief Changes the current device to the specified device index. + * + * @param device_index The new device index to set. + * + * Minimum compatible version: PyTorch 2.9. + */ + void set_index(DeviceIndex device_index) { + TORCH_ERROR_CODE_CHECK( + aoti_torch_device_guard_set_index(guard_.get(), device_index)); + } + + private: + std::unique_ptr guard_; +}; + +class Stream { + public: + explicit Stream() = delete; + + // Construct a stable::Stream from a StreamHandle + // Steals ownership from the StreamHandle + explicit Stream(StreamHandle stream) + : stream_(stream, [](StreamHandle stream) { + TORCH_ERROR_CODE_CHECK(aoti_torch_delete_stream(stream)); + }) {} + + StreamId id() const { + StreamId stream_id; + TORCH_ERROR_CODE_CHECK(aoti_torch_stream_id(stream_.get(), &stream_id)); + return stream_id; + } + + private: + std::shared_ptr stream_; +}; + +inline Stream getCurrentStream(DeviceIndex device_index) { + StreamHandle stream = nullptr; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_current_stream(device_index, &stream)); + return Stream(stream); +} + +/** + * @brief Gets the current device index. + * + * Returns the index of the currently active device for the accelerator. + * + * @return The current device index. + * + * Minimum compatible version: PyTorch 2.9. + */ +inline DeviceIndex getCurrentDeviceIndex() { + DeviceIndex device_index; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_current_device_index(&device_index)); + return device_index; +} + +HIDDEN_NAMESPACE_END(torch, stable, accelerator) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/c/shim.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/c/shim.h new file mode 100644 index 0000000000000000000000000000000000000000..3844a3d5cc21df5163bd1b672019c0e13a070965 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/c/shim.h @@ -0,0 +1,230 @@ +#ifndef STABLE_TORCH_SHIM +#define STABLE_TORCH_SHIM + +#include + +#include + +// This header defines stable C API extensions for backward/forward +// compatibility when calling ATen operations through the dispatcher. +// +// This is separate from the main AOTI shim to provide versioning capabilities +// for schema changes in native ATen functions. + +#ifdef __cplusplus +extern "C" { +#endif + +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + +// Has the same semantic as aoti_torch_call_dispatcher, but takes an +// additional argument for the extension build version. This is +// needed for backward compatibility when calling native functions via +// the dispatcher. The caller should pass in the libtorch version the +// extension is building with (NOT target version). +AOTI_TORCH_EXPORT AOTITorchError torch_call_dispatcher( + const char* opName, + const char* overloadName, + StableIValue* stack, + uint64_t extension_build_version); + +// Version-aware variant of aoti_torch_library_impl that takes an +// extension_build_version parameter for backward compatibility +AOTI_TORCH_EXPORT AOTITorchError torch_library_impl( + TorchLibraryHandle self, + const char* name, + void (*fn)(StableIValue*, uint64_t, uint64_t), + uint64_t extension_build_version); + +struct StableListOpaque; +using StableListHandle = StableListOpaque*; + +// returns an owning reference of a StableList. callee is responsible for +// freeing memory. +AOTI_TORCH_EXPORT AOTITorchError +torch_new_list_reserve_size(size_t size, StableListHandle* ret); + +AOTI_TORCH_EXPORT AOTITorchError +torch_list_size(StableListHandle list_handle, size_t* size); + +AOTI_TORCH_EXPORT AOTITorchError torch_list_get_item( + StableListHandle list_handle, + size_t index, + StableIValue* element); + +AOTI_TORCH_EXPORT AOTITorchError torch_list_set_item( + StableListHandle list_handle, + size_t index, + StableIValue element); + +AOTI_TORCH_EXPORT AOTITorchError +torch_list_push_back(StableListHandle list_handle, StableIValue element); + +// deletes the underlying list referenced by list_handle +AOTI_TORCH_EXPORT AOTITorchError +torch_delete_list(StableListHandle list_handle); + +// Helper function to parse device string using c10::Device +// Returns device type and index via output parameters +AOTI_TORCH_EXPORT AOTITorchError torch_parse_device_string( + const char* device_string, + uint32_t* out_device_type, + int32_t* out_device_index); + +// Parallel utility APIs for stable ABI +// Function pointer type for parallel_for callback +// The callback receives begin and end indices for a range to process +typedef void (*ParallelFunc)(int64_t begin, int64_t end, void* ctx); + +AOTI_TORCH_EXPORT AOTITorchError torch_parallel_for( + int64_t begin, + int64_t end, + int64_t grain_size, + ParallelFunc func, + void* ctx); + +// Get the current thread index in a parallel region +// Returns 0 if not in a parallel region +AOTI_TORCH_EXPORT AOTITorchError torch_get_thread_idx(uint32_t* out_thread_idx); + +// Get the number of threads for the parallel backend +AOTI_TORCH_EXPORT AOTITorchError +torch_get_num_threads(uint32_t* out_num_threads); + +// Get a pointer to the underlying storage data +AOTI_TORCH_EXPORT AOTITorchError torch_get_mutable_data_ptr( + AtenTensorHandle tensor, + void** ret_data_ptr // returns borrowed reference +); + +AOTI_TORCH_EXPORT AOTITorchError torch_get_const_data_ptr( + AtenTensorHandle tensor, + const void** ret_data_ptr // returns borrowed reference +); + +struct StringOpaque; +using StringHandle = StringOpaque*; + +AOTI_TORCH_EXPORT AOTITorchError +torch_new_string_handle(const char* data, size_t length, StringHandle* handle); + +AOTI_TORCH_EXPORT AOTITorchError torch_delete_string(StringHandle handle); + +AOTI_TORCH_EXPORT AOTITorchError +torch_string_length(StringHandle handle, size_t* length); + +AOTI_TORCH_EXPORT AOTITorchError +torch_string_c_str(StringHandle handle, const char** data); + +#ifdef USE_CUDA + +AOTI_TORCH_EXPORT AOTITorchError +torch_get_current_cuda_blas_handle(void** ret_handle); + +AOTI_TORCH_EXPORT AOTITorchError +torch_set_current_cuda_stream(void* stream, int32_t device_index); + +AOTI_TORCH_EXPORT AOTITorchError torch_get_cuda_stream_from_pool( + bool isHighPriority, + int32_t device_index, + void** ret_stream); + +AOTI_TORCH_EXPORT AOTITorchError +torch_cuda_stream_synchronize(void* stream, int32_t device_index); + +// Wrapper around c10_cuda_check_implementation that captures the error message +// without propagating the exception. The caller must free error_msg using +// torch_c10_cuda_free_error_msg if it is non-null. +AOTI_TORCH_EXPORT AOTITorchError torch_c10_cuda_check_msg( + int32_t err, + const char* filename, + const char* function_name, + uint32_t line_number, + bool include_device_assertions, + char** error_msg); + +// Free error message allocated by torch_c10_cuda_check_msg +AOTI_TORCH_EXPORT void torch_c10_cuda_free_error_msg(char* error_msg); + +#endif // USE_CUDA + +// Set requires_grad on a tensor +AOTI_TORCH_EXPORT AOTITorchError +torch_set_requires_grad(AtenTensorHandle tensor, bool requires_grad); + +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + +/** + * The beginning of all shims added in 2.11.0 onwards. + */ +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_11_0 + +// Shims for the a few dtypes not already in +// torch/csrc/inductor/aoti_torch/c/shim.h +AOTI_TORCH_EXPORT int32_t torch_dtype_float8_e8m0fnu(); +AOTI_TORCH_EXPORT int32_t torch_dtype_float4_e2m1fn_x2(); + +// Creates a tensor from an existing data blob with an optional deleter. +// The deleter receives both the data pointer and a caller-supplied context +// pointer, which allows passing capturing lambdas across the C ABI boundary +// by heap-allocating the callable and passing it as deleter_ctx. +AOTI_TORCH_EXPORT AOTITorchError torch_from_blob( + void* data, + int64_t ndim, + const int64_t* sizes_ptr, + const int64_t* strides_ptr, + int64_t storage_offset, + int32_t dtype, + int32_t device_type, + int32_t device_index, + AtenTensorHandle* ret, // returns new reference + int32_t layout, + const uint8_t* opaque_metadata, + int64_t opaque_metadata_size, + void (*deleter)(void* data, void* ctx), + void* deleter_ctx); + +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_11_0 + +/** + * The beginning of all shims added in 2.12.0 onwards. + */ +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_12_0 + +// Tag getter functions for ABI-stable tag passing. By hiding these behind +// functions, the precise enum ordinal is NOT part of the ABI contract. +AOTI_TORCH_EXPORT int32_t torch_tag_core(); +AOTI_TORCH_EXPORT int32_t torch_tag_cudagraph_unsafe(); +AOTI_TORCH_EXPORT int32_t torch_tag_data_dependent_output(); +AOTI_TORCH_EXPORT int32_t torch_tag_dynamic_output_shape(); +AOTI_TORCH_EXPORT int32_t torch_tag_flexible_layout(); +AOTI_TORCH_EXPORT int32_t torch_tag_generated(); +AOTI_TORCH_EXPORT int32_t torch_tag_inplace_view(); +AOTI_TORCH_EXPORT int32_t torch_tag_maybe_aliasing_or_mutating(); +AOTI_TORCH_EXPORT int32_t torch_tag_needs_contiguous_strides(); +AOTI_TORCH_EXPORT int32_t torch_tag_needs_exact_strides(); +AOTI_TORCH_EXPORT int32_t torch_tag_needs_fixed_stride_order(); +AOTI_TORCH_EXPORT int32_t torch_tag_nondeterministic_bitwise(); +AOTI_TORCH_EXPORT int32_t torch_tag_nondeterministic_seeded(); +AOTI_TORCH_EXPORT int32_t torch_tag_out_variant(); +AOTI_TORCH_EXPORT int32_t torch_tag_pointwise(); +AOTI_TORCH_EXPORT int32_t torch_tag_pt2_compliant_tag(); +AOTI_TORCH_EXPORT int32_t torch_tag_reduction(); +AOTI_TORCH_EXPORT int32_t torch_tag_view_copy(); + +// Stable corollary to torch::Library method m.def() with tags. +// Tags are passed as int32_t values obtained from torch_tag_*() getters, +// not raw enum ordinals, so the ABI is stable across versions. +AOTI_TORCH_EXPORT AOTITorchError torch_library_def_with_tags( + TorchLibraryHandle self, + const char* schema, + const int32_t* tags, + int32_t num_tags); + +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_12_0 + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // STABLE_TORCH_SHIM diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/device.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/device.h new file mode 100644 index 0000000000000000000000000000000000000000..223e3320a4fd341ba0b388b1dfe08ff38f2d94df --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/device.h @@ -0,0 +1,4 @@ +#pragma once + +#include +#include diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/device_inl.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/device_inl.h new file mode 100644 index 0000000000000000000000000000000000000000..8c9685f0d7da7822ddca6fbe80eab065895b8933 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/device_inl.h @@ -0,0 +1,41 @@ +#pragma once + +// This file implements device.h. We separated out the Device struct so that +// other files can depend on the Device struct (like stableivalue_conversions.h) +// and the implementations of the Device methods can depend on APIs in +// stableivalue_conversions.h without circular dependencies. + +#include +#include +#include +#include +#include +#include +#include + +#include + +HIDDEN_NAMESPACE_BEGIN(torch, stable) + +using DeviceType = torch::headeronly::DeviceType; +using DeviceIndex = torch::stable::accelerator::DeviceIndex; + +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + +inline Device::Device(const std::string& device_string) { + uint32_t device_type; + int32_t device_index; + + TORCH_ERROR_CODE_CHECK(torch_parse_device_string( + device_string.c_str(), &device_type, &device_index)); + + DeviceType dt = torch::stable::detail::to( + torch::stable::detail::from(device_type)); + DeviceIndex di = static_cast(device_index); + + *this = Device(dt, di); +} + +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + +HIDDEN_NAMESPACE_END(torch, stable) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/device_struct.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/device_struct.h new file mode 100644 index 0000000000000000000000000000000000000000..e7c478578cc09e198c2f6bc8d7d4dbfed8b4957b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/device_struct.h @@ -0,0 +1,189 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +HIDDEN_NAMESPACE_BEGIN(torch, stable) + +using DeviceType = torch::headeronly::DeviceType; +using DeviceIndex = torch::stable::accelerator::DeviceIndex; + +// The torch::stable::Device class is an approximate copy of c10::Device. +// It has some slight modifications: +// 1. TORCH_INTERNAL_ASSERT_DEBUG_ONLY -> STD_TORCH_CHECK +// 2. Has a string constructor that uses a shim function +// 3. does not include some is_{device} variants that we can add later +// +// We chose to copy it rather than moving it to headeronly as +// 1. Device is < 8 bytes so the *Handle approach used for tensor doesn't make +// sense +// 2. c10::Device is not header-only due to its string constructor. +// +// StableIValue conversions handle conversion between c10::Device (in libtorch) +// and torch::stable::Device (in stable user extensions) + +/** + * @brief A stable version of c10::Device. + * + * Minimum compatible version: PyTorch 2.9. + */ +class Device { + private: + DeviceType type_; + DeviceIndex index_ = -1; + + void validate() { + STD_TORCH_CHECK( + index_ >= -1, + "Device index must be -1 or non-negative, got ", + static_cast(index_)); + STD_TORCH_CHECK( + type_ != DeviceType::CPU || index_ <= 0, + "CPU device index must be -1 or zero, got ", + static_cast(index_)); + } + + public: + /** + * @brief Constructs a Device from a DeviceType and optional device index. + * + * @param type The type of device (e.g., DeviceType::CPU, DeviceType::CUDA). + * @param index The device index. Default is -1 (current device). + * + * Minimum compatible version: PyTorch 2.9. + */ + /* implicit */ Device(DeviceType type, DeviceIndex index = -1) + : type_(type), index_(index) { + validate(); + } + +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + // Defined in device_inl.h to avoid circular dependencies. + /** + * @brief Constructs a stable::Device from a string description. + * + * The string must follow the schema: (cpu|cuda|...)[:] + * + * @param device_string A string describing the device (e.g., "cuda:0", + * "cpu"). + * + * Minimum compatible version: PyTorch 2.10. + */ + /* implicit */ Device(const std::string& device_string); +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + + // Copy and move constructors can be default + /// \private + Device(const Device& other) = default; + /// \private + Device(Device&& other) noexcept = default; + + // Copy and move assignment operators can be default + /// \private + Device& operator=(const Device& other) = default; + /// \private + Device& operator=(Device&& other) noexcept = default; + + // Destructor can be default + /// \private + ~Device() = default; + + /** + * @brief Checks if two devices are equal. + * + * @param other The device to compare with. + * @return true if both type and index match, false otherwise. + * + * Minimum compatible version: PyTorch 2.9. + */ + bool operator==(const Device& other) const noexcept { + return type() == other.type() && index() == other.index(); + } + + /** + * @brief Checks if two devices are not equal. + * + * @param other The device to compare with. + * @return true if type or index differ, false otherwise. + * + * Minimum compatible version: PyTorch 2.9. + */ + bool operator!=(const Device& other) const noexcept { + return !(*this == other); + } + + /** + * @brief Sets the device index. + * + * @param index The new device index. + * + * Minimum compatible version: PyTorch 2.9. + */ + void set_index(DeviceIndex index) { + index_ = index; + } + + /** + * @brief Returns the device type. + * + * @return The DeviceType of this device. + * + * Minimum compatible version: PyTorch 2.9. + */ + DeviceType type() const noexcept { + return type_; + } + + /** + * @brief Returns the device index. + * + * @return The device index, or -1 if no specific index is set. + * + * Minimum compatible version: PyTorch 2.9. + */ + DeviceIndex index() const noexcept { + return index_; + } + + /** + * @brief Checks if this device has a specific index. + * + * @return true if index is not -1, false otherwise. + * + * Minimum compatible version: PyTorch 2.9. + */ + bool has_index() const noexcept { + return index_ != -1; + } + + /** + * @brief Checks if this is a CUDA device. + * + * @return true if the device type is CUDA, false otherwise. + * + * Minimum compatible version: PyTorch 2.9. + */ + bool is_cuda() const noexcept { + return type_ == DeviceType::CUDA; + } + + /** + * @brief Checks if this is a CPU device. + * + * @return true if the device type is CPU, false otherwise. + * + * Minimum compatible version: PyTorch 2.9. + */ + bool is_cpu() const noexcept { + return type_ == DeviceType::CPU; + } +}; + +HIDDEN_NAMESPACE_END(torch, stable) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/library.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/library.h new file mode 100644 index 0000000000000000000000000000000000000000..f12f0d768acfc361825875fb50565a0c5f8343ad --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/library.h @@ -0,0 +1,372 @@ +#pragma once +// this file can only have stable stuff! Akin to shim.h +// but unlike shim.h, this file can contain header-only C++ +// code for better UX. + +#include +#include +#include +#include +#include + +// Technically, this file doesn't use anything from stableivalue_conversions.h, +// but we need to include it here as the contents of stableivalue_conversions.h +// used to live here and so we need to expose them for backwards compatibility. +#include +#include + +HIDDEN_NAMESPACE_BEGIN(torch, stable, detail) + +class StableLibrary final { + private: + TorchLibraryHandle lib_; + + public: + enum class Kind { + DEF, + IMPL, + FRAGMENT, + }; + + // constructor + /// \private + /// + /// Use STABLE_TORCH_LIBRARY or STABLE_TORCH_LIBRARY_IMPL() instead of using + /// these constructors directly + StableLibrary( + Kind kind, + const char* ns, + const char* k, + const char* file, + uint32_t line) { + if (kind == Kind::IMPL) { + aoti_torch_library_init_impl(ns, k, file, line, &lib_); + } else if (kind == Kind::DEF) { + aoti_torch_library_init_def(ns, file, line, &lib_); + } else { // kind == FRAGMENT + aoti_torch_library_init_fragment(ns, file, line, &lib_); + } + } + + // do not permit copy + StableLibrary(const StableLibrary&) = delete; + StableLibrary& operator=(const StableLibrary&) = delete; + + // do not permit move + StableLibrary(StableLibrary&& other) = delete; + StableLibrary& operator=(StableLibrary&& other) = delete; + + ~StableLibrary() { + aoti_torch_delete_library_object(lib_); + } + + // corresponds to a limited, stable version of torch::library::impl() + // Inputs: + // name: the name of the function to implement + // fn: a boxed function with schema + // (StableIValue* stack, uint64_t num_inputs, uint64_t num_outputs) -> + // void + // fn should follow the calling convention of our boxed kernels that convert + // to IValues. fn will be called with a StableIValue* array of length + // max(num_inputs, num_outputs), where the first num_inputs entries are + // populated with inputs. fn is responsible for stealing the memory of the + // inputs, in effect "popping" them off the stack, and then populating the + // stack with StableIValue outputs. Concretely, fn should: + // 1. read StableIValue inputs from the given stack + // 2. convert the inputs to the proper types + // 3. call the function corresponding to name with the inputs + // 4. convert the outputs to StableIValues + // 5. populate the now empty stack with StableIValue outputs + // If the operation corresponding to name takes in 4 inputs and returns 2 + // outputs, fn should expect stack to contain 4 StableIValues: + // [stable_arg1, stable_arg2, stable_arg3, stable_arg4] + // to end, fn should fill the stack with 2 StableIValues representing outputs: + // [stable_ret1, stable_ret2, -, -] + StableLibrary& impl( + const char* name, + void (*fn)(StableIValue*, uint64_t, uint64_t)) { +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + torch_library_impl(lib_, name, fn, TORCH_ABI_VERSION); +#else + aoti_torch_library_impl(lib_, name, fn); +#endif + return *this; + } + + // corresponds to a limited, stable version of torch::library::def() + StableLibrary& def(const char* schema) { + aoti_torch_library_def(lib_, schema); + return *this; + } + +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_12_0 + // corresponds to a limited, stable version of torch::library::def() with tags + StableLibrary& def(const char* schema, const std::vector& tags) { + std::vector tag_ints; + tag_ints.reserve(tags.size()); + for (auto t : tags) { + tag_ints.push_back( + torch::stable::detail::to(torch::stable::detail::from(t))); + } + torch_library_def_with_tags( + lib_, schema, tag_ints.data(), static_cast(tag_ints.size())); + return *this; + } +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_12_0 +}; + +class StableTorchLibraryInit final { + private: + using InitFn = void(StableLibrary&); + StableLibrary lib_; + + public: + StableTorchLibraryInit( + StableLibrary::Kind kind, + InitFn* fn, + const char* ns, + const char* k, + const char* file, + uint32_t line) + : lib_(kind, ns, k, file, line) { + fn(lib_); + } +}; + +// type mapper: since to> cannot exist, +// we map that to to> to preserve ownership semantics. +// note that unbox_type_t is used to convert ParamTypes, so that +// the tuple holding the arguments will have proper ownership too. +template +struct UnboxType { + using type = T; +}; + +template +struct UnboxType> { + using type = std::vector; +}; + +template +struct UnboxType>> { + using type = std::optional>; +}; + +template <> +struct UnboxType { + using type = std::string; +}; + +// const and reference are stripped before UnboxType is applied +// in order to avoid ambiguous template matches +template +using unbox_type_t = + typename UnboxType>>::type; + +template +std::tuple unbox_to_tuple_impl( + StableIValue* stack, + std::index_sequence /*unused*/) { + return std::make_tuple(to(stack[I])...); +} + +template +std::tuple unbox_to_tuple(StableIValue* stack) { + return unbox_to_tuple_impl( + stack, std::make_index_sequence()); +} + +template +void box_from_tuple_impl( + StableIValue* stack, + std::tuple vals, + std::index_sequence /*unused*/) { + ((stack[I] = from(std::get(vals))), ...); +} + +template +void box_from_tuple(StableIValue* stack, std::tuple vals) { + box_from_tuple_impl( + stack, vals, std::make_index_sequence()); +} + +template < + typename ReturnType, + typename ParameterTypeList, + typename FuncT, + FuncT* func> +struct boxer_impl { + static_assert( + torch::headeronly::guts::false_t::value, + "Unsupported function schema for TORCH_BOX."); +}; + +// Multiple returns +template < + typename... ReturnTypes, + typename... ParameterTypes, + typename FuncT, + FuncT* func> +struct boxer_impl< + std::tuple, + torch::headeronly::guts::typelist::typelist, + FuncT, + func> { + static void boxed_fn( + StableIValue* stack, + uint64_t num_args, + uint64_t num_outputs) { + STD_TORCH_CHECK( + num_args == sizeof...(ParameterTypes), + "Registered schema has ", + num_args, + " args, but the kernel to box has ", + sizeof...(ParameterTypes)); + STD_TORCH_CHECK( + num_outputs == sizeof...(ReturnTypes), + "Registered schema has ", + num_outputs, + " outputs, but the kernel to box has ", + sizeof...(ReturnTypes)); + std::tuple...> args = + unbox_to_tuple...>(stack); + auto res = std::apply(func, args); + box_from_tuple(stack, res); + } +}; + +// Single return +template < + typename ReturnType, + typename... ParameterTypes, + typename FuncT, + FuncT* func> +struct boxer_impl< + ReturnType, + torch::headeronly::guts::typelist::typelist, + FuncT, + func> { + static void boxed_fn( + StableIValue* stack, + uint64_t num_args, + uint64_t num_outputs) { + STD_TORCH_CHECK( + num_args == sizeof...(ParameterTypes), + "Registered schema has ", + num_args, + " args, but the kernel to box has ", + sizeof...(ParameterTypes)); + STD_TORCH_CHECK( + num_outputs == 1, + "Registered schema has ", + num_outputs, + " outputs, but the kernel to box has ", + 1); + std::tuple...> args = + unbox_to_tuple...>(stack); + auto res = std::apply(func, args); + stack[0] = from(res); + } +}; + +// No/void return +template +struct boxer_impl< + void, + torch::headeronly::guts::typelist::typelist, + FuncT, + func> { + static void boxed_fn( + StableIValue* stack, + uint64_t num_args, + uint64_t num_outputs) { + STD_TORCH_CHECK( + num_args == sizeof...(ParameterTypes), + "Registered schema has ", + num_args, + " args, but the kernel to box has ", + sizeof...(ParameterTypes)); + STD_TORCH_CHECK( + num_outputs == 0, + "Registered schema has ", + num_outputs, + " outputs, but the kernel to box has ", + 0); + std::tuple...> args = + unbox_to_tuple...>(stack); + std::apply(func, args); + } +}; + +template +struct boxer { + using FunctionTraits = + torch::headeronly::guts::infer_function_traits_t; + + static void boxed_fn( + StableIValue* stack, + uint64_t num_args, + uint64_t num_outputs) { + boxer_impl< + typename FunctionTraits::return_type, + typename FunctionTraits::parameter_types, + FuncT, + func>::boxed_fn(stack, num_args, num_outputs); + } +}; + +HIDDEN_NAMESPACE_END(torch, stable, detail) + +#define TORCH_BOX(func) \ + torch::stable::detail::boxer< \ + std::remove_pointer_t>, \ + (func)>::boxed_fn + +#define STABLE_TORCH_LIBRARY_IMPL(ns, k, m) \ + _STABLE_TORCH_LIBRARY_IMPL(ns, k, m, C10_UID) + +#define _STABLE_TORCH_LIBRARY_IMPL(ns, k, m, uid) \ + static void C10_CONCATENATE( \ + STABLE_TORCH_LIBRARY_IMPL_init_##ns##_##k##_, \ + uid)(torch::stable::detail::StableLibrary&); \ + static const torch::stable::detail::StableTorchLibraryInit C10_CONCATENATE( \ + STABLE_TORCH_LIBRARY_IMPL_static_init_##ns##_##k##_, uid)( \ + torch::stable::detail::StableLibrary::Kind::IMPL, \ + &C10_CONCATENATE(STABLE_TORCH_LIBRARY_IMPL_init_##ns##_##k##_, uid), \ + C10_STRINGIZE(ns), \ + C10_STRINGIZE(k), \ + __FILE__, \ + __LINE__); \ + void C10_CONCATENATE(STABLE_TORCH_LIBRARY_IMPL_init_##ns##_##k##_, uid)( \ + torch::stable::detail::StableLibrary & m) + +#define STABLE_TORCH_LIBRARY(ns, m) \ + static void STABLE_TORCH_LIBRARY_init_##ns( \ + torch::stable::detail::StableLibrary&); \ + static const torch::stable::detail::StableTorchLibraryInit \ + STABLE_TORCH_LIBRARY_static_init_##ns( \ + torch::stable::detail::StableLibrary::Kind::DEF, \ + &STABLE_TORCH_LIBRARY_init_##ns, \ + C10_STRINGIZE(ns), \ + nullptr, \ + __FILE__, \ + __LINE__); \ + void STABLE_TORCH_LIBRARY_init_##ns(torch::stable::detail::StableLibrary& m) + +#define STABLE_TORCH_LIBRARY_FRAGMENT(ns, m) \ + _STABLE_TORCH_LIBRARY_FRAGMENT(ns, m, C10_UID) + +#define _STABLE_TORCH_LIBRARY_FRAGMENT(ns, m, uid) \ + static void C10_CONCATENATE( \ + STABLE_TORCH_LIBRARY_FRAGMENT_init_##ns##_, \ + uid)(torch::stable::detail::StableLibrary&); \ + static const torch::stable::detail::StableTorchLibraryInit C10_CONCATENATE( \ + STABLE_TORCH_LIBRARY_FRAGMENT_static_init_##ns##_, uid)( \ + torch::stable::detail::StableLibrary::Kind::FRAGMENT, \ + &C10_CONCATENATE(STABLE_TORCH_LIBRARY_FRAGMENT_init_##ns##_, uid), \ + C10_STRINGIZE(ns), \ + nullptr, \ + __FILE__, \ + __LINE__); \ + void C10_CONCATENATE(STABLE_TORCH_LIBRARY_FRAGMENT_init_##ns##_, uid)( \ + torch::stable::detail::StableLibrary & m) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/macros.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/macros.h new file mode 100644 index 0000000000000000000000000000000000000000..52f108d500683299ca44ee0dddc772a68edafa21 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/macros.h @@ -0,0 +1,30 @@ +#include + +#include +#include + +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + +// Users of this macro are expected to include cuda_runtime.h +#define STD_CUDA_CHECK(EXPR) \ + do { \ + const cudaError_t __err = EXPR; \ + char* __error_msg = nullptr; \ + torch_c10_cuda_check_msg( \ + static_cast(__err), \ + __FILE__, \ + __func__, \ + static_cast(__LINE__), \ + true, \ + &__error_msg); \ + if (__error_msg != nullptr) { \ + std::string __msg(__error_msg); \ + torch_c10_cuda_free_error_msg(__error_msg); \ + throw std::runtime_error(__msg); \ + } \ + } while (0) + +// Users of this macro are expected to include cuda_runtime.h +#define STD_CUDA_KERNEL_LAUNCH_CHECK() STD_CUDA_CHECK(cudaGetLastError()) + +#endif diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/ops.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/ops.h new file mode 100644 index 0000000000000000000000000000000000000000..dbede4faba49eca9984488c0d7ccad1879c6f82f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/ops.h @@ -0,0 +1,1134 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +HIDDEN_NAMESPACE_BEGIN(torch, stable) + +/// A function pointer type for data deleters used with from_blob. +/// The deleter is called with the data pointer when the tensor's storage +/// is deallocated. +using DeleterFnPtr = void (*)(void*); + +/// Stable version of the empty_like op. +/// +/// Creates a new uninitialized tensor with the same size, dtype, layout, and +/// device as the input tensor. This version does not support kwargs (device, +/// dtype, layout, memory_format) - kwargs support may be added in the future. +/// +/// Minimum compatible version: PyTorch 2.9. +/// +/// @param self The input tensor whose properties will be used for the new +/// tensor. +/// @return A new uninitialized tensor with the same properties as self. +inline torch::stable::Tensor empty_like(const torch::stable::Tensor& self) { + const auto num_args = 6; + std::array stack{ + torch::stable::detail::from(self), + torch::stable::detail::from(std::nullopt), + torch::stable::detail::from(std::nullopt), + torch::stable::detail::from(std::nullopt), + torch::stable::detail::from(std::nullopt), + torch::stable::detail::from(std::nullopt)}; +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::empty_like", "", stack.data(), TORCH_ABI_VERSION)); +#else + TORCH_ERROR_CODE_CHECK( + aoti_torch_call_dispatcher("aten::empty_like", "", stack.data())); +#endif + return torch::stable::detail::to(stack[0]); +} + +/// Stable version of the fill_.Scalar op. +/// +/// Fills the input tensor with the specified scalar value in-place and returns +/// it. This has identical semantics to the existing fill_.Scalar op. +/// +/// Minimum compatible version: PyTorch 2.9. +/// +/// @note The value parameter is typed as double +/// This is because Scalar.h is currently not header-only. +/// +/// @param self The tensor to fill. +/// @param value The scalar value to fill the tensor with. +/// @return The input tensor, now filled with the specified value. +inline torch::stable::Tensor fill_( + const torch::stable::Tensor& self, + double value) { + TORCH_ERROR_CODE_CHECK(aoti_torch_aten_fill__Scalar(self.get(), value)); + return self; +} + +/// Stable version of the narrow.default op. +/// +/// Returns a new tensor that is a narrowed version of the input tensor. The +/// dimension dim is narrowed from start to start + length. +/// +/// Minimum compatible version: PyTorch 2.9. +/// +/// @note The start and length parameters +/// is not yet header-only. +/// +/// @param self The input tensor to narrow. +/// @param dim The dimension along which to narrow. +/// @param start The starting index for the narrowed dimension. +/// @param length The length of the narrowed dimension. +/// @return A new tensor that is a narrowed view of the input. +inline torch::stable::Tensor narrow( + torch::stable::Tensor& self, + int64_t dim, + int64_t start, + int64_t length) { + AtenTensorHandle ret0 = nullptr; + + TORCH_ERROR_CODE_CHECK( + aoti_torch_aten_narrow(self.get(), dim, start, length, &ret0)); + return torch::stable::Tensor(ret0); +} + +#if TORCH_FEATURE_VERSION < TORCH_VERSION_2_10_0 +/// Stable version of the new_empty op (2.9 version). +/// +/// Creates a new uninitialized tensor with the specified size, inheriting +/// device and layout from the input tensor. This version only supports the +/// dtype kwarg. For the full kwargs version, use PyTorch 2.10+. +/// +/// Minimum compatible version: PyTorch 2.9. For full kwargs support, use +/// PyTorch 2.10+. +/// +/// @param self The input tensor whose device +/// @param size The desired size of the output tensor. +/// @param dtype Optional scalar type for the tensor elements. If not provided, +/// inherits from self. +/// @return A new uninitialized tensor with the specified properties. +inline torch::stable::Tensor new_empty( + const torch::stable::Tensor& self, + torch::headeronly::IntHeaderOnlyArrayRef size, + std::optional dtype = std::nullopt) { + int32_t device_type; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_device_type(self.get(), &device_type)); + + int32_t device_index; + TORCH_ERROR_CODE_CHECK( + aoti_torch_get_device_index(self.get(), &device_index)); + + int32_t target_dtype; + if (dtype.has_value()) { + target_dtype = torch::stable::detail::to( + torch::stable::detail::from(dtype.value())); + } else { + TORCH_ERROR_CODE_CHECK(aoti_torch_get_dtype(self.get(), &target_dtype)); + } + + int32_t layout; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_layout(self.get(), &layout)); + + AtenTensorHandle ret0; + TORCH_ERROR_CODE_CHECK(aoti_torch_aten_new_empty( + self.get(), + size.data(), + static_cast(size.size()), + &target_dtype, + &layout, + &device_type, + device_index, + nullptr, // pin_memory (nullptr for default) + &ret0)); + + return torch::stable::Tensor(ret0); +} + +/// Stable version of the new_zeros op (2.9 version). +/// +/// Creates a new tensor filled with zeros with the specified size, inheriting +/// device and layout from the input tensor. This version only supports the +/// dtype kwarg. For the full kwargs version, use PyTorch 2.10+. +/// +/// Minimum compatible version: PyTorch 2.9. For full kwargs support, use +/// PyTorch 2.10+. +/// +/// @param self The input tensor whose device and layout will be inherited. +/// @param size The desired size of the output tensor. +/// @param dtype Optional scalar type for the tensor elements. If not provided, +/// inherits from self. +/// @return A new zero-filled tensor with the specified properties. +inline torch::stable::Tensor new_zeros( + const torch::stable::Tensor& self, + torch::headeronly::IntHeaderOnlyArrayRef size, + std::optional dtype = std::nullopt) { + int32_t device_type; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_device_type(self.get(), &device_type)); + + int32_t device_index; + TORCH_ERROR_CODE_CHECK( + aoti_torch_get_device_index(self.get(), &device_index)); + + int32_t target_dtype; + if (dtype.has_value()) { + target_dtype = torch::stable::detail::to( + torch::stable::detail::from(dtype.value())); + } else { + TORCH_ERROR_CODE_CHECK(aoti_torch_get_dtype(self.get(), &target_dtype)); + } + + int32_t layout; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_layout(self.get(), &layout)); + + AtenTensorHandle ath; + TORCH_ERROR_CODE_CHECK(aoti_torch_aten_new_zeros( + self.get(), + size.data(), + static_cast(size.size()), + &target_dtype, + &layout, + &device_type, + device_index, + nullptr, // pin_memory (nullptr for default) + &ath)); + + return torch::stable::Tensor(ath); +} +#endif // TORCH_FEATURE_VERSION < TORCH_VERSION_2_10_0 + +/// Stable version of the pad.default op. +/// +/// Pads the input tensor according to the specified padding sizes. The padding +/// is applied symmetrically to each dimension, with the padding sizes specified +/// in reverse order (last dimension first). +/// +/// Minimum compatible version: PyTorch 2.9. +/// +/// @note The pad parameter is typed +/// not yet header-only. +/// +/// @param self The input tensor to pad. +/// @param pad The padding sizes for each dimension (in pairs, starting from +/// the last dimension). +/// @param mode The padding mode: "constant", "reflect", "replicate", or +/// "circular". Defaults to "constant". +/// @param value The fill value for constant padding. Defaults to 0.0. +/// @return A new padded tensor. +inline torch::stable::Tensor pad( + const torch::stable::Tensor& self, + torch::headeronly::IntHeaderOnlyArrayRef pad, + const std::string& mode = "constant", + double value = 0.0) { + AtenTensorHandle ret0 = nullptr; + + TORCH_ERROR_CODE_CHECK(aoti_torch_aten_pad( + self.get(), pad.data(), pad.size(), mode.c_str(), &value, &ret0)); + return torch::stable::Tensor(ret0); +} + +/// Stable version of the amax.default op (single dimension). +/// +/// Computes the maximum value along the specified dimension. If keepdim is +/// true, the output tensor has the same number of dimensions as the input, +/// with the reduced dimension having size 1. Otherwise, the reduced dimension +/// is removed. +/// +/// Minimum compatible version: PyTorch 2.9. +/// +/// @param self The input tensor. +/// @param dim The dimension along which to compute the maximum. +/// @param keepdim Whether to retain +/// @return A tensor containing the maximum values along the specified +/// dimension. +inline torch::stable::Tensor amax( + const torch::stable::Tensor& self, + int64_t dim, + bool keepdim = false) { + AtenTensorHandle ret = nullptr; + TORCH_ERROR_CODE_CHECK( + aoti_torch_aten_amax(self.get(), &dim, 1, keepdim, &ret)); + return torch::stable::Tensor(ret); +} + +/// Stable version of the amax.default op (multiple dimensions). +/// +/// Computes the maximum value reducing over all the specified dimensions. If +/// keepdim is true, the output tensor has the same number of dimensions as the +/// input, with the reduced dimensions having size 1. Otherwise, the reduced +/// dimensions are removed. +/// +/// Minimum compatible version: PyTorch 2.9. +/// +/// @note The dims parameter is typed +/// is not yet header-only. +/// +/// @param self The input tensor. +/// @param dims The dimensions along which to compute the maximum. +/// @param keepdim Whether to retain the reduced dimensions. Defaults to false. +/// @return A tensor containing the maximum values. +inline torch::stable::Tensor amax( + const torch::stable::Tensor& self, + torch::headeronly::IntHeaderOnlyArrayRef dims, + bool keepdim = false) { + AtenTensorHandle ret = nullptr; + TORCH_ERROR_CODE_CHECK(aoti_torch_aten_amax( + self.get(), + dims.data(), + static_cast(dims.size()), + keepdim, + &ret)); + return torch::stable::Tensor(ret); +} + +/// Stable version of the transpose.int op. +/// +/// Returns a tensor that is a transposed version of the input, with dimensions +/// dim0 and dim1 swapped. The returned tensor shares storage with the input. +/// +/// Minimum compatible version: PyTorch 2.9. +/// +/// @param self The input tensor. +/// @param dim0 The first dimension to transpose. +/// @param dim1 The second dimension to transpose. +/// @return A transposed view of the input tensor. +inline torch::stable::Tensor transpose( + const torch::stable::Tensor& self, + int64_t dim0, + int64_t dim1) { + const auto num_args = 3; + std::array stack{ + torch::stable::detail::from(self), + torch::stable::detail::from(dim0), + torch::stable::detail::from(dim1)}; +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::transpose", "int", stack.data(), TORCH_ABI_VERSION)); +#else + TORCH_ERROR_CODE_CHECK( + aoti_torch_call_dispatcher("aten::transpose", "int", stack.data())); +#endif + return torch::stable::detail::to(stack[0]); +} + +/// Stable version of the zero_ op. +/// +/// Fills the input tensor with zeros in-place and returns it. Unlike the +/// tensor method version (t.zero_()), this is called as a function: zero_(t). +/// +/// Minimum compatible version: PyTorch 2.9. +/// +/// @param self The tensor to fill with zeros. +/// @return The input tensor, now filled with zeros. +inline torch::stable::Tensor zero_(torch::stable::Tensor& self) { + const auto num_args = 1; + std::array stack{torch::stable::detail::from(self)}; +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::zero_", "", stack.data(), TORCH_ABI_VERSION)); +#else + TORCH_ERROR_CODE_CHECK( + aoti_torch_call_dispatcher("aten::zero_", "", stack.data())); +#endif + return torch::stable::detail::to(stack[0]); +} + +/// Stable version of the copy_ op. +/// +/// Copies the elements from the source tensor into the destination tensor +/// in-place and returns the destination tensor. The tensors must be +/// broadcastable. +/// +/// Minimum compatible version: PyTorch 2.9. +/// +/// @param self The destination tensor (modified in-place). +/// @param src The source tensor to copy from. +/// @param non_blocking If true, the copy may occur asynchronously with respect +/// to the host. Defaults to false. +/// @return The destination tensor with copied values. +inline torch::stable::Tensor copy_( + torch::stable::Tensor& self, + const torch::stable::Tensor& src, + std::optional non_blocking = std::nullopt) { + const auto num_args = 3; + std::array stack{ + torch::stable::detail::from(self), + torch::stable::detail::from(src), + torch::stable::detail::from(non_blocking.value_or(false))}; +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::copy_", "", stack.data(), TORCH_ABI_VERSION)); +#else + TORCH_ERROR_CODE_CHECK( + aoti_torch_call_dispatcher("aten::copy_", "", stack.data())); +#endif + return torch::stable::detail::to(stack[0]); +} + +/// Stable version of the clone op. +/// +/// Returns a copy of the input tensor. The returned tensor has the same data +/// and type as the input, but is stored in a new memory location. +/// +/// Minimum compatible version: PyTorch 2.9. +/// +/// @note Optional memory_format kwarg support +/// +/// @param self The input tensor to clone. +/// @return A new tensor with copied data. +inline torch::stable::Tensor clone(const torch::stable::Tensor& self) { + const auto num_args = 2; + std::array stack{ + torch::stable::detail::from(self), + torch::stable::detail::from(std::nullopt)}; +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::clone", "", stack.data(), TORCH_ABI_VERSION)); +#else + TORCH_ERROR_CODE_CHECK( + aoti_torch_call_dispatcher("aten::clone", "", stack.data())); +#endif + return torch::stable::detail::to(stack[0]); +} + +/// Stable version of the flatten.using_ints op. +/// +/// Flattens the input tensor by reshaping it into a one-dimensional tensor. +/// If start_dim or end_dim are specified, only dimensions starting from +/// start_dim to end_dim are flattened. +/// +/// Minimum compatible version: PyTorch 2.9. +/// +/// @param self The input tensor to flatten. +/// @param start_dim The first dimension to flatten. Defaults to 0. +/// @param end_dim The last dimension to flatten. Defaults to -1 (last dim). +/// @return A flattened tensor. +inline torch::stable::Tensor flatten( + const torch::stable::Tensor& self, + int64_t start_dim = 0, + int64_t end_dim = -1) { + const auto num_args = 3; + std::array stack{ + torch::stable::detail::from(self), + torch::stable::detail::from(start_dim), + torch::stable::detail::from(end_dim)}; +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::flatten", "using_ints", stack.data(), TORCH_ABI_VERSION)); +#else + TORCH_ERROR_CODE_CHECK( + aoti_torch_call_dispatcher("aten::flatten", "using_ints", stack.data())); +#endif + return torch::stable::detail::to(stack[0]); +} + +/// Stable version of the unsqueeze op. +/// +/// Returns a new tensor with a dimension of size one inserted at the specified +/// position. The returned tensor shares the same underlying data with the input +/// tensor. +/// +/// Minimum compatible version: PyTorch 2.9. +/// +/// @param self The input tensor. +/// @param dim The index at which to insert +/// values are supported. +/// @return A tensor with an additional dimension. +inline torch::stable::Tensor unsqueeze( + const torch::stable::Tensor& self, + int64_t dim) { + const auto num_args = 2; + std::array stack{ + torch::stable::detail::from(self), torch::stable::detail::from(dim)}; +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::unsqueeze", "", stack.data(), TORCH_ABI_VERSION)); +#else + TORCH_ERROR_CODE_CHECK( + aoti_torch_call_dispatcher("aten::unsqueeze", "", stack.data())); +#endif + return torch::stable::detail::to(stack[0]); +} + +/// Stable version of the squeeze.dim op. +/// +/// Returns a tensor with the dimension of size one at the specified position +/// removed. The returned tensor shares the same underlying data with the input +/// tensor. +/// +/// Minimum compatible version: PyTorch 2.9. +/// +/// @param self The input tensor. +/// @param dim The dimension to squeeze. +/// the tensor is returned unchanged. +/// @return A tensor with the specified dimension removed (if size was 1). +inline torch::stable::Tensor squeeze( + const torch::stable::Tensor& self, + int64_t dim) { + const auto num_args = 2; + std::array stack{ + torch::stable::detail::from(self), torch::stable::detail::from(dim)}; +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::squeeze", "dim", stack.data(), TORCH_ABI_VERSION)); +#else + TORCH_ERROR_CODE_CHECK( + aoti_torch_call_dispatcher("aten::squeeze", "dim", stack.data())); +#endif + return torch::stable::detail::to(stack[0]); +} + +/// Stable version of the select.int op. +/// +/// Slices the input tensor along the specified dimension at the given index. +/// This function returns a view of the original tensor with the given dimension +/// removed. +/// +/// Minimum compatible version: PyTorch 2.9. +/// +/// @note The index parameter is typed +/// header-only. +/// +/// @param self The input tensor. +/// @param dim The dimension to slice. +/// @param index The index to select along the dimension. +/// @return A tensor with one fewer dimension. +inline torch::stable::Tensor select( + const torch::stable::Tensor& self, + int64_t dim, + int64_t index) { + const auto num_args = 3; + std::array stack{ + torch::stable::detail::from(self), + torch::stable::detail::from(dim), + torch::stable::detail::from(index)}; +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::select", "int", stack.data(), TORCH_ABI_VERSION)); +#else + TORCH_ERROR_CODE_CHECK( + aoti_torch_call_dispatcher("aten::select", "int", stack.data())); +#endif + return torch::stable::detail::to(stack[0]); +} + +/// Stable version of the matmul op. +/// +/// Performs matrix multiplication between two tensors. The behavior depends on +/// the dimensionality of the tensors (see PyTorch documentation for details on +/// broadcasting rules for matmul). +/// +/// Minimum compatible version: PyTorch 2.9. +/// +/// @param self The first input tensor. +/// @param other The second input tensor. +/// @return The result of matrix multiplication. +inline torch::stable::Tensor matmul( + const torch::stable::Tensor& self, + const torch::stable::Tensor& other) { + const auto num_args = 2; + std::array stack{ + torch::stable::detail::from(self), torch::stable::detail::from(other)}; +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::matmul", "", stack.data(), TORCH_ABI_VERSION)); +#else + TORCH_ERROR_CODE_CHECK( + aoti_torch_call_dispatcher("aten::matmul", "", stack.data())); +#endif + return torch::stable::detail::to(stack[0]); +} + +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + +/// Stable parallel_for utility. +/// +/// Provides a stable interface to at::parallel_for for parallel execution. +/// The function f will be called with (begin, end) ranges to process in +/// parallel. grain_size controls the minimum work size per thread for efficient +/// parallelization. +/// +/// Minimum compatible version: PyTorch 2.10. +/// +/// @tparam F The callable type +/// @param begin The start of the iteration range. +/// @param end The end of the iteration range (exclusive). +/// @param grain_size The minimum number of iterations per thread. +/// @param f The function to execute in parallel. +template +inline void parallel_for( + const int64_t begin, + const int64_t end, + const int64_t grain_size, + const F& f) { + auto callback = [](int64_t cb_begin, int64_t cb_end, void* ctx) { + const F* func = static_cast(ctx); + (*func)(cb_begin, cb_end); + }; + TORCH_ERROR_CODE_CHECK(torch_parallel_for( + begin, + end, + grain_size, + callback, + const_cast(static_cast(&f)))); +} + +/// Gets the number of threads for the parallel backend. +/// +/// Provides a stable interface to at::get_num_threads. +/// +/// Minimum compatible version: PyTorch 2.10. +/// +/// @return The number of threads +inline uint32_t get_num_threads() { + uint32_t num_threads; + TORCH_ERROR_CODE_CHECK(torch_get_num_threads(&num_threads)); + return num_threads; +} + +/// Stable version of the empty.memory_format op. +/// +/// Creates a new uninitialized tensor with the specified size and options. +/// This function supports full tensor creation options including device, +/// dtype, layout, and memory format. +/// +/// Minimum compatible version: PyTorch 2.10. +/// +/// @param size The desired size of the output tensor. +/// @param dtype Optional scalar type for the tensor elements. +/// @param layout Optional memory layout (e.g., strided, sparse). +/// @param device Optional device to place the tensor on. +/// @param pin_memory Optional flag to use pinned memory (for CUDA tensors). +/// @param memory_format Optional memory format for the tensor. +/// @return A new uninitialized tensor with the specified properties. +inline torch::stable::Tensor empty( + torch::headeronly::IntHeaderOnlyArrayRef size, + std::optional dtype = std::nullopt, + std::optional layout = std::nullopt, + std::optional device = std::nullopt, + std::optional pin_memory = std::nullopt, + std::optional memory_format = + std::nullopt) { + const auto num_args = 6; + std::array stack{ + torch::stable::detail::from(size), + torch::stable::detail::from(dtype), + torch::stable::detail::from(layout), + torch::stable::detail::from(device), + torch::stable::detail::from(pin_memory), + torch::stable::detail::from(memory_format)}; + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::empty", "memory_format", stack.data(), TORCH_ABI_VERSION)); + return torch::stable::detail::to(stack[0]); +} + +/// Stable version of the reshape op. +/// +/// Returns a tensor with the same data and number of elements as the input, +/// but with the specified shape. When possible, the returned tensor will be +/// a view of the input. +/// +/// Minimum compatible version: PyTorch 2.10. +/// +/// @param self The input tensor. +/// @param shape The desired output shape. +/// @return A tensor with the specified shape. +inline torch::stable::Tensor reshape( + const torch::stable::Tensor& self, + torch::headeronly::IntHeaderOnlyArrayRef shape) { + const auto num_args = 2; + std::array stack{ + torch::stable::detail::from(self), torch::stable::detail::from(shape)}; + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::reshape", "", stack.data(), TORCH_ABI_VERSION)); + return torch::stable::detail::to(stack[0]); +} + +/// Stable version of the view op. +/// +/// Returns a new tensor with the same data as the input tensor but with a +/// different shape. The returned tensor shares the same data and must have +/// the same number of elements. +/// +/// Minimum compatible version: PyTorch 2.10. +/// +/// @param self The input tensor. +/// @param size The desired output shape. +/// @return A view tensor with the specified shape. +inline torch::stable::Tensor view( + const torch::stable::Tensor& self, + torch::headeronly::IntHeaderOnlyArrayRef size) { + const auto num_args = 2; + std::array stack{ + torch::stable::detail::from(self), torch::stable::detail::from(size)}; + TORCH_ERROR_CODE_CHECK( + torch_call_dispatcher("aten::view", "", stack.data(), TORCH_ABI_VERSION)); + return torch::stable::detail::to(stack[0]); +} + +/// Creates a tensor from an existing data blob. +/// +/// Creates a tensor that uses the provided data pointer as its storage. +/// The tensor does not own the data, so the caller must ensure the data +/// remains valid for the lifetime of the tensor. +/// +/// Minimum compatible version: PyTorch 2.10. +/// +/// @param data Pointer to the data buffer. +/// @param sizes The size of each dimension of the tensor. +/// @param strides The stride for each dimension. +/// @param device The device where the data resides. +/// @param dtype The scalar type of the data. +/// @param storage_offset The offset into the data buffer. Defaults to 0. +/// @param layout The memory layout. Defaults to Strided. +/// @return A tensor backed by the provided data. +inline torch::stable::Tensor from_blob( + void* data, + torch::headeronly::IntHeaderOnlyArrayRef sizes, + torch::headeronly::IntHeaderOnlyArrayRef strides, + torch::stable::Device device, + torch::headeronly::ScalarType dtype, + int64_t storage_offset = 0, + torch::headeronly::Layout layout = torch::headeronly::Layout::Strided) { + auto shim_dtype = + torch::stable::detail::to(torch::stable::detail::from(dtype)); + auto shim_device_type = torch::stable::detail::to( + torch::stable::detail::from(device.type())); + auto shim_layout = + torch::stable::detail::to(torch::stable::detail::from(layout)); + AtenTensorHandle ath; + TORCH_ERROR_CODE_CHECK(aoti_torch_create_tensor_from_blob_v2( + data, + sizes.size(), + sizes.data(), + strides.data(), + storage_offset, + shim_dtype, + shim_device_type, + device.index(), + &ath, + shim_layout, + nullptr, + 0)); + return torch::stable::Tensor(ath); +} + +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_11_0 +/// Creates a tensor from an existing data blob with a custom deleter. +/// +/// This is the same as the from_blob function above, but allows specifying a +/// custom deleter function that will be called when the tensor's storage is +/// deallocated. Accepts both plain function pointers and capturing lambdas. +/// +/// Minimum compatible version: PyTorch 2.11. +/// +/// @tparam F The callable type. Must be invocable with (void*). +/// @param data Pointer to the data buffer. +/// @param sizes The size of each dimension of the tensor. +/// @param strides The stride for each dimension. +/// @param device The device where the data resides. +/// @param dtype The scalar type of the data. +/// @param deleter Callable to invoke when the tensor is deallocated. +/// @param storage_offset The offset into the data buffer. Defaults to 0. +/// @param layout The memory layout. Defaults to Strided. +/// @return A tensor backed by the provided data. +template , int> = 0> +inline torch::stable::Tensor from_blob( + void* data, + torch::headeronly::IntHeaderOnlyArrayRef sizes, + torch::headeronly::IntHeaderOnlyArrayRef strides, + torch::stable::Device device, + torch::headeronly::ScalarType dtype, + F deleter, + int64_t storage_offset = 0, + torch::headeronly::Layout layout = torch::headeronly::Layout::Strided) { + auto shim_dtype = + torch::stable::detail::to(torch::stable::detail::from(dtype)); + auto shim_device_type = torch::stable::detail::to( + torch::stable::detail::from(device.type())); + auto shim_layout = + torch::stable::detail::to(torch::stable::detail::from(layout)); + + AtenTensorHandle ath; + if constexpr (std::is_convertible_v) { + // Simple function pointer: pass it as ctx, no heap allocation. + auto deleter_callback = [](void* data, void* ctx) { + auto fn = reinterpret_cast(ctx); + fn(data); + }; + TORCH_ERROR_CODE_CHECK(torch_from_blob( + data, + sizes.size(), + sizes.data(), + strides.data(), + storage_offset, + shim_dtype, + shim_device_type, + device.index(), + &ath, + shim_layout, + nullptr, + 0, + deleter_callback, + reinterpret_cast(static_cast(deleter)))); + } else { + // Capturing lambda: heap-allocate and type-erase. + F* heap_allocated_deleter = new F(std::move(deleter)); + auto deleter_callback = [](void* data, void* ctx) { + F* func = static_cast(ctx); + (*func)(data); + delete func; + }; + TORCH_ERROR_CODE_CHECK(torch_from_blob( + data, + sizes.size(), + sizes.data(), + strides.data(), + storage_offset, + shim_dtype, + shim_device_type, + device.index(), + &ath, + shim_layout, + nullptr, + 0, + deleter_callback, + static_cast(heap_allocated_deleter))); + } + return torch::stable::Tensor(ath); +} +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_11_0 + +/// Stable version of the to.dtype_layout op. +/// +/// Converts a tensor to the specified dtype, layout, device, and/or memory +/// format. Returns a new tensor with the specified properties. +/// +/// Minimum compatible version: PyTorch 2.10. +/// +/// @param self The input tensor. +/// @param dtype Optional target scalar type. +/// @param layout Optional target memory layout. +/// @param device Optional target device. +/// @param pin_memory Optional flag to use pinned memory. +/// @param non_blocking If true, the operation may be asynchronous. Defaults to +/// false. +/// @param copy If true, always create a copy. Defaults to false. +/// @param memory_format Optional target memory format. +/// @return A tensor with the specified properties. +inline torch::stable::Tensor to( + const torch::stable::Tensor& self, + std::optional dtype = std::nullopt, + std::optional layout = std::nullopt, + std::optional device = std::nullopt, + std::optional pin_memory = std::nullopt, + bool non_blocking = false, + bool copy = false, + std::optional memory_format = + std::nullopt) { + const auto num_args = 8; + std::array stack{ + torch::stable::detail::from(self), + torch::stable::detail::from(dtype), + torch::stable::detail::from(layout), + torch::stable::detail::from(device), + torch::stable::detail::from(pin_memory), + torch::stable::detail::from(non_blocking), + torch::stable::detail::from(copy), + torch::stable::detail::from(memory_format)}; + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::to", "dtype_layout", stack.data(), TORCH_ABI_VERSION)); + return torch::stable::detail::to(stack[0]); +} + +/// Convenience overload for moving a tensor to a device. +/// +/// Moves the tensor to the specified device. This is a convenience wrapper +/// around the full to() function. +/// +/// Minimum compatible version: PyTorch 2.10. +/// +/// @param self The input tensor. +/// @param device The target device. +/// @param non_blocking If true, the operation may be asynchronous. Defaults to +/// false. +/// @param copy If true, always create a copy. Defaults to false. +/// @return A tensor on the specified device. +inline torch::stable::Tensor to( + const torch::stable::Tensor& self, + torch::stable::Device device, + bool non_blocking = false, + bool copy = false) { + return to( + self, + std::nullopt, + std::nullopt, + device, + std::nullopt, + non_blocking, + copy, + std::nullopt); +} + +/// Stable version of the contiguous op. +/// +/// Returns a contiguous in memory tensor containing the same data as the input +/// tensor. If the input tensor is already contiguous in the specified memory +/// format, the input tensor is returned. +/// +/// Minimum compatible version: PyTorch 2.10. +/// +/// @param self The input tensor. +/// @param memory_format The desired memory format. +/// @return A contiguous tensor. +inline torch::stable::Tensor contiguous( + const torch::stable::Tensor& self, + torch::headeronly::MemoryFormat memory_format = + torch::headeronly::MemoryFormat::Contiguous) { + const auto num_args = 2; + std::array stack{ + torch::stable::detail::from(self), + torch::stable::detail::from(memory_format)}; + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::contiguous", "", stack.data(), TORCH_ABI_VERSION)); + return torch::stable::detail::to(stack[0]); +} + +/// Stable version of the new_empty op (2.10 version with full kwargs). +/// +/// Creates a new uninitialized tensor with the specified size and options. +/// This version supports all tensor creation kwargs. For versions < 2.10, +/// a simpler overload that only takes dtype is available. +/// +/// Minimum compatible version: PyTorch 2.10. +/// +/// @param self The input tensor whose properties may be inherited if kwargs are +/// not provided. +/// @param size The desired size of the output tensor. +/// @param dtype Optional scalar type for the tensor elements. +/// @param layout Optional memory layout (e.g., strided, sparse). +/// @param device Optional device to place the tensor on. +/// @param pin_memory Optional flag to use pinned memory (for CUDA tensors). +/// @return A new uninitialized tensor with the specified properties. +inline torch::stable::Tensor new_empty( + const torch::stable::Tensor& self, + torch::headeronly::IntHeaderOnlyArrayRef size, + std::optional dtype = std::nullopt, + std::optional layout = std::nullopt, + std::optional device = std::nullopt, + std::optional pin_memory = std::nullopt) { + const auto num_args = 6; + std::array stack{ + torch::stable::detail::from(self), + torch::stable::detail::from(size), + torch::stable::detail::from(dtype), + torch::stable::detail::from(layout), + torch::stable::detail::from(device), + torch::stable::detail::from(pin_memory)}; + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::new_empty", "", stack.data(), TORCH_ABI_VERSION)); + return torch::stable::detail::to(stack[0]); +} + +/// Stable version of the new_zeros op (2.10 version with full kwargs). +/// +/// Creates a new zero-filled tensor with the specified size and options. +/// This version supports all tensor creation kwargs. For versions < 2.10, +/// a simpler overload that only takes dtype is available. +/// +/// Minimum compatible version: PyTorch 2.10. +/// +/// @param self The input tensor whose properties may be inherited if kwargs are +/// not provided. +/// @param size The desired size of the output tensor. +/// @param dtype Optional scalar type for the tensor elements. +/// @param layout Optional memory layout (e.g., strided, sparse). +/// @param device Optional device to place the tensor on. +/// @param pin_memory Optional flag to use pinned memory (for CUDA tensors). +/// @return A new zero-filled tensor with the specified properties. +inline torch::stable::Tensor new_zeros( + const torch::stable::Tensor& self, + torch::headeronly::IntHeaderOnlyArrayRef size, + std::optional dtype = std::nullopt, + std::optional layout = std::nullopt, + std::optional device = std::nullopt, + std::optional pin_memory = std::nullopt) { + const auto num_args = 6; + std::array stack{ + torch::stable::detail::from(self), + torch::stable::detail::from(size), + torch::stable::detail::from(dtype), + torch::stable::detail::from(layout), + torch::stable::detail::from(device), + torch::stable::detail::from(pin_memory)}; + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::new_zeros", "", stack.data(), TORCH_ABI_VERSION)); + return torch::stable::detail::to(stack[0]); +} + +/// Stable version of the sum.dim_IntList op. +/// +/// Computes the sum of the input tensor along the specified dimensions. +/// If dim is not provided, sums over all dimensions. +/// +/// Minimum compatible version: PyTorch 2.10. +/// +/// @param self The input tensor. +/// @param dim Optional dimensions to reduce. If not provided, reduces all +/// dimensions. +/// @param keepdim Whether to retain the reduced dimensions. Defaults to false. +/// @param dtype Optional output dtype. If not provided, uses the input dtype. +/// @return A tensor containing the sum. +inline torch::stable::Tensor sum( + const torch::stable::Tensor& self, + std::optional dim = std::nullopt, + bool keepdim = false, + std::optional dtype = std::nullopt) { + const auto num_args = 4; + std::array stack{ + torch::stable::detail::from(self), + torch::stable::detail::from(dim), + torch::stable::detail::from(keepdim), + torch::stable::detail::from(dtype)}; + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::sum", "dim_IntList", stack.data(), TORCH_ABI_VERSION)); + return torch::stable::detail::to(stack[0]); +} + +/// Stable version of the sum.IntList_out op. +/// +/// Computes the sum of the input tensor along the specified dimensions, +/// storing the result in the provided output tensor. Following C++ convention, +/// the out parameter comes first. +/// +/// Minimum compatible version: PyTorch 2.10. +/// +/// @param out The output tensor (modified in-place). +/// @param self The input tensor. +/// @param dim Optional dimensions to reduce. +/// @param keepdim Whether to retain the reduced dimensions. Defaults to false. +/// @param dtype Optional output dtype. +/// @return Reference to the output tensor. +inline torch::stable::Tensor& sum_out( + torch::stable::Tensor& out, + const torch::stable::Tensor& self, + std::optional dim = std::nullopt, + bool keepdim = false, + std::optional dtype = std::nullopt) { + const auto num_args = 5; + std::array stack{ + torch::stable::detail::from(self), + torch::stable::detail::from(dim), + torch::stable::detail::from(keepdim), + torch::stable::detail::from(dtype), + torch::stable::detail::from(out)}; + TORCH_ERROR_CODE_CHECK(torch_call_dispatcher( + "aten::sum", "IntList_out", stack.data(), TORCH_ABI_VERSION)); + // Clean up the handle in stack[0], discard the temporary + (void)torch::stable::detail::to(stack[0]); + return out; +} + +/// Stable version of the subtract.Tensor op. +/// +/// Subtracts the other tensor from self, with an optional scaling factor alpha. +/// Computes: self - alpha * other. +/// +/// Minimum compatible version: PyTorch 2.10. +/// +/// @note The alpha parameter is typed as double +/// API uses double for the Scalar parameter. +/// +/// @param self The input tensor. +/// @param other The tensor to subtract. +/// @param alpha The scaling factor for other. Defaults to 1.0. +/// @return The result of self - alpha * other. +inline torch::stable::Tensor subtract( + const torch::stable::Tensor& self, + const torch::stable::Tensor& other, + double alpha = 1.0) { + AtenTensorHandle ret0; + TORCH_ERROR_CODE_CHECK( + aoti_torch_aten_subtract_Tensor(self.get(), other.get(), alpha, &ret0)); + return torch::stable::Tensor(ret0); +} + +/// Stable version of the full.default op. +/// +/// Creates a tensor of the specified size filled with the given value. +/// +/// Minimum compatible version: PyTorch 2.10. +/// +/// @note The fill_value parameter is typed +/// C shim API uses double for the Scalar parameter. +/// +/// @param size The desired size of the output tensor. +/// @param fill_value The value to fill the tensor with. +/// @param dtype Optional scalar type for the tensor elements. +/// @param layout Optional memory layout. +/// @param device Optional device to place the tensor on. +/// @param pin_memory Optional flag to use pinned memory. +/// @return A new tensor filled with the specified value. +inline torch::stable::Tensor full( + torch::headeronly::IntHeaderOnlyArrayRef size, + double fill_value, + std::optional dtype = std::nullopt, + std::optional layout = std::nullopt, + std::optional device = std::nullopt, + std::optional pin_memory = std::nullopt) { + int32_t* dtype_ptr = nullptr; + int32_t dtype_val; + if (dtype.has_value()) { + dtype_val = torch::stable::detail::to( + torch::stable::detail::from(dtype.value())); + dtype_ptr = &dtype_val; + } + + int32_t* layout_ptr = nullptr; + int32_t layout_val; + if (layout.has_value()) { + layout_val = torch::stable::detail::to( + torch::stable::detail::from(layout.value())); + layout_ptr = &layout_val; + } + + int32_t* device_type_ptr = nullptr; + int32_t device_type_val; + int32_t device_index = 0; + if (device.has_value()) { + device_type_val = torch::stable::detail::to( + torch::stable::detail::from(device.value().type())); + device_type_ptr = &device_type_val; + device_index = device.value().index(); + } + + int32_t* pin_memory_ptr = nullptr; + int32_t pin_memory_val; + if (pin_memory.has_value()) { + pin_memory_val = pin_memory.value() ? 1 : 0; + pin_memory_ptr = &pin_memory_val; + } + + AtenTensorHandle ret0; + TORCH_ERROR_CODE_CHECK(aoti_torch_aten_full( + size.data(), + static_cast(size.size()), + fill_value, + dtype_ptr, + layout_ptr, + device_type_ptr, + device_index, + pin_memory_ptr, + &ret0)); + + return torch::stable::Tensor(ret0); +} + +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + +HIDDEN_NAMESPACE_END(torch, stable) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/stableivalue_conversions.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/stableivalue_conversions.h new file mode 100644 index 0000000000000000000000000000000000000000..eece32c7eb33defaed09117fd53e89e475a3d4e7 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/stableivalue_conversions.h @@ -0,0 +1,996 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +HIDDEN_NAMESPACE_BEGIN(torch, stable, detail) + +// Helper variable templates to detect 2.10+ types for better compile-time error +// messages +template +inline constexpr bool is_header_only_array_ref_v = false; + +template +inline constexpr bool + is_header_only_array_ref_v> = true; + +template +inline constexpr bool is_std_vector_v = false; + +template +inline constexpr bool is_std_vector_v> = true; + +// forward declare so that the from/to() implementations in the detail +// namespace of library.h where the real work is done can compile. +template +StableIValue from(T val); +template +T to(StableIValue val); + +// ============================================================================= +// Below are the helpers for converting between StableIValue and T +// ============================================================================= +// ============================================================================= +// FROM CONVERSIONS (T -> StableIValue) +// ====================================================================== + +// Specialization for general copyable types (catch-all) => StableIValue +template +struct FromImpl { + static StableIValue call( + T val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + // Ensure 2.10+ types don't accidentally use the base case - provide clear + // compile-time errors. + static_assert( + !std::is_same_v, + "torch::stable::Device requires TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0"); + static_assert( + !is_header_only_array_ref_v, + "HeaderOnlyArrayRef requires TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0"); + static_assert( + !is_std_vector_v, + "std::vector requires TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0"); + static_assert( + !std::is_same_v, + "std::string requires TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0"); + static_assert( + sizeof(T) <= sizeof(StableIValue), + "StableLibrary stack does not support parameter types larger than 64 bits."); + static_assert(std::is_trivially_copyable_v); + // Initialization should be cheap enough; let's give people well-specified + // reproducible behavior. + StableIValue result = 0; + // NOTE [ -Wclass-memaccess ]: reinterpret_cast to suppress + // overzealous -Wclass-memaccess. (see + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107361) We have a + // static_assert above that T is trivially copyable, which should be + // enough. +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + std::memcpy(&result, reinterpret_cast(&val), sizeof(val)); +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + // if value has size less than sizeof(StableIValue), then only lowest bytes + // have to be updated + std::memcpy( + reinterpret_cast(&result) + sizeof(StableIValue) - + sizeof(val), + reinterpret_cast(&val), + sizeof(val)); +#else +#error "Unexpected or undefined __BYTE_ORDER__" +#endif + return result; + } +}; + +// Specialization for torch::headeronly::ScalarType => StableIValue +// Note that we call into the shim to translate between the user's +// ScalarType and libtorch's ScalarType, which can be different! +// Also note that the list below is not comprehensive, as it does not +// include types that are no longer really used and should probably be +// deprecated (like qint8). +using torch::headeronly::ScalarType; +template <> +struct FromImpl { + static StableIValue call( + ScalarType val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + switch (val) { + case ScalarType::Byte: + return torch::stable::detail::from(aoti_torch_dtype_uint8()); + case ScalarType::Char: + return torch::stable::detail::from(aoti_torch_dtype_int8()); + case ScalarType::Short: + return torch::stable::detail::from(aoti_torch_dtype_int16()); + case ScalarType::Int: + return torch::stable::detail::from(aoti_torch_dtype_int32()); + case ScalarType::Long: + return torch::stable::detail::from(aoti_torch_dtype_int64()); + case ScalarType::Half: + return torch::stable::detail::from(aoti_torch_dtype_float16()); + case ScalarType::Float: + return torch::stable::detail::from(aoti_torch_dtype_float32()); + case ScalarType::Double: + return torch::stable::detail::from(aoti_torch_dtype_float64()); + case ScalarType::ComplexHalf: + return torch::stable::detail::from(aoti_torch_dtype_complex32()); + case ScalarType::ComplexFloat: + return torch::stable::detail::from(aoti_torch_dtype_complex64()); + case ScalarType::ComplexDouble: + return torch::stable::detail::from(aoti_torch_dtype_complex128()); + case ScalarType::Bool: + return torch::stable::detail::from(aoti_torch_dtype_bool()); + case ScalarType::BFloat16: + return torch::stable::detail::from(aoti_torch_dtype_bfloat16()); + case ScalarType::Float8_e5m2: + return torch::stable::detail::from(aoti_torch_dtype_float8_e5m2()); + case ScalarType::Float8_e4m3fn: + return torch::stable::detail::from(aoti_torch_dtype_float8_e4m3fn()); + case ScalarType::Float8_e5m2fnuz: + return torch::stable::detail::from(aoti_torch_dtype_float8_e5m2fnuz()); + case ScalarType::Float8_e4m3fnuz: + return torch::stable::detail::from(aoti_torch_dtype_float8_e4m3fnuz()); + case ScalarType::UInt16: + return torch::stable::detail::from(aoti_torch_dtype_uint16()); + case ScalarType::UInt32: + return torch::stable::detail::from(aoti_torch_dtype_uint32()); + case ScalarType::UInt64: + return torch::stable::detail::from(aoti_torch_dtype_uint64()); +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_11_0 + case ScalarType::Float8_e8m0fnu: + return torch::stable::detail::from(torch_dtype_float8_e8m0fnu()); + case ScalarType::Float4_e2m1fn_x2: + return torch::stable::detail::from(torch_dtype_float4_e2m1fn_x2()); +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_11_0 + default: + STD_TORCH_CHECK( + false, + "Not yet supported ScalarType ", + toString(val), + ", please file an issue describing your use case."); + } + } +}; + +// [Note DeviceType version guard] +// This conversion was introduced in 2.10. However, we do not gate it +// with TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 because this +// conversion is not actually used to pass DeviceType between user +// extensions and libtorch (i.e. there is no c10::TypeKind::DeviceType). +// The purpose of gating other conversions is to ensure that user +// extensions do not try to pass a StableIValue that libtorch is +// unable to interpret. +// This conversion is only used +// (1) In the conversion for torch::stable::Device (already gated) +// (2) Within the user extension to translate between libtorch/extension's +// DeviceType (no gating needed) +// Specialization for torch::headeronly::DeviceType => StableIValue +// Note that we call into the shim to translate between the user's +// DeviceType and libtorch's DeviceType, which can be different! +using torch::headeronly::DeviceType; +template <> +struct FromImpl { + static StableIValue call( + DeviceType val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + switch (val) { + case DeviceType::CPU: + return torch::stable::detail::from(aoti_torch_device_type_cpu()); + case DeviceType::CUDA: + return torch::stable::detail::from(aoti_torch_device_type_cuda()); + case DeviceType::Meta: + return torch::stable::detail::from(aoti_torch_device_type_meta()); + case DeviceType::XPU: + return torch::stable::detail::from(aoti_torch_device_type_xpu()); + case DeviceType::MPS: + return torch::stable::detail::from(aoti_torch_device_type_mps()); + case DeviceType::PrivateUse1: + return torch::stable::detail::from( + aoti_torch_device_type_privateuse1()); + default: + STD_TORCH_CHECK( + false, + "Not yet supported DeviceType, please file an issue describing your use case."); + } + } +}; + +// Specialization for std::nullopt_t => StableIValue +template <> +struct FromImpl { + static StableIValue call( + std::nullopt_t val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + return torch::stable::detail::from(nullptr); + } +}; + +// Specialization for std::optional => StableIValue +// [Handling std::optional] +// When the schema is represented by an optional type, say int?, then we +// expect the custom extension representation to be a std::optional +// (critically NOT int!). In order for all parameters to be stably parsed and +// handled by our dispatcher, we liaison custom extension parameters through +// boxed kernels, meaning that every value will make its way to be an IValue: +// +// custom extension value --(from)-> StableIValue --(to_ivalue)-> IValue +// +// When the custom extension value is a literal that can be trivially +// casted to StableIValue, e.g., an int, a float, a pointer, this route is +// ...trivial. The below specialization is for a case when the custom +// extension value would NOT fit within a StableIValue: a std::optional. +// +// If the std::optional has no value, it is treated as std::nullopt, +// whose StableIValue representation is from(nullptr). Otherwise, we: +// 1. unwrap the std::optional +// 2. recursively convert its value of type T to a StableIValue +// 3. allocate heap space for said StableIValue +// 4. convert the resulting StableIValue* into a StableIValue +// +// note that this allocates heap memory! which we expect to be cleaned +// up in the to_ivalue() function defined in shim_common.cpp. We +// purposefully hide this implementation detail from the user so that +// all the user needs to know is: +// +// The schema requests an optional (T?) so I must call `from` on a +// std::optional or a std::nullopt. +template +struct FromImpl> { + static StableIValue call( + const std::optional& val, + uint64_t extension_build_version, + bool is_internal) { + if (!val.has_value()) { + return torch::stable::detail::from(std::nullopt); + } + return torch::stable::detail::from( + new StableIValue(detail::FromImpl::call( + val.value(), extension_build_version, is_internal))); + } +}; + +// Specialization for torch::stable::Tensor => StableIValue +// Returns a new owning reference of the underlying Tensor. +template <> +struct FromImpl { + static StableIValue call( + const torch::stable::Tensor& val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + AtenTensorHandle new_ath; + TORCH_ERROR_CODE_CHECK(aoti_torch_new_tensor_handle(val.get(), &new_ath)); + return torch::stable::detail::from(new_ath); + } +}; + +// ============================================================================= +// FROM CONVERSIONS requiring TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 +// ============================================================================= +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + +// Specialization for torch::headeronly::Layout => StableIValue +// Note that we call into the shim to translate between the user's +// Layout and libtorch's Layout, which can be different! +using torch::headeronly::Layout; +template <> +struct FromImpl { + static StableIValue call( + Layout val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + switch (val) { + case Layout::Strided: + return torch::stable::detail::from(aoti_torch_layout_strided()); + case Layout::Sparse: + return torch::stable::detail::from(aoti_torch_layout_sparse_coo()); + case Layout::SparseCsr: + return torch::stable::detail::from(aoti_torch_layout_sparse_csr()); + case Layout::SparseCsc: + return torch::stable::detail::from(aoti_torch_layout_sparse_csc()); + case Layout::SparseBsr: + return torch::stable::detail::from(aoti_torch_layout_sparse_bsr()); + case Layout::SparseBsc: + return torch::stable::detail::from(aoti_torch_layout_sparse_bsc()); + case Layout::Mkldnn: + return torch::stable::detail::from(aoti_torch_layout__mkldnn()); + case Layout::Jagged: + return torch::stable::detail::from(aoti_torch_layout_jagged()); + default: + STD_TORCH_CHECK( + false, + "Not yet supported Layout, please file an issue describing your use case."); + } + } +}; + +// Specialization for torch::headeronly::MemoryFormat => StableIValue +// Note that we call into the shim to translate between the user's +// MemoryFormat and libtorch's MemoryFormat, which can be different! +using torch::headeronly::MemoryFormat; +template <> +struct FromImpl { + static StableIValue call( + MemoryFormat val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + switch (val) { + case MemoryFormat::Contiguous: + return torch::stable::detail::from( + aoti_torch_memory_format_contiguous_format()); + case MemoryFormat::Preserve: + return torch::stable::detail::from( + aoti_torch_memory_format_preserve_format()); + case MemoryFormat::ChannelsLast: + return torch::stable::detail::from( + aoti_torch_memory_format_channels_last()); + case MemoryFormat::ChannelsLast3d: + return torch::stable::detail::from( + aoti_torch_memory_format_channels_last_3d()); + default: + STD_TORCH_CHECK( + false, + "Not yet supported MemoryFormat, please file an issue describing your use case."); + } + } +}; + +// Specialization for torch::headeronly::HeaderOnlyArrayRef => StableIValue +// Returns a new owning reference of the underlying list. +template +struct FromImpl> { + static StableIValue call( + const torch::headeronly::HeaderOnlyArrayRef& val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + StableListHandle new_list_handle; + try { + TORCH_ERROR_CODE_CHECK( + torch_new_list_reserve_size(val.size(), &new_list_handle)); + for (const auto& elem : val) { + TORCH_ERROR_CODE_CHECK(torch_list_push_back( + new_list_handle, torch::stable::detail::from(elem))); + } + return torch::stable::detail::from(new_list_handle); + } catch (const std::runtime_error&) { + if (new_list_handle != nullptr) { + // clean up memory if an error was thrown + TORCH_ERROR_CODE_CHECK(torch_delete_list(new_list_handle)); + } + throw; + } + } +}; + +// Specialization for std::vector => StableIValue, which is implemented the +// same way as HeaderOnlyArrayRef => StableIValue +// Returns a new owning reference of the underlying list. +template +struct FromImpl> { + static StableIValue call( + const std::vector& val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + return torch::stable::detail::from< + torch::headeronly::HeaderOnlyArrayRef>(val); + } +}; + +// Specialization for torch::stable::Device => StableIValue +// Pack the device type and index into a StableIValue in a platform-independent +// format. We use the shim representation for DeviceType (int32_t) for ABI +// stability. StableIValue layout: DeviceIndex in lower 32 bits, +// DeviceType (shim int32_t) in upper 32 bits +template <> +struct FromImpl { + static StableIValue call( + const torch::stable::Device& val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + // Convert DeviceType to shim representation (int32_t) + StableIValue device_type_shim = torch::stable::detail::from(val.type()); + // Pack: lower 32 bits = device index, upper 32 bits = device type (shim) + uint64_t device_index_bits = + static_cast(static_cast(val.index())); + uint64_t device_type_bits = + static_cast(static_cast(device_type_shim)) << 32; + return device_index_bits | device_type_bits; + } +}; + +// Specialization for std::string, which should return a new owning reference of +// the string +template <> +struct FromImpl { + static StableIValue call( + const std::string& val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + StringHandle handle; + TORCH_ERROR_CODE_CHECK( + torch_new_string_handle(val.c_str(), val.length(), &handle)) + return torch::stable::detail::from(handle); + } +}; + +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + +// ============================================================================= +// TO CONVERSIONS (StableIValue -> T) +// ============================================================================= + +// Specialization for StableIValue => general copyable types (catch-all) +template +struct ToImpl { + static T call( + StableIValue val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + // Ensure 2.10+ types don't accidentally use the base case - provide clear + // compile-time errors. + static_assert( + !std::is_same_v, + "torch::stable::Device requires TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0"); + static_assert( + !is_header_only_array_ref_v, + "HeaderOnlyArrayRef requires TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0"); + static_assert( + !is_std_vector_v, + "std::vector requires TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0"); + static_assert( + !std::is_same_v, + "std::string requires TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0"); + static_assert(std::is_trivially_copyable_v); + // T may not have a default constructor. (For example, it might be + // c10::Device.) However, std::memcpy implicitly creates a T at the + // destination. So, we can use a union to work around this lack of + // default constructor. + union Result { + Result() {} + T t; + }; + Result result; + // See NOTE[ -Wclass-memaccess ] above. +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + std::memcpy(reinterpret_cast(&result.t), &val, sizeof(result)); +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + static_assert( + sizeof(T) <= sizeof(StableIValue), + "StableLibrary stack does not support parameter types larger than 64 bits."); + // if value has size less than sizeof(StableIValue), then only lowest bytes + // have to be updated + std::memcpy( + reinterpret_cast(&result.t), + reinterpret_cast(&val) + sizeof(StableIValue) - + sizeof(result), + sizeof(result)); +#else +#error "Unexpected or undefined __BYTE_ORDER__" +#endif + return result.t; + } +}; + +// Specialization for StableIValue => torch::headeronly::ScalarType +template <> +struct ToImpl { + static ScalarType call( + StableIValue val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + int32_t shim_scalartype = torch::stable::detail::to(val); + if (shim_scalartype == aoti_torch_dtype_uint8()) { + return ScalarType::Byte; + } else if (shim_scalartype == aoti_torch_dtype_int8()) { + return ScalarType::Char; + } else if (shim_scalartype == aoti_torch_dtype_int16()) { + return ScalarType::Short; + } else if (shim_scalartype == aoti_torch_dtype_int32()) { + return ScalarType::Int; + } else if (shim_scalartype == aoti_torch_dtype_int64()) { + return ScalarType::Long; + } else if (shim_scalartype == aoti_torch_dtype_float16()) { + return ScalarType::Half; + } else if (shim_scalartype == aoti_torch_dtype_float32()) { + return ScalarType::Float; + } else if (shim_scalartype == aoti_torch_dtype_float64()) { + return ScalarType::Double; + } else if (shim_scalartype == aoti_torch_dtype_complex32()) { + return ScalarType::ComplexHalf; + } else if (shim_scalartype == aoti_torch_dtype_complex64()) { + return ScalarType::ComplexFloat; + } else if (shim_scalartype == aoti_torch_dtype_complex128()) { + return ScalarType::ComplexDouble; + } else if (shim_scalartype == aoti_torch_dtype_bool()) { + return ScalarType::Bool; + } else if (shim_scalartype == aoti_torch_dtype_bfloat16()) { + return ScalarType::BFloat16; + } else if (shim_scalartype == aoti_torch_dtype_float8_e5m2()) { + return ScalarType::Float8_e5m2; + } else if (shim_scalartype == aoti_torch_dtype_float8_e4m3fn()) { + return ScalarType::Float8_e4m3fn; + } else if (shim_scalartype == aoti_torch_dtype_float8_e5m2fnuz()) { + return ScalarType::Float8_e5m2fnuz; + } else if (shim_scalartype == aoti_torch_dtype_float8_e4m3fnuz()) { + return ScalarType::Float8_e4m3fnuz; + } else if (shim_scalartype == aoti_torch_dtype_uint16()) { + return ScalarType::UInt16; + } else if (shim_scalartype == aoti_torch_dtype_uint32()) { + return ScalarType::UInt32; + } else if (shim_scalartype == aoti_torch_dtype_uint64()) { + return ScalarType::UInt64; +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_11_0 + } else if (shim_scalartype == torch_dtype_float8_e8m0fnu()) { + return ScalarType::Float8_e8m0fnu; + } else if (shim_scalartype == torch_dtype_float4_e2m1fn_x2()) { + return ScalarType::Float4_e2m1fn_x2; +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_11_0 + } else { + STD_TORCH_CHECK( + false, + "Not yet supported ScalarType ", + std::to_string(shim_scalartype), + ", please file an issue describing your use case."); + } + } +}; + +// See [Note DeviceType version guard] +// Specialization for StableIValue => torch::headeronly::DeviceType +template <> +struct ToImpl { + static DeviceType call( + StableIValue val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + int32_t shim_devicetype = torch::stable::detail::to(val); + if (shim_devicetype == aoti_torch_device_type_cpu()) { + return DeviceType::CPU; + } else if (shim_devicetype == aoti_torch_device_type_cuda()) { + return DeviceType::CUDA; + } else if (shim_devicetype == aoti_torch_device_type_meta()) { + return DeviceType::Meta; + } else if (shim_devicetype == aoti_torch_device_type_xpu()) { + return DeviceType::XPU; + } else if (shim_devicetype == aoti_torch_device_type_mps()) { + return DeviceType::MPS; + } else if (shim_devicetype == aoti_torch_device_type_privateuse1()) { + return DeviceType::PrivateUse1; + } else { + STD_TORCH_CHECK( + false, + "Not yet supported DeviceType ", + std::to_string(shim_devicetype), + ", please file an issue describing your use case."); + } + } +}; + +// Specialization for StableIValue => std::nullopt_t +template <> +struct ToImpl { + static std::nullopt_t call( + StableIValue val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + // val should be equivalent to from(nullptr) + return std::nullopt; + } +}; + +// Specialization for StableIValue => std::optional, see [Handling +// std::optional] as the semantic is the same but in reverse direction as we go +// from IValue --(from_ivalue)-> StableIValue --(to)-> T in custom extension +template +struct ToImpl> { + static std::optional call( + StableIValue val, + uint64_t extension_build_version, + bool is_internal) { + auto sivp = torch::stable::detail::to(val); + + // sivp is either nullptr or a pointer to a StableIValue + if (sivp == nullptr) { + return {}; + } + auto inner_val = + detail::ToImpl::call(*sivp, extension_build_version, is_internal); + + // free the memory associated with StableIValue* sivp + delete sivp; + + return std::make_optional(inner_val); + } +}; + +// Specialization for StableIValue => torch::stable::Tensor +// The resulting stable::Tensor steals ownership of the input's +// underlying AtenTensorHandle. +template <> +struct ToImpl { + static torch::stable::Tensor call( + StableIValue val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + return torch::stable::Tensor( + torch::stable::detail::to(val)); + } +}; + +// ============================================================================= +// TO CONVERSIONS requiring TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 +// ============================================================================= +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + +// Specialization for StableIValue => torch::headeronly::Layout +template <> +struct ToImpl { + static Layout call( + StableIValue val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + int32_t shim_layout = torch::stable::detail::to(val); + if (shim_layout == aoti_torch_layout_strided()) { + return Layout::Strided; + } else if (shim_layout == aoti_torch_layout_sparse_coo()) { + return Layout::Sparse; + } else if (shim_layout == aoti_torch_layout_sparse_csr()) { + return Layout::SparseCsr; + } else if (shim_layout == aoti_torch_layout_sparse_csc()) { + return Layout::SparseCsc; + } else if (shim_layout == aoti_torch_layout_sparse_bsr()) { + return Layout::SparseBsr; + } else if (shim_layout == aoti_torch_layout_sparse_bsc()) { + return Layout::SparseBsc; + } else if (shim_layout == aoti_torch_layout__mkldnn()) { + return Layout::Mkldnn; + } else if (shim_layout == aoti_torch_layout_jagged()) { + return Layout::Jagged; + } else { + STD_TORCH_CHECK( + false, + "Not yet supported Layout ", + std::to_string(shim_layout), + ", please file an issue describing your use case."); + } + } +}; + +// Specialization for StableIValue => torch::headeronly::MemoryFormat +template <> +struct ToImpl { + static MemoryFormat call( + StableIValue val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + int32_t shim_memory_format = torch::stable::detail::to(val); + if (shim_memory_format == aoti_torch_memory_format_contiguous_format()) { + return MemoryFormat::Contiguous; + } else if ( + shim_memory_format == aoti_torch_memory_format_preserve_format()) { + return MemoryFormat::Preserve; + } else if (shim_memory_format == aoti_torch_memory_format_channels_last()) { + return MemoryFormat::ChannelsLast; + } else if ( + shim_memory_format == aoti_torch_memory_format_channels_last_3d()) { + return MemoryFormat::ChannelsLast3d; + } else { + STD_TORCH_CHECK( + false, + "Not yet supported MemoryFormat ", + std::to_string(shim_memory_format), + ", please file an issue describing your use case."); + } + } +}; + +// Specialization for StableIValue => std::vector +// std::vector should be represented as a StableListHandle +// filled with StableIValues +// The new std::vector steals ownership of the underlying elements +// and we free the underlying list referred by the input StableListHandle. +template +struct ToImpl> { + static std::vector call( + StableIValue val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + auto list_handle = torch::stable::detail::to(val); + size_t size; + try { + TORCH_ERROR_CODE_CHECK(torch_list_size(list_handle, &size)); + std::vector result; + result.reserve(size); + for (size_t i = 0; i < size; i++) { + StableIValue element; + TORCH_ERROR_CODE_CHECK(torch_list_get_item(list_handle, i, &element)); + result.push_back(torch::stable::detail::to(element)); + } + TORCH_ERROR_CODE_CHECK(torch_delete_list(list_handle)); + return result; + } catch (const std::runtime_error&) { + // clean up memory if an exception is thrown, and rethrow + TORCH_ERROR_CODE_CHECK(torch_delete_list(list_handle)); + throw; + } + } +}; + +// Specialization for StableIValue => torch::stable::Device +// Unpack device type and index from StableIValue in platform-independent +// format. StableIValue layout: DeviceIndex in lower 32 bits, +// DeviceType (shim int32_t) in upper 32 bits +template <> +struct ToImpl { + static torch::stable::Device call( + StableIValue val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + // Unpack: lower 32 bits = device index, upper 32 bits = device type (shim) + int32_t device_index = static_cast(val & 0xFFFFFFFF); + StableIValue device_type_shim = (val >> 32) & 0xFFFFFFFF; + DeviceType device_type = + torch::stable::detail::to(device_type_shim); + return torch::stable::Device(device_type, device_index); + } +}; + +// Specialization for std::string +// Returns a new std::string; the string in val is deleted. +template <> +struct ToImpl { + static std::string call( + StableIValue val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + StringHandle handle = torch::stable::detail::to(val); + size_t length; + TORCH_ERROR_CODE_CHECK(torch_string_length(handle, &length)); + const char* data; + TORCH_ERROR_CODE_CHECK(torch_string_c_str(handle, &data)); + auto strptr = new std::string(data, length); + + // delete the old string before returning new string + TORCH_ERROR_CODE_CHECK(torch_delete_string(handle)); + return *strptr; + } +}; + +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + +// ============================================================================= +// FROM/TO CONVERSIONS requiring TORCH_FEATURE_VERSION >= TORCH_VERSION_2_12_0 +// ============================================================================= +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_12_0 + +// Specialization for torch::headeronly::Tag => StableIValue +// Uses shim getter functions so the integer representation is resolved at +// runtime from libtorch, not baked in at extension compile time. +using torch::headeronly::Tag; +template <> +struct FromImpl { + static StableIValue call( + Tag val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + switch (val) { + case Tag::core: + return torch::stable::detail::from(torch_tag_core()); + case Tag::cudagraph_unsafe: + return torch::stable::detail::from(torch_tag_cudagraph_unsafe()); + case Tag::data_dependent_output: + return torch::stable::detail::from(torch_tag_data_dependent_output()); + case Tag::dynamic_output_shape: + return torch::stable::detail::from(torch_tag_dynamic_output_shape()); + case Tag::flexible_layout: + return torch::stable::detail::from(torch_tag_flexible_layout()); + case Tag::generated: + return torch::stable::detail::from(torch_tag_generated()); + case Tag::inplace_view: + return torch::stable::detail::from(torch_tag_inplace_view()); + case Tag::maybe_aliasing_or_mutating: + return torch::stable::detail::from( + torch_tag_maybe_aliasing_or_mutating()); + case Tag::needs_contiguous_strides: + return torch::stable::detail::from( + torch_tag_needs_contiguous_strides()); + case Tag::needs_exact_strides: + return torch::stable::detail::from(torch_tag_needs_exact_strides()); + case Tag::needs_fixed_stride_order: + return torch::stable::detail::from( + torch_tag_needs_fixed_stride_order()); + case Tag::nondeterministic_bitwise: + return torch::stable::detail::from( + torch_tag_nondeterministic_bitwise()); + case Tag::nondeterministic_seeded: + return torch::stable::detail::from(torch_tag_nondeterministic_seeded()); + case Tag::out_variant: + return torch::stable::detail::from(torch_tag_out_variant()); + case Tag::pointwise: + return torch::stable::detail::from(torch_tag_pointwise()); + case Tag::pt2_compliant_tag: + return torch::stable::detail::from(torch_tag_pt2_compliant_tag()); + case Tag::reduction: + return torch::stable::detail::from(torch_tag_reduction()); + case Tag::view_copy: + return torch::stable::detail::from(torch_tag_view_copy()); + default: + STD_TORCH_CHECK( + false, + "Not yet supported Tag, please file an issue describing your use case."); + } + } +}; + +// Specialization for StableIValue => torch::headeronly::Tag +template <> +struct ToImpl { + static Tag call( + StableIValue val, + [[maybe_unused]] uint64_t extension_build_version, + [[maybe_unused]] bool is_internal) { + int32_t shim_tag = torch::stable::detail::to(val); + if (shim_tag == torch_tag_core()) { + return Tag::core; + } else if (shim_tag == torch_tag_cudagraph_unsafe()) { + return Tag::cudagraph_unsafe; + } else if (shim_tag == torch_tag_data_dependent_output()) { + return Tag::data_dependent_output; + } else if (shim_tag == torch_tag_dynamic_output_shape()) { + return Tag::dynamic_output_shape; + } else if (shim_tag == torch_tag_flexible_layout()) { + return Tag::flexible_layout; + } else if (shim_tag == torch_tag_generated()) { + return Tag::generated; + } else if (shim_tag == torch_tag_inplace_view()) { + return Tag::inplace_view; + } else if (shim_tag == torch_tag_maybe_aliasing_or_mutating()) { + return Tag::maybe_aliasing_or_mutating; + } else if (shim_tag == torch_tag_needs_contiguous_strides()) { + return Tag::needs_contiguous_strides; + } else if (shim_tag == torch_tag_needs_exact_strides()) { + return Tag::needs_exact_strides; + } else if (shim_tag == torch_tag_needs_fixed_stride_order()) { + return Tag::needs_fixed_stride_order; + } else if (shim_tag == torch_tag_nondeterministic_bitwise()) { + return Tag::nondeterministic_bitwise; + } else if (shim_tag == torch_tag_nondeterministic_seeded()) { + return Tag::nondeterministic_seeded; + } else if (shim_tag == torch_tag_out_variant()) { + return Tag::out_variant; + } else if (shim_tag == torch_tag_pointwise()) { + return Tag::pointwise; + } else if (shim_tag == torch_tag_pt2_compliant_tag()) { + return Tag::pt2_compliant_tag; + } else if (shim_tag == torch_tag_reduction()) { + return Tag::reduction; + } else if (shim_tag == torch_tag_view_copy()) { + return Tag::view_copy; + } else { + STD_TORCH_CHECK( + false, + "Not yet supported Tag ", + std::to_string(shim_tag), + ", please file an issue describing your use case."); + } + } +}; + +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_12_0 + +// ============================================================================= +// end to helpers for converting between StableIValue and T +// ============================================================================= + +// Expose the partially templated class functions through single functions +// The non-private versions will be used by the extension or headers that +// the extension includes. +template +inline StableIValue from(T val) { + return detail::FromImpl::call( + val, aoti_torch_abi_version(), /*is_internal=*/false); +} + +template +inline StableIValue from(const std::optional& val) { + return detail::FromImpl>::call( + val, aoti_torch_abi_version(), /*is_internal=*/false); +} + +// The below overload is used! See https://godbolt.org/z/859cshxrW +// We are suppressing the warning for versions clang12- and gcc11- +[[maybe_unused]] inline StableIValue from(const torch::stable::Tensor& val) { + return detail::FromImpl::call( + val, aoti_torch_abi_version(), /*is_internal=*/false); +} + +template +inline T to(StableIValue val) { + return detail::ToImpl::call( + val, aoti_torch_abi_version(), /*is_internal=*/false); +} + +// Internal conversion functions used by from_ivalue and to_ivalue. +// These are used in libtorch +template +inline StableIValue _from(T val, uint64_t extension_build_version) { + return detail::FromImpl::call( + val, extension_build_version, /*is_internal=*/true); +} + +template +inline StableIValue _from( + const std::optional& val, + uint64_t extension_build_version) { + return detail::FromImpl>::call( + val, extension_build_version, /*is_internal=*/true); +} + +[[maybe_unused]] inline StableIValue _from( + const torch::stable::Tensor& val, + uint64_t extension_build_version) { + return detail::FromImpl::call( + val, extension_build_version, /*is_internal=*/true); +} + +template +inline T _to(StableIValue val, uint64_t extension_build_version) { + return detail::ToImpl::call( + val, extension_build_version, /*is_internal=*/true); +} + +HIDDEN_NAMESPACE_END(torch, stable, detail) + +// [global from/to deprecation note] +// WARNING! the following APIs will be removed!! We deprecated global from/to +// (in 2.10) in favor of torch::stable::detail from/to to not pollute the global +// namespace. We are only including the following wrappers for backwards +// compatibility. + +// WARNING! Will be removed. Only exists for BC. See [global from/to deprecation +// note] +template +[[deprecated("Use torch::stable::detail::from instead.")]] +inline StableIValue from(T val) { + return torch::stable::detail::from(val); +} + +// WARNING! Will be removed. Only exists for BC. See [global from/to deprecation +// note] +template +[[deprecated("Use torch::stable::detail::from instead.")]] +inline StableIValue from(const std::optional& val) { + return torch::stable::detail::from(val); +} + +// WARNING! Will be removed. Only exists for BC. See [global from/to deprecation +// note] +[[deprecated( + "Use torch::stable::detail::from instead.")]] [[maybe_unused]] inline StableIValue +from(const torch::stable::Tensor& val) { + return torch::stable::detail::from(val); +} + +// WARNING! Will be removed. Only exists for BC. See [global from/to deprecation +// note] +template +[[deprecated("Use torch::stable::detail::to instead.")]] +inline T to(StableIValue val) { + return torch::stable::detail::to(val); +} diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/tensor.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/tensor.h new file mode 100644 index 0000000000000000000000000000000000000000..8762372a415cf30f429808980e0e2f2af7942b1d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/tensor.h @@ -0,0 +1,4 @@ +#pragma once + +#include +#include diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/tensor_inl.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/tensor_inl.h new file mode 100644 index 0000000000000000000000000000000000000000..f6e7ecaf7456fdb9e9ae589f57b1c115b1857a58 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/tensor_inl.h @@ -0,0 +1,77 @@ +#pragma once + +// This file implements tensor.h. We separated out the Tensor struct so that +// other files can depend on the Tensor struct (like library.h) and the +// implementations of the Tensor methods can depend on APIs in library.h +// without circular dependencies. + +#include +#include +#include +#include +#include +#include + +HIDDEN_NAMESPACE_BEGIN(torch, stable) + +using torch::headeronly::Layout; +using torch::headeronly::ScalarType; + +inline ScalarType Tensor::scalar_type() const { + int32_t dtype; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_dtype(ath_.get(), &dtype)); + return torch::stable::detail::to( + torch::stable::detail::from(dtype)); +} + +inline Device Tensor::device() const { + int32_t device_type; + int32_t device_index; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_device_type(ath_.get(), &device_type)); + TORCH_ERROR_CODE_CHECK( + aoti_torch_get_device_index(ath_.get(), &device_index)); + DeviceType extension_device_type = torch::stable::detail::to( + torch::stable::detail::from(device_type)); + return Device(extension_device_type, static_cast(device_index)); +} + +inline Layout Tensor::layout() const { + int32_t layout; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_layout(ath_.get(), &layout)); + return torch::stable::detail::to(torch::stable::detail::from(layout)); +} + +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 +// The following data ptr cast methods mirror the methods defined in +// aten/src/ATen/templates/TensorMethods.cpp +#define DEFINE_DATA_PTR_CAST(T, name, PRED) \ + template <> \ + inline T* Tensor::mutable_data_ptr() const { \ + auto stype = scalar_type(); \ + STD_TORCH_CHECK( \ + PRED(stype, torch::headeronly::ScalarType::name), \ + "expected scalar type " #name " but found ", \ + torch::headeronly::toString(stype)); \ + return static_cast(mutable_data_ptr()); \ + } \ + template <> \ + inline const T* Tensor::const_data_ptr() const { \ + auto stype = scalar_type(); \ + STD_TORCH_CHECK( \ + PRED(stype, torch::headeronly::ScalarType::name), \ + "expected scalar type " #name " but found ", \ + torch::headeronly::toString(stype)); \ + return static_cast(const_data_ptr()); \ + } + +#define _PRED(S1, S2) S1 == S2 +#define DEFINE_CAST(T, name) DEFINE_DATA_PTR_CAST(T, name, _PRED) +AT_FORALL_SCALAR_TYPES_WITH_COMPLEX(DEFINE_CAST) +DEFINE_CAST(uint16_t, UInt16) +DEFINE_CAST(uint32_t, UInt32) +DEFINE_CAST(uint64_t, UInt64) +#undef DEFINE_CAST +#undef _PRED +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + +HIDDEN_NAMESPACE_END(torch, stable) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/tensor_struct.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/tensor_struct.h new file mode 100644 index 0000000000000000000000000000000000000000..45461211955990e8c022bd6026ed6d1ab259858e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/tensor_struct.h @@ -0,0 +1,447 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +HIDDEN_NAMESPACE_BEGIN(torch, stable) + +using accelerator::DeviceIndex; +using torch::headeronly::IntHeaderOnlyArrayRef; +using torch::headeronly::Layout; +using torch::headeronly::ScalarType; + +// The torch::stable::Tensor class is a highlevel C++ wrapper around +// the C shim Tensor APIs. We've modeled this class after TensorBase, as custom +// op kernels only really need to interact with Tensor metadata (think sizes, +// strides, device, dtype). Other functions on Tensor (like empty_like) should +// live like the ATen op that they are and exist outside of this struct. +// +// There are several goals of this class over AtenTensorHandle and +// RAIIAtenTensorHandle: +// 1. torch::stable::Tensor is a nicer UX much closer to torch::Tensor than the +// C APIs with AtenTensorHandle. Under the hood we still call to these C shim +// APIs to preserve stability. +// 2. RAIIAtenTensorHandle boils down to a uniq_ptr that forces the user to pass +// around ownership. This makes it difficult to pass one input into 2 +// different functions, e.g., doing something like c = a(t) + b(t) for +// stable::Tensor t. Thus, we use a shared_ptr here. + +/** + * @brief An ABI stable wrapper around PyTorch tensors. + * + * This class is modeled after TensorBase, as custom + * op kernels primarily need to interact with Tensor metadata (sizes, + * strides, device, dtype). Other tensor operations (like ``empty_like``) exist + * as standalone functions outside of this struct. + * + * Minimum compatible version: PyTorch 2.9. + */ +class Tensor { + private: + std::shared_ptr ath_; + + public: + /** + * @brief Constructs a Tensor with an uninitialized AtenTensorHandle. + * + * Creates a new stable::Tensor by allocating an uninitialized tensor handle. + * The ownership of the handle is managed internally via shared_ptr. + * + * Minimum compatible version: PyTorch 2.9. + */ + Tensor() { + AtenTensorHandle ret; + TORCH_ERROR_CODE_CHECK(aoti_torch_new_uninitialized_tensor(&ret)); + ath_ = std::shared_ptr(ret, [](AtenTensorHandle ath) { + TORCH_ERROR_CODE_CHECK(aoti_torch_delete_tensor_object(ath)); + }); + } + + /** + * @brief Constructs a Tensor from an existing AtenTensorHandle. + * + * Steals ownership of the provided AtenTensorHandle. + * + * @param ath The AtenTensorHandle to wrap. Ownership is transferred to this + * Tensor. + * + * Minimum compatible version: PyTorch 2.9. + */ + explicit Tensor(AtenTensorHandle ath) + : ath_(ath, [](AtenTensorHandle ath) { + TORCH_ERROR_CODE_CHECK(aoti_torch_delete_tensor_object(ath)); + }) {} + + // Copy and move constructors can be default cuz the underlying handle is a + // shared_ptr + /// \private + Tensor(const Tensor& other) = default; + /// \private + Tensor(Tensor&& other) noexcept = default; + + // Copy and move assignment operators can be default cuz the underlying handle + // is a shared_ptr + /// \private + Tensor& operator=(const Tensor& other) = default; + /// \private + Tensor& operator=(Tensor&& other) noexcept = default; + + // Destructor can be default: shared ptr has custom deletion logic + /// \private + ~Tensor() = default; + + /** + * @brief Returns a borrowed reference to the underlying AtenTensorHandle. + * + * @return The underlying AtenTensorHandle. + * + * Minimum compatible version: PyTorch 2.9. + */ + AtenTensorHandle get() const { + return ath_.get(); + } + + // ============================================================================= + // C-shimified TensorBase APIs: the below APIs have the same signatures and + // semantics as their counterparts in TensorBase.h. + // ============================================================================= + + /** + * @brief Returns a pointer to the tensor's data. + * + * @return A void pointer to the tensor's data storage. + * + * Minimum compatible version: PyTorch 2.9. + */ + void* data_ptr() const { + void* data_ptr; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_data_ptr(ath_.get(), &data_ptr)); + return data_ptr; + } + +#if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + /** + * @brief Returns a mutable pointer to the tensor's data. + * + * @return A mutable void pointer to the tensor's data storage. + * + * Minimum compatible version: PyTorch 2.10. + */ + void* mutable_data_ptr() const { + void* data_ptr{}; + TORCH_ERROR_CODE_CHECK(torch_get_mutable_data_ptr(ath_.get(), &data_ptr)); + return data_ptr; + } + + /** + * @brief Returns a const pointer to the tensor's data. + * + * @return A const void pointer to the tensor's data storage. + * + * Minimum compatible version: PyTorch 2.10. + */ + const void* const_data_ptr() const { + const void* data_ptr{}; + TORCH_ERROR_CODE_CHECK(torch_get_const_data_ptr(ath_.get(), &data_ptr)); + return data_ptr; + } + + /** + * @brief Returns a typed mutable pointer to the tensor's data. + * + * @tparam T The type to cast the data pointer to. + * @return A mutable pointer to the tensor's data cast to type T*. + * + * Minimum compatible version: PyTorch 2.10. + */ + template + T* mutable_data_ptr() const; + + /** + * @brief Returns a typed const pointer to the tensor's data. + * + * @tparam T The type to cast the data pointer to. Must not be + * const-qualified. + * @return A const pointer to the tensor's data cast to type const T*. + * + * Minimum compatible version: PyTorch 2.10. + */ + template , int> = 0> + const T* const_data_ptr() const; + + /** + * @brief Sets whether this tensor requires gradient computation. + * + * @param requires_grad If true, gradients will be computed for this tensor + * during backpropagation. + * @return A reference to this Tensor. + * + * Minimum compatible version: PyTorch 2.10. + */ + const Tensor& set_requires_grad(bool requires_grad) const { + TORCH_ERROR_CODE_CHECK(torch_set_requires_grad(ath_.get(), requires_grad)); + return *this; + } +#endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 + + /** + * @brief Returns the number of dimensions of the tensor. + * + * @return The number of dimensions (rank) of the tensor. + * + * Minimum compatible version: PyTorch 2.9. + */ + int64_t dim() const { + int64_t dim; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_dim(ath_.get(), &dim)); + return dim; + } + + /** + * @brief Returns the total number of elements in the tensor. + * + * @return The total number of elements across all dimensions. + * + * Minimum compatible version: PyTorch 2.9. + */ + int64_t numel() const { + int64_t numel; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_numel(ath_.get(), &numel)); + return numel; + } + + // note: sizes and strides, for all intents and purposes, the same as in + // TensorBase.h: it returns a borrowed reference of the dimension sizes of + // a Tensor. + // + // The only difference is that it returns a header-only IntHeaderOnlyArrayRef, + // which has slightly less functionality than a regular IntArrayRef. See + // [HeaderOnlyArrayRef vs ArrayRef note] for more details. + /** + * @brief Returns the sizes (shape) of the tensor. + * + * Returns a borrowed reference of the dimension sizes of the tensor. + * + * @return An IntHeaderOnlyArrayRef containing the size of each dimension. + * + * Minimum compatible version: PyTorch 2.9. + */ + IntHeaderOnlyArrayRef sizes() const { + int64_t* sizes; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_sizes(ath_.get(), &sizes)); + return IntHeaderOnlyArrayRef(sizes, dim()); + } + + /** + * @brief Returns the strides of the tensor. + * + * Returns a borrowed reference of the strides of the tensor. + * + * + * @return An IntHeaderOnlyArrayRef containing the stride of each dimension. + * + * Minimum compatible version: PyTorch 2.9. + */ + IntHeaderOnlyArrayRef strides() const { + int64_t* strides; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_strides(ath_.get(), &strides)); + return IntHeaderOnlyArrayRef(strides, dim()); + } + + /** + * @brief Checks if the tensor is contiguous in memory. + * + * @note This is a subset of the original TensorBase API. It takes no + * arguments whereas the original API takes a memory format argument. + * Here, we assume the default contiguous memory format. + * + * @return true if the tensor is contiguous, false otherwise. + * + * Minimum compatible version: PyTorch 2.9. + */ + bool is_contiguous() const { + bool is_contiguous; + TORCH_ERROR_CODE_CHECK( + aoti_torch_is_contiguous(ath_.get(), &is_contiguous)); + return is_contiguous; + } + + /** + * @brief Returns the stride of a specific dimension. + * + * @param dim The dimension index to query. + * @return The stride of the specified dimension. + * + * Minimum compatible version: PyTorch 2.9. + */ + int64_t stride(int64_t dim) const { + int64_t stride; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_stride(ath_.get(), dim, &stride)); + return stride; + } + + // This is almost the same API as the one in TensorBase.h, except + // we add a check that the returned device_index is within the + // range of int8_t. + /// \private + int8_t get_device() const { + int32_t device_index; + TORCH_ERROR_CODE_CHECK( + aoti_torch_get_device_index(ath_.get(), &device_index)); + STD_TORCH_CHECK( + device_index >= std::numeric_limits::min() && + device_index <= std::numeric_limits::max(), + "Device index is out of range of return type int8_t, please use get_device_index() instead."); + return static_cast(device_index); + } + + // The same as get_device but with two differences: + // 1. it has a more suiting name + // 2. it returns a DeviceIndex, which is int32_t in this world + // that should be more stable than the likely shifting + // DeviceIndex in libtorch (it is int8_t that might become int16_t) + /** + * @brief Returns the device index of the tensor. + * + * @return The device index as DeviceIndex (int32_t). + * + * Minimum compatible version: PyTorch 2.9. + */ + DeviceIndex get_device_index() const { + int32_t device_index; + TORCH_ERROR_CODE_CHECK( + aoti_torch_get_device_index(ath_.get(), &device_index)); + return device_index; + } + + /** + * @brief Checks if the tensor is on a CUDA device. + * + * @return true if the tensor is on a CUDA device, false otherwise. + * + * Minimum compatible version: PyTorch 2.9. + */ + bool is_cuda() const { + int32_t device_type; + TORCH_ERROR_CODE_CHECK( + aoti_torch_get_device_type(ath_.get(), &device_type)); + return device_type == aoti_torch_device_type_cuda(); + } + + /** + * @brief Checks if the tensor is on the CPU. + * + * @return true if the tensor is on the CPU, false otherwise. + * + * Minimum compatible version: PyTorch 2.9. + */ + bool is_cpu() const { + int32_t device_type; + TORCH_ERROR_CODE_CHECK( + aoti_torch_get_device_type(ath_.get(), &device_type)); + return device_type == aoti_torch_device_type_cpu(); + } + + /** + * @brief Returns the size of a specific dimension. + * + * @param dim The dimension index to query. + * @return The size of the specified dimension. + * + * Minimum compatible version: PyTorch 2.9. + */ + int64_t size(int64_t dim) const { + int64_t size; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_size(ath_.get(), dim, &size)); + return size; + } + + /** + * @brief Checks if the tensor is defined (not null). + * + * @return true if the tensor is defined, false otherwise. + * + * Minimum compatible version: PyTorch 2.9. + */ + bool defined() const { + bool defined; + TORCH_ERROR_CODE_CHECK(aoti_torch_is_defined(ath_.get(), &defined)); + return defined; + } + + /** + * @brief Returns the storage offset of the tensor. + * + * The storage offset is the number of elements from the beginning of the + * underlying storage to the first element of the tensor. + * + * @return The storage offset in number of elements. + * + * Minimum compatible version: PyTorch 2.9. + */ + int64_t storage_offset() const { + int64_t storage_offset; + TORCH_ERROR_CODE_CHECK( + aoti_torch_get_storage_offset(ath_.get(), &storage_offset)); + return storage_offset; + } + + /** + * @brief Returns the size in bytes of each element in the tensor. + * + * @return The element size in bytes. + * + * Minimum compatible version: PyTorch 2.9. + */ + size_t element_size() const { + int32_t dtype; + TORCH_ERROR_CODE_CHECK(aoti_torch_get_dtype(ath_.get(), &dtype)); + return aoti_torch_dtype_element_size(dtype); + } + + // defined in tensor-inl.h to avoid circular dependencies + /** + * @brief Returns the scalar type (dtype) of the tensor. + * + * @return The ScalarType of the tensor. + * + * Minimum compatible version: PyTorch 2.9. + */ + ScalarType scalar_type() const; + + // defined in tensor-inl.h to avoid circular dependencies + /** + * @brief Returns the device of the tensor. + * + * @return The Device on which the tensor resides. + * + * Minimum compatible version: PyTorch 2.9. + */ + Device device() const; + + // defined in tensor_inl.h to avoid circular dependencies + /** + * @brief Returns the layout of the tensor. + * + * @return The Layout of the tensor (e.g., Strided, Sparse). + * + * Minimum compatible version: PyTorch 2.9. + */ + Layout layout() const; + + // ============================================================================= + // END of C-shimified TensorBase APIs + // ============================================================================= +}; + +HIDDEN_NAMESPACE_END(torch, stable) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/version.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/version.h new file mode 100644 index 0000000000000000000000000000000000000000..eeb4f9152546aab161d6ac468eb8f1d2221982e8 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/stable/version.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +// Stable ABI Version Targeting +// +// This header provides version targeting capabilities for the PyTorch Stable +// ABI. Users can define TORCH_TARGET_VERSION to target a specific stable ABI +// version instead of using the current TORCH_ABI_VERSION of libtorch at +// compile time. +// +// Usage: +// Default behavior (uses current ABI version): +// #include +// +// Target a specific stable version (major.minor) (e.g. PyTorch 2.9): +// (1) Pass a compiler flag -DTORCH_TARGET_VERSION=0x0209000000000000 +// (2) Alternatively, define TORCH_TARGET_VERSION in the source code before +// including any header files: +// #define TORCH_TARGET_VERSION (((0ULL + 2) << 56) | ((0ULL + 9) << 48)) +// #include + +#ifdef TORCH_TARGET_VERSION +#define TORCH_FEATURE_VERSION TORCH_TARGET_VERSION +#else +#define TORCH_FEATURE_VERSION TORCH_ABI_VERSION +#endif + +#define TORCH_VERSION_2_10_0 (((0ULL + 2) << 56) | ((0ULL + 10) << 48)) +#define TORCH_VERSION_2_11_0 (((0ULL + 2) << 56) | ((0ULL + 11) << 48)) +#define TORCH_VERSION_2_12_0 (((0ULL + 2) << 56) | ((0ULL + 12) << 48)) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/tensor/python_tensor.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/tensor/python_tensor.h new file mode 100644 index 0000000000000000000000000000000000000000..87183f3f4eed50b44407c6df72e9e39ead754db8 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/tensor/python_tensor.h @@ -0,0 +1,40 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace at { +class Tensor; +} // namespace at + +namespace torch::tensors { + +// Initializes the Python tensor type objects: torch.FloatTensor, +// torch.DoubleTensor, etc. and binds them in their containing modules. +TORCH_PYTHON_API void initialize_python_bindings(); + +// Same as set_default_tensor_type() but takes a PyObject* +TORCH_PYTHON_API void py_set_default_tensor_type(PyObject* type_obj); + +// Same as py_set_default_tensor_type, but only changes the dtype (ScalarType). +TORCH_PYTHON_API void py_set_default_dtype(PyObject* dtype_obj); + +// Gets the DispatchKey for the default tensor type. +// +// TODO: This is nuts! There is no reason to let the default tensor type id +// change. Probably only store ScalarType, as that's the only flex point +// we support. +TORCH_PYTHON_API c10::DispatchKey get_default_dispatch_key(); +TORCH_PYTHON_API at::Device get_default_device(); + +// Gets the ScalarType for the default tensor type. +TORCH_PYTHON_API at::ScalarType get_default_scalar_type(); +} // namespace torch::tensors + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils.h new file mode 100644 index 0000000000000000000000000000000000000000..36869bdc99dd4fcf67f5c5b7a10bc495d1d81f0c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils.h @@ -0,0 +1,130 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define THPUtils_(NAME) TH_CONCAT_4(THP, Real, Utils_, NAME) + +#define THPUtils_typename(obj) (Py_TYPE(obj)->tp_name) + +#if defined(__GNUC__) || defined(__ICL) || defined(__clang__) +#define THP_EXPECT(x, y) (__builtin_expect((x), (y))) +#else +#define THP_EXPECT(x, y) (x) +#endif + +#define THPUtils_unpackReal_FLOAT(object) \ + (PyFloat_Check(object) ? PyFloat_AsDouble(object) \ + : PyLong_Check(object) \ + ? PyLong_AsLongLong(object) \ + : (throw std::runtime_error("Could not parse real"), 0)) + +#define THPUtils_checkReal_INT(object) PyLong_Check(object) + +#define THPUtils_unpackReal_INT(object) \ + (PyLong_Check(object) \ + ? PyLong_AsLongLong(object) \ + : (throw std::runtime_error("Could not parse real"), 0)) + +#define THPUtils_unpackReal_BOOL(object) \ + (PyBool_Check(object) \ + ? object \ + : (throw std::runtime_error("Could not parse real"), Py_False)) + +#define THPUtils_unpackReal_COMPLEX(object) \ + (PyComplex_Check(object) \ + ? (c10::complex( \ + PyComplex_RealAsDouble(object), PyComplex_ImagAsDouble(object))) \ + : PyFloat_Check(object) \ + ? (c10::complex(PyFloat_AsDouble(object), 0)) \ + : PyLong_Check(object) \ + ? (c10::complex(PyLong_AsLongLong(object), 0)) \ + : (throw std::runtime_error("Could not parse real"), \ + c10::complex(0, 0))) + +#define THPBoolUtils_unpackReal(object) THPUtils_unpackReal_BOOL(object) +#define THPBoolUtils_checkAccreal(object) THPUtils_checkReal_BOOL(object) +#define THPByteUtils_checkReal(object) THPUtils_checkReal_INT(object) +#define THPByteUtils_unpackReal(object) \ + (unsigned char)THPUtils_unpackReal_INT(object) + +/* + From https://github.com/python/cpython/blob/v3.7.0/Modules/xxsubtype.c + If compiled as a shared library, some compilers don't allow addresses of + Python objects defined in other libraries to be used in static PyTypeObject + initializers. The DEFERRED_ADDRESS macro is used to tag the slots where such + addresses appear; the module init function that adds the PyTypeObject to the + module must fill in the tagged slots at runtime. The argument is for + documentation -- the macro ignores it. +*/ +#define DEFERRED_ADDRESS(ADDR) nullptr + +TORCH_PYTHON_API void THPUtils_setError(const char* format, ...); +TORCH_PYTHON_API void THPUtils_invalidArguments( + PyObject* given_args, + PyObject* given_kwargs, + const char* function_name, + size_t num_options, + ...); + +bool THPUtils_checkIntTuple(PyObject* arg); +std::vector THPUtils_unpackIntTuple(PyObject* arg); + +TORCH_PYTHON_API void THPUtils_addPyMethodDefs( + std::vector& vector, + const PyMethodDef* methods); + +int THPUtils_getCallable(PyObject* arg, PyObject** result); + +typedef THPPointer THPGeneratorPtr; +typedef class THPPointer THPStoragePtr; + +TORCH_PYTHON_API std::vector THPUtils_unpackLongs(PyObject* arg); +PyObject* THPUtils_dispatchStateless( + PyObject* tensor, + const char* name, + PyObject* args, + PyObject* kwargs); + +template +struct mod_traits {}; + +template +struct mod_traits<_real, std::enable_if_t>> { + static _real mod(_real a, _real b) { + return fmod(a, b); + } +}; + +template +struct mod_traits<_real, std::enable_if_t>> { + static _real mod(_real a, _real b) { + return a % b; + } +}; + +void setBackCompatBroadcastWarn(bool warn); +bool getBackCompatBroadcastWarn(); + +void setBackCompatKeepdimWarn(bool warn); +bool getBackCompatKeepdimWarn(); +bool maybeThrowBackCompatKeepdimWarn(char* func); + +void storage_fill(const at::Storage& self, uint8_t value); +void storage_set(const at::Storage& self, ptrdiff_t idx, uint8_t value); +uint8_t storage_get(const at::Storage& self, ptrdiff_t idx); + +std::string uuid_to_string(const char* uuid_bytes); + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/byte_order.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/byte_order.h new file mode 100644 index 0000000000000000000000000000000000000000..74ce8c0dadbe4e7baa6f9237520edce5921cb19c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/byte_order.h @@ -0,0 +1,86 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __FreeBSD__ +#include +#include +#define thp_bswap16(x) bswap16(x) +#define thp_bswap32(x) bswap32(x) +#define thp_bswap64(x) bswap64(x) +#elif defined(__APPLE__) +#include +#define thp_bswap16(x) OSSwapInt16(x) +#define thp_bswap32(x) OSSwapInt32(x) +#define thp_bswap64(x) OSSwapInt64(x) +#elif defined(__GNUC__) && !defined(__MINGW32__) +#include +#define thp_bswap16(x) bswap_16(x) +#define thp_bswap32(x) bswap_32(x) +#define thp_bswap64(x) bswap_64(x) +#elif defined _WIN32 || defined _WIN64 +#define thp_bswap16(x) _byteswap_ushort(x) +#define thp_bswap32(x) _byteswap_ulong(x) +#define thp_bswap64(x) _byteswap_uint64(x) +#endif + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define to_be16(x) thp_bswap16(x) +#define from_be16(x) thp_bswap16(x) +#define to_be32(x) thp_bswap32(x) +#define from_be32(x) thp_bswap32(x) +#define to_be64(x) thp_bswap64(x) +#define from_be64(x) thp_bswap64(x) +#define to_le16(x) (x) +#define from_le16(x) (x) +#define to_le32(x) (x) +#define from_le32(x) (x) +#define to_le64(x) (x) +#define from_le64(x) (x) +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define to_be16(x) (x) +#define from_be16(x) (x) +#define to_be32(x) (x) +#define from_be32(x) (x) +#define to_be64(x) (x) +#define from_be64(x) (x) +#define to_le16(x) thp_bswap16(x) +#define from_le16(x) thp_bswap16(x) +#define to_le32(x) thp_bswap32(x) +#define from_le32(x) thp_bswap32(x) +#define to_le64(x) thp_bswap64(x) +#define from_le64(x) thp_bswap64(x) +#else +#error Unexpected or undefined __BYTE_ORDER__ +#endif + +namespace torch::utils { + +enum THPByteOrder { THP_LITTLE_ENDIAN = 0, THP_BIG_ENDIAN = 1 }; + +TORCH_API THPByteOrder THP_nativeByteOrder(); + +template +TORCH_API void THP_decodeBuffer(T* dst, const uint8_t* src, U type, size_t len); + +template +TORCH_API void THP_encodeBuffer( + uint8_t* dst, + const T* src, + THPByteOrder order, + size_t len); + +} // namespace torch::utils + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/cpp_stacktraces.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/cpp_stacktraces.h new file mode 100644 index 0000000000000000000000000000000000000000..2e24da7a55d82a86777253263813ff58b1264ed6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/cpp_stacktraces.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch { +TORCH_API bool get_cpp_stacktraces_enabled(); +TORCH_API torch::unwind::Mode get_symbolize_mode(); +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/cuda_enabled.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/cuda_enabled.h new file mode 100644 index 0000000000000000000000000000000000000000..7704171f7c8e889a2680ef2815f1b2b0c04c7d92 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/cuda_enabled.h @@ -0,0 +1,18 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +namespace torch::utils { + +inline constexpr bool cuda_enabled() { +#ifdef USE_CUDA + return true; +#else + return false; +#endif +} + +} // namespace torch::utils + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/device_lazy_init.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/device_lazy_init.h new file mode 100644 index 0000000000000000000000000000000000000000..0f48437820daeb566418292c1de24c21b3f136b1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/device_lazy_init.h @@ -0,0 +1,92 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +// device_lazy_init() is always compiled, even for CPU-only builds. + +namespace torch::utils { + +/** + * This mechanism of lazy initialization is designed for each device backend. + * Currently, CUDA and XPU follow this design. This function `device_lazy_init` + * MUST be called before you attempt to access any Type(CUDA or XPU) object + * from ATen, in any way. It guarantees that the device runtime status is lazily + * initialized when the first runtime API is requested. + * + * Here are some common ways that a device object may be retrieved: + * - You call getNonVariableType or getNonVariableTypeOpt + * - You call toBackend() on a Type + * + * It's important to do this correctly, because if you forget to add it you'll + * get an oblique error message seems like "Cannot initialize CUDA without + * ATen_cuda library" or "Cannot initialize XPU without ATen_xpu library" if you + * try to use CUDA or XPU functionality from a CPU-only build, which is not good + * UX. + */ +TORCH_PYTHON_API void device_lazy_init(at::DeviceType device_type); +TORCH_PYTHON_API void set_requires_device_init( + at::DeviceType device_type, + bool value); + +inline bool is_device_lazy_init_supported(at::DeviceType device_type) { + // Add more devices here to enable lazy initialization. + return ( + device_type == at::DeviceType::CUDA || + device_type == at::DeviceType::XPU || + device_type == at::DeviceType::HPU || + device_type == at::DeviceType::MTIA || + device_type == at::DeviceType::PrivateUse1); +} + +inline void maybe_initialize_device(at::Device& device) { + if (is_device_lazy_init_supported(device.type())) { + device_lazy_init(device.type()); + } +} + +inline void maybe_initialize_device(std::optional& device) { + if (!device.has_value()) { + return; + } + maybe_initialize_device(device.value()); +} + +inline void maybe_initialize_device(const at::TensorOptions& options) { + auto device = options.device(); + maybe_initialize_device(device); +} + +inline void maybe_initialize_device( + std::optional& device_type) { + if (!device_type.has_value()) { + return; + } + maybe_initialize_device(device_type.value()); +} + +bool is_device_initialized(at::DeviceType device_type); + +TORCH_PYTHON_API bool is_device_in_bad_fork(at::DeviceType device_type); + +TORCH_PYTHON_API void set_device_in_bad_fork( + at::DeviceType device_type, + bool value); + +TORCH_PYTHON_API void register_fork_handler_for_device_init( + at::DeviceType device_type); + +inline void maybe_register_fork_handler_for_device_init( + std::optional& device_type) { + if (!device_type.has_value()) { + return; + } + register_fork_handler_for_device_init(device_type.value()); +} + +} // namespace torch::utils + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/disable_torch_function.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/disable_torch_function.h new file mode 100644 index 0000000000000000000000000000000000000000..694a47e8fd6cf4af36aa1e749a26979eee1799c8 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/disable_torch_function.h @@ -0,0 +1,52 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include +#include +#include + +namespace torch { +// Sometimes we don't want infinite recursion for subclasses, +// Or a way to achieve the old behaviour. + +// This is an internal utility, not exposed to users. +bool torch_function_enabled(); +PyObject* disabled_torch_function_impl(); +PyObject* disabled_torch_dispatch_impl(); +void set_disabled_torch_function_impl(PyObject* value); +void set_disabled_torch_dispatch_impl(PyObject* value); +// Set ignore_mode to true if you're trying to collect overloaded arguments; +// using mode here will improperly cause you to add ALL objects to the +// overloaded list even if they don't actually have __torch_function__ +bool check_has_torch_function(PyObject* obj, bool ignore_mode = false); + +struct DisableTorchDispatch { + DisableTorchDispatch() + : guard_(c10::DispatchKeySet( + {c10::DispatchKey::Python, c10::DispatchKey::PreDispatch})), + guard_tls_snapshot_(c10::DispatchKey::PythonTLSSnapshot) {} + c10::impl::ExcludeDispatchKeyGuard guard_; + c10::impl::ExcludeDispatchKeyGuard guard_tls_snapshot_; +}; + +} // namespace torch + +PyObject* THPModule_isEnabledTorchFunction(PyObject* self, PyObject* unused); +PyObject* THPModule_isAllDisabledTorchFunction( + PyObject* self, + PyObject* unused); +PyObject* THPModule_DisableTorchFunctionType(); +PyObject* THPModule_DisableTorchFunctionSubclassType(); +PyObject* THPModule_disable_torch_function(PyObject* self, PyObject* args); +PyObject* THPModule_disable_torch_dispatch(PyObject* self, PyObject* args); +PyObject* THPModule_has_torch_function(PyObject* /*unused*/, PyObject* arg); +PyObject* THPModule_has_torch_function_unary( + PyObject* /*unused*/, + PyObject* obj); +PyObject* THPModule_has_torch_function_variadic( + PyObject* /*unused*/, + PyObject* const* args, + Py_ssize_t nargs); + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/generated_serialization_types.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/generated_serialization_types.h new file mode 100644 index 0000000000000000000000000000000000000000..55d7be4cba1b71babfa500055577852a1a64a32a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/generated_serialization_types.h @@ -0,0 +1,3937 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// @generated by update_schema.py +// checksum<> +// clang-format off + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN namespace nlohmann { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END } +#endif + +// https://github.com/nlohmann/json/pull/2117 +NLOHMANN_JSON_NAMESPACE_BEGIN +template +struct adl_serializer> { + static void to_json(json& j, const std::optional& opt) { + if (opt == std::nullopt) { + j = nullptr; + } else { + j = *opt; // this will call adl_serializer::to_json which will + // find the free function to_json in T's namespace! + } + } + + static void from_json(const json& j, std::optional& opt) { + if (j.is_null()) { + opt = std::nullopt; + } else { + opt = j.template get(); // same as above, but with + // adl_serializer::from_json + } + } +}; +NLOHMANN_JSON_NAMESPACE_END + +namespace torch { +namespace _export { + +template +class ForwardRef { + static_assert(!std::is_reference_v, "ForwardRef cannot be a reference type"); + + public: + ForwardRef(): ptr_(std::make_unique()) {} + ForwardRef(ForwardRef&&); + ForwardRef(const ForwardRef& other): ptr_(std::make_unique(*other.ptr_)) {} + ForwardRef& operator=(ForwardRef&&); + ForwardRef& operator=(const ForwardRef& other) { + ptr_ = std::make_unique(*other.ptr_); + return *this; + } + ~ForwardRef(); + const T& operator*() const { + return *ptr_; + } + + const T* operator->() const { + return ptr_.get(); + } + + void emplace(T&& t) { + ptr_ = std::make_unique(std::move(t)); + } + + private: + std::unique_ptr ptr_; +}; + +template +void to_json(nlohmann::json& j, const ForwardRef& p) { + j = *p; +} + +template +void from_json(const nlohmann::json& j, ForwardRef& p) { + p.emplace(j.template get()); +} + +class F64 { + public: + double get() const { + return value_; + } + + void set(double value) { + value_ = value; + } + + private: + double value_; +}; + +inline void to_json(nlohmann::json& j, const F64& f) { + if (std::isinf(f.get())) { + j = "Infinity"; + } else if (std::isinf(-f.get())) { + j = "-Infinity"; + } else if (std::isnan(f.get())) { + j = "NaN"; + } else { + j = f.get(); + } +} + +inline void from_json(const nlohmann::json& j, F64& f) { + if (j == "Infinity") { + f.set(std::numeric_limits::infinity()); + } else if (j == "-Infinity") { + f.set(-std::numeric_limits::infinity()); + } else if (j == "NaN") { + f.set(std::numeric_limits::quiet_NaN()); + } else { + f.set(j.get()); + } +} + +class AOTInductorModelPickleData; +class Argument; +class BufferMutationSpec; +class ComplexValue; +class ConstantValue; +class CustomObjArgument; +class Device; +class ExportedProgram; +class ExternKernelNode; +class ExternKernelNodes; +class GradientToParameterSpec; +class GradientToUserInputSpec; +class Graph; +class GraphArgument; +class GraphModule; +class GraphSignature; +class InputSpec; +class InputToBufferSpec; +class InputToConstantInputSpec; +class InputToCustomObjSpec; +class InputToParameterSpec; +class InputToTensorConstantSpec; +class InputTokenSpec; +class LossOutputSpec; +class ModuleCallEntry; +class ModuleCallSignature; +class NamedArgument; +class NamedTupleDef; +class Node; +class OptionalTensorArgument; +class OutputSpec; +class OutputTokenSpec; +class ParameterMutationSpec; +class PayloadConfig; +class PayloadMeta; +class RangeConstraint; +class SchemaVersion; +class SymBool; +class SymBoolArgument; +class SymExpr; +class SymExprHint; +class SymFloat; +class SymFloatArgument; +class SymInt; +class SymIntArgument; +class TensorArgument; +class TensorMeta; +class TokenArgument; +class UserInputMutationSpec; +class UserInputSpec; +class UserOutputSpec; + +enum class ArgumentKind { + UNKNOWN = 0, + POSITIONAL = 1, + KEYWORD = 2, +}; + +inline std::string_view printEnum(const ArgumentKind& e) { + switch (e) { + case ArgumentKind::UNKNOWN: return "UNKNOWN"; + case ArgumentKind::POSITIONAL: return "POSITIONAL"; + case ArgumentKind::KEYWORD: return "KEYWORD"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, ArgumentKind& t) { + if (s == "UNKNOWN") { t = ArgumentKind::UNKNOWN; return; } + if (s == "POSITIONAL") { t = ArgumentKind::POSITIONAL; return; } + if (s == "KEYWORD") { t = ArgumentKind::KEYWORD; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + +enum class Layout { + Unknown = 0, + SparseCoo = 1, + SparseCsr = 2, + SparseCsc = 3, + SparseBsr = 4, + SparseBsc = 5, + _mkldnn = 6, + Strided = 7, +}; + +inline std::string_view printEnum(const Layout& e) { + switch (e) { + case Layout::Unknown: return "Unknown"; + case Layout::SparseCoo: return "SparseCoo"; + case Layout::SparseCsr: return "SparseCsr"; + case Layout::SparseCsc: return "SparseCsc"; + case Layout::SparseBsr: return "SparseBsr"; + case Layout::SparseBsc: return "SparseBsc"; + case Layout::_mkldnn: return "_mkldnn"; + case Layout::Strided: return "Strided"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, Layout& t) { + if (s == "Unknown") { t = Layout::Unknown; return; } + if (s == "SparseCoo") { t = Layout::SparseCoo; return; } + if (s == "SparseCsr") { t = Layout::SparseCsr; return; } + if (s == "SparseCsc") { t = Layout::SparseCsc; return; } + if (s == "SparseBsr") { t = Layout::SparseBsr; return; } + if (s == "SparseBsc") { t = Layout::SparseBsc; return; } + if (s == "_mkldnn") { t = Layout::_mkldnn; return; } + if (s == "Strided") { t = Layout::Strided; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + +enum class MemoryFormat { + Unknown = 0, + ContiguousFormat = 1, + ChannelsLast = 2, + ChannelsLast3d = 3, + PreserveFormat = 4, +}; + +inline std::string_view printEnum(const MemoryFormat& e) { + switch (e) { + case MemoryFormat::Unknown: return "Unknown"; + case MemoryFormat::ContiguousFormat: return "ContiguousFormat"; + case MemoryFormat::ChannelsLast: return "ChannelsLast"; + case MemoryFormat::ChannelsLast3d: return "ChannelsLast3d"; + case MemoryFormat::PreserveFormat: return "PreserveFormat"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, MemoryFormat& t) { + if (s == "Unknown") { t = MemoryFormat::Unknown; return; } + if (s == "ContiguousFormat") { t = MemoryFormat::ContiguousFormat; return; } + if (s == "ChannelsLast") { t = MemoryFormat::ChannelsLast; return; } + if (s == "ChannelsLast3d") { t = MemoryFormat::ChannelsLast3d; return; } + if (s == "PreserveFormat") { t = MemoryFormat::PreserveFormat; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + +enum class ScalarType { + UNKNOWN = 0, + BYTE = 1, + CHAR = 2, + SHORT = 3, + INT = 4, + LONG = 5, + HALF = 6, + FLOAT = 7, + DOUBLE = 8, + COMPLEXHALF = 9, + COMPLEXFLOAT = 10, + COMPLEXDOUBLE = 11, + BOOL = 12, + BFLOAT16 = 13, + UINT16 = 28, + FLOAT8E4M3FN = 29, + FLOAT8E5M2 = 30, + FLOAT8E4M3FNUZ = 31, + FLOAT8E5M2FNUZ = 32, + FLOAT8E8M0FNU = 33, + UINT32 = 34, + UINT64 = 35, +}; + +inline std::string_view printEnum(const ScalarType& e) { + switch (e) { + case ScalarType::UNKNOWN: return "UNKNOWN"; + case ScalarType::BYTE: return "BYTE"; + case ScalarType::CHAR: return "CHAR"; + case ScalarType::SHORT: return "SHORT"; + case ScalarType::INT: return "INT"; + case ScalarType::LONG: return "LONG"; + case ScalarType::HALF: return "HALF"; + case ScalarType::FLOAT: return "FLOAT"; + case ScalarType::DOUBLE: return "DOUBLE"; + case ScalarType::COMPLEXHALF: return "COMPLEXHALF"; + case ScalarType::COMPLEXFLOAT: return "COMPLEXFLOAT"; + case ScalarType::COMPLEXDOUBLE: return "COMPLEXDOUBLE"; + case ScalarType::BOOL: return "BOOL"; + case ScalarType::BFLOAT16: return "BFLOAT16"; + case ScalarType::UINT16: return "UINT16"; + case ScalarType::FLOAT8E4M3FN: return "FLOAT8E4M3FN"; + case ScalarType::FLOAT8E5M2: return "FLOAT8E5M2"; + case ScalarType::FLOAT8E4M3FNUZ: return "FLOAT8E4M3FNUZ"; + case ScalarType::FLOAT8E5M2FNUZ: return "FLOAT8E5M2FNUZ"; + case ScalarType::FLOAT8E8M0FNU: return "FLOAT8E8M0FNU"; + case ScalarType::UINT32: return "UINT32"; + case ScalarType::UINT64: return "UINT64"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, ScalarType& t) { + if (s == "UNKNOWN") { t = ScalarType::UNKNOWN; return; } + if (s == "BYTE") { t = ScalarType::BYTE; return; } + if (s == "CHAR") { t = ScalarType::CHAR; return; } + if (s == "SHORT") { t = ScalarType::SHORT; return; } + if (s == "INT") { t = ScalarType::INT; return; } + if (s == "LONG") { t = ScalarType::LONG; return; } + if (s == "HALF") { t = ScalarType::HALF; return; } + if (s == "FLOAT") { t = ScalarType::FLOAT; return; } + if (s == "DOUBLE") { t = ScalarType::DOUBLE; return; } + if (s == "COMPLEXHALF") { t = ScalarType::COMPLEXHALF; return; } + if (s == "COMPLEXFLOAT") { t = ScalarType::COMPLEXFLOAT; return; } + if (s == "COMPLEXDOUBLE") { t = ScalarType::COMPLEXDOUBLE; return; } + if (s == "BOOL") { t = ScalarType::BOOL; return; } + if (s == "BFLOAT16") { t = ScalarType::BFLOAT16; return; } + if (s == "UINT16") { t = ScalarType::UINT16; return; } + if (s == "FLOAT8E4M3FN") { t = ScalarType::FLOAT8E4M3FN; return; } + if (s == "FLOAT8E5M2") { t = ScalarType::FLOAT8E5M2; return; } + if (s == "FLOAT8E4M3FNUZ") { t = ScalarType::FLOAT8E4M3FNUZ; return; } + if (s == "FLOAT8E5M2FNUZ") { t = ScalarType::FLOAT8E5M2FNUZ; return; } + if (s == "FLOAT8E8M0FNU") { t = ScalarType::FLOAT8E8M0FNU; return; } + if (s == "UINT32") { t = ScalarType::UINT32; return; } + if (s == "UINT64") { t = ScalarType::UINT64; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + + +class Device { + private: + std::string type; + std::optional index = std::nullopt; + + public: + + const std::string& get_type() const { + return type; + } + + void set_type(std::string def) { + type = std::move(def); + } + + const std::optional& get_index() const { + return index; + } + + void set_index(std::optional def) { + index = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const Device& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, Device& nlohmann_json_t); +}; + +class SymExprHint { + struct Void {}; + + public: + enum class Tag { + AS_INT, AS_BOOL, AS_FLOAT + }; + + private: + std::variant variant_; + Tag tag_; + + public: + Tag tag() const { + return tag_; + } + + const int64_t& get_as_int() const { + return std::get<1>(variant_); + } + + void set_as_int(int64_t def) { + variant_.emplace<1>(std::move(def)); + tag_ = Tag::AS_INT; + } + + const bool& get_as_bool() const { + return std::get<2>(variant_); + } + + void set_as_bool(bool def) { + variant_.emplace<2>(std::move(def)); + tag_ = Tag::AS_BOOL; + } + + const F64& get_as_float() const { + return std::get<3>(variant_); + } + + void set_as_float(F64 def) { + variant_.emplace<3>(std::move(def)); + tag_ = Tag::AS_FLOAT; + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const SymExprHint& nlohmann_json_t) { + + if (nlohmann_json_t.tag_ == Tag::AS_INT) { + nlohmann_json_j["as_int"] = nlohmann_json_t.get_as_int(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_BOOL) { + nlohmann_json_j["as_bool"] = nlohmann_json_t.get_as_bool(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_FLOAT) { + nlohmann_json_j["as_float"] = nlohmann_json_t.get_as_float(); + return; + } + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, SymExprHint& nlohmann_json_t) { + + if (nlohmann_json_j.contains("as_int")) { + nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_int").template get()); + nlohmann_json_t.tag_ = Tag::AS_INT; + return; + } + if (nlohmann_json_j.contains("as_bool")) { + nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_bool").template get()); + nlohmann_json_t.tag_ = Tag::AS_BOOL; + return; + } + if (nlohmann_json_j.contains("as_float")) { + nlohmann_json_t.variant_.emplace<3>(nlohmann_json_j.at("as_float").template get()); + nlohmann_json_t.tag_ = Tag::AS_FLOAT; + return; + } + } +}; + +inline std::string_view printEnum(const SymExprHint::Tag& e) { + switch (e) { + case SymExprHint::Tag::AS_INT: return "AS_INT"; + case SymExprHint::Tag::AS_BOOL: return "AS_BOOL"; + case SymExprHint::Tag::AS_FLOAT: return "AS_FLOAT"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, SymExprHint::Tag& t) { + if (s == "AS_INT") { t = SymExprHint::Tag::AS_INT; return; } + if (s == "AS_BOOL") { t = SymExprHint::Tag::AS_BOOL; return; } + if (s == "AS_FLOAT") { t = SymExprHint::Tag::AS_FLOAT; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + + +class SymExpr { + private: + std::string expr_str; + std::optional hint = std::nullopt; + + public: + + const std::string& get_expr_str() const { + return expr_str; + } + + void set_expr_str(std::string def) { + expr_str = std::move(def); + } + + const std::optional& get_hint() const { + return hint; + } + + void set_hint(std::optional def) { + hint = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const SymExpr& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, SymExpr& nlohmann_json_t); +}; + +class SymInt { + struct Void {}; + + public: + enum class Tag { + AS_EXPR, AS_INT + }; + + private: + std::variant variant_; + Tag tag_; + + public: + Tag tag() const { + return tag_; + } + + const SymExpr& get_as_expr() const { + return std::get<1>(variant_); + } + + void set_as_expr(SymExpr def) { + variant_.emplace<1>(std::move(def)); + tag_ = Tag::AS_EXPR; + } + + const int64_t& get_as_int() const { + return std::get<2>(variant_); + } + + void set_as_int(int64_t def) { + variant_.emplace<2>(std::move(def)); + tag_ = Tag::AS_INT; + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const SymInt& nlohmann_json_t) { + + if (nlohmann_json_t.tag_ == Tag::AS_EXPR) { + nlohmann_json_j["as_expr"] = nlohmann_json_t.get_as_expr(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_INT) { + nlohmann_json_j["as_int"] = nlohmann_json_t.get_as_int(); + return; + } + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, SymInt& nlohmann_json_t) { + + if (nlohmann_json_j.contains("as_expr")) { + nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_expr").template get()); + nlohmann_json_t.tag_ = Tag::AS_EXPR; + return; + } + if (nlohmann_json_j.contains("as_int")) { + nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_int").template get()); + nlohmann_json_t.tag_ = Tag::AS_INT; + return; + } + } +}; + +inline std::string_view printEnum(const SymInt::Tag& e) { + switch (e) { + case SymInt::Tag::AS_EXPR: return "AS_EXPR"; + case SymInt::Tag::AS_INT: return "AS_INT"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, SymInt::Tag& t) { + if (s == "AS_EXPR") { t = SymInt::Tag::AS_EXPR; return; } + if (s == "AS_INT") { t = SymInt::Tag::AS_INT; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + + +class SymFloat { + struct Void {}; + + public: + enum class Tag { + AS_EXPR, AS_FLOAT + }; + + private: + std::variant variant_; + Tag tag_; + + public: + Tag tag() const { + return tag_; + } + + const SymExpr& get_as_expr() const { + return std::get<1>(variant_); + } + + void set_as_expr(SymExpr def) { + variant_.emplace<1>(std::move(def)); + tag_ = Tag::AS_EXPR; + } + + const F64& get_as_float() const { + return std::get<2>(variant_); + } + + void set_as_float(F64 def) { + variant_.emplace<2>(std::move(def)); + tag_ = Tag::AS_FLOAT; + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const SymFloat& nlohmann_json_t) { + + if (nlohmann_json_t.tag_ == Tag::AS_EXPR) { + nlohmann_json_j["as_expr"] = nlohmann_json_t.get_as_expr(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_FLOAT) { + nlohmann_json_j["as_float"] = nlohmann_json_t.get_as_float(); + return; + } + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, SymFloat& nlohmann_json_t) { + + if (nlohmann_json_j.contains("as_expr")) { + nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_expr").template get()); + nlohmann_json_t.tag_ = Tag::AS_EXPR; + return; + } + if (nlohmann_json_j.contains("as_float")) { + nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_float").template get()); + nlohmann_json_t.tag_ = Tag::AS_FLOAT; + return; + } + } +}; + +inline std::string_view printEnum(const SymFloat::Tag& e) { + switch (e) { + case SymFloat::Tag::AS_EXPR: return "AS_EXPR"; + case SymFloat::Tag::AS_FLOAT: return "AS_FLOAT"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, SymFloat::Tag& t) { + if (s == "AS_EXPR") { t = SymFloat::Tag::AS_EXPR; return; } + if (s == "AS_FLOAT") { t = SymFloat::Tag::AS_FLOAT; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + + +class SymBool { + struct Void {}; + + public: + enum class Tag { + AS_EXPR, AS_BOOL + }; + + private: + std::variant variant_; + Tag tag_; + + public: + Tag tag() const { + return tag_; + } + + const SymExpr& get_as_expr() const { + return std::get<1>(variant_); + } + + void set_as_expr(SymExpr def) { + variant_.emplace<1>(std::move(def)); + tag_ = Tag::AS_EXPR; + } + + const bool& get_as_bool() const { + return std::get<2>(variant_); + } + + void set_as_bool(bool def) { + variant_.emplace<2>(std::move(def)); + tag_ = Tag::AS_BOOL; + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const SymBool& nlohmann_json_t) { + + if (nlohmann_json_t.tag_ == Tag::AS_EXPR) { + nlohmann_json_j["as_expr"] = nlohmann_json_t.get_as_expr(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_BOOL) { + nlohmann_json_j["as_bool"] = nlohmann_json_t.get_as_bool(); + return; + } + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, SymBool& nlohmann_json_t) { + + if (nlohmann_json_j.contains("as_expr")) { + nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_expr").template get()); + nlohmann_json_t.tag_ = Tag::AS_EXPR; + return; + } + if (nlohmann_json_j.contains("as_bool")) { + nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_bool").template get()); + nlohmann_json_t.tag_ = Tag::AS_BOOL; + return; + } + } +}; + +inline std::string_view printEnum(const SymBool::Tag& e) { + switch (e) { + case SymBool::Tag::AS_EXPR: return "AS_EXPR"; + case SymBool::Tag::AS_BOOL: return "AS_BOOL"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, SymBool::Tag& t) { + if (s == "AS_EXPR") { t = SymBool::Tag::AS_EXPR; return; } + if (s == "AS_BOOL") { t = SymBool::Tag::AS_BOOL; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + + +class TensorMeta { + private: + int64_t dtype; + std::vector sizes; + bool requires_grad; + Device device; + std::vector strides; + SymInt storage_offset; + int64_t layout; + + public: + + ScalarType get_dtype() const { + return static_cast(dtype); + } + + void set_dtype(ScalarType def) { + dtype = static_cast(def); + } + + const std::vector& get_sizes() const { + return sizes; + } + + void set_sizes(std::vector def) { + sizes = std::move(def); + } + + const bool& get_requires_grad() const { + return requires_grad; + } + + void set_requires_grad(bool def) { + requires_grad = std::move(def); + } + + const Device& get_device() const { + return device; + } + + void set_device(Device def) { + device = std::move(def); + } + + const std::vector& get_strides() const { + return strides; + } + + void set_strides(std::vector def) { + strides = std::move(def); + } + + const SymInt& get_storage_offset() const { + return storage_offset; + } + + void set_storage_offset(SymInt def) { + storage_offset = std::move(def); + } + + Layout get_layout() const { + return static_cast(layout); + } + + void set_layout(Layout def) { + layout = static_cast(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const TensorMeta& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, TensorMeta& nlohmann_json_t); +}; + +class SymIntArgument { + struct Void {}; + + public: + enum class Tag { + AS_NAME, AS_INT + }; + + private: + std::variant variant_; + Tag tag_; + + public: + Tag tag() const { + return tag_; + } + + const std::string& get_as_name() const { + return std::get<1>(variant_); + } + + void set_as_name(std::string def) { + variant_.emplace<1>(std::move(def)); + tag_ = Tag::AS_NAME; + } + + const int64_t& get_as_int() const { + return std::get<2>(variant_); + } + + void set_as_int(int64_t def) { + variant_.emplace<2>(std::move(def)); + tag_ = Tag::AS_INT; + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const SymIntArgument& nlohmann_json_t) { + + if (nlohmann_json_t.tag_ == Tag::AS_NAME) { + nlohmann_json_j["as_name"] = nlohmann_json_t.get_as_name(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_INT) { + nlohmann_json_j["as_int"] = nlohmann_json_t.get_as_int(); + return; + } + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, SymIntArgument& nlohmann_json_t) { + + if (nlohmann_json_j.contains("as_name")) { + nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_name").template get()); + nlohmann_json_t.tag_ = Tag::AS_NAME; + return; + } + if (nlohmann_json_j.contains("as_int")) { + nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_int").template get()); + nlohmann_json_t.tag_ = Tag::AS_INT; + return; + } + } +}; + +inline std::string_view printEnum(const SymIntArgument::Tag& e) { + switch (e) { + case SymIntArgument::Tag::AS_NAME: return "AS_NAME"; + case SymIntArgument::Tag::AS_INT: return "AS_INT"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, SymIntArgument::Tag& t) { + if (s == "AS_NAME") { t = SymIntArgument::Tag::AS_NAME; return; } + if (s == "AS_INT") { t = SymIntArgument::Tag::AS_INT; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + + +class SymFloatArgument { + struct Void {}; + + public: + enum class Tag { + AS_NAME, AS_FLOAT + }; + + private: + std::variant variant_; + Tag tag_; + + public: + Tag tag() const { + return tag_; + } + + const std::string& get_as_name() const { + return std::get<1>(variant_); + } + + void set_as_name(std::string def) { + variant_.emplace<1>(std::move(def)); + tag_ = Tag::AS_NAME; + } + + const F64& get_as_float() const { + return std::get<2>(variant_); + } + + void set_as_float(F64 def) { + variant_.emplace<2>(std::move(def)); + tag_ = Tag::AS_FLOAT; + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const SymFloatArgument& nlohmann_json_t) { + + if (nlohmann_json_t.tag_ == Tag::AS_NAME) { + nlohmann_json_j["as_name"] = nlohmann_json_t.get_as_name(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_FLOAT) { + nlohmann_json_j["as_float"] = nlohmann_json_t.get_as_float(); + return; + } + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, SymFloatArgument& nlohmann_json_t) { + + if (nlohmann_json_j.contains("as_name")) { + nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_name").template get()); + nlohmann_json_t.tag_ = Tag::AS_NAME; + return; + } + if (nlohmann_json_j.contains("as_float")) { + nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_float").template get()); + nlohmann_json_t.tag_ = Tag::AS_FLOAT; + return; + } + } +}; + +inline std::string_view printEnum(const SymFloatArgument::Tag& e) { + switch (e) { + case SymFloatArgument::Tag::AS_NAME: return "AS_NAME"; + case SymFloatArgument::Tag::AS_FLOAT: return "AS_FLOAT"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, SymFloatArgument::Tag& t) { + if (s == "AS_NAME") { t = SymFloatArgument::Tag::AS_NAME; return; } + if (s == "AS_FLOAT") { t = SymFloatArgument::Tag::AS_FLOAT; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + + +class SymBoolArgument { + struct Void {}; + + public: + enum class Tag { + AS_NAME, AS_BOOL + }; + + private: + std::variant variant_; + Tag tag_; + + public: + Tag tag() const { + return tag_; + } + + const std::string& get_as_name() const { + return std::get<1>(variant_); + } + + void set_as_name(std::string def) { + variant_.emplace<1>(std::move(def)); + tag_ = Tag::AS_NAME; + } + + const bool& get_as_bool() const { + return std::get<2>(variant_); + } + + void set_as_bool(bool def) { + variant_.emplace<2>(std::move(def)); + tag_ = Tag::AS_BOOL; + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const SymBoolArgument& nlohmann_json_t) { + + if (nlohmann_json_t.tag_ == Tag::AS_NAME) { + nlohmann_json_j["as_name"] = nlohmann_json_t.get_as_name(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_BOOL) { + nlohmann_json_j["as_bool"] = nlohmann_json_t.get_as_bool(); + return; + } + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, SymBoolArgument& nlohmann_json_t) { + + if (nlohmann_json_j.contains("as_name")) { + nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_name").template get()); + nlohmann_json_t.tag_ = Tag::AS_NAME; + return; + } + if (nlohmann_json_j.contains("as_bool")) { + nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_bool").template get()); + nlohmann_json_t.tag_ = Tag::AS_BOOL; + return; + } + } +}; + +inline std::string_view printEnum(const SymBoolArgument::Tag& e) { + switch (e) { + case SymBoolArgument::Tag::AS_NAME: return "AS_NAME"; + case SymBoolArgument::Tag::AS_BOOL: return "AS_BOOL"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, SymBoolArgument::Tag& t) { + if (s == "AS_NAME") { t = SymBoolArgument::Tag::AS_NAME; return; } + if (s == "AS_BOOL") { t = SymBoolArgument::Tag::AS_BOOL; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + + +class TensorArgument { + private: + std::string name; + + public: + + const std::string& get_name() const { + return name; + } + + void set_name(std::string def) { + name = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const TensorArgument& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, TensorArgument& nlohmann_json_t); +}; + +class TokenArgument { + private: + std::string name; + + public: + + const std::string& get_name() const { + return name; + } + + void set_name(std::string def) { + name = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const TokenArgument& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, TokenArgument& nlohmann_json_t); +}; + +class OptionalTensorArgument { + struct Void {}; + + public: + enum class Tag { + AS_TENSOR, AS_NONE + }; + + private: + std::variant variant_; + Tag tag_; + + public: + Tag tag() const { + return tag_; + } + + const TensorArgument& get_as_tensor() const { + return std::get<1>(variant_); + } + + void set_as_tensor(TensorArgument def) { + variant_.emplace<1>(std::move(def)); + tag_ = Tag::AS_TENSOR; + } + + const bool& get_as_none() const { + return std::get<2>(variant_); + } + + void set_as_none(bool def) { + variant_.emplace<2>(std::move(def)); + tag_ = Tag::AS_NONE; + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const OptionalTensorArgument& nlohmann_json_t) { + + if (nlohmann_json_t.tag_ == Tag::AS_TENSOR) { + nlohmann_json_j["as_tensor"] = nlohmann_json_t.get_as_tensor(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_NONE) { + nlohmann_json_j["as_none"] = nlohmann_json_t.get_as_none(); + return; + } + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, OptionalTensorArgument& nlohmann_json_t) { + + if (nlohmann_json_j.contains("as_tensor")) { + nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_tensor").template get()); + nlohmann_json_t.tag_ = Tag::AS_TENSOR; + return; + } + if (nlohmann_json_j.contains("as_none")) { + nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_none").template get()); + nlohmann_json_t.tag_ = Tag::AS_NONE; + return; + } + } +}; + +inline std::string_view printEnum(const OptionalTensorArgument::Tag& e) { + switch (e) { + case OptionalTensorArgument::Tag::AS_TENSOR: return "AS_TENSOR"; + case OptionalTensorArgument::Tag::AS_NONE: return "AS_NONE"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, OptionalTensorArgument::Tag& t) { + if (s == "AS_TENSOR") { t = OptionalTensorArgument::Tag::AS_TENSOR; return; } + if (s == "AS_NONE") { t = OptionalTensorArgument::Tag::AS_NONE; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + + +class GraphArgument { + private: + std::string name; + ForwardRef graph; + + public: + + const std::string& get_name() const { + return name; + } + + void set_name(std::string def) { + name = std::move(def); + } + + const ForwardRef& get_graph() const { + return graph; + } + + void set_graph(ForwardRef def) { + graph = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const GraphArgument& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, GraphArgument& nlohmann_json_t); +}; + +class CustomObjArgument { + private: + std::string name; + std::string class_fqn; + + public: + + const std::string& get_name() const { + return name; + } + + void set_name(std::string def) { + name = std::move(def); + } + + const std::string& get_class_fqn() const { + return class_fqn; + } + + void set_class_fqn(std::string def) { + class_fqn = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const CustomObjArgument& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, CustomObjArgument& nlohmann_json_t); +}; + +class ComplexValue { + private: + F64 real; + F64 imag; + + public: + + const F64& get_real() const { + return real; + } + + void set_real(F64 def) { + real = std::move(def); + } + + const F64& get_imag() const { + return imag; + } + + void set_imag(F64 def) { + imag = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const ComplexValue& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, ComplexValue& nlohmann_json_t); +}; + +class Argument { + struct Void {}; + + public: + enum class Tag { + AS_NONE, AS_TENSOR, AS_TENSORS, AS_INT, AS_INTS, AS_FLOAT, AS_FLOATS, AS_STRING, AS_STRINGS, AS_SYM_INT, AS_SYM_INTS, AS_SCALAR_TYPE, AS_MEMORY_FORMAT, AS_LAYOUT, AS_DEVICE, AS_BOOL, AS_BOOLS, AS_SYM_BOOL, AS_SYM_BOOLS, AS_GRAPH, AS_OPTIONAL_TENSORS, AS_CUSTOM_OBJ, AS_OPERATOR, AS_SYM_FLOAT, AS_SYM_FLOATS, AS_OPTIONAL_TENSOR, AS_COMPLEX, AS_NESTED_TENSORS, AS_INT_LISTS, AS_STRING_TO_ARGUMENT, AS_FLOAT_LISTS + }; + + private: + std::variant, int64_t, std::vector, F64, std::vector, std::string, std::vector, SymIntArgument, std::vector, ScalarType, MemoryFormat, Layout, Device, bool, std::vector, SymBoolArgument, std::vector, GraphArgument, std::vector, CustomObjArgument, std::string, SymFloatArgument, std::vector, OptionalTensorArgument, ComplexValue, std::vector>, std::vector>, std::unordered_map>, std::vector>> variant_; + Tag tag_; + + public: + Tag tag() const { + return tag_; + } + + const bool& get_as_none() const { + return std::get<1>(variant_); + } + + void set_as_none(bool def) { + variant_.emplace<1>(std::move(def)); + tag_ = Tag::AS_NONE; + } + + const TensorArgument& get_as_tensor() const { + return std::get<2>(variant_); + } + + void set_as_tensor(TensorArgument def) { + variant_.emplace<2>(std::move(def)); + tag_ = Tag::AS_TENSOR; + } + + const std::vector& get_as_tensors() const { + return std::get<3>(variant_); + } + + void set_as_tensors(std::vector def) { + variant_.emplace<3>(std::move(def)); + tag_ = Tag::AS_TENSORS; + } + + const int64_t& get_as_int() const { + return std::get<4>(variant_); + } + + void set_as_int(int64_t def) { + variant_.emplace<4>(std::move(def)); + tag_ = Tag::AS_INT; + } + + const std::vector& get_as_ints() const { + return std::get<5>(variant_); + } + + void set_as_ints(std::vector def) { + variant_.emplace<5>(std::move(def)); + tag_ = Tag::AS_INTS; + } + + const F64& get_as_float() const { + return std::get<6>(variant_); + } + + void set_as_float(F64 def) { + variant_.emplace<6>(std::move(def)); + tag_ = Tag::AS_FLOAT; + } + + const std::vector& get_as_floats() const { + return std::get<7>(variant_); + } + + void set_as_floats(std::vector def) { + variant_.emplace<7>(std::move(def)); + tag_ = Tag::AS_FLOATS; + } + + const std::string& get_as_string() const { + return std::get<8>(variant_); + } + + void set_as_string(std::string def) { + variant_.emplace<8>(std::move(def)); + tag_ = Tag::AS_STRING; + } + + const std::vector& get_as_strings() const { + return std::get<9>(variant_); + } + + void set_as_strings(std::vector def) { + variant_.emplace<9>(std::move(def)); + tag_ = Tag::AS_STRINGS; + } + + const SymIntArgument& get_as_sym_int() const { + return std::get<10>(variant_); + } + + void set_as_sym_int(SymIntArgument def) { + variant_.emplace<10>(std::move(def)); + tag_ = Tag::AS_SYM_INT; + } + + const std::vector& get_as_sym_ints() const { + return std::get<11>(variant_); + } + + void set_as_sym_ints(std::vector def) { + variant_.emplace<11>(std::move(def)); + tag_ = Tag::AS_SYM_INTS; + } + + const ScalarType& get_as_scalar_type() const { + return std::get<12>(variant_); + } + + void set_as_scalar_type(ScalarType def) { + variant_.emplace<12>(std::move(def)); + tag_ = Tag::AS_SCALAR_TYPE; + } + + const MemoryFormat& get_as_memory_format() const { + return std::get<13>(variant_); + } + + void set_as_memory_format(MemoryFormat def) { + variant_.emplace<13>(std::move(def)); + tag_ = Tag::AS_MEMORY_FORMAT; + } + + const Layout& get_as_layout() const { + return std::get<14>(variant_); + } + + void set_as_layout(Layout def) { + variant_.emplace<14>(std::move(def)); + tag_ = Tag::AS_LAYOUT; + } + + const Device& get_as_device() const { + return std::get<15>(variant_); + } + + void set_as_device(Device def) { + variant_.emplace<15>(std::move(def)); + tag_ = Tag::AS_DEVICE; + } + + const bool& get_as_bool() const { + return std::get<16>(variant_); + } + + void set_as_bool(bool def) { + variant_.emplace<16>(std::move(def)); + tag_ = Tag::AS_BOOL; + } + + const std::vector& get_as_bools() const { + return std::get<17>(variant_); + } + + void set_as_bools(std::vector def) { + variant_.emplace<17>(std::move(def)); + tag_ = Tag::AS_BOOLS; + } + + const SymBoolArgument& get_as_sym_bool() const { + return std::get<18>(variant_); + } + + void set_as_sym_bool(SymBoolArgument def) { + variant_.emplace<18>(std::move(def)); + tag_ = Tag::AS_SYM_BOOL; + } + + const std::vector& get_as_sym_bools() const { + return std::get<19>(variant_); + } + + void set_as_sym_bools(std::vector def) { + variant_.emplace<19>(std::move(def)); + tag_ = Tag::AS_SYM_BOOLS; + } + + const GraphArgument& get_as_graph() const { + return std::get<20>(variant_); + } + + void set_as_graph(GraphArgument def) { + variant_.emplace<20>(std::move(def)); + tag_ = Tag::AS_GRAPH; + } + + const std::vector& get_as_optional_tensors() const { + return std::get<21>(variant_); + } + + void set_as_optional_tensors(std::vector def) { + variant_.emplace<21>(std::move(def)); + tag_ = Tag::AS_OPTIONAL_TENSORS; + } + + const CustomObjArgument& get_as_custom_obj() const { + return std::get<22>(variant_); + } + + void set_as_custom_obj(CustomObjArgument def) { + variant_.emplace<22>(std::move(def)); + tag_ = Tag::AS_CUSTOM_OBJ; + } + + const std::string& get_as_operator() const { + return std::get<23>(variant_); + } + + void set_as_operator(std::string def) { + variant_.emplace<23>(std::move(def)); + tag_ = Tag::AS_OPERATOR; + } + + const SymFloatArgument& get_as_sym_float() const { + return std::get<24>(variant_); + } + + void set_as_sym_float(SymFloatArgument def) { + variant_.emplace<24>(std::move(def)); + tag_ = Tag::AS_SYM_FLOAT; + } + + const std::vector& get_as_sym_floats() const { + return std::get<25>(variant_); + } + + void set_as_sym_floats(std::vector def) { + variant_.emplace<25>(std::move(def)); + tag_ = Tag::AS_SYM_FLOATS; + } + + const OptionalTensorArgument& get_as_optional_tensor() const { + return std::get<26>(variant_); + } + + void set_as_optional_tensor(OptionalTensorArgument def) { + variant_.emplace<26>(std::move(def)); + tag_ = Tag::AS_OPTIONAL_TENSOR; + } + + const ComplexValue& get_as_complex() const { + return std::get<27>(variant_); + } + + void set_as_complex(ComplexValue def) { + variant_.emplace<27>(std::move(def)); + tag_ = Tag::AS_COMPLEX; + } + + const std::vector>& get_as_nested_tensors() const { + return std::get<28>(variant_); + } + + void set_as_nested_tensors(std::vector> def) { + variant_.emplace<28>(std::move(def)); + tag_ = Tag::AS_NESTED_TENSORS; + } + + const std::vector>& get_as_int_lists() const { + return std::get<29>(variant_); + } + + void set_as_int_lists(std::vector> def) { + variant_.emplace<29>(std::move(def)); + tag_ = Tag::AS_INT_LISTS; + } + + const std::unordered_map>& get_as_string_to_argument() const { + return std::get<30>(variant_); + } + + void set_as_string_to_argument(std::unordered_map> def) { + variant_.emplace<30>(std::move(def)); + tag_ = Tag::AS_STRING_TO_ARGUMENT; + } + + const std::vector>& get_as_float_lists() const { + return std::get<31>(variant_); + } + + void set_as_float_lists(std::vector> def) { + variant_.emplace<31>(std::move(def)); + tag_ = Tag::AS_FLOAT_LISTS; + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const Argument& nlohmann_json_t) { + + if (nlohmann_json_t.tag_ == Tag::AS_NONE) { + nlohmann_json_j["as_none"] = nlohmann_json_t.get_as_none(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_TENSOR) { + nlohmann_json_j["as_tensor"] = nlohmann_json_t.get_as_tensor(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_TENSORS) { + nlohmann_json_j["as_tensors"] = nlohmann_json_t.get_as_tensors(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_INT) { + nlohmann_json_j["as_int"] = nlohmann_json_t.get_as_int(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_INTS) { + nlohmann_json_j["as_ints"] = nlohmann_json_t.get_as_ints(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_FLOAT) { + nlohmann_json_j["as_float"] = nlohmann_json_t.get_as_float(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_FLOATS) { + nlohmann_json_j["as_floats"] = nlohmann_json_t.get_as_floats(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_STRING) { + nlohmann_json_j["as_string"] = nlohmann_json_t.get_as_string(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_STRINGS) { + nlohmann_json_j["as_strings"] = nlohmann_json_t.get_as_strings(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_SYM_INT) { + nlohmann_json_j["as_sym_int"] = nlohmann_json_t.get_as_sym_int(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_SYM_INTS) { + nlohmann_json_j["as_sym_ints"] = nlohmann_json_t.get_as_sym_ints(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_SCALAR_TYPE) { + nlohmann_json_j["as_scalar_type"] = nlohmann_json_t.get_as_scalar_type(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_MEMORY_FORMAT) { + nlohmann_json_j["as_memory_format"] = nlohmann_json_t.get_as_memory_format(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_LAYOUT) { + nlohmann_json_j["as_layout"] = nlohmann_json_t.get_as_layout(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_DEVICE) { + nlohmann_json_j["as_device"] = nlohmann_json_t.get_as_device(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_BOOL) { + nlohmann_json_j["as_bool"] = nlohmann_json_t.get_as_bool(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_BOOLS) { + nlohmann_json_j["as_bools"] = nlohmann_json_t.get_as_bools(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_SYM_BOOL) { + nlohmann_json_j["as_sym_bool"] = nlohmann_json_t.get_as_sym_bool(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_SYM_BOOLS) { + nlohmann_json_j["as_sym_bools"] = nlohmann_json_t.get_as_sym_bools(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_GRAPH) { + nlohmann_json_j["as_graph"] = nlohmann_json_t.get_as_graph(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_OPTIONAL_TENSORS) { + nlohmann_json_j["as_optional_tensors"] = nlohmann_json_t.get_as_optional_tensors(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_CUSTOM_OBJ) { + nlohmann_json_j["as_custom_obj"] = nlohmann_json_t.get_as_custom_obj(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_OPERATOR) { + nlohmann_json_j["as_operator"] = nlohmann_json_t.get_as_operator(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_SYM_FLOAT) { + nlohmann_json_j["as_sym_float"] = nlohmann_json_t.get_as_sym_float(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_SYM_FLOATS) { + nlohmann_json_j["as_sym_floats"] = nlohmann_json_t.get_as_sym_floats(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_OPTIONAL_TENSOR) { + nlohmann_json_j["as_optional_tensor"] = nlohmann_json_t.get_as_optional_tensor(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_COMPLEX) { + nlohmann_json_j["as_complex"] = nlohmann_json_t.get_as_complex(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_NESTED_TENSORS) { + nlohmann_json_j["as_nested_tensors"] = nlohmann_json_t.get_as_nested_tensors(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_INT_LISTS) { + nlohmann_json_j["as_int_lists"] = nlohmann_json_t.get_as_int_lists(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_STRING_TO_ARGUMENT) { + nlohmann_json_j["as_string_to_argument"] = nlohmann_json_t.get_as_string_to_argument(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_FLOAT_LISTS) { + nlohmann_json_j["as_float_lists"] = nlohmann_json_t.get_as_float_lists(); + return; + } + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, Argument& nlohmann_json_t) { + + if (nlohmann_json_j.contains("as_none")) { + nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_none").template get()); + nlohmann_json_t.tag_ = Tag::AS_NONE; + return; + } + if (nlohmann_json_j.contains("as_tensor")) { + nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_tensor").template get()); + nlohmann_json_t.tag_ = Tag::AS_TENSOR; + return; + } + if (nlohmann_json_j.contains("as_tensors")) { + nlohmann_json_t.variant_.emplace<3>(nlohmann_json_j.at("as_tensors").template get>()); + nlohmann_json_t.tag_ = Tag::AS_TENSORS; + return; + } + if (nlohmann_json_j.contains("as_int")) { + nlohmann_json_t.variant_.emplace<4>(nlohmann_json_j.at("as_int").template get()); + nlohmann_json_t.tag_ = Tag::AS_INT; + return; + } + if (nlohmann_json_j.contains("as_ints")) { + nlohmann_json_t.variant_.emplace<5>(nlohmann_json_j.at("as_ints").template get>()); + nlohmann_json_t.tag_ = Tag::AS_INTS; + return; + } + if (nlohmann_json_j.contains("as_float")) { + nlohmann_json_t.variant_.emplace<6>(nlohmann_json_j.at("as_float").template get()); + nlohmann_json_t.tag_ = Tag::AS_FLOAT; + return; + } + if (nlohmann_json_j.contains("as_floats")) { + nlohmann_json_t.variant_.emplace<7>(nlohmann_json_j.at("as_floats").template get>()); + nlohmann_json_t.tag_ = Tag::AS_FLOATS; + return; + } + if (nlohmann_json_j.contains("as_string")) { + nlohmann_json_t.variant_.emplace<8>(nlohmann_json_j.at("as_string").template get()); + nlohmann_json_t.tag_ = Tag::AS_STRING; + return; + } + if (nlohmann_json_j.contains("as_strings")) { + nlohmann_json_t.variant_.emplace<9>(nlohmann_json_j.at("as_strings").template get>()); + nlohmann_json_t.tag_ = Tag::AS_STRINGS; + return; + } + if (nlohmann_json_j.contains("as_sym_int")) { + nlohmann_json_t.variant_.emplace<10>(nlohmann_json_j.at("as_sym_int").template get()); + nlohmann_json_t.tag_ = Tag::AS_SYM_INT; + return; + } + if (nlohmann_json_j.contains("as_sym_ints")) { + nlohmann_json_t.variant_.emplace<11>(nlohmann_json_j.at("as_sym_ints").template get>()); + nlohmann_json_t.tag_ = Tag::AS_SYM_INTS; + return; + } + if (nlohmann_json_j.contains("as_scalar_type")) { + nlohmann_json_t.variant_.emplace<12>(nlohmann_json_j.at("as_scalar_type").template get()); + nlohmann_json_t.tag_ = Tag::AS_SCALAR_TYPE; + return; + } + if (nlohmann_json_j.contains("as_memory_format")) { + nlohmann_json_t.variant_.emplace<13>(nlohmann_json_j.at("as_memory_format").template get()); + nlohmann_json_t.tag_ = Tag::AS_MEMORY_FORMAT; + return; + } + if (nlohmann_json_j.contains("as_layout")) { + nlohmann_json_t.variant_.emplace<14>(nlohmann_json_j.at("as_layout").template get()); + nlohmann_json_t.tag_ = Tag::AS_LAYOUT; + return; + } + if (nlohmann_json_j.contains("as_device")) { + nlohmann_json_t.variant_.emplace<15>(nlohmann_json_j.at("as_device").template get()); + nlohmann_json_t.tag_ = Tag::AS_DEVICE; + return; + } + if (nlohmann_json_j.contains("as_bool")) { + nlohmann_json_t.variant_.emplace<16>(nlohmann_json_j.at("as_bool").template get()); + nlohmann_json_t.tag_ = Tag::AS_BOOL; + return; + } + if (nlohmann_json_j.contains("as_bools")) { + nlohmann_json_t.variant_.emplace<17>(nlohmann_json_j.at("as_bools").template get>()); + nlohmann_json_t.tag_ = Tag::AS_BOOLS; + return; + } + if (nlohmann_json_j.contains("as_sym_bool")) { + nlohmann_json_t.variant_.emplace<18>(nlohmann_json_j.at("as_sym_bool").template get()); + nlohmann_json_t.tag_ = Tag::AS_SYM_BOOL; + return; + } + if (nlohmann_json_j.contains("as_sym_bools")) { + nlohmann_json_t.variant_.emplace<19>(nlohmann_json_j.at("as_sym_bools").template get>()); + nlohmann_json_t.tag_ = Tag::AS_SYM_BOOLS; + return; + } + if (nlohmann_json_j.contains("as_graph")) { + nlohmann_json_t.variant_.emplace<20>(nlohmann_json_j.at("as_graph").template get()); + nlohmann_json_t.tag_ = Tag::AS_GRAPH; + return; + } + if (nlohmann_json_j.contains("as_optional_tensors")) { + nlohmann_json_t.variant_.emplace<21>(nlohmann_json_j.at("as_optional_tensors").template get>()); + nlohmann_json_t.tag_ = Tag::AS_OPTIONAL_TENSORS; + return; + } + if (nlohmann_json_j.contains("as_custom_obj")) { + nlohmann_json_t.variant_.emplace<22>(nlohmann_json_j.at("as_custom_obj").template get()); + nlohmann_json_t.tag_ = Tag::AS_CUSTOM_OBJ; + return; + } + if (nlohmann_json_j.contains("as_operator")) { + nlohmann_json_t.variant_.emplace<23>(nlohmann_json_j.at("as_operator").template get()); + nlohmann_json_t.tag_ = Tag::AS_OPERATOR; + return; + } + if (nlohmann_json_j.contains("as_sym_float")) { + nlohmann_json_t.variant_.emplace<24>(nlohmann_json_j.at("as_sym_float").template get()); + nlohmann_json_t.tag_ = Tag::AS_SYM_FLOAT; + return; + } + if (nlohmann_json_j.contains("as_sym_floats")) { + nlohmann_json_t.variant_.emplace<25>(nlohmann_json_j.at("as_sym_floats").template get>()); + nlohmann_json_t.tag_ = Tag::AS_SYM_FLOATS; + return; + } + if (nlohmann_json_j.contains("as_optional_tensor")) { + nlohmann_json_t.variant_.emplace<26>(nlohmann_json_j.at("as_optional_tensor").template get()); + nlohmann_json_t.tag_ = Tag::AS_OPTIONAL_TENSOR; + return; + } + if (nlohmann_json_j.contains("as_complex")) { + nlohmann_json_t.variant_.emplace<27>(nlohmann_json_j.at("as_complex").template get()); + nlohmann_json_t.tag_ = Tag::AS_COMPLEX; + return; + } + if (nlohmann_json_j.contains("as_nested_tensors")) { + nlohmann_json_t.variant_.emplace<28>(nlohmann_json_j.at("as_nested_tensors").template get>>()); + nlohmann_json_t.tag_ = Tag::AS_NESTED_TENSORS; + return; + } + if (nlohmann_json_j.contains("as_int_lists")) { + nlohmann_json_t.variant_.emplace<29>(nlohmann_json_j.at("as_int_lists").template get>>()); + nlohmann_json_t.tag_ = Tag::AS_INT_LISTS; + return; + } + if (nlohmann_json_j.contains("as_string_to_argument")) { + nlohmann_json_t.variant_.emplace<30>(nlohmann_json_j.at("as_string_to_argument").template get>>()); + nlohmann_json_t.tag_ = Tag::AS_STRING_TO_ARGUMENT; + return; + } + if (nlohmann_json_j.contains("as_float_lists")) { + nlohmann_json_t.variant_.emplace<31>(nlohmann_json_j.at("as_float_lists").template get>>()); + nlohmann_json_t.tag_ = Tag::AS_FLOAT_LISTS; + return; + } + } +}; + +inline std::string_view printEnum(const Argument::Tag& e) { + switch (e) { + case Argument::Tag::AS_NONE: return "AS_NONE"; + case Argument::Tag::AS_TENSOR: return "AS_TENSOR"; + case Argument::Tag::AS_TENSORS: return "AS_TENSORS"; + case Argument::Tag::AS_INT: return "AS_INT"; + case Argument::Tag::AS_INTS: return "AS_INTS"; + case Argument::Tag::AS_FLOAT: return "AS_FLOAT"; + case Argument::Tag::AS_FLOATS: return "AS_FLOATS"; + case Argument::Tag::AS_STRING: return "AS_STRING"; + case Argument::Tag::AS_STRINGS: return "AS_STRINGS"; + case Argument::Tag::AS_SYM_INT: return "AS_SYM_INT"; + case Argument::Tag::AS_SYM_INTS: return "AS_SYM_INTS"; + case Argument::Tag::AS_SCALAR_TYPE: return "AS_SCALAR_TYPE"; + case Argument::Tag::AS_MEMORY_FORMAT: return "AS_MEMORY_FORMAT"; + case Argument::Tag::AS_LAYOUT: return "AS_LAYOUT"; + case Argument::Tag::AS_DEVICE: return "AS_DEVICE"; + case Argument::Tag::AS_BOOL: return "AS_BOOL"; + case Argument::Tag::AS_BOOLS: return "AS_BOOLS"; + case Argument::Tag::AS_SYM_BOOL: return "AS_SYM_BOOL"; + case Argument::Tag::AS_SYM_BOOLS: return "AS_SYM_BOOLS"; + case Argument::Tag::AS_GRAPH: return "AS_GRAPH"; + case Argument::Tag::AS_OPTIONAL_TENSORS: return "AS_OPTIONAL_TENSORS"; + case Argument::Tag::AS_CUSTOM_OBJ: return "AS_CUSTOM_OBJ"; + case Argument::Tag::AS_OPERATOR: return "AS_OPERATOR"; + case Argument::Tag::AS_SYM_FLOAT: return "AS_SYM_FLOAT"; + case Argument::Tag::AS_SYM_FLOATS: return "AS_SYM_FLOATS"; + case Argument::Tag::AS_OPTIONAL_TENSOR: return "AS_OPTIONAL_TENSOR"; + case Argument::Tag::AS_COMPLEX: return "AS_COMPLEX"; + case Argument::Tag::AS_NESTED_TENSORS: return "AS_NESTED_TENSORS"; + case Argument::Tag::AS_INT_LISTS: return "AS_INT_LISTS"; + case Argument::Tag::AS_STRING_TO_ARGUMENT: return "AS_STRING_TO_ARGUMENT"; + case Argument::Tag::AS_FLOAT_LISTS: return "AS_FLOAT_LISTS"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, Argument::Tag& t) { + if (s == "AS_NONE") { t = Argument::Tag::AS_NONE; return; } + if (s == "AS_TENSOR") { t = Argument::Tag::AS_TENSOR; return; } + if (s == "AS_TENSORS") { t = Argument::Tag::AS_TENSORS; return; } + if (s == "AS_INT") { t = Argument::Tag::AS_INT; return; } + if (s == "AS_INTS") { t = Argument::Tag::AS_INTS; return; } + if (s == "AS_FLOAT") { t = Argument::Tag::AS_FLOAT; return; } + if (s == "AS_FLOATS") { t = Argument::Tag::AS_FLOATS; return; } + if (s == "AS_STRING") { t = Argument::Tag::AS_STRING; return; } + if (s == "AS_STRINGS") { t = Argument::Tag::AS_STRINGS; return; } + if (s == "AS_SYM_INT") { t = Argument::Tag::AS_SYM_INT; return; } + if (s == "AS_SYM_INTS") { t = Argument::Tag::AS_SYM_INTS; return; } + if (s == "AS_SCALAR_TYPE") { t = Argument::Tag::AS_SCALAR_TYPE; return; } + if (s == "AS_MEMORY_FORMAT") { t = Argument::Tag::AS_MEMORY_FORMAT; return; } + if (s == "AS_LAYOUT") { t = Argument::Tag::AS_LAYOUT; return; } + if (s == "AS_DEVICE") { t = Argument::Tag::AS_DEVICE; return; } + if (s == "AS_BOOL") { t = Argument::Tag::AS_BOOL; return; } + if (s == "AS_BOOLS") { t = Argument::Tag::AS_BOOLS; return; } + if (s == "AS_SYM_BOOL") { t = Argument::Tag::AS_SYM_BOOL; return; } + if (s == "AS_SYM_BOOLS") { t = Argument::Tag::AS_SYM_BOOLS; return; } + if (s == "AS_GRAPH") { t = Argument::Tag::AS_GRAPH; return; } + if (s == "AS_OPTIONAL_TENSORS") { t = Argument::Tag::AS_OPTIONAL_TENSORS; return; } + if (s == "AS_CUSTOM_OBJ") { t = Argument::Tag::AS_CUSTOM_OBJ; return; } + if (s == "AS_OPERATOR") { t = Argument::Tag::AS_OPERATOR; return; } + if (s == "AS_SYM_FLOAT") { t = Argument::Tag::AS_SYM_FLOAT; return; } + if (s == "AS_SYM_FLOATS") { t = Argument::Tag::AS_SYM_FLOATS; return; } + if (s == "AS_OPTIONAL_TENSOR") { t = Argument::Tag::AS_OPTIONAL_TENSOR; return; } + if (s == "AS_COMPLEX") { t = Argument::Tag::AS_COMPLEX; return; } + if (s == "AS_NESTED_TENSORS") { t = Argument::Tag::AS_NESTED_TENSORS; return; } + if (s == "AS_INT_LISTS") { t = Argument::Tag::AS_INT_LISTS; return; } + if (s == "AS_STRING_TO_ARGUMENT") { t = Argument::Tag::AS_STRING_TO_ARGUMENT; return; } + if (s == "AS_FLOAT_LISTS") { t = Argument::Tag::AS_FLOAT_LISTS; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + + +class NamedArgument { + private: + std::string name; + Argument arg; + std::optional kind = std::nullopt; + + public: + + const std::string& get_name() const { + return name; + } + + void set_name(std::string def) { + name = std::move(def); + } + + const Argument& get_arg() const { + return arg; + } + + void set_arg(Argument def) { + arg = std::move(def); + } + + const std::optional& get_kind() const { + return kind; + } + + void set_kind(std::optional def) { + kind = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const NamedArgument& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, NamedArgument& nlohmann_json_t); +}; + +class Node { + private: + std::string target; + std::vector inputs; + std::vector outputs; + std::unordered_map metadata; + std::optional is_hop_single_tensor_return = std::nullopt; + std::optional name = std::nullopt; + + public: + + const std::string& get_target() const { + return target; + } + + void set_target(std::string def) { + target = std::move(def); + } + + const std::vector& get_inputs() const { + return inputs; + } + + void set_inputs(std::vector def) { + inputs = std::move(def); + } + + const std::vector& get_outputs() const { + return outputs; + } + + void set_outputs(std::vector def) { + outputs = std::move(def); + } + + const std::unordered_map& get_metadata() const { + return metadata; + } + + void set_metadata(std::unordered_map def) { + metadata = std::move(def); + } + + const std::optional& get_is_hop_single_tensor_return() const { + return is_hop_single_tensor_return; + } + + void set_is_hop_single_tensor_return(std::optional def) { + is_hop_single_tensor_return = std::move(def); + } + + const std::optional& get_name() const { + return name; + } + + void set_name(std::optional def) { + name = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const Node& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, Node& nlohmann_json_t); +}; + +class Graph { + private: + std::vector inputs; + std::vector outputs; + std::vector nodes; + std::unordered_map tensor_values; + std::unordered_map sym_int_values; + std::unordered_map sym_bool_values; + bool is_single_tensor_return = false; + std::unordered_map custom_obj_values = {}; + std::unordered_map sym_float_values = {}; + + public: + + const std::vector& get_inputs() const { + return inputs; + } + + void set_inputs(std::vector def) { + inputs = std::move(def); + } + + const std::vector& get_outputs() const { + return outputs; + } + + void set_outputs(std::vector def) { + outputs = std::move(def); + } + + const std::vector& get_nodes() const { + return nodes; + } + + void set_nodes(std::vector def) { + nodes = std::move(def); + } + + const std::unordered_map& get_tensor_values() const { + return tensor_values; + } + + void set_tensor_values(std::unordered_map def) { + tensor_values = std::move(def); + } + + const std::unordered_map& get_sym_int_values() const { + return sym_int_values; + } + + void set_sym_int_values(std::unordered_map def) { + sym_int_values = std::move(def); + } + + const std::unordered_map& get_sym_bool_values() const { + return sym_bool_values; + } + + void set_sym_bool_values(std::unordered_map def) { + sym_bool_values = std::move(def); + } + + const bool& get_is_single_tensor_return() const { + return is_single_tensor_return; + } + + void set_is_single_tensor_return(bool def) { + is_single_tensor_return = std::move(def); + } + + const std::unordered_map& get_custom_obj_values() const { + return custom_obj_values; + } + + void set_custom_obj_values(std::unordered_map def) { + custom_obj_values = std::move(def); + } + + const std::unordered_map& get_sym_float_values() const { + return sym_float_values; + } + + void set_sym_float_values(std::unordered_map def) { + sym_float_values = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const Graph& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, Graph& nlohmann_json_t); +}; + +class UserInputSpec { + private: + Argument arg; + + public: + + const Argument& get_arg() const { + return arg; + } + + void set_arg(Argument def) { + arg = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const UserInputSpec& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, UserInputSpec& nlohmann_json_t); +}; + +class ConstantValue { + struct Void {}; + + public: + enum class Tag { + AS_NONE, AS_INT, AS_FLOAT, AS_STRING, AS_BOOL + }; + + private: + std::variant variant_; + Tag tag_; + + public: + Tag tag() const { + return tag_; + } + + const bool& get_as_none() const { + return std::get<1>(variant_); + } + + void set_as_none(bool def) { + variant_.emplace<1>(std::move(def)); + tag_ = Tag::AS_NONE; + } + + const int64_t& get_as_int() const { + return std::get<2>(variant_); + } + + void set_as_int(int64_t def) { + variant_.emplace<2>(std::move(def)); + tag_ = Tag::AS_INT; + } + + const F64& get_as_float() const { + return std::get<3>(variant_); + } + + void set_as_float(F64 def) { + variant_.emplace<3>(std::move(def)); + tag_ = Tag::AS_FLOAT; + } + + const std::string& get_as_string() const { + return std::get<4>(variant_); + } + + void set_as_string(std::string def) { + variant_.emplace<4>(std::move(def)); + tag_ = Tag::AS_STRING; + } + + const bool& get_as_bool() const { + return std::get<5>(variant_); + } + + void set_as_bool(bool def) { + variant_.emplace<5>(std::move(def)); + tag_ = Tag::AS_BOOL; + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const ConstantValue& nlohmann_json_t) { + + if (nlohmann_json_t.tag_ == Tag::AS_NONE) { + nlohmann_json_j["as_none"] = nlohmann_json_t.get_as_none(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_INT) { + nlohmann_json_j["as_int"] = nlohmann_json_t.get_as_int(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_FLOAT) { + nlohmann_json_j["as_float"] = nlohmann_json_t.get_as_float(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_STRING) { + nlohmann_json_j["as_string"] = nlohmann_json_t.get_as_string(); + return; + } + if (nlohmann_json_t.tag_ == Tag::AS_BOOL) { + nlohmann_json_j["as_bool"] = nlohmann_json_t.get_as_bool(); + return; + } + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, ConstantValue& nlohmann_json_t) { + + if (nlohmann_json_j.contains("as_none")) { + nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_none").template get()); + nlohmann_json_t.tag_ = Tag::AS_NONE; + return; + } + if (nlohmann_json_j.contains("as_int")) { + nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_int").template get()); + nlohmann_json_t.tag_ = Tag::AS_INT; + return; + } + if (nlohmann_json_j.contains("as_float")) { + nlohmann_json_t.variant_.emplace<3>(nlohmann_json_j.at("as_float").template get()); + nlohmann_json_t.tag_ = Tag::AS_FLOAT; + return; + } + if (nlohmann_json_j.contains("as_string")) { + nlohmann_json_t.variant_.emplace<4>(nlohmann_json_j.at("as_string").template get()); + nlohmann_json_t.tag_ = Tag::AS_STRING; + return; + } + if (nlohmann_json_j.contains("as_bool")) { + nlohmann_json_t.variant_.emplace<5>(nlohmann_json_j.at("as_bool").template get()); + nlohmann_json_t.tag_ = Tag::AS_BOOL; + return; + } + } +}; + +inline std::string_view printEnum(const ConstantValue::Tag& e) { + switch (e) { + case ConstantValue::Tag::AS_NONE: return "AS_NONE"; + case ConstantValue::Tag::AS_INT: return "AS_INT"; + case ConstantValue::Tag::AS_FLOAT: return "AS_FLOAT"; + case ConstantValue::Tag::AS_STRING: return "AS_STRING"; + case ConstantValue::Tag::AS_BOOL: return "AS_BOOL"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, ConstantValue::Tag& t) { + if (s == "AS_NONE") { t = ConstantValue::Tag::AS_NONE; return; } + if (s == "AS_INT") { t = ConstantValue::Tag::AS_INT; return; } + if (s == "AS_FLOAT") { t = ConstantValue::Tag::AS_FLOAT; return; } + if (s == "AS_STRING") { t = ConstantValue::Tag::AS_STRING; return; } + if (s == "AS_BOOL") { t = ConstantValue::Tag::AS_BOOL; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + + +class InputToConstantInputSpec { + private: + std::string name; + ConstantValue value; + + public: + + const std::string& get_name() const { + return name; + } + + void set_name(std::string def) { + name = std::move(def); + } + + const ConstantValue& get_value() const { + return value; + } + + void set_value(ConstantValue def) { + value = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const InputToConstantInputSpec& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, InputToConstantInputSpec& nlohmann_json_t); +}; + +class InputToParameterSpec { + private: + TensorArgument arg; + std::string parameter_name; + + public: + + const TensorArgument& get_arg() const { + return arg; + } + + void set_arg(TensorArgument def) { + arg = std::move(def); + } + + const std::string& get_parameter_name() const { + return parameter_name; + } + + void set_parameter_name(std::string def) { + parameter_name = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const InputToParameterSpec& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, InputToParameterSpec& nlohmann_json_t); +}; + +class InputToBufferSpec { + private: + TensorArgument arg; + std::string buffer_name; + bool persistent; + + public: + + const TensorArgument& get_arg() const { + return arg; + } + + void set_arg(TensorArgument def) { + arg = std::move(def); + } + + const std::string& get_buffer_name() const { + return buffer_name; + } + + void set_buffer_name(std::string def) { + buffer_name = std::move(def); + } + + const bool& get_persistent() const { + return persistent; + } + + void set_persistent(bool def) { + persistent = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const InputToBufferSpec& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, InputToBufferSpec& nlohmann_json_t); +}; + +class InputToTensorConstantSpec { + private: + TensorArgument arg; + std::string tensor_constant_name; + + public: + + const TensorArgument& get_arg() const { + return arg; + } + + void set_arg(TensorArgument def) { + arg = std::move(def); + } + + const std::string& get_tensor_constant_name() const { + return tensor_constant_name; + } + + void set_tensor_constant_name(std::string def) { + tensor_constant_name = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const InputToTensorConstantSpec& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, InputToTensorConstantSpec& nlohmann_json_t); +}; + +class InputToCustomObjSpec { + private: + CustomObjArgument arg; + std::string custom_obj_name; + + public: + + const CustomObjArgument& get_arg() const { + return arg; + } + + void set_arg(CustomObjArgument def) { + arg = std::move(def); + } + + const std::string& get_custom_obj_name() const { + return custom_obj_name; + } + + void set_custom_obj_name(std::string def) { + custom_obj_name = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const InputToCustomObjSpec& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, InputToCustomObjSpec& nlohmann_json_t); +}; + +class InputTokenSpec { + private: + TokenArgument arg; + + public: + + const TokenArgument& get_arg() const { + return arg; + } + + void set_arg(TokenArgument def) { + arg = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const InputTokenSpec& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, InputTokenSpec& nlohmann_json_t); +}; + +class InputSpec { + struct Void {}; + + public: + enum class Tag { + USER_INPUT, PARAMETER, BUFFER, TENSOR_CONSTANT, CUSTOM_OBJ, TOKEN, CONSTANT_INPUT + }; + + private: + std::variant variant_; + Tag tag_; + + public: + Tag tag() const { + return tag_; + } + + const UserInputSpec& get_user_input() const { + return std::get<1>(variant_); + } + + void set_user_input(UserInputSpec def) { + variant_.emplace<1>(std::move(def)); + tag_ = Tag::USER_INPUT; + } + + const InputToParameterSpec& get_parameter() const { + return std::get<2>(variant_); + } + + void set_parameter(InputToParameterSpec def) { + variant_.emplace<2>(std::move(def)); + tag_ = Tag::PARAMETER; + } + + const InputToBufferSpec& get_buffer() const { + return std::get<3>(variant_); + } + + void set_buffer(InputToBufferSpec def) { + variant_.emplace<3>(std::move(def)); + tag_ = Tag::BUFFER; + } + + const InputToTensorConstantSpec& get_tensor_constant() const { + return std::get<4>(variant_); + } + + void set_tensor_constant(InputToTensorConstantSpec def) { + variant_.emplace<4>(std::move(def)); + tag_ = Tag::TENSOR_CONSTANT; + } + + const InputToCustomObjSpec& get_custom_obj() const { + return std::get<5>(variant_); + } + + void set_custom_obj(InputToCustomObjSpec def) { + variant_.emplace<5>(std::move(def)); + tag_ = Tag::CUSTOM_OBJ; + } + + const InputTokenSpec& get_token() const { + return std::get<6>(variant_); + } + + void set_token(InputTokenSpec def) { + variant_.emplace<6>(std::move(def)); + tag_ = Tag::TOKEN; + } + + const InputToConstantInputSpec& get_constant_input() const { + return std::get<7>(variant_); + } + + void set_constant_input(InputToConstantInputSpec def) { + variant_.emplace<7>(std::move(def)); + tag_ = Tag::CONSTANT_INPUT; + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const InputSpec& nlohmann_json_t) { + + if (nlohmann_json_t.tag_ == Tag::USER_INPUT) { + nlohmann_json_j["user_input"] = nlohmann_json_t.get_user_input(); + return; + } + if (nlohmann_json_t.tag_ == Tag::PARAMETER) { + nlohmann_json_j["parameter"] = nlohmann_json_t.get_parameter(); + return; + } + if (nlohmann_json_t.tag_ == Tag::BUFFER) { + nlohmann_json_j["buffer"] = nlohmann_json_t.get_buffer(); + return; + } + if (nlohmann_json_t.tag_ == Tag::TENSOR_CONSTANT) { + nlohmann_json_j["tensor_constant"] = nlohmann_json_t.get_tensor_constant(); + return; + } + if (nlohmann_json_t.tag_ == Tag::CUSTOM_OBJ) { + nlohmann_json_j["custom_obj"] = nlohmann_json_t.get_custom_obj(); + return; + } + if (nlohmann_json_t.tag_ == Tag::TOKEN) { + nlohmann_json_j["token"] = nlohmann_json_t.get_token(); + return; + } + if (nlohmann_json_t.tag_ == Tag::CONSTANT_INPUT) { + nlohmann_json_j["constant_input"] = nlohmann_json_t.get_constant_input(); + return; + } + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, InputSpec& nlohmann_json_t) { + + if (nlohmann_json_j.contains("user_input")) { + nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("user_input").template get()); + nlohmann_json_t.tag_ = Tag::USER_INPUT; + return; + } + if (nlohmann_json_j.contains("parameter")) { + nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("parameter").template get()); + nlohmann_json_t.tag_ = Tag::PARAMETER; + return; + } + if (nlohmann_json_j.contains("buffer")) { + nlohmann_json_t.variant_.emplace<3>(nlohmann_json_j.at("buffer").template get()); + nlohmann_json_t.tag_ = Tag::BUFFER; + return; + } + if (nlohmann_json_j.contains("tensor_constant")) { + nlohmann_json_t.variant_.emplace<4>(nlohmann_json_j.at("tensor_constant").template get()); + nlohmann_json_t.tag_ = Tag::TENSOR_CONSTANT; + return; + } + if (nlohmann_json_j.contains("custom_obj")) { + nlohmann_json_t.variant_.emplace<5>(nlohmann_json_j.at("custom_obj").template get()); + nlohmann_json_t.tag_ = Tag::CUSTOM_OBJ; + return; + } + if (nlohmann_json_j.contains("token")) { + nlohmann_json_t.variant_.emplace<6>(nlohmann_json_j.at("token").template get()); + nlohmann_json_t.tag_ = Tag::TOKEN; + return; + } + if (nlohmann_json_j.contains("constant_input")) { + nlohmann_json_t.variant_.emplace<7>(nlohmann_json_j.at("constant_input").template get()); + nlohmann_json_t.tag_ = Tag::CONSTANT_INPUT; + return; + } + } +}; + +inline std::string_view printEnum(const InputSpec::Tag& e) { + switch (e) { + case InputSpec::Tag::USER_INPUT: return "USER_INPUT"; + case InputSpec::Tag::PARAMETER: return "PARAMETER"; + case InputSpec::Tag::BUFFER: return "BUFFER"; + case InputSpec::Tag::TENSOR_CONSTANT: return "TENSOR_CONSTANT"; + case InputSpec::Tag::CUSTOM_OBJ: return "CUSTOM_OBJ"; + case InputSpec::Tag::TOKEN: return "TOKEN"; + case InputSpec::Tag::CONSTANT_INPUT: return "CONSTANT_INPUT"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, InputSpec::Tag& t) { + if (s == "USER_INPUT") { t = InputSpec::Tag::USER_INPUT; return; } + if (s == "PARAMETER") { t = InputSpec::Tag::PARAMETER; return; } + if (s == "BUFFER") { t = InputSpec::Tag::BUFFER; return; } + if (s == "TENSOR_CONSTANT") { t = InputSpec::Tag::TENSOR_CONSTANT; return; } + if (s == "CUSTOM_OBJ") { t = InputSpec::Tag::CUSTOM_OBJ; return; } + if (s == "TOKEN") { t = InputSpec::Tag::TOKEN; return; } + if (s == "CONSTANT_INPUT") { t = InputSpec::Tag::CONSTANT_INPUT; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + + +class UserOutputSpec { + private: + Argument arg; + + public: + + const Argument& get_arg() const { + return arg; + } + + void set_arg(Argument def) { + arg = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const UserOutputSpec& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, UserOutputSpec& nlohmann_json_t); +}; + +class LossOutputSpec { + private: + TensorArgument arg; + + public: + + const TensorArgument& get_arg() const { + return arg; + } + + void set_arg(TensorArgument def) { + arg = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const LossOutputSpec& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, LossOutputSpec& nlohmann_json_t); +}; + +class BufferMutationSpec { + private: + TensorArgument arg; + std::string buffer_name; + + public: + + const TensorArgument& get_arg() const { + return arg; + } + + void set_arg(TensorArgument def) { + arg = std::move(def); + } + + const std::string& get_buffer_name() const { + return buffer_name; + } + + void set_buffer_name(std::string def) { + buffer_name = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const BufferMutationSpec& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, BufferMutationSpec& nlohmann_json_t); +}; + +class ParameterMutationSpec { + private: + TensorArgument arg; + std::string parameter_name; + + public: + + const TensorArgument& get_arg() const { + return arg; + } + + void set_arg(TensorArgument def) { + arg = std::move(def); + } + + const std::string& get_parameter_name() const { + return parameter_name; + } + + void set_parameter_name(std::string def) { + parameter_name = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const ParameterMutationSpec& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, ParameterMutationSpec& nlohmann_json_t); +}; + +class GradientToParameterSpec { + private: + TensorArgument arg; + std::string parameter_name; + + public: + + const TensorArgument& get_arg() const { + return arg; + } + + void set_arg(TensorArgument def) { + arg = std::move(def); + } + + const std::string& get_parameter_name() const { + return parameter_name; + } + + void set_parameter_name(std::string def) { + parameter_name = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const GradientToParameterSpec& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, GradientToParameterSpec& nlohmann_json_t); +}; + +class GradientToUserInputSpec { + private: + TensorArgument arg; + std::string user_input_name; + + public: + + const TensorArgument& get_arg() const { + return arg; + } + + void set_arg(TensorArgument def) { + arg = std::move(def); + } + + const std::string& get_user_input_name() const { + return user_input_name; + } + + void set_user_input_name(std::string def) { + user_input_name = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const GradientToUserInputSpec& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, GradientToUserInputSpec& nlohmann_json_t); +}; + +class UserInputMutationSpec { + private: + TensorArgument arg; + std::string user_input_name; + + public: + + const TensorArgument& get_arg() const { + return arg; + } + + void set_arg(TensorArgument def) { + arg = std::move(def); + } + + const std::string& get_user_input_name() const { + return user_input_name; + } + + void set_user_input_name(std::string def) { + user_input_name = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const UserInputMutationSpec& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, UserInputMutationSpec& nlohmann_json_t); +}; + +class OutputTokenSpec { + private: + TokenArgument arg; + + public: + + const TokenArgument& get_arg() const { + return arg; + } + + void set_arg(TokenArgument def) { + arg = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const OutputTokenSpec& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, OutputTokenSpec& nlohmann_json_t); +}; + +class OutputSpec { + struct Void {}; + + public: + enum class Tag { + USER_OUTPUT, LOSS_OUTPUT, BUFFER_MUTATION, GRADIENT_TO_PARAMETER, GRADIENT_TO_USER_INPUT, USER_INPUT_MUTATION, TOKEN, PARAMETER_MUTATION + }; + + private: + std::variant variant_; + Tag tag_; + + public: + Tag tag() const { + return tag_; + } + + const UserOutputSpec& get_user_output() const { + return std::get<1>(variant_); + } + + void set_user_output(UserOutputSpec def) { + variant_.emplace<1>(std::move(def)); + tag_ = Tag::USER_OUTPUT; + } + + const LossOutputSpec& get_loss_output() const { + return std::get<2>(variant_); + } + + void set_loss_output(LossOutputSpec def) { + variant_.emplace<2>(std::move(def)); + tag_ = Tag::LOSS_OUTPUT; + } + + const BufferMutationSpec& get_buffer_mutation() const { + return std::get<3>(variant_); + } + + void set_buffer_mutation(BufferMutationSpec def) { + variant_.emplace<3>(std::move(def)); + tag_ = Tag::BUFFER_MUTATION; + } + + const GradientToParameterSpec& get_gradient_to_parameter() const { + return std::get<4>(variant_); + } + + void set_gradient_to_parameter(GradientToParameterSpec def) { + variant_.emplace<4>(std::move(def)); + tag_ = Tag::GRADIENT_TO_PARAMETER; + } + + const GradientToUserInputSpec& get_gradient_to_user_input() const { + return std::get<5>(variant_); + } + + void set_gradient_to_user_input(GradientToUserInputSpec def) { + variant_.emplace<5>(std::move(def)); + tag_ = Tag::GRADIENT_TO_USER_INPUT; + } + + const UserInputMutationSpec& get_user_input_mutation() const { + return std::get<6>(variant_); + } + + void set_user_input_mutation(UserInputMutationSpec def) { + variant_.emplace<6>(std::move(def)); + tag_ = Tag::USER_INPUT_MUTATION; + } + + const OutputTokenSpec& get_token() const { + return std::get<7>(variant_); + } + + void set_token(OutputTokenSpec def) { + variant_.emplace<7>(std::move(def)); + tag_ = Tag::TOKEN; + } + + const ParameterMutationSpec& get_parameter_mutation() const { + return std::get<8>(variant_); + } + + void set_parameter_mutation(ParameterMutationSpec def) { + variant_.emplace<8>(std::move(def)); + tag_ = Tag::PARAMETER_MUTATION; + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const OutputSpec& nlohmann_json_t) { + + if (nlohmann_json_t.tag_ == Tag::USER_OUTPUT) { + nlohmann_json_j["user_output"] = nlohmann_json_t.get_user_output(); + return; + } + if (nlohmann_json_t.tag_ == Tag::LOSS_OUTPUT) { + nlohmann_json_j["loss_output"] = nlohmann_json_t.get_loss_output(); + return; + } + if (nlohmann_json_t.tag_ == Tag::BUFFER_MUTATION) { + nlohmann_json_j["buffer_mutation"] = nlohmann_json_t.get_buffer_mutation(); + return; + } + if (nlohmann_json_t.tag_ == Tag::GRADIENT_TO_PARAMETER) { + nlohmann_json_j["gradient_to_parameter"] = nlohmann_json_t.get_gradient_to_parameter(); + return; + } + if (nlohmann_json_t.tag_ == Tag::GRADIENT_TO_USER_INPUT) { + nlohmann_json_j["gradient_to_user_input"] = nlohmann_json_t.get_gradient_to_user_input(); + return; + } + if (nlohmann_json_t.tag_ == Tag::USER_INPUT_MUTATION) { + nlohmann_json_j["user_input_mutation"] = nlohmann_json_t.get_user_input_mutation(); + return; + } + if (nlohmann_json_t.tag_ == Tag::TOKEN) { + nlohmann_json_j["token"] = nlohmann_json_t.get_token(); + return; + } + if (nlohmann_json_t.tag_ == Tag::PARAMETER_MUTATION) { + nlohmann_json_j["parameter_mutation"] = nlohmann_json_t.get_parameter_mutation(); + return; + } + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, OutputSpec& nlohmann_json_t) { + + if (nlohmann_json_j.contains("user_output")) { + nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("user_output").template get()); + nlohmann_json_t.tag_ = Tag::USER_OUTPUT; + return; + } + if (nlohmann_json_j.contains("loss_output")) { + nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("loss_output").template get()); + nlohmann_json_t.tag_ = Tag::LOSS_OUTPUT; + return; + } + if (nlohmann_json_j.contains("buffer_mutation")) { + nlohmann_json_t.variant_.emplace<3>(nlohmann_json_j.at("buffer_mutation").template get()); + nlohmann_json_t.tag_ = Tag::BUFFER_MUTATION; + return; + } + if (nlohmann_json_j.contains("gradient_to_parameter")) { + nlohmann_json_t.variant_.emplace<4>(nlohmann_json_j.at("gradient_to_parameter").template get()); + nlohmann_json_t.tag_ = Tag::GRADIENT_TO_PARAMETER; + return; + } + if (nlohmann_json_j.contains("gradient_to_user_input")) { + nlohmann_json_t.variant_.emplace<5>(nlohmann_json_j.at("gradient_to_user_input").template get()); + nlohmann_json_t.tag_ = Tag::GRADIENT_TO_USER_INPUT; + return; + } + if (nlohmann_json_j.contains("user_input_mutation")) { + nlohmann_json_t.variant_.emplace<6>(nlohmann_json_j.at("user_input_mutation").template get()); + nlohmann_json_t.tag_ = Tag::USER_INPUT_MUTATION; + return; + } + if (nlohmann_json_j.contains("token")) { + nlohmann_json_t.variant_.emplace<7>(nlohmann_json_j.at("token").template get()); + nlohmann_json_t.tag_ = Tag::TOKEN; + return; + } + if (nlohmann_json_j.contains("parameter_mutation")) { + nlohmann_json_t.variant_.emplace<8>(nlohmann_json_j.at("parameter_mutation").template get()); + nlohmann_json_t.tag_ = Tag::PARAMETER_MUTATION; + return; + } + } +}; + +inline std::string_view printEnum(const OutputSpec::Tag& e) { + switch (e) { + case OutputSpec::Tag::USER_OUTPUT: return "USER_OUTPUT"; + case OutputSpec::Tag::LOSS_OUTPUT: return "LOSS_OUTPUT"; + case OutputSpec::Tag::BUFFER_MUTATION: return "BUFFER_MUTATION"; + case OutputSpec::Tag::GRADIENT_TO_PARAMETER: return "GRADIENT_TO_PARAMETER"; + case OutputSpec::Tag::GRADIENT_TO_USER_INPUT: return "GRADIENT_TO_USER_INPUT"; + case OutputSpec::Tag::USER_INPUT_MUTATION: return "USER_INPUT_MUTATION"; + case OutputSpec::Tag::TOKEN: return "TOKEN"; + case OutputSpec::Tag::PARAMETER_MUTATION: return "PARAMETER_MUTATION"; + default: + throw std::runtime_error("Unknown enum value"); + } +} + +inline void parseEnum(std::string_view s, OutputSpec::Tag& t) { + if (s == "USER_OUTPUT") { t = OutputSpec::Tag::USER_OUTPUT; return; } + if (s == "LOSS_OUTPUT") { t = OutputSpec::Tag::LOSS_OUTPUT; return; } + if (s == "BUFFER_MUTATION") { t = OutputSpec::Tag::BUFFER_MUTATION; return; } + if (s == "GRADIENT_TO_PARAMETER") { t = OutputSpec::Tag::GRADIENT_TO_PARAMETER; return; } + if (s == "GRADIENT_TO_USER_INPUT") { t = OutputSpec::Tag::GRADIENT_TO_USER_INPUT; return; } + if (s == "USER_INPUT_MUTATION") { t = OutputSpec::Tag::USER_INPUT_MUTATION; return; } + if (s == "TOKEN") { t = OutputSpec::Tag::TOKEN; return; } + if (s == "PARAMETER_MUTATION") { t = OutputSpec::Tag::PARAMETER_MUTATION; return; } + throw std::runtime_error("Unknown enum value: " + std::string{s}); +} + + +class GraphSignature { + private: + std::vector input_specs; + std::vector output_specs; + + public: + + const std::vector& get_input_specs() const { + return input_specs; + } + + void set_input_specs(std::vector def) { + input_specs = std::move(def); + } + + const std::vector& get_output_specs() const { + return output_specs; + } + + void set_output_specs(std::vector def) { + output_specs = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const GraphSignature& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, GraphSignature& nlohmann_json_t); +}; + +class RangeConstraint { + private: + std::optional min_val; + std::optional max_val; + + public: + + const std::optional& get_min_val() const { + return min_val; + } + + void set_min_val(std::optional def) { + min_val = std::move(def); + } + + const std::optional& get_max_val() const { + return max_val; + } + + void set_max_val(std::optional def) { + max_val = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const RangeConstraint& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, RangeConstraint& nlohmann_json_t); +}; + +class ModuleCallSignature { + private: + std::vector inputs; + std::vector outputs; + std::string in_spec; + std::string out_spec; + std::optional> forward_arg_names = std::nullopt; + + public: + + const std::vector& get_inputs() const { + return inputs; + } + + void set_inputs(std::vector def) { + inputs = std::move(def); + } + + const std::vector& get_outputs() const { + return outputs; + } + + void set_outputs(std::vector def) { + outputs = std::move(def); + } + + const std::string& get_in_spec() const { + return in_spec; + } + + void set_in_spec(std::string def) { + in_spec = std::move(def); + } + + const std::string& get_out_spec() const { + return out_spec; + } + + void set_out_spec(std::string def) { + out_spec = std::move(def); + } + + const std::optional>& get_forward_arg_names() const { + return forward_arg_names; + } + + void set_forward_arg_names(std::optional> def) { + forward_arg_names = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const ModuleCallSignature& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, ModuleCallSignature& nlohmann_json_t); +}; + +class ModuleCallEntry { + private: + std::string fqn; + std::optional signature = std::nullopt; + + public: + + const std::string& get_fqn() const { + return fqn; + } + + void set_fqn(std::string def) { + fqn = std::move(def); + } + + const std::optional& get_signature() const { + return signature; + } + + void set_signature(std::optional def) { + signature = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const ModuleCallEntry& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, ModuleCallEntry& nlohmann_json_t); +}; + +class NamedTupleDef { + private: + std::vector field_names; + + public: + + const std::vector& get_field_names() const { + return field_names; + } + + void set_field_names(std::vector def) { + field_names = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const NamedTupleDef& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, NamedTupleDef& nlohmann_json_t); +}; + +class GraphModule { + private: + Graph graph; + GraphSignature signature; + std::vector module_call_graph; + std::unordered_map metadata = {}; + std::unordered_map treespec_namedtuple_fields = {}; + + public: + + const Graph& get_graph() const { + return graph; + } + + void set_graph(Graph def) { + graph = std::move(def); + } + + const GraphSignature& get_signature() const { + return signature; + } + + void set_signature(GraphSignature def) { + signature = std::move(def); + } + + const std::vector& get_module_call_graph() const { + return module_call_graph; + } + + void set_module_call_graph(std::vector def) { + module_call_graph = std::move(def); + } + + const std::unordered_map& get_metadata() const { + return metadata; + } + + void set_metadata(std::unordered_map def) { + metadata = std::move(def); + } + + const std::unordered_map& get_treespec_namedtuple_fields() const { + return treespec_namedtuple_fields; + } + + void set_treespec_namedtuple_fields(std::unordered_map def) { + treespec_namedtuple_fields = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const GraphModule& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, GraphModule& nlohmann_json_t); +}; + +class SchemaVersion { + private: + int64_t major; + int64_t minor; + + public: + + const int64_t& get_major() const { + return major; + } + + void set_major(int64_t def) { + major = std::move(def); + } + + const int64_t& get_minor() const { + return minor; + } + + void set_minor(int64_t def) { + minor = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const SchemaVersion& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, SchemaVersion& nlohmann_json_t); +}; + +class ExportedProgram { + private: + GraphModule graph_module; + std::unordered_map opset_version; + std::unordered_map range_constraints; + SchemaVersion schema_version; + std::vector verifiers = {}; + std::string torch_version = "<=2.4"; + std::vector guards_code = {}; + + public: + + const GraphModule& get_graph_module() const { + return graph_module; + } + + void set_graph_module(GraphModule def) { + graph_module = std::move(def); + } + + const std::unordered_map& get_opset_version() const { + return opset_version; + } + + void set_opset_version(std::unordered_map def) { + opset_version = std::move(def); + } + + const std::unordered_map& get_range_constraints() const { + return range_constraints; + } + + void set_range_constraints(std::unordered_map def) { + range_constraints = std::move(def); + } + + const SchemaVersion& get_schema_version() const { + return schema_version; + } + + void set_schema_version(SchemaVersion def) { + schema_version = std::move(def); + } + + const std::vector& get_verifiers() const { + return verifiers; + } + + void set_verifiers(std::vector def) { + verifiers = std::move(def); + } + + const std::string& get_torch_version() const { + return torch_version; + } + + void set_torch_version(std::string def) { + torch_version = std::move(def); + } + + const std::vector& get_guards_code() const { + return guards_code; + } + + void set_guards_code(std::vector def) { + guards_code = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const ExportedProgram& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, ExportedProgram& nlohmann_json_t); +}; + +class PayloadMeta { + private: + std::string path_name; + bool is_param; + bool use_pickle; + std::optional tensor_meta; + + public: + + const std::string& get_path_name() const { + return path_name; + } + + void set_path_name(std::string def) { + path_name = std::move(def); + } + + const bool& get_is_param() const { + return is_param; + } + + void set_is_param(bool def) { + is_param = std::move(def); + } + + const bool& get_use_pickle() const { + return use_pickle; + } + + void set_use_pickle(bool def) { + use_pickle = std::move(def); + } + + const std::optional& get_tensor_meta() const { + return tensor_meta; + } + + void set_tensor_meta(std::optional def) { + tensor_meta = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const PayloadMeta& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, PayloadMeta& nlohmann_json_t); +}; + +class PayloadConfig { + private: + std::unordered_map config; + + public: + + const std::unordered_map& get_config() const { + return config; + } + + void set_config(std::unordered_map def) { + config = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const PayloadConfig& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, PayloadConfig& nlohmann_json_t); +}; + +class AOTInductorModelPickleData { + private: + std::string library_basename; + std::vector input_names; + std::vector output_names; + std::optional floating_point_input_dtype = std::nullopt; + std::optional floating_point_output_dtype = std::nullopt; + std::optional aot_inductor_model_is_cpu = std::nullopt; + + public: + + const std::string& get_library_basename() const { + return library_basename; + } + + void set_library_basename(std::string def) { + library_basename = std::move(def); + } + + const std::vector& get_input_names() const { + return input_names; + } + + void set_input_names(std::vector def) { + input_names = std::move(def); + } + + const std::vector& get_output_names() const { + return output_names; + } + + void set_output_names(std::vector def) { + output_names = std::move(def); + } + + const std::optional& get_floating_point_input_dtype() const { + return floating_point_input_dtype; + } + + void set_floating_point_input_dtype(std::optional def) { + floating_point_input_dtype = std::move(def); + } + + const std::optional& get_floating_point_output_dtype() const { + return floating_point_output_dtype; + } + + void set_floating_point_output_dtype(std::optional def) { + floating_point_output_dtype = std::move(def); + } + + const std::optional& get_aot_inductor_model_is_cpu() const { + return aot_inductor_model_is_cpu; + } + + void set_aot_inductor_model_is_cpu(std::optional def) { + aot_inductor_model_is_cpu = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const AOTInductorModelPickleData& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, AOTInductorModelPickleData& nlohmann_json_t); +}; + +class ExternKernelNode { + private: + std::string name; + Node node; + + public: + + const std::string& get_name() const { + return name; + } + + void set_name(std::string def) { + name = std::move(def); + } + + const Node& get_node() const { + return node; + } + + void set_node(Node def) { + node = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const ExternKernelNode& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, ExternKernelNode& nlohmann_json_t); +}; + +class ExternKernelNodes { + private: + std::vector nodes; + + public: + + const std::vector& get_nodes() const { + return nodes; + } + + void set_nodes(std::vector def) { + nodes = std::move(def); + } + + friend void to_json(nlohmann::json& nlohmann_json_j, const ExternKernelNodes& nlohmann_json_t); + friend void from_json(const nlohmann::json& nlohmann_json_j, ExternKernelNodes& nlohmann_json_t); +}; + +inline void to_json(nlohmann::json& nlohmann_json_j, const AOTInductorModelPickleData& nlohmann_json_t) { + nlohmann_json_j["library_basename"] = nlohmann_json_t.library_basename; + nlohmann_json_j["input_names"] = nlohmann_json_t.input_names; + nlohmann_json_j["output_names"] = nlohmann_json_t.output_names; + nlohmann_json_j["floating_point_input_dtype"] = nlohmann_json_t.floating_point_input_dtype; + nlohmann_json_j["floating_point_output_dtype"] = nlohmann_json_t.floating_point_output_dtype; + nlohmann_json_j["aot_inductor_model_is_cpu"] = nlohmann_json_t.aot_inductor_model_is_cpu; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, AOTInductorModelPickleData& nlohmann_json_t) { + AOTInductorModelPickleData nlohmann_json_default_obj; + nlohmann_json_t.library_basename = nlohmann_json_j.value("library_basename", nlohmann_json_default_obj.library_basename); + nlohmann_json_t.input_names = nlohmann_json_j.value("input_names", nlohmann_json_default_obj.input_names); + nlohmann_json_t.output_names = nlohmann_json_j.value("output_names", nlohmann_json_default_obj.output_names); + nlohmann_json_t.floating_point_input_dtype = nlohmann_json_j.value("floating_point_input_dtype", nlohmann_json_default_obj.floating_point_input_dtype); + nlohmann_json_t.floating_point_output_dtype = nlohmann_json_j.value("floating_point_output_dtype", nlohmann_json_default_obj.floating_point_output_dtype); + nlohmann_json_t.aot_inductor_model_is_cpu = nlohmann_json_j.value("aot_inductor_model_is_cpu", nlohmann_json_default_obj.aot_inductor_model_is_cpu); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const BufferMutationSpec& nlohmann_json_t) { + nlohmann_json_j["arg"] = nlohmann_json_t.arg; + nlohmann_json_j["buffer_name"] = nlohmann_json_t.buffer_name; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, BufferMutationSpec& nlohmann_json_t) { + BufferMutationSpec nlohmann_json_default_obj; + nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg); + nlohmann_json_t.buffer_name = nlohmann_json_j.value("buffer_name", nlohmann_json_default_obj.buffer_name); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const ComplexValue& nlohmann_json_t) { + nlohmann_json_j["real"] = nlohmann_json_t.real; + nlohmann_json_j["imag"] = nlohmann_json_t.imag; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, ComplexValue& nlohmann_json_t) { + ComplexValue nlohmann_json_default_obj; + nlohmann_json_t.real = nlohmann_json_j.value("real", nlohmann_json_default_obj.real); + nlohmann_json_t.imag = nlohmann_json_j.value("imag", nlohmann_json_default_obj.imag); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const CustomObjArgument& nlohmann_json_t) { + nlohmann_json_j["name"] = nlohmann_json_t.name; + nlohmann_json_j["class_fqn"] = nlohmann_json_t.class_fqn; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, CustomObjArgument& nlohmann_json_t) { + CustomObjArgument nlohmann_json_default_obj; + nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name); + nlohmann_json_t.class_fqn = nlohmann_json_j.value("class_fqn", nlohmann_json_default_obj.class_fqn); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const Device& nlohmann_json_t) { + nlohmann_json_j["type"] = nlohmann_json_t.type; + nlohmann_json_j["index"] = nlohmann_json_t.index; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, Device& nlohmann_json_t) { + Device nlohmann_json_default_obj; + nlohmann_json_t.type = nlohmann_json_j.value("type", nlohmann_json_default_obj.type); + nlohmann_json_t.index = nlohmann_json_j.value("index", nlohmann_json_default_obj.index); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const ExportedProgram& nlohmann_json_t) { + nlohmann_json_j["graph_module"] = nlohmann_json_t.graph_module; + nlohmann_json_j["opset_version"] = nlohmann_json_t.opset_version; + nlohmann_json_j["range_constraints"] = nlohmann_json_t.range_constraints; + nlohmann_json_j["schema_version"] = nlohmann_json_t.schema_version; + nlohmann_json_j["verifiers"] = nlohmann_json_t.verifiers; + nlohmann_json_j["torch_version"] = nlohmann_json_t.torch_version; + nlohmann_json_j["guards_code"] = nlohmann_json_t.guards_code; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, ExportedProgram& nlohmann_json_t) { + ExportedProgram nlohmann_json_default_obj; + nlohmann_json_t.graph_module = nlohmann_json_j.value("graph_module", nlohmann_json_default_obj.graph_module); + nlohmann_json_t.opset_version = nlohmann_json_j.value("opset_version", nlohmann_json_default_obj.opset_version); + nlohmann_json_t.range_constraints = nlohmann_json_j.value("range_constraints", nlohmann_json_default_obj.range_constraints); + nlohmann_json_t.schema_version = nlohmann_json_j.value("schema_version", nlohmann_json_default_obj.schema_version); + nlohmann_json_t.verifiers = nlohmann_json_j.value("verifiers", nlohmann_json_default_obj.verifiers); + nlohmann_json_t.torch_version = nlohmann_json_j.value("torch_version", nlohmann_json_default_obj.torch_version); + nlohmann_json_t.guards_code = nlohmann_json_j.value("guards_code", nlohmann_json_default_obj.guards_code); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const ExternKernelNode& nlohmann_json_t) { + nlohmann_json_j["name"] = nlohmann_json_t.name; + nlohmann_json_j["node"] = nlohmann_json_t.node; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, ExternKernelNode& nlohmann_json_t) { + ExternKernelNode nlohmann_json_default_obj; + nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name); + nlohmann_json_t.node = nlohmann_json_j.value("node", nlohmann_json_default_obj.node); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const ExternKernelNodes& nlohmann_json_t) { + nlohmann_json_j["nodes"] = nlohmann_json_t.nodes; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, ExternKernelNodes& nlohmann_json_t) { + ExternKernelNodes nlohmann_json_default_obj; + nlohmann_json_t.nodes = nlohmann_json_j.value("nodes", nlohmann_json_default_obj.nodes); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const GradientToParameterSpec& nlohmann_json_t) { + nlohmann_json_j["arg"] = nlohmann_json_t.arg; + nlohmann_json_j["parameter_name"] = nlohmann_json_t.parameter_name; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, GradientToParameterSpec& nlohmann_json_t) { + GradientToParameterSpec nlohmann_json_default_obj; + nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg); + nlohmann_json_t.parameter_name = nlohmann_json_j.value("parameter_name", nlohmann_json_default_obj.parameter_name); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const GradientToUserInputSpec& nlohmann_json_t) { + nlohmann_json_j["arg"] = nlohmann_json_t.arg; + nlohmann_json_j["user_input_name"] = nlohmann_json_t.user_input_name; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, GradientToUserInputSpec& nlohmann_json_t) { + GradientToUserInputSpec nlohmann_json_default_obj; + nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg); + nlohmann_json_t.user_input_name = nlohmann_json_j.value("user_input_name", nlohmann_json_default_obj.user_input_name); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const Graph& nlohmann_json_t) { + nlohmann_json_j["inputs"] = nlohmann_json_t.inputs; + nlohmann_json_j["outputs"] = nlohmann_json_t.outputs; + nlohmann_json_j["nodes"] = nlohmann_json_t.nodes; + nlohmann_json_j["tensor_values"] = nlohmann_json_t.tensor_values; + nlohmann_json_j["sym_int_values"] = nlohmann_json_t.sym_int_values; + nlohmann_json_j["sym_bool_values"] = nlohmann_json_t.sym_bool_values; + nlohmann_json_j["is_single_tensor_return"] = nlohmann_json_t.is_single_tensor_return; + nlohmann_json_j["custom_obj_values"] = nlohmann_json_t.custom_obj_values; + nlohmann_json_j["sym_float_values"] = nlohmann_json_t.sym_float_values; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, Graph& nlohmann_json_t) { + Graph nlohmann_json_default_obj; + nlohmann_json_t.inputs = nlohmann_json_j.value("inputs", nlohmann_json_default_obj.inputs); + nlohmann_json_t.outputs = nlohmann_json_j.value("outputs", nlohmann_json_default_obj.outputs); + nlohmann_json_t.nodes = nlohmann_json_j.value("nodes", nlohmann_json_default_obj.nodes); + nlohmann_json_t.tensor_values = nlohmann_json_j.value("tensor_values", nlohmann_json_default_obj.tensor_values); + nlohmann_json_t.sym_int_values = nlohmann_json_j.value("sym_int_values", nlohmann_json_default_obj.sym_int_values); + nlohmann_json_t.sym_bool_values = nlohmann_json_j.value("sym_bool_values", nlohmann_json_default_obj.sym_bool_values); + nlohmann_json_t.is_single_tensor_return = nlohmann_json_j.value("is_single_tensor_return", nlohmann_json_default_obj.is_single_tensor_return); + nlohmann_json_t.custom_obj_values = nlohmann_json_j.value("custom_obj_values", nlohmann_json_default_obj.custom_obj_values); + nlohmann_json_t.sym_float_values = nlohmann_json_j.value("sym_float_values", nlohmann_json_default_obj.sym_float_values); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const GraphArgument& nlohmann_json_t) { + nlohmann_json_j["name"] = nlohmann_json_t.name; + nlohmann_json_j["graph"] = nlohmann_json_t.graph; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, GraphArgument& nlohmann_json_t) { + GraphArgument nlohmann_json_default_obj; + nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name); + nlohmann_json_t.graph = nlohmann_json_j.value("graph", nlohmann_json_default_obj.graph); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const GraphModule& nlohmann_json_t) { + nlohmann_json_j["graph"] = nlohmann_json_t.graph; + nlohmann_json_j["signature"] = nlohmann_json_t.signature; + nlohmann_json_j["module_call_graph"] = nlohmann_json_t.module_call_graph; + nlohmann_json_j["metadata"] = nlohmann_json_t.metadata; + nlohmann_json_j["treespec_namedtuple_fields"] = nlohmann_json_t.treespec_namedtuple_fields; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, GraphModule& nlohmann_json_t) { + GraphModule nlohmann_json_default_obj; + nlohmann_json_t.graph = nlohmann_json_j.value("graph", nlohmann_json_default_obj.graph); + nlohmann_json_t.signature = nlohmann_json_j.value("signature", nlohmann_json_default_obj.signature); + nlohmann_json_t.module_call_graph = nlohmann_json_j.value("module_call_graph", nlohmann_json_default_obj.module_call_graph); + nlohmann_json_t.metadata = nlohmann_json_j.value("metadata", nlohmann_json_default_obj.metadata); + nlohmann_json_t.treespec_namedtuple_fields = nlohmann_json_j.value("treespec_namedtuple_fields", nlohmann_json_default_obj.treespec_namedtuple_fields); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const GraphSignature& nlohmann_json_t) { + nlohmann_json_j["input_specs"] = nlohmann_json_t.input_specs; + nlohmann_json_j["output_specs"] = nlohmann_json_t.output_specs; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, GraphSignature& nlohmann_json_t) { + GraphSignature nlohmann_json_default_obj; + nlohmann_json_t.input_specs = nlohmann_json_j.value("input_specs", nlohmann_json_default_obj.input_specs); + nlohmann_json_t.output_specs = nlohmann_json_j.value("output_specs", nlohmann_json_default_obj.output_specs); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const InputToBufferSpec& nlohmann_json_t) { + nlohmann_json_j["arg"] = nlohmann_json_t.arg; + nlohmann_json_j["buffer_name"] = nlohmann_json_t.buffer_name; + nlohmann_json_j["persistent"] = nlohmann_json_t.persistent; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, InputToBufferSpec& nlohmann_json_t) { + InputToBufferSpec nlohmann_json_default_obj; + nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg); + nlohmann_json_t.buffer_name = nlohmann_json_j.value("buffer_name", nlohmann_json_default_obj.buffer_name); + nlohmann_json_t.persistent = nlohmann_json_j.value("persistent", nlohmann_json_default_obj.persistent); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const InputToConstantInputSpec& nlohmann_json_t) { + nlohmann_json_j["name"] = nlohmann_json_t.name; + nlohmann_json_j["value"] = nlohmann_json_t.value; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, InputToConstantInputSpec& nlohmann_json_t) { + InputToConstantInputSpec nlohmann_json_default_obj; + nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name); + nlohmann_json_t.value = nlohmann_json_j.value("value", nlohmann_json_default_obj.value); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const InputToCustomObjSpec& nlohmann_json_t) { + nlohmann_json_j["arg"] = nlohmann_json_t.arg; + nlohmann_json_j["custom_obj_name"] = nlohmann_json_t.custom_obj_name; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, InputToCustomObjSpec& nlohmann_json_t) { + InputToCustomObjSpec nlohmann_json_default_obj; + nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg); + nlohmann_json_t.custom_obj_name = nlohmann_json_j.value("custom_obj_name", nlohmann_json_default_obj.custom_obj_name); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const InputToParameterSpec& nlohmann_json_t) { + nlohmann_json_j["arg"] = nlohmann_json_t.arg; + nlohmann_json_j["parameter_name"] = nlohmann_json_t.parameter_name; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, InputToParameterSpec& nlohmann_json_t) { + InputToParameterSpec nlohmann_json_default_obj; + nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg); + nlohmann_json_t.parameter_name = nlohmann_json_j.value("parameter_name", nlohmann_json_default_obj.parameter_name); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const InputToTensorConstantSpec& nlohmann_json_t) { + nlohmann_json_j["arg"] = nlohmann_json_t.arg; + nlohmann_json_j["tensor_constant_name"] = nlohmann_json_t.tensor_constant_name; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, InputToTensorConstantSpec& nlohmann_json_t) { + InputToTensorConstantSpec nlohmann_json_default_obj; + nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg); + nlohmann_json_t.tensor_constant_name = nlohmann_json_j.value("tensor_constant_name", nlohmann_json_default_obj.tensor_constant_name); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const InputTokenSpec& nlohmann_json_t) { + nlohmann_json_j["arg"] = nlohmann_json_t.arg; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, InputTokenSpec& nlohmann_json_t) { + InputTokenSpec nlohmann_json_default_obj; + nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const LossOutputSpec& nlohmann_json_t) { + nlohmann_json_j["arg"] = nlohmann_json_t.arg; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, LossOutputSpec& nlohmann_json_t) { + LossOutputSpec nlohmann_json_default_obj; + nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const ModuleCallEntry& nlohmann_json_t) { + nlohmann_json_j["fqn"] = nlohmann_json_t.fqn; + nlohmann_json_j["signature"] = nlohmann_json_t.signature; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, ModuleCallEntry& nlohmann_json_t) { + ModuleCallEntry nlohmann_json_default_obj; + nlohmann_json_t.fqn = nlohmann_json_j.value("fqn", nlohmann_json_default_obj.fqn); + nlohmann_json_t.signature = nlohmann_json_j.value("signature", nlohmann_json_default_obj.signature); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const ModuleCallSignature& nlohmann_json_t) { + nlohmann_json_j["inputs"] = nlohmann_json_t.inputs; + nlohmann_json_j["outputs"] = nlohmann_json_t.outputs; + nlohmann_json_j["in_spec"] = nlohmann_json_t.in_spec; + nlohmann_json_j["out_spec"] = nlohmann_json_t.out_spec; + nlohmann_json_j["forward_arg_names"] = nlohmann_json_t.forward_arg_names; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, ModuleCallSignature& nlohmann_json_t) { + ModuleCallSignature nlohmann_json_default_obj; + nlohmann_json_t.inputs = nlohmann_json_j.value("inputs", nlohmann_json_default_obj.inputs); + nlohmann_json_t.outputs = nlohmann_json_j.value("outputs", nlohmann_json_default_obj.outputs); + nlohmann_json_t.in_spec = nlohmann_json_j.value("in_spec", nlohmann_json_default_obj.in_spec); + nlohmann_json_t.out_spec = nlohmann_json_j.value("out_spec", nlohmann_json_default_obj.out_spec); + nlohmann_json_t.forward_arg_names = nlohmann_json_j.value("forward_arg_names", nlohmann_json_default_obj.forward_arg_names); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const NamedArgument& nlohmann_json_t) { + nlohmann_json_j["name"] = nlohmann_json_t.name; + nlohmann_json_j["arg"] = nlohmann_json_t.arg; + nlohmann_json_j["kind"] = nlohmann_json_t.kind; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, NamedArgument& nlohmann_json_t) { + NamedArgument nlohmann_json_default_obj; + nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name); + nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg); + nlohmann_json_t.kind = nlohmann_json_j.value("kind", nlohmann_json_default_obj.kind); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const NamedTupleDef& nlohmann_json_t) { + nlohmann_json_j["field_names"] = nlohmann_json_t.field_names; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, NamedTupleDef& nlohmann_json_t) { + NamedTupleDef nlohmann_json_default_obj; + nlohmann_json_t.field_names = nlohmann_json_j.value("field_names", nlohmann_json_default_obj.field_names); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const Node& nlohmann_json_t) { + nlohmann_json_j["target"] = nlohmann_json_t.target; + nlohmann_json_j["inputs"] = nlohmann_json_t.inputs; + nlohmann_json_j["outputs"] = nlohmann_json_t.outputs; + nlohmann_json_j["metadata"] = nlohmann_json_t.metadata; + nlohmann_json_j["is_hop_single_tensor_return"] = nlohmann_json_t.is_hop_single_tensor_return; + nlohmann_json_j["name"] = nlohmann_json_t.name; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, Node& nlohmann_json_t) { + Node nlohmann_json_default_obj; + nlohmann_json_t.target = nlohmann_json_j.value("target", nlohmann_json_default_obj.target); + nlohmann_json_t.inputs = nlohmann_json_j.value("inputs", nlohmann_json_default_obj.inputs); + nlohmann_json_t.outputs = nlohmann_json_j.value("outputs", nlohmann_json_default_obj.outputs); + nlohmann_json_t.metadata = nlohmann_json_j.value("metadata", nlohmann_json_default_obj.metadata); + nlohmann_json_t.is_hop_single_tensor_return = nlohmann_json_j.value("is_hop_single_tensor_return", nlohmann_json_default_obj.is_hop_single_tensor_return); + nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const OutputTokenSpec& nlohmann_json_t) { + nlohmann_json_j["arg"] = nlohmann_json_t.arg; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, OutputTokenSpec& nlohmann_json_t) { + OutputTokenSpec nlohmann_json_default_obj; + nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const ParameterMutationSpec& nlohmann_json_t) { + nlohmann_json_j["arg"] = nlohmann_json_t.arg; + nlohmann_json_j["parameter_name"] = nlohmann_json_t.parameter_name; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, ParameterMutationSpec& nlohmann_json_t) { + ParameterMutationSpec nlohmann_json_default_obj; + nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg); + nlohmann_json_t.parameter_name = nlohmann_json_j.value("parameter_name", nlohmann_json_default_obj.parameter_name); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const PayloadConfig& nlohmann_json_t) { + nlohmann_json_j["config"] = nlohmann_json_t.config; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, PayloadConfig& nlohmann_json_t) { + PayloadConfig nlohmann_json_default_obj; + nlohmann_json_t.config = nlohmann_json_j.value("config", nlohmann_json_default_obj.config); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const PayloadMeta& nlohmann_json_t) { + nlohmann_json_j["path_name"] = nlohmann_json_t.path_name; + nlohmann_json_j["is_param"] = nlohmann_json_t.is_param; + nlohmann_json_j["use_pickle"] = nlohmann_json_t.use_pickle; + nlohmann_json_j["tensor_meta"] = nlohmann_json_t.tensor_meta; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, PayloadMeta& nlohmann_json_t) { + PayloadMeta nlohmann_json_default_obj; + nlohmann_json_t.path_name = nlohmann_json_j.value("path_name", nlohmann_json_default_obj.path_name); + nlohmann_json_t.is_param = nlohmann_json_j.value("is_param", nlohmann_json_default_obj.is_param); + nlohmann_json_t.use_pickle = nlohmann_json_j.value("use_pickle", nlohmann_json_default_obj.use_pickle); + nlohmann_json_t.tensor_meta = nlohmann_json_j.value("tensor_meta", nlohmann_json_default_obj.tensor_meta); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const RangeConstraint& nlohmann_json_t) { + nlohmann_json_j["min_val"] = nlohmann_json_t.min_val; + nlohmann_json_j["max_val"] = nlohmann_json_t.max_val; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, RangeConstraint& nlohmann_json_t) { + RangeConstraint nlohmann_json_default_obj; + nlohmann_json_t.min_val = nlohmann_json_j.value("min_val", nlohmann_json_default_obj.min_val); + nlohmann_json_t.max_val = nlohmann_json_j.value("max_val", nlohmann_json_default_obj.max_val); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const SchemaVersion& nlohmann_json_t) { + nlohmann_json_j["major"] = nlohmann_json_t.major; + nlohmann_json_j["minor"] = nlohmann_json_t.minor; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, SchemaVersion& nlohmann_json_t) { + SchemaVersion nlohmann_json_default_obj; + nlohmann_json_t.major = nlohmann_json_j.value("major", nlohmann_json_default_obj.major); + nlohmann_json_t.minor = nlohmann_json_j.value("minor", nlohmann_json_default_obj.minor); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const SymExpr& nlohmann_json_t) { + nlohmann_json_j["expr_str"] = nlohmann_json_t.expr_str; + nlohmann_json_j["hint"] = nlohmann_json_t.hint; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, SymExpr& nlohmann_json_t) { + SymExpr nlohmann_json_default_obj; + nlohmann_json_t.expr_str = nlohmann_json_j.value("expr_str", nlohmann_json_default_obj.expr_str); + nlohmann_json_t.hint = nlohmann_json_j.value("hint", nlohmann_json_default_obj.hint); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const TensorArgument& nlohmann_json_t) { + nlohmann_json_j["name"] = nlohmann_json_t.name; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, TensorArgument& nlohmann_json_t) { + TensorArgument nlohmann_json_default_obj; + nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const TensorMeta& nlohmann_json_t) { + nlohmann_json_j["dtype"] = nlohmann_json_t.dtype; + nlohmann_json_j["sizes"] = nlohmann_json_t.sizes; + nlohmann_json_j["requires_grad"] = nlohmann_json_t.requires_grad; + nlohmann_json_j["device"] = nlohmann_json_t.device; + nlohmann_json_j["strides"] = nlohmann_json_t.strides; + nlohmann_json_j["storage_offset"] = nlohmann_json_t.storage_offset; + nlohmann_json_j["layout"] = nlohmann_json_t.layout; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, TensorMeta& nlohmann_json_t) { + TensorMeta nlohmann_json_default_obj; + nlohmann_json_t.dtype = nlohmann_json_j.value("dtype", nlohmann_json_default_obj.dtype); + nlohmann_json_t.sizes = nlohmann_json_j.value("sizes", nlohmann_json_default_obj.sizes); + nlohmann_json_t.requires_grad = nlohmann_json_j.value("requires_grad", nlohmann_json_default_obj.requires_grad); + nlohmann_json_t.device = nlohmann_json_j.value("device", nlohmann_json_default_obj.device); + nlohmann_json_t.strides = nlohmann_json_j.value("strides", nlohmann_json_default_obj.strides); + nlohmann_json_t.storage_offset = nlohmann_json_j.value("storage_offset", nlohmann_json_default_obj.storage_offset); + nlohmann_json_t.layout = nlohmann_json_j.value("layout", nlohmann_json_default_obj.layout); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const TokenArgument& nlohmann_json_t) { + nlohmann_json_j["name"] = nlohmann_json_t.name; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, TokenArgument& nlohmann_json_t) { + TokenArgument nlohmann_json_default_obj; + nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const UserInputMutationSpec& nlohmann_json_t) { + nlohmann_json_j["arg"] = nlohmann_json_t.arg; + nlohmann_json_j["user_input_name"] = nlohmann_json_t.user_input_name; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, UserInputMutationSpec& nlohmann_json_t) { + UserInputMutationSpec nlohmann_json_default_obj; + nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg); + nlohmann_json_t.user_input_name = nlohmann_json_j.value("user_input_name", nlohmann_json_default_obj.user_input_name); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const UserInputSpec& nlohmann_json_t) { + nlohmann_json_j["arg"] = nlohmann_json_t.arg; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, UserInputSpec& nlohmann_json_t) { + UserInputSpec nlohmann_json_default_obj; + nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg); +} + +inline void to_json(nlohmann::json& nlohmann_json_j, const UserOutputSpec& nlohmann_json_t) { + nlohmann_json_j["arg"] = nlohmann_json_t.arg; +} + +inline void from_json(const nlohmann::json& nlohmann_json_j, UserOutputSpec& nlohmann_json_t) { + UserOutputSpec nlohmann_json_default_obj; + nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg); +} + + +template ForwardRef::ForwardRef(ForwardRef&&) = default; +template ForwardRef& ForwardRef::operator=(ForwardRef&&) = default; +template ForwardRef::~ForwardRef() = default; +} // namespace _export +} // namespace torch + +// clang-format on + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/init.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/init.h new file mode 100644 index 0000000000000000000000000000000000000000..0496865beeb547590c24aa992f4484333fe02230 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/init.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::throughput_benchmark { + +void initThroughputBenchmarkBindings(PyObject* module); + +} // namespace torch::throughput_benchmark + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/invalid_arguments.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/invalid_arguments.h new file mode 100644 index 0000000000000000000000000000000000000000..d2e818adf738250bc1a707af802d2915e9711067 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/invalid_arguments.h @@ -0,0 +1,20 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace torch { + +std::string format_invalid_args( + PyObject* given_args, + PyObject* given_kwargs, + const std::string& function_name, + const std::vector& options); + +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/nested.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/nested.h new file mode 100644 index 0000000000000000000000000000000000000000..0d06a65acbe2b076b72dd01d6ceed3f10cc51dc6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/nested.h @@ -0,0 +1,20 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include + +namespace torch::utils { + +at::Tensor nested_tensor_ctor( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PythonArgs& r); + +} // namespace torch::utils + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/numpy_stub.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/numpy_stub.h new file mode 100644 index 0000000000000000000000000000000000000000..11846d0879f0b2b95c46190d997ac9a0e011e840 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/numpy_stub.h @@ -0,0 +1,26 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +#ifdef USE_NUMPY + +#if !defined(NO_IMPORT_ARRAY) && !defined(WITH_NUMPY_IMPORT_ARRAY) +#define NO_IMPORT_ARRAY +#endif + +#ifndef PY_ARRAY_UNIQUE_SYMBOL +#define PY_ARRAY_UNIQUE_SYMBOL __numpy_array_api +#endif + +#ifndef NPY_NO_DEPRECATED_API +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#endif + +#include + +#endif // USE_NUMPY + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/object_ptr.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/object_ptr.h new file mode 100644 index 0000000000000000000000000000000000000000..aabd25e545d5df22e2480dce0cd01d9f69c68d3b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/object_ptr.h @@ -0,0 +1,86 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +template +class TORCH_PYTHON_API THPPointer { + public: + THPPointer() : ptr(nullptr) {} + explicit THPPointer(T* ptr) noexcept : ptr(ptr) {} + THPPointer(THPPointer&& p) noexcept : ptr(std::exchange(p.ptr, nullptr)) {} + THPPointer(const THPPointer& p) = delete; + THPPointer& operator=(const THPPointer&) = delete; + + ~THPPointer() { + free(); + } + T* get() { + return ptr; + } + const T* get() const { + return ptr; + } + THPPointer dup() const { + return dup(ptr); + } + static THPPointer dup(const T* ptr) { + Py_XINCREF(ptr); + return THPPointer( + const_cast(ptr)); // NOLINT(cppcoreguidelines-pro-type-const-cast) + } + static THPPointer none() { + Py_INCREF(Py_None); + return THPPointer(reinterpret_cast(Py_None)); + } + T* release() { + T* tmp = ptr; + ptr = nullptr; + return tmp; + } + operator T*() { + return ptr; + } + THPPointer& operator=(T* new_ptr) noexcept { + free(); + ptr = new_ptr; + return *this; + } + THPPointer& operator=(THPPointer&& p) noexcept { + free(); + ptr = p.ptr; + p.ptr = nullptr; + return *this; + } + T* operator->() { + return ptr; + } + explicit operator bool() const { + return ptr != nullptr; + } + + private: + void free(); + T* ptr = nullptr; +}; + +/** + * An RAII-style, owning pointer to a PyObject. You must protect + * destruction of this object with the GIL. + * + * WARNING: Think twice before putting this as a field in a C++ + * struct. This class does NOT take out the GIL on destruction, + * so if you will need to ensure that the destructor of your struct + * is either (a) always invoked when the GIL is taken or (b) takes + * out the GIL itself. Easiest way to avoid this problem is to + * not use THPPointer in this situation. + */ +using THPObjectPtr = THPPointer; +using THPCodeObjectPtr = THPPointer; +using THPFrameObjectPtr = THPPointer; + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/out_types.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/out_types.h new file mode 100644 index 0000000000000000000000000000000000000000..baa59bad3c1fce24c4f8dcaca5a3a9bf2ac99d89 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/out_types.h @@ -0,0 +1,20 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::utils { + +TORCH_API void check_out_type_matches( + const at::Tensor& result, + std::optional scalarType, + bool scalarType_is_none, + std::optional layout, + std::optional device, + bool device_is_none); + +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/pybind.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/pybind.h new file mode 100644 index 0000000000000000000000000000000000000000..4c399988a8d8a05859c9b71917e9e94c8b4147f6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/pybind.h @@ -0,0 +1,425 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace py = pybind11; + +#define IS_PYBIND_2_13_PLUS PYBIND11_VERSION_HEX >= 0x020D0000 + +// This makes intrusive_ptr to be available as a custom pybind11 holder type, +// see +// https://pybind11.readthedocs.io/en/stable/advanced/smart_ptrs.html#custom-smart-pointers +PYBIND11_DECLARE_HOLDER_TYPE(T, c10::intrusive_ptr, true) + +PYBIND11_DECLARE_HOLDER_TYPE(T, c10::SingletonOrSharedTypePtr) +PYBIND11_DECLARE_HOLDER_TYPE(T, c10::SingletonTypePtr, true) + +namespace pybind11::detail { + +// torch.Tensor <-> at::Tensor conversions (without unwrapping) +template <> +struct TORCH_PYTHON_API type_caster { + public: + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + PYBIND11_TYPE_CASTER(at::Tensor, _("torch.Tensor")); + + bool load(handle src, bool /*unused*/); + + static handle cast( + const at::Tensor& src, + return_value_policy /* policy */, + handle /* parent */); +}; + +// torch._StorageBase <-> at::Storage +template <> +struct type_caster { + public: + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + PYBIND11_TYPE_CASTER(at::Storage, _("torch.StorageBase")); + + bool load(handle src, bool /*unused*/) { + PyObject* obj = src.ptr(); + if (torch::isStorage(obj)) { + value = torch::createStorage(obj); + return true; + } + return false; + } + + static handle cast( + const at::Storage& src, + return_value_policy /* policy */, + handle /* parent */) { + return handle(torch::createPyObject(src)); + } +}; + +template <> +struct type_caster { + public: + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + PYBIND11_TYPE_CASTER(at::Generator, _("torch.Generator")); + + bool load(handle src, bool /*unused*/) { + PyObject* obj = src.ptr(); + if (THPGenerator_Check(obj)) { + value = reinterpret_cast(obj)->cdata; + return true; + } + return false; + } + + static handle cast( + const at::Generator& src, + return_value_policy /* policy */, + handle /* parent */) { + return handle(THPGenerator_Wrap(src)); + } +}; + +template <> +struct TORCH_PYTHON_API type_caster { + public: + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + PYBIND11_TYPE_CASTER(at::IntArrayRef, _("Tuple[int, ...]")); + + bool load(handle src, bool /*unused*/); + static handle cast( + at::IntArrayRef src, + return_value_policy /* policy */, + handle /* parent */); + + private: + std::vector v_value; +}; + +template <> +struct TORCH_PYTHON_API type_caster { + public: + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + PYBIND11_TYPE_CASTER(at::SymIntArrayRef, _("List[int]")); + + bool load(handle src, bool /*unused*/); + static handle cast( + at::SymIntArrayRef src, + return_value_policy /* policy */, + handle /* parent */); + + private: + std::vector v_value; +}; + +template <> +struct TORCH_PYTHON_API type_caster> { + public: + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + PYBIND11_TYPE_CASTER(at::ArrayRef, _("List[SymNode]")); + + bool load(handle src, bool /*unused*/); + static handle cast( + at::ArrayRef src, + return_value_policy /* policy */, + handle /* parent */); + + private: + std::vector v_value; +}; + +template <> +struct type_caster { + public: + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + PYBIND11_TYPE_CASTER(at::MemoryFormat, _("torch.memory_format")); + + bool load(handle src, bool /*unused*/) { + PyObject* obj = src.ptr(); + if (THPMemoryFormat_Check(obj)) { + value = reinterpret_cast(obj)->memory_format; + return true; + } + return false; + } + static handle cast( + at::MemoryFormat src, + return_value_policy /* policy */, + handle /* parent */) { + return handle(Py_NewRef(torch::utils::getTHPMemoryFormat(src))); + } +}; + +template <> +struct type_caster { + public: + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + PYBIND11_TYPE_CASTER(at::Device, _("torch.device")); + + // PYBIND11_TYPE_CASTER defines a member field called value. Since at::Device + // cannot be default-initialized, we provide this constructor to explicitly + // initialize that field. The value doesn't matter as it will be overwritten + // after a successful call to load. + type_caster() : value(c10::kCPU) {} + + bool load(handle src, bool /*unused*/) { + PyObject* obj = src.ptr(); + if (THPDevice_Check(obj)) { + value = reinterpret_cast(obj)->device; + return true; + } + return false; + } + + static handle cast( + const at::Device& src, + return_value_policy /* policy */, + handle /* parent */) { + return handle(THPDevice_New(src)); + } +}; + +template <> +struct type_caster { + public: + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + PYBIND11_TYPE_CASTER(at::ScalarType, _("torch.dtype")); + + // PYBIND11_TYPE_CASTER defines a member field called value. at::ScalarType + // cannot be default-initialized, we provide this constructor to explicitly + // initialize that field. The value doesn't matter as it will be overwritten + // after a successful call to load. + type_caster() : value(at::kFloat) {} + + bool load(handle src, bool /*unused*/) { + PyObject* obj = src.ptr(); + if (THPDtype_Check(obj)) { + value = reinterpret_cast(obj)->scalar_type; + return true; + } + return false; + } + + static handle cast( + const at::ScalarType& src, + return_value_policy /* policy */, + handle /* parent */) { + return Py_NewRef(torch::getTHPDtype(src)); + } +}; + +template <> +struct type_caster { + public: + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + PYBIND11_TYPE_CASTER(c10::Stream, _("torch.Stream")); + + // PYBIND11_TYPE_CASTER defines a member field called value. Since c10::Stream + // cannot be default-initialized, we provide this constructor to explicitly + // initialize that field. The value doesn't matter as it will be overwritten + // after a successful call to load. + type_caster() : value(c10::Stream::DEFAULT, c10::Device(c10::kCPU, 0)) {} + + bool load(handle src, bool /*unused*/) { + PyObject* obj = src.ptr(); + if (THPStream_Check(obj)) { + value = c10::Stream::unpack3( + ((THPStream*)obj)->stream_id, + static_cast(((THPStream*)obj)->device_index), + static_cast(((THPStream*)obj)->device_type)); + return true; + } + return false; + } + + static handle cast( + const c10::Stream& src, + return_value_policy /* policy */, + handle /* parent */) { + return handle(THPStream_Wrap(src)); + } +}; + +template <> +struct type_caster + : public type_caster_base { + using base = type_caster_base; + c10::DispatchKey tmp{}; + + public: + bool load(handle src, bool convert) { + if (base::load(src, convert)) { + return true; + } else if (py::isinstance( + src, py::module_::import("builtins").attr("str"))) { + tmp = c10::parseDispatchKey(py::cast(src)); + value = &tmp; + return true; + } + return false; + } + + static handle cast( + c10::DispatchKey src, + return_value_policy policy, + handle parent) { + return base::cast(src, policy, parent); + } +}; + +template <> +struct TORCH_PYTHON_API type_caster { + public: + PYBIND11_TYPE_CASTER( + c10::Scalar, + _("Union[Number, torch.SymInt, torch.SymFloat, torch.SymBool]")); + bool load(py::handle src, bool /*unused*/); + + static py::handle cast( + const c10::Scalar& si, + return_value_policy /* policy */, + handle /* parent */); +}; + +template <> +struct TORCH_PYTHON_API type_caster { + public: + PYBIND11_TYPE_CASTER(c10::SymInt, _("Union[int, torch.SymInt]")); + bool load(py::handle src, bool /*unused*/); + + static py::handle cast( + const c10::SymInt& si, + return_value_policy /* policy */, + handle /* parent */); +}; + +template <> +struct TORCH_PYTHON_API type_caster { + public: + PYBIND11_TYPE_CASTER(c10::SymFloat, _("float")); + bool load(py::handle src, bool /*unused*/); + + static py::handle cast( + const c10::SymFloat& si, + return_value_policy /* policy */, + handle /* parent */); +}; + +template <> +struct TORCH_PYTHON_API type_caster { + public: + PYBIND11_TYPE_CASTER(c10::SymBool, _("Union[bool, torch.SymBool]")); + bool load(py::handle src, bool /*unused*/); + + static py::handle cast( + const c10::SymBool& si, + return_value_policy /* policy */, + handle /* parent */); +}; + +template +struct type_caster> { + public: + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + PYBIND11_TYPE_CASTER(c10::complex, _("complex")); + + bool load(handle src, bool /*unused*/) { + PyObject* obj = src.ptr(); + + // Referred from `THPUtils_unpackComplexDouble` + Py_complex py_complex = PyComplex_AsCComplex(obj); + if (py_complex.real == -1.0 && PyErr_Occurred()) { + return false; + } + + // Python's Complex is always double precision. + value = c10::complex(py_complex.real, py_complex.imag); + return true; + } + + static handle cast( + const c10::complex& complex, + return_value_policy /* policy */, + handle /* parent */) { + // Python only knows double precision complex. + return handle(PyComplex_FromDoubles(complex.real(), complex.imag())); + } +}; + +} // namespace pybind11::detail + +namespace torch::impl { + +// Use this function if you have a C++ object that is used from both C++ +// and Python contexts, and you need its GIL to be released when you +// destruct it in the Python context. +// +// This function is a valid shared_ptr destructor and can be used to +// conveniently allocate a shared_ptr to an object whose destructor will be run +// without the GIL. Pass it as the second argument to shared_ptr, e.g., +// +// shared_ptr(new T(), destroy_without_gil) +// +// Attaching the GIL release logic to the holder pointer rather than the +// actual destructor of T is helpful when T is Python-agnostic and +// shouldn't refer to the PYthon API. +// +// Note there are limitations to the correctness of code that makes use of this. +// In particular, if a shared_ptr is constructed from C++ code without this +// destructor and then passed to pybind11, pybind11 will happily take ownership +// of the shared_ptr (and be willing to destruct it from a context where it is +// holding the GIL). unique_ptr with a type branded deleter is less prone to +// this problem, because a stock deleter unique_ptr is not convertible with it. +// I plan to mitigate this problem by adding DEBUG-only asserts to the true C++ +// destructors that the GIL is not held (using a virtual call to get to the +// Python interpreter); alternately, we could use a virtual call to simply +// ensure we release the GIL in the C++ destructor, however, this is a layering +// violation (why does code that is ostensibly Python agnostic calling into the +// GIL). +// +// Adapted from +// https://github.com/pybind/pybind11/issues/1446#issuecomment-406341510 +template +inline void destroy_without_gil(T* ptr) { + // Because the ownership of a shared_ptr is diffuse, it's not possible to + // necessarily predict whether or not the last reference to an object will + // be destructed from Python or C++. This means that in the destructor here, + // we don't necessarily know if we actually have the GIL or not; in fact, + // we don't even know if the Python interpreter still exists! Thus, we have + // to test for it before releasing the GIL. + // + // PyGILState_Check is hopefully self explanatory. But Py_IsInitialized or + // _PyIsFinalizing? Both get set at the same time during the Python + // destruction process: + // https://github.com/python/cpython/blob/d92513390a1a0da781bb08c284136f4d7abea36d/Python/pylifecycle.c#L1716-L1717 + // so the operant question is whether or not you want to release the GIL after + // finalization has completed (and there is just no Python interpreter). + // Clearly there is no need to release GIL in that state, so we want + // Py_IsInitialized. + if (Py_IsInitialized() && PyGILState_Check()) { + pybind11::gil_scoped_release nogil; + delete ptr; + } else { + delete ptr; + } +} + +} // namespace torch::impl + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/pycfunction_helpers.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/pycfunction_helpers.h new file mode 100644 index 0000000000000000000000000000000000000000..a4c40edc4d326b36ef1ab8f162e08a4fa70f01be --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/pycfunction_helpers.h @@ -0,0 +1,31 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include + +inline PyCFunction castPyCFunctionWithKeywords(PyCFunctionWithKeywords func) { + C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED("-Wcast-function-type") + C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED("-Wcast-function-type-strict") + return reinterpret_cast(func); + C10_DIAGNOSTIC_POP() + C10_DIAGNOSTIC_POP() +} + +#if !IS_PYTHON_3_13_PLUS +using PyCFunctionFast = _PyCFunctionFast; +#endif + +inline PyCFunction castPyCFunctionFast(PyCFunctionFast func) { + C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED("-Wcast-function-type") + C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED("-Wcast-function-type-strict") + return reinterpret_cast(func); + C10_DIAGNOSTIC_POP() + C10_DIAGNOSTIC_POP() +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/pyobject_preservation.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/pyobject_preservation.h new file mode 100644 index 0000000000000000000000000000000000000000..5c8183ae78cac120a7423a8917c9761cb9b79cf4 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/pyobject_preservation.h @@ -0,0 +1,36 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +// This file contains utilities used for handling PyObject preservation + +namespace c10 { +class intrusive_ptr_target; +namespace impl { +struct PyObjectSlot; +} // namespace impl +} // namespace c10 + +namespace torch::utils { + +class PyObjectPreservation { + public: + // Store a PyObject wrapper on a fresh c10 wrapper. The caller must hold + // a unique reference to `target`. + static void init_fresh_nonatomic( + c10::intrusive_ptr_target* target, + c10::impl::PyObjectSlot* slot, + PyObject* pyobj); + + static PyObject* init_once( + c10::intrusive_ptr_target* target, + c10::impl::PyObjectSlot* slot, + PyObject* pyobj); +}; + +} // namespace torch::utils + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_arg_parser.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_arg_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..4e170dcdbdf839890d9686d01c6d6ca7f841fb87 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_arg_parser.h @@ -0,0 +1,1377 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +// Parse arguments to Python functions implemented in C++ +// This is similar to PyArg_ParseTupleAndKeywords(), but specifically handles +// the types relevant to PyTorch and distinguishes between overloaded function +// signatures. +// +// Example: +// +// static PythonArgParser parser({ +// "norm(Scalar p, int64_t dim, bool keepdim=False)", +// "norm(Scalar p=2)", +// }); +// ParsedArgs<3> parsed_args; +// auto r = parser.parse(args, kwargs, parsed_args); +// if (r.idx == 0) { +// norm(r.scalar(0), r.int64(1), r.bool(0)); +// } else { +// norm(r.scalar(0)); +// } +// +// We auto-generate most uses of PythonArgParser; the generated files +// are torch/csrc/autograd/generated/python_*.cpp +// +// Some gotchas that you should watch out for: +// +// - Note [Order of overloads matters] +// Order of overloads matters. A set of input arguments may +// bind to multiple argument specs; we will always pick the +// first one in PythonArgParser. However, when you are writing +// overloads in, e.g., native_functions.yaml, you don't have to +// worry about what order you write them, because the code +// generation logic always gives the overloads a canonical +// order, where Tensor overloads come first, before Scalar overloads. +// This logic is in sort_declarations in +// tools/autograd/gen_python_functions.py +// +// - Zero-dim tensors (e.g., torch.tensor(2)) bind to both +// Scalar and Tensor, UNLESS they require grad (in which case +// they only bind to Tensor). + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +inline bool THPUtils_checkScalar(PyObject* obj) { +#ifdef USE_NUMPY + if (torch::utils::is_numpy_scalar(obj)) { + return true; + } +#endif + return PyFloat_Check(obj) || PyLong_Check(obj) || PyComplex_Check(obj) || + torch::is_symint(py::handle(obj)) || torch::is_dynint(py::handle(obj)) || + torch::is_symfloat(py::handle(obj)) || torch::is_symbool(py::handle(obj)); +} + +namespace torch { + +TORCH_PYTHON_API bool should_allow_numbers_as_tensors(const std::string& name); + +enum class ParameterType { + TENSOR, + SCALAR, + INT64, + SYM_INT, + DOUBLE, + COMPLEX, + TENSOR_LIST, + INT_LIST, + GENERATOR, + BOOL, + STORAGE, + PYOBJECT, + SCALARTYPE, + LAYOUT, + MEMORY_FORMAT, + DEVICE, + STREAM, + STRING, + DIMNAME, + DIMNAME_LIST, + QSCHEME, + FLOAT_LIST, + SCALAR_LIST, + SYM_INT_LIST, + DISPATCH_KEY_SET +}; + +struct PythonArgs; + +// Contains bound Python arguments in declaration order +template +struct ParsedArgs { + ParsedArgs() : args() {} + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays) + PyObject* args[N]; +}; + +// FunctionParameter is a single formal parameter of a Python function. +// It is immutable once constructed. +struct FunctionParameter { + FunctionParameter(const std::string& fmt, bool keyword_only); + + bool check( + PyObject* obj, + std::vector& overloaded_args, + int argnum, + int64_t* failed_idx = nullptr); + + bool _check( + PyObject* obj, + std::vector& overloaded_args, + int argnum, + int64_t* failed_idx = nullptr); + + void set_default_str(const std::string& str); + TORCH_PYTHON_API std::string type_name() const; + + ParameterType type_; + bool optional{false}; + bool allow_none{false}; + bool keyword_only; + bool allow_numbers_as_tensors = false; + int size{0}; + std::string name; + // having this as a raw PyObject * will presumably leak it, but these are only + // held by static objects anyway, and Py_Finalize can already be called when + // this is destructed. + PyObject* python_name; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) + at::SmallVector numpy_python_names; + at::Scalar default_scalar; + std::vector default_intlist; + std::string default_string; + union { + bool default_bool; + int64_t default_int; + double default_double; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays) + double default_complex[2]; // see Scalar + at::ScalarType default_scalartype; + at::Layout default_layout; + }; + std::string default_value; +}; + +// FunctionSignature represents a single valid signature for a Python function. +// It is immutable once constructed. The contained data can be concurrently +// accessed by multiple calls. +struct FunctionSignature { + explicit FunctionSignature(const std::string& fmt, int index); + + bool parse( + PyObject* self, + PyObject* args, + PyObject* kwargs, + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays) + PyObject* dst[], + std::vector& overloaded_args, + bool raise_exception); + + std::string toString() const; + + std::string name; + std::vector params; + size_t min_args{0}; + size_t max_args{0}; + size_t max_pos_args{0}; + int index; + bool hidden{false}; + bool deprecated{false}; +}; + +// A PythonArgParser contains a list of valid signatures. Instances are +// typically global variables and should be immutable. +struct PYBIND11_EXPORT PythonArgParser { + explicit PythonArgParser( + const std::vector& fmts, + bool traceable = false); + + // meant only for `torch` functions. + template + inline PythonArgs parse( + PyObject* self, + PyObject* args, + PyObject* kwargs, + ParsedArgs& dst); + + template + inline PythonArgs parse(PyObject* args, PyObject* kwargs, ParsedArgs& dst); + + inline PythonArgs parse(PyObject* self, ParsedArgs<0>& dst); + + // Formatted strings of non-hidden signatures + std::vector get_signatures() const; + + private: + [[noreturn]] void print_error( + PyObject* self, + PyObject* args, + PyObject* kwargs, + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays) + PyObject* parsed_args[]); + void check_deprecated(const FunctionSignature& signature); + PythonArgs raw_parse( + PyObject* self, + PyObject* args, + PyObject* kwargs, + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays) + PyObject* parsed_args[]); + + std::vector signatures_; + std::string function_name; + size_t max_args{0}; + bool traceable; +}; + +// PythonArgs contains bound Python arguments for an actual invocation +// along with references to the matched signature. +struct TORCH_PYTHON_API PythonArgs { + PythonArgs( + bool traceable, + const FunctionSignature& signature, + PyObject** args, + std::vector overloaded_args) + : idx(signature.index), + traceable(traceable), + signature(signature), + args(args), + overloaded_args(std::move(overloaded_args)) {} + + int idx; + bool traceable; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const FunctionSignature& signature; + PyObject** args; + std::vector overloaded_args; // NOTE: borrowed references + + inline bool has_torch_function(); + inline std::string get_func_name(); + inline at::Tensor tensor(int i); + inline std::optional optionalTensor(int i); + inline at::Scalar scalar(int i); + inline at::Scalar scalarWithDefault(int i, const at::Scalar& default_scalar); + inline std::vector scalarlist(int i); + inline std::vector tensorlist(int i); + inline torch::List> list_of_optional_tensors(int i); + template + inline std::array tensorlist_n(int i); + inline std::vector intlist(int i); + inline std::vector symintlist(int i); + inline c10::OptionalArray intlistOptional(int i); + inline c10::OptionalArray symintlistOptional(int i); + inline std::vector intlistWithDefault( + int i, + std::vector default_intlist); + inline std::optional generator(int i); + inline at::Storage storage(int i); + inline at::Storage storage( + int i, + at::ScalarType& storage_scalar_type, + bool& is_typed_storage); + inline c10::Stream stream(int i); + inline at::ScalarType scalartype(int i); + inline at::ScalarType scalartypeWithDefault( + int i, + at::ScalarType default_scalartype); + inline std::optional scalartypeOptional(int i); + inline std::optional scalarOptional(int i); + inline std::optional toInt64Optional(int i); + inline std::optional toSymIntOptional(int i); + inline std::optional toBoolOptional(int i); + inline std::optional toDoubleOptional(int i); + inline c10::OptionalArray doublelistOptional(int i); + inline std::vector doublelist(int i); + inline std::vector getDoublelist(int i); + inline at::Layout layout(int i); + inline at::Layout layoutWithDefault(int i, at::Layout default_layout); + inline std::optional layoutOptional(int i); + inline at::Device device(int i); + inline at::Device deviceWithDefault(int i, const at::Device& default_device); + inline std::optional deviceOptional(int i); + inline at::Dimname dimname(int i); + inline std::vector dimnamelist(int i); + inline std::optional> toDimnameListOptional(int i); + inline at::MemoryFormat memoryformat(int i); + inline std::optional memoryformatOptional(int i); + inline at::QScheme toQScheme(int i); + inline std::string string(int i); + inline std::string stringWithDefault(int i, const std::string& default_str); + inline std::optional stringOptional(int i); + inline std::string_view stringView(int i); + inline std::string_view stringViewWithDefault( + int i, + const std::string_view default_str); + inline std::optional stringViewOptional(int i); + inline PyObject* pyobject(int i); + inline int64_t toInt64(int i); + inline c10::SymInt toSymInt(int i); + inline c10::SymBool toSymBool(int i); + inline int64_t toInt64WithDefault(int i, int64_t default_int); + inline double toDouble(int i); + inline double toDoubleWithDefault(int i, double default_double); + inline c10::complex toComplex(int i); + inline c10::complex toComplexWithDefault( + int i, + c10::complex default_complex); + inline bool toBool(int i); + inline bool toBoolWithDefault(int i, bool default_bool); + inline bool isNone(int i); + inline std::optional toDispatchKeySetOptional(int i); + + private: + // Non-inline functions' symbols are exposed to torch_python DLL + // via TORCH_PYTHON_API tag at struct level. + at::Tensor tensor_slow(int i); + at::Scalar scalar_slow(int i); + at::Scalar scalar_slow(PyObject* arg); +}; + +template +inline PythonArgs PythonArgParser::parse( + PyObject* self, + PyObject* args, + PyObject* kwargs, + ParsedArgs& dst) { + TORCH_CHECK_VALUE( + N >= max_args, + "PythonArgParser: dst ParsedArgs buffer does not have enough capacity, expected ", + max_args, + " (got ", + N, + ")"); + return raw_parse(self, args, kwargs, dst.args); +} + +template +inline PythonArgs PythonArgParser::parse( + PyObject* args, + PyObject* kwargs, + ParsedArgs& dst) { + return parse(nullptr, args, kwargs, dst); +} + +inline PythonArgs PythonArgParser::parse(PyObject* self, ParsedArgs<0>& dst) { + return parse(self, nullptr, nullptr, dst); +} + +inline bool PythonArgs::has_torch_function() { + return !overloaded_args.empty() || at::impl::torch_function_mode_enabled(); +} + +inline std::string PythonArgs::get_func_name() { + return signature.name; +} + +// TODO: this can return MaybeOwned +inline at::Tensor PythonArgs::tensor(int i) { + if (args[i] && THPVariable_CheckExact(args[i])) { + return THPVariable_Unpack(args[i]); + } + return tensor_slow(i); +} + +inline std::optional PythonArgs::optionalTensor(int i) { + at::Tensor t = tensor(i); + // NOLINTNEXTLINE(bugprone-branch-clone) + if (t.defined()) { + return t; + } else { + return std::nullopt; + } +} + +inline at::Scalar PythonArgs::scalar(int i) { + if (!args[i]) + return signature.params[i].default_scalar; + return scalar_slow(i); +} + +inline std::vector PythonArgs::scalarlist(int i) { + if (!args[i]) + return std::vector(); + auto tuple = PyTuple_Check(args[i]); + TORCH_INTERNAL_ASSERT_DEBUG_ONLY(tuple || PyList_Check(args[i])); + // NOLINTNEXTLINE(bugprone-branch-clone) + auto size = tuple ? PyTuple_GET_SIZE(args[i]) : PyList_GET_SIZE(args[i]); + std::vector res(size); + for (const auto idx : c10::irange(size)) { + PyObject* obj = + tuple ? PyTuple_GET_ITEM(args[i], idx) : PyList_GET_ITEM(args[i], idx); + res[idx] = scalar_slow(obj); + } + return res; +} + +inline at::Scalar PythonArgs::scalarWithDefault( + int i, + const at::Scalar& default_scalar) { + if (!args[i]) + return default_scalar; + return scalar_slow(i); +} + +inline std::optional PythonArgs::scalarOptional(int i) { + if (!args[i]) + return std::nullopt; + return scalar_slow(i); +} + +inline std::vector PythonArgs::tensorlist(int i) { + if (!args[i]) + return std::vector(); + auto tuple = PyTuple_Check(args[i]); + TORCH_INTERNAL_ASSERT_DEBUG_ONLY(tuple || PyList_Check(args[i])); + // NOLINTNEXTLINE(bugprone-branch-clone) + auto size = tuple ? PyTuple_GET_SIZE(args[i]) : PyList_GET_SIZE(args[i]); + std::vector res(size); + for (const auto idx : c10::irange(size)) { + PyObject* obj = + tuple ? PyTuple_GET_ITEM(args[i], idx) : PyList_GET_ITEM(args[i], idx); + // This is checked by the argument parser so it's safe to cast without + // checking if this is a tensor first + res[idx] = THPVariable_Unpack(obj); + } + return res; +} + +inline torch::List> PythonArgs:: + list_of_optional_tensors(int i) { + if (!args[i]) + return torch::List>(); + auto tuple = PyTuple_Check(args[i]); + TORCH_INTERNAL_ASSERT_DEBUG_ONLY(tuple || PyList_Check(args[i])); + // NOLINTNEXTLINE(bugprone-branch-clone) + auto size = tuple ? PyTuple_GET_SIZE(args[i]) : PyList_GET_SIZE(args[i]); + torch::List> res; + res.reserve(size); + for (const auto idx : c10::irange(size)) { + PyObject* obj = + tuple ? PyTuple_GET_ITEM(args[i], idx) : PyList_GET_ITEM(args[i], idx); + // This is checked by the argument parser so it's safe to cast without + // checking if this is a tensor first + res.push_back(THPVariable_Unpack(obj)); + } + return res; +} + +template +inline std::array PythonArgs::tensorlist_n(int i) { + auto res = std::array(); + if (!args[i]) + return res; + auto tuple = PyTuple_Check(args[i]); + TORCH_INTERNAL_ASSERT_DEBUG_ONLY(tuple || PyList_Check(args[i])); + // NOLINTNEXTLINE(bugprone-branch-clone) + auto size = tuple ? PyTuple_GET_SIZE(args[i]) : PyList_GET_SIZE(args[i]); + if (size != N) { + TORCH_CHECK_TYPE( + false, + fmt::format("expected tuple of {} elements but got {}", N, size)); + } + for (const auto idx : c10::irange(size)) { + PyObject* obj = + tuple ? PyTuple_GET_ITEM(args[i], idx) : PyList_GET_ITEM(args[i], idx); + // This is checked by the argument parser so it's safe to cast without + // checking if this is a tensor first + res[idx] = THPVariable_Unpack(obj); + } + return res; +} + +inline std::vector PythonArgs::intlist(int i) { + return intlistWithDefault(i, signature.params[i].default_intlist); +} + +inline PyObject* toPyObject(const c10::SymInt& symint) { + if (symint.is_symbolic()) { + auto r = py::cast(symint).release().ptr(); + TORCH_INTERNAL_ASSERT(r); + return r; + } else { + auto m = symint.maybe_as_int(); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + return THPUtils_packInt64(m.value()); + } +} + +inline void throw_intlist_exception( + const torch::PythonArgs* args, + size_t i, + PyObject* obj, + size_t idx, + const std::exception& e = python_error()) { + std::string error = strlen(e.what()) + ? e.what() + : std::string("type must be ") + args->signature.params[i].type_name() + + ",but got " + Py_TYPE(obj)->tp_name; + TORCH_CHECK_TYPE( + false, + fmt::format( + "{}(): argument '{}' failed to unpack the object at pos {} with error \"{}\"", + args->signature.name, + args->signature.params[i].name, + idx + 1, + error)); +} + +inline std::vector PythonArgs::symintlist(int i) { + if (!args[i]) { + return c10::fmap(signature.params[i].default_intlist, [](int64_t di) { + return c10::SymInt(di); + }); + } + + const auto size1 = signature.params[i].size; + if (size1 > 0 && THPUtils_checkLong(args[i])) { + return std::vector( + size1, c10::SymInt(THPUtils_unpackLong(args[i]))); + } + + if (size1 > 0 && torch::is_symint(py::handle(args[i]))) { + auto si = py::handle(args[i]).cast(); + return std::vector(size1, si); + } + + if (size1 > 0 && THPVariable_Check(args[i])) { + return std::vector( + size1, THPVariable_Unpack(args[i]).item().toSymInt()); + } + + PyObject* arg = args[i]; + auto tuple = PyTuple_Check(arg); + if (!tuple) { + TORCH_INTERNAL_ASSERT(PyList_Check(arg), "expected tuple or list"); + } + // NOLINTNEXTLINE(bugprone-branch-clone) + const auto size2 = tuple ? PyTuple_GET_SIZE(arg) : PyList_GET_SIZE(arg); + std::vector res; + res.reserve(size2); + for (const auto idx : c10::irange(size2)) { + PyObject* obj = + tuple ? PyTuple_GET_ITEM(arg, idx) : PyList_GET_ITEM(arg, idx); + + // Elements of torch.Size are tensors during tracing, and we need to + // record extra information before they are turned into an IntArrayRef + if (traceable && jit::tracer::isTracing() && THPVariable_Check(obj)) { + auto& var = THPVariable_Unpack(obj); + jit::tracer::ArgumentStash::stashIntArrayRefElem( + signature.params[i].name, size2, idx, var); + try { + res.emplace_back(var.item()); + continue; + } catch (std::exception& e) { + throw_intlist_exception(this, i, obj, idx, e); + } + continue; + } else { + // convert tensor to scalar outside of try / catch, + // so that Tensor subclass exceptions will not be caught. + if (THPUtils_checkLongExact(obj)) { + // Fast path for plain numbers + try { + res.emplace_back(THPUtils_unpackLong(obj)); + } catch (std::exception& e) { + throw_intlist_exception(this, i, obj, idx, e); + } + } else if (THPVariable_Check(obj)) { + auto& var = THPVariable_Unpack(obj); + if (var.numel() != 1 || + !at::isIntegralType( + var.dtype().toScalarType(), /*include_bool*/ true)) { + throw_intlist_exception(this, i, obj, idx); + } + auto scalar = var.item(); + TORCH_CHECK(scalar.isIntegral(/*include bool*/ false)); + res.push_back(scalar.toSymInt()); + } else { + try { + if (is_symint(py::handle(obj))) { + res.push_back(py::handle(obj).cast()); + } else if (is_dynint(py::handle(obj))) { + res.emplace_back(py::handle(obj).cast()); + } else { + res.emplace_back(THPUtils_unpackIndex(obj)); + } + } catch (std::exception& e) { + throw_intlist_exception(this, i, obj, idx, e); + } + } + } + } + + return res; +} + +inline std::vector PythonArgs::intlistWithDefault( + int i, + std::vector default_intlist) { + if (!args[i]) + return default_intlist; + PyObject* arg = args[i]; + const auto size1 = signature.params[i].size; + if (size1 > 0 && THPUtils_checkLong(arg)) { + return std::vector(size1, THPUtils_unpackLong(arg)); + } + if (size1 > 0 && torch::is_symint(py::handle(arg))) { + return std::vector( + size1, + py::handle(arg).cast().guard_int(__FILE__, __LINE__)); + } + if (size1 > 0 && torch::is_dynint(py::handle(arg))) { + return std::vector(size1, py::handle(arg).cast()); + } + if (size1 > 0 && THPVariable_Check(arg)) { + return std::vector(size1, THPVariable_Unpack(arg).item()); + } + auto tuple = PyTuple_Check(arg); + if (!tuple) { + TORCH_INTERNAL_ASSERT(PyList_Check(arg), "expected tuple or list"); + } + // NOLINTNEXTLINE(bugprone-branch-clone) + const auto size2 = tuple ? PyTuple_GET_SIZE(arg) : PyList_GET_SIZE(arg); + std::vector res(size2); + for (const auto idx : c10::irange(size2)) { + PyObject* obj = + tuple ? PyTuple_GET_ITEM(arg, idx) : PyList_GET_ITEM(arg, idx); + // Elements of torch.Size are tensors during tracing, and we need to + // record extra information before they are turned into an IntArrayRef + if (traceable && jit::tracer::isTracing() && THPVariable_Check(obj)) { + auto& var = THPVariable_Unpack(obj); + jit::tracer::ArgumentStash::stashIntArrayRefElem( + signature.params[i].name, size2, idx, var); + try { + res[idx] = var.item(); + continue; + } catch (std::exception& e) { + throw_intlist_exception(this, i, obj, idx, e); + } + } else { + // convert tensor to scalar outside of try / catch, + // so that Tensor subclass exceptions will not be caught. + if (THPUtils_checkLongExact(obj)) { + // Fast path for plain numbers + try { + res[idx] = THPUtils_unpackLong(obj); + } catch (std::exception& e) { + throw_intlist_exception(this, i, obj, idx, e); + } + } else if (torch::is_symint(py::handle(obj))) { + res[idx] = py::cast(py::handle(obj)) + .guard_int(__FILE__, __LINE__); + } else if (torch::is_dynint(py::handle(obj))) { + res[idx] = py::handle(obj).cast(); + } else if (THPVariable_Check(obj)) { + auto& var = THPVariable_Unpack(obj); + if (var.numel() != 1 || + !at::isIntegralType( + var.dtype().toScalarType(), /*include_bool*/ true)) { + throw_intlist_exception(this, i, obj, idx); + } + res[idx] = var.item(); + } else { + try { + res[idx] = THPUtils_unpackIndex(obj); + } catch (std::exception& e) { + throw_intlist_exception(this, i, obj, idx, e); + } + } + } + } + return res; +} + +inline c10::OptionalArray PythonArgs::intlistOptional(int i) { + if (!args[i]) { + return {}; + } + return intlist(i); +} + +inline c10::OptionalArray PythonArgs::symintlistOptional(int i) { + if (!args[i]) { + return {}; + } + return symintlist(i); +} + +inline std::vector PythonArgs::getDoublelist(int i) { + PyObject* arg = args[i]; + auto tuple = PyTuple_Check(arg); + if (!tuple) { + TORCH_INTERNAL_ASSERT(PyList_Check(arg), "expected tuple or list"); + } + // NOLINTNEXTLINE(bugprone-branch-clone) + auto size = tuple ? PyTuple_GET_SIZE(arg) : PyList_GET_SIZE(arg); + std::vector res(size); + for (const auto idx : c10::irange(size)) { + PyObject* obj = + tuple ? PyTuple_GET_ITEM(arg, idx) : PyList_GET_ITEM(arg, idx); + try { + if (torch::is_symfloat(py::handle(obj))) { + res[idx] = py::cast(py::handle(obj)) + .guard_float(__FILE__, __LINE__); + } else { + res[idx] = THPUtils_unpackDouble(obj); + } + } catch (const std::exception&) { + TORCH_CHECK_TYPE( + false, + fmt::format( + "{}(): argument '{}' must be {}, but found element of type {} at pos {}", + signature.name, + signature.params[i].name, + signature.params[i].type_name(), + Py_TYPE(obj)->tp_name, + idx + 1)); + } + } + return res; +} + +inline c10::OptionalArray PythonArgs::doublelistOptional(int i) { + if (!args[i]) { + return {}; + } + return this->getDoublelist(i); +} + +inline std::vector PythonArgs::doublelist(int i) { + if (!args[i]) { + return {}; + } + return this->getDoublelist(i); +} + +inline std::optional PythonArgs::toDispatchKeySetOptional( + int i) { + if (!args[i]) { + return {}; + } + return py::cast(py::handle(args[i])); +} + +inline at::ScalarType PythonArgs::scalartypeWithDefault( + int i, + at::ScalarType default_scalartype) { + if (!args[i]) + return default_scalartype; + return scalartype(i); +} + +inline at::ScalarType toScalarType(PyObject* obj) { + if (obj == (PyObject*)&PyFloat_Type) { + return at::ScalarType::Double; + } + if (obj == (PyObject*)&PyBool_Type) { + return at::ScalarType::Bool; + } + if (obj == (PyObject*)&PyLong_Type) { + return at::ScalarType::Long; + } + if (obj == (PyObject*)&PyComplex_Type) { + return at::ScalarType::ComplexDouble; + } + return reinterpret_cast(obj)->scalar_type; +} + +inline at::ScalarType PythonArgs::scalartype(int i) { + if (!args[i]) { + auto scalartype = signature.params[i].default_scalartype; + return (scalartype == at::ScalarType::Undefined) + ? torch::tensors::get_default_scalar_type() + : scalartype; + } + PyObject* obj = args[i]; + return toScalarType(obj); +} + +inline std::optional PythonArgs::scalartypeOptional(int i) { + if (!args[i]) + return std::nullopt; + return scalartype(i); +} + +inline at::Layout toLayout(PyObject* obj) { + const auto layout = reinterpret_cast(obj); + return layout->layout; +} + +inline at::Layout PythonArgs::layout(int i) { + if (!args[i]) + return signature.params[i].default_layout; + return toLayout(args[i]); +} + +inline at::Layout PythonArgs::layoutWithDefault( + int i, + at::Layout default_layout) { + if (!args[i]) + return default_layout; + return layout(i); +} + +inline std::optional PythonArgs::layoutOptional(int i) { + if (!args[i]) + return std::nullopt; + return layout(i); +} + +inline at::Device deviceFromLong(int64_t device_index) { + TORCH_CHECK(device_index >= 0, "Device index must not be negative"); + return at::Device( + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + at::getAccelerator(true).value(), + static_cast(device_index)); +} + +inline at::Device toDevice(PyObject* obj) { + if (THPDevice_Check(obj)) { + const auto device = reinterpret_cast(obj); + return device->device; + } + if (THPUtils_checkLong(obj)) { + return deviceFromLong(THPUtils_unpackLong(obj)); + } + if (torch::is_symint(py::handle(obj))) { + auto device_index = + py::cast(py::handle(obj)).guard_int(__FILE__, __LINE__); + return deviceFromLong(device_index); + } + if (torch::is_dynint(py::handle(obj))) { + auto device_index = py::cast(py::handle(obj)); + return deviceFromLong(device_index); + } + const std::string& device_str = THPUtils_unpackString(obj); + return at::Device(device_str); +} + +inline at::Device PythonArgs::device(int i) { + if (!args[i]) { + return torch::tensors::get_default_device(); + } + return toDevice(args[i]); +} + +inline at::Device PythonArgs::deviceWithDefault( + int i, + const at::Device& default_device) { + if (!args[i]) + return default_device; + return device(i); +} + +inline std::optional PythonArgs::deviceOptional(int i) { + if (!args[i]) + return std::nullopt; + return device(i); +} + +inline at::Dimname PythonArgs::dimname(int i) { + TORCH_INTERNAL_ASSERT(args[i] != nullptr); + return THPDimname_parse(args[i]); +} + +inline std::vector parseDimnameList(PyObject* arg) { + auto tuple = PyTuple_Check(arg); + if (!tuple) { + TORCH_INTERNAL_ASSERT(PyList_Check(arg), "expected tuple or list"); + } + // NOLINTNEXTLINE(bugprone-branch-clone) + auto size = tuple ? PyTuple_GET_SIZE(arg) : PyList_GET_SIZE(arg); + std::vector res; + res.reserve(size); + for (const auto idx : c10::irange(size)) { + PyObject* obj = + tuple ? PyTuple_GET_ITEM(arg, idx) : PyList_GET_ITEM(arg, idx); + res.push_back(THPDimname_parse(obj)); + } + return res; +} + +inline std::optional> PythonArgs:: + toDimnameListOptional(int i) { + if (!args[i]) + return std::nullopt; + return parseDimnameList(args[i]); +} + +inline std::vector PythonArgs::dimnamelist(int i) { + TORCH_INTERNAL_ASSERT(args[i]); + PyObject* arg = args[i]; + auto size = signature.params[i].size; + TORCH_INTERNAL_ASSERT(size == 0 || size == 1); + if (size == 1 && THPUtils_checkDimname(arg)) { + return {THPDimname_parse(arg)}; + } + return parseDimnameList(arg); +} + +inline at::MemoryFormat PythonArgs::memoryformat(int i) { + if (!args[i]) + return at::MemoryFormat::Contiguous; + TORCH_CHECK( + THPMemoryFormat_Check(args[i]), + "memory_format arg must be an instance of the torch.memory_format"); + const auto memory_format = reinterpret_cast(args[i]); + return memory_format->memory_format; +} + +inline std::optional PythonArgs::memoryformatOptional(int i) { + if (!args[i]) + return std::nullopt; + return memoryformat(i); +} + +inline at::QScheme PythonArgs::toQScheme(int i) { + if (!args[i]) + return at::kPerTensorAffine; + TORCH_CHECK( + THPQScheme_Check(args[i]), + "qscheme arg must be an instance of the torch.qscheme"); + const auto qscheme = reinterpret_cast(args[i]); + return qscheme->qscheme; +} + +inline std::string PythonArgs::string(int i) { + return stringWithDefault(i, signature.params[i].default_string); +} + +inline std::string PythonArgs::stringWithDefault( + int i, + const std::string& default_str) { + if (!args[i]) + return default_str; + return THPUtils_unpackString(args[i]); +} + +inline std::optional PythonArgs::stringOptional(int i) { + if (!args[i]) + return std::nullopt; + return THPUtils_unpackString(args[i]); +} + +inline std::string_view PythonArgs::stringView(int i) { + return stringViewWithDefault(i, signature.params[i].default_string); +} + +inline std::string_view PythonArgs::stringViewWithDefault( + int i, + const std::string_view default_str) { + if (!args[i]) + return default_str; + return THPUtils_unpackStringView(args[i]); +} + +inline std::optional PythonArgs::stringViewOptional(int i) { + if (!args[i]) + return std::nullopt; + return THPUtils_unpackStringView(args[i]); +} + +inline int64_t PythonArgs::toInt64(int i) { + if (!args[i]) + return signature.params[i].default_int; + if (traceable && jit::tracer::isTracing() && THPVariable_Check(args[i])) { + auto& var = THPVariable_Unpack(args[i]); + jit::tracer::ArgumentStash::stashValue( + signature.params[i].name, idx, var, c10::IntType::get()); + } + if (torch::is_symint(py::handle(args[i]))) { + return py::cast(py::handle(args[i])) + .guard_int(__FILE__, __LINE__); + } + if (torch::is_dynint(py::handle(args[i]))) { + return py::cast(py::handle(args[i])); + } + return THPUtils_unpackLong(args[i]); +} + +inline c10::SymInt PythonArgs::toSymInt(int i) { + if (!args[i]) { + return c10::SymInt(signature.params[i].default_int); + } + + if (traceable && jit::tracer::isTracing() && THPVariable_Check(args[i])) { + auto& var = THPVariable_Unpack(args[i]); + jit::tracer::ArgumentStash::stashValue( + signature.params[i].name, idx, var, c10::IntType::get()); + } + + return py::cast(py::handle(args[i])); +} + +inline c10::SymBool PythonArgs::toSymBool(int i) { + if (!args[i]) { + return c10::SymBool(signature.params[i].default_bool); + } + if (traceable && jit::tracer::isTracing() && THPVariable_Check(args[i])) { + auto& var = THPVariable_Unpack(args[i]); + jit::tracer::ArgumentStash::stashValue( + signature.params[i].name, idx, var, c10::BoolType::get()); + } + + return py::cast(py::handle(args[i])); +} + +inline int64_t PythonArgs::toInt64WithDefault(int i, int64_t default_int) { + if (!args[i]) + return default_int; + return toInt64(i); +} + +inline std::optional PythonArgs::toInt64Optional(int i) { + if (!args[i]) + return std::nullopt; + return toInt64(i); +} + +inline std::optional PythonArgs::toSymIntOptional(int i) { + if (!args[i]) + return std::nullopt; + return toSymInt(i); +} + +inline std::optional PythonArgs::toBoolOptional(int i) { + if (!args[i]) { + return std::nullopt; + } + return toBool(i); +} + +inline std::optional PythonArgs::toDoubleOptional(int i) { + if (!args[i]) { + return std::nullopt; + } + return toDouble(i); +} + +inline double PythonArgs::toDouble(int i) { + if (!args[i]) + return signature.params[i].default_double; + if (torch::is_symfloat(py::handle(args[i]))) { + return py::cast(py::handle(args[i])) + .guard_float(__FILE__, __LINE__); + } + if (torch::is_symint(py::handle(args[i]))) { + return static_cast(py::cast(py::handle(args[i])) + .guard_int(__FILE__, __LINE__)); + } + if (torch::is_dynint(py::handle(args[i]))) { + return static_cast(py::cast(py::handle(args[i]))); + } + return THPUtils_unpackDouble(args[i]); +} + +inline bool PythonArgs::toBool(int i) { + if (!args[i]) { + return signature.params[i].default_bool; + } + if (args[i] == Py_True) { + return true; + } + if (args[i] == Py_False) { + return false; + } + if (torch::is_symbool(py::handle(args[i]))) { + return py::cast(py::handle(args[i])) + .guard_bool(__FILE__, __LINE__); + } + return false; +} + +inline double PythonArgs::toDoubleWithDefault(int i, double default_double) { + if (!args[i]) + return default_double; + return toDouble(i); +} + +inline c10::complex PythonArgs::toComplex(int i) { + if (!args[i]) + return *(reinterpret_cast*>( + signature.params[i].default_complex)); + return THPUtils_unpackComplexDouble(args[i]); +} + +inline c10::complex PythonArgs::toComplexWithDefault( + int i, + c10::complex default_complex) { + if (!args[i]) + return default_complex; + return toComplex(i); +} + +inline bool PythonArgs::toBoolWithDefault(int i, bool default_bool) { + if (!args[i]) + return default_bool; + return toBool(i); +} + +inline bool PythonArgs::isNone(int i) { + return args[i] == nullptr; +} + +inline std::optional PythonArgs::generator(int i) { + if (!args[i]) + return std::nullopt; + return reinterpret_cast(args[i])->cdata; +} + +inline at::Storage PythonArgs::storage(int i) { + if (!args[i]) + return at::Storage(); + return createStorage(args[i]); +} + +inline at::Storage PythonArgs::storage( + int i, + at::ScalarType& storage_scalar_type, + bool& is_typed_storage) { + at::Storage storage; + if (!args[i]) { + storage = at::Storage(); + is_typed_storage = false; + storage_scalar_type = at::ScalarType::Undefined; + } else { + std::tie(storage, storage_scalar_type, is_typed_storage) = + createStorageGetType(args[i]); + } + return storage; +} + +inline c10::Stream PythonArgs::stream(int i) { + if (!args[i]) + return c10::Stream( + c10::Stream::Default::DEFAULT, c10::Device(c10::DeviceType::CPU, -1)); + if (!THPStream_Check(args[i])) { + TORCH_CHECK_TYPE( + false, + fmt::format( + "expected Stream object. Got '{}'", Py_TYPE(args[i])->tp_name)); + } + return c10::Stream::unpack3( + ((THPStream*)args[i])->stream_id, + static_cast(((THPStream*)args[i])->device_index), + static_cast(((THPStream*)args[i])->device_type)); +} + +inline PyObject* PythonArgs::pyobject(int i) { + if (!args[i]) + return Py_None; + return args[i]; +} + +/* + * + * Handle __torch_function__ overrides if we know that there are overloaded + * arguments. All objects stored in r.overloaded_args must have a + * __torch_function__ implementation and the arguments must be ordered in order + * of precedence. Precedence goes from left to right in the order of the + * signature of the function the overloaded arguments were passed to, except + * subclasses are always considered before superclasses. + * + * If the result of calling __torch_function__ is NotImplemented, the + * next implementation in the precedence order is called. If all + * arguments return NotImplemented from their __torch_function__ + * implementation, a TypeError is raised in Python. + * + * Assumes overloaded_args has at least one entry. All entries must have + * a __torch_function__ attribute that resolves to a callable that + * accepts a torch API function, a tuple of arguments, and a dict of + * keyword arguments for the torch API function. + * + * It is sufficient to call PythonArgs::has_torch_function before + * calling this function to verify that there are valid arguments + * present. If that is not done then special care must be taken to + * ensure there are arguments that are overloaded with + * __torch_function__. + * + * See torch._overrides.handle_torch_function for the equivalent + * code in the pure-python implementation. + * + * 'r' is a parsed PythonArgs instance, returned from + * PythonArgParser::parse. + * + * 'args' is a reference to the python tuple of arguments to the torch + * API function. + * + * 'kwargs' is a reference to the python dict of keyword arguments to + * the torch API function. + * + * 'torch_api' is a reference to a python torch API namespace. + * + * 'torch_api_function' is the reference to the original torch method, usually, + * we can use torch_api and func_name to get torch_api_function. In some cases, + * e.g., torch custom op, we create the function in C++, if we still use + * torch_api and func_name to fetch original api, a cyclic call will happen. + * + * 'overloaded_args' is the args which have overloaded __torch_function__. + * + * 'func_name' is the named of the original torch method. + * + * TODO: we could use different names for the following 'handle_torch_function' + * instead of overloading. + * + */ +// Used for Tensor methods with arguments. +auto handle_torch_function( + PythonArgs& r, + PyObject* self, + PyObject* args, + PyObject* kwargs, + PyObject* torch_api, + const char* module_name, + const char* func_name_override = nullptr) -> PyObject*; + +// Used for functions which needs to parse python args. +auto handle_torch_function( + PythonArgs& r, + PyObject* args, + PyObject* kwargs, + PyObject* torch_api, + const char* module_name, + const char* func_name_override = nullptr) -> PyObject*; + +// Used for functions that have no argument parsing. +auto handle_torch_function( + PyObject* self, + const std::string& func_name, + PyObject* args = nullptr, + PyObject* kwargs = nullptr, + PyObject* torch_api = THPVariableClass, + const std::string& module_name = "torch.Tensor") -> PyObject*; + +// Used for functions created in C++, e.g., C++ custom op, which doesn't use +// PythonArgParser to get overloaded_args. +enum class TorchFunctionName { TorchFunction, TorchDispatch }; + +auto TORCH_PYTHON_API handle_torch_function_no_python_arg_parser( + at::ArrayRef overloaded_args, + PyObject* args, + PyObject* kwargs, + const char* func_name, + PyObject* torch_api_function, + const char* module_name, + TorchFunctionName torch_function_name = TorchFunctionName::TorchFunction) + -> PyObject*; + +auto handle_torch_function_no_python_arg_parser( + at::ArrayRef overloaded_args, + PyObject* args, + PyObject* kwargs, + const char* func_name, + PyObject* torch_api_function, + const char* module_name, + const c10::OperatorHandle* opt_op, + torch::jit::Stack* opt_stack, + TorchFunctionName torch_function_name = TorchFunctionName::TorchFunction) + -> PyObject*; + +// Used for getters of Tensor properties +auto handle_torch_function_getter( + THPVariable* self, + const std::string& property_name) -> PyObject*; + +// Used for setters of Tensor properties. +auto handle_torch_function_setter( + THPVariable* self, + const std::string& property_name, + PyObject* value) -> int; + +// Used for __getitem__ and __setitem__ +auto handle_torch_function_indexing( + PyObject* self, + PyObject* index, + PyObject* val = nullptr) -> PyObject*; + +/* + * Check if the input obj is Tensor type, including its subclass, or overloaded + * type. If the type defines __torch_function__, it also returns true. + * Otherwise returns false. If the class is not torch.Tensor, and it defines + * __torch_function__, we append obj to overloaded_args. + * + * 'obj': the input argument to be checked + * 'overloaded_args': the vector to append the overloaded args. + */ +bool is_tensor_and_append_overloaded( + PyObject* obj, + std::vector* overloaded_args); + +/* + * Check if the input obj is Tensor List or Tensor Tuple type. First check + * whether obj is Tuple or List type, if true, iterate over each element and + * check whether it is Tensor type, including its subclass or overloaded type. + * At the same time, the overloaded arg is appended to the overloaded_args. + * + * 'obj': the input argument to be checked + * 'overloaded_args': the vector to append the overloaded args. + * 'argnum': the number of total arguments of the function being checked. + * 'throw_error': whether throw error if any element in the list or tuple is + * not tensor type or overloaded. + */ +bool is_tensor_list_and_append_overloaded( + PyObject* obj, + std::vector* overloaded_args, + size_t argnum, + bool throw_error); + +/* Given an argument that is definitely a tensor and is definitely overloaded, + * append it to the overloaded arguments list. Use this instead of + * is_tensor_and_append_overloaded in situations where you have a PyObject + * and you know it definitely is a Tensor and it is definitely overloaded. + * + * 'overloaded_args': the vector to append the overloaded args + * 'obj': the input tensor that is overloaded + */ +void append_overloaded_tensor( + std::vector* overloaded_args, + PyObject* obj); + +/* Given an argument that is definitely a type and is definitely overloaded, + * append it to the overloaded arguments list. Use this only with + * __torch_dispatch__, where we operate on classes that have a + * __torch_dispatch__ classmethod. + * + * 'overloaded_args': the vector to append the overloaded type + * 'obj': the input class that has a __torch_dispatch__ classmethod. + */ +void append_overloaded_type( + std::vector* overloaded_args, + PyObject* obj); + +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_compat.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_compat.h new file mode 100644 index 0000000000000000000000000000000000000000..fe047faa9c15bf044dd80f1045a845b36c1878de --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_compat.h @@ -0,0 +1,44 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#ifndef PYTHON_COMPAT +#define PYTHON_COMPAT + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// PyTorch-only compat functions + +#define IS_PYTHON_3_11_PLUS (PY_VERSION_HEX >= 0x030B00C1) +#define IS_PYTHON_3_12_PLUS (PY_VERSION_HEX >= 0x030C0000) +#define IS_PYTHON_3_13_PLUS (PY_VERSION_HEX >= 0x030D0000) +#define IS_PYTHON_3_14_PLUS (PY_VERSION_HEX >= 0x030E0000) +#define IS_PYTHON_3_15_PLUS (PY_VERSION_HEX >= 0x030F0000) + +static inline int PyCode_GetNCellvars(PyCodeObject* code) { +// gh-26364 added co_ncellvars to Python 3.11.0rc1 +#if IS_PYTHON_3_11_PLUS + return code->co_ncellvars; +#else + return PyTuple_GET_SIZE(code->co_cellvars); +#endif +} + +static inline int PyCode_GetNFreevars(PyCodeObject* code) { +// gh-26364 added co_nfreevars to Python 3.11.0rc1 +#if IS_PYTHON_3_11_PLUS + return code->co_nfreevars; +#else + return PyTuple_GET_SIZE(code->co_freevars); +#endif +} + +#ifdef __cplusplus +} +#endif +#endif // PYTHON_COMPAT + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_dispatch.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_dispatch.h new file mode 100644 index 0000000000000000000000000000000000000000..3106c43acf60806568929f9e56338d7493ea32a7 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_dispatch.h @@ -0,0 +1,21 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include +#include + +namespace torch::impl::dispatch { + +void initDispatchBindings(PyObject* module); + +void python_op_registration_trampoline_impl( + const c10::OperatorHandle& op, + c10::DispatchKey key, + c10::DispatchKeySet keyset, + torch::jit::Stack* stack, + bool with_keyset, + bool with_op); + +} // namespace torch::impl::dispatch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_numbers.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_numbers.h new file mode 100644 index 0000000000000000000000000000000000000000..371e793c508109be654ece27230f0603fab4f266 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_numbers.h @@ -0,0 +1,232 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// largest integer that can be represented consecutively in a double +const int64_t DOUBLE_INT_MAX = 9007199254740992; + +inline PyObject* THPUtils_packDeviceIndex(c10::DeviceIndex value) { + return PyLong_FromLong(value); +} + +inline PyObject* THPUtils_packInt32(int32_t value) { + return PyLong_FromLong(value); +} + +inline PyObject* THPUtils_packInt64(int64_t value) { + return PyLong_FromLongLong(value); +} + +inline PyObject* THPUtils_packUInt32(uint32_t value) { + return PyLong_FromUnsignedLong(value); +} + +inline PyObject* THPUtils_packUInt64(uint64_t value) { + return PyLong_FromUnsignedLongLong(value); +} + +inline PyObject* THPUtils_packDoubleAsInt(double value) { + return PyLong_FromDouble(value); +} + +inline bool THPUtils_checkLongExact(PyObject* obj) { + return PyLong_CheckExact(obj) && !PyBool_Check(obj); +} + +inline bool THPUtils_checkLong(PyObject* obj) { + // Fast path + if (THPUtils_checkLongExact(obj)) { + return true; + } + +#ifdef USE_NUMPY + if (torch::utils::is_numpy_int(obj)) { + return true; + } +#endif + + return PyLong_Check(obj) && !PyBool_Check(obj); +} + +inline int32_t THPUtils_unpackInt(PyObject* obj) { + int overflow = 0; + long value = PyLong_AsLongAndOverflow(obj, &overflow); + if (value == -1 && PyErr_Occurred()) { + throw python_error(); + } + TORCH_CHECK_VALUE(overflow == 0, "Overflow when unpacking long long"); + TORCH_CHECK_VALUE( + value <= std::numeric_limits::max() && + value >= std::numeric_limits::min(), + "Overflow when unpacking long"); + return (int32_t)value; +} + +inline int64_t THPUtils_unpackLong(PyObject* obj) { + int overflow = 0; + long long value = PyLong_AsLongLongAndOverflow(obj, &overflow); + if (value == -1 && PyErr_Occurred()) { + throw python_error(); + } + TORCH_CHECK_VALUE(overflow == 0, "Overflow when unpacking long long"); + return (int64_t)value; +} + +inline uint32_t THPUtils_unpackUInt32(PyObject* obj) { + unsigned long value = PyLong_AsUnsignedLong(obj); + if (PyErr_Occurred()) { + throw python_error(); + } + TORCH_CHECK_VALUE( + value <= std::numeric_limits::max(), + "Overflow when unpacking long long"); + return (uint32_t)value; +} + +inline uint64_t THPUtils_unpackUInt64(PyObject* obj) { + unsigned long long value = PyLong_AsUnsignedLongLong(obj); + if (PyErr_Occurred()) { + throw python_error(); + } + return (uint64_t)value; +} + +bool THPUtils_checkIndex(PyObject* obj); + +inline int64_t THPUtils_unpackIndex(PyObject* obj) { + if (!THPUtils_checkLong(obj)) { + auto index = THPObjectPtr(PyNumber_Index(obj)); + if (index == nullptr) { + throw python_error(); + } + // NB: This needs to be called before `index` goes out of scope and the + // underlying object's refcount is decremented + return THPUtils_unpackLong(index.get()); + } + return THPUtils_unpackLong(obj); +} + +inline bool THPUtils_unpackBool(PyObject* obj) { + if (obj == Py_True) { + return true; + } else if (obj == Py_False) { + return false; + } else { + TORCH_CHECK(false, "couldn't convert python object to boolean"); + } +} + +inline bool THPUtils_checkBool(PyObject* obj) { +#ifdef USE_NUMPY + if (torch::utils::is_numpy_bool(obj)) { + return true; + } +#endif + return PyBool_Check(obj); +} + +inline bool THPUtils_checkDouble(PyObject* obj) { +#ifdef USE_NUMPY + if (torch::utils::is_numpy_scalar(obj)) { + return true; + } +#endif + return PyFloat_Check(obj) || PyLong_Check(obj); +} + +inline double THPUtils_unpackDouble(PyObject* obj) { + if (PyFloat_Check(obj)) { + return PyFloat_AS_DOUBLE(obj); + } + double value = PyFloat_AsDouble(obj); + if (value == -1 && PyErr_Occurred()) { + throw python_error(); + } + return value; +} + +inline c10::complex THPUtils_unpackComplexDouble(PyObject* obj) { + Py_complex value = PyComplex_AsCComplex(obj); + if (value.real == -1.0 && PyErr_Occurred()) { + throw python_error(); + } + + return c10::complex(value.real, value.imag); +} + +inline bool THPUtils_unpackNumberAsBool(PyObject* obj) { +#ifdef USE_NUMPY + // Handle NumPy boolean scalars (np.bool_) + if (torch::utils::is_numpy_bool(obj)) { + int truth = PyObject_IsTrue(obj); + if (truth == -1) { + throw python_error(); + } + return truth != 0; + } +#endif + if (PyFloat_Check(obj)) { + return (bool)PyFloat_AS_DOUBLE(obj); + } + + if (PyComplex_Check(obj)) { + double real_val = PyComplex_RealAsDouble(obj); + double imag_val = PyComplex_ImagAsDouble(obj); + return !(real_val == 0 && imag_val == 0); + } + + int overflow = 0; + long long value = PyLong_AsLongLongAndOverflow(obj, &overflow); + if (value == -1 && PyErr_Occurred()) { + throw python_error(); + } + // No need to check overflow, because when overflow occurred, it should + // return true in order to keep the same behavior of numpy. + return (bool)value; +} + +inline c10::DeviceIndex THPUtils_unpackDeviceIndex(PyObject* obj) { + int overflow = 0; + long value = PyLong_AsLongAndOverflow(obj, &overflow); + if (value == -1 && PyErr_Occurred()) { + throw python_error(); + } + TORCH_CHECK(overflow == 0, "Overflow when unpacking DeviceIndex"); + TORCH_CHECK( + value <= std::numeric_limits::max() && + value >= std::numeric_limits::min(), + "Overflow when unpacking DeviceIndex"); + return (c10::DeviceIndex)value; +} + +template +inline T THPUtils_unpackInteger(PyObject* obj) { + int overflow = -1; + const auto value = PyLong_AsLongLongAndOverflow(obj, &overflow); + if (value == -1 && PyErr_Occurred()) { + throw python_error(); + } + if (!overflow) { + return static_cast(value); + } + // try unsigned + const auto uvalue = PyLong_AsUnsignedLongLong(obj); + if (uvalue == static_cast>(-1) && + PyErr_Occurred()) { + throw python_error(); + } + return static_cast(uvalue); +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_raii.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_raii.h new file mode 100644 index 0000000000000000000000000000000000000000..25d0b62bf6fa77adc2c19cfe7cb921de7830a90c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_raii.h @@ -0,0 +1,89 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#include +#include +#include + +namespace torch::impl { + +template +struct RAIIContextManager { + explicit RAIIContextManager(Args&&... args) + : args_(std::forward(args)...) {} + + void enter() { + auto emplace = [&](Args... args) { + guard_.emplace(std::forward(args)...); + }; + std::apply(std::move(emplace), args_); + } + + void exit() { + guard_ = std::nullopt; + } + + private: + std::optional guard_; + std::tuple args_; +}; + +// Turns a C++ RAII guard into a Python context manager. +// See _ExcludeDispatchKeyGuard in python_dispatch.cpp for example. +template +void py_context_manager(const py::module& m, const char* name) { + using ContextManagerT = RAIIContextManager; + py::class_(m, name) + .def(py::init()) + .def("__enter__", [](ContextManagerT& guard) { guard.enter(); }) + .def( + "__exit__", + [](ContextManagerT& guard, + const py::object& exc_type, + const py::object& exc_value, + const py::object& traceback) { guard.exit(); }); +} + +template +struct DeprecatedRAIIContextManager { + explicit DeprecatedRAIIContextManager(Args&&... args) { + guard_.emplace(std::forward(args)...); + } + + void enter() {} + + void exit() { + guard_ = std::nullopt; + } + + private: + std::optional guard_; + std::tuple args_; +}; + +// Definition: a "Python RAII guard" is an object in Python that acquires +// a resource on init and releases the resource on deletion. +// +// This API turns a C++ RAII guard into an object can be used either as a +// Python context manager or as a "Python RAII guard". +// +// Please prefer `py_context_manager` to this API if you are binding a new +// RAII guard into Python because "Python RAII guards" don't work as expected +// in Python (Python makes no guarantees about when an object gets deleted) +template +void py_context_manager_DEPRECATED(const py::module& m, const char* name) { + using ContextManagerT = DeprecatedRAIIContextManager; + py::class_(m, name) + .def(py::init()) + .def("__enter__", [](ContextManagerT& guard) { guard.enter(); }) + .def( + "__exit__", + [](ContextManagerT& guard, + const py::object& exc_type, + const py::object& exc_value, + const py::object& traceback) { guard.exit(); }); +} + +} // namespace torch::impl + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_scalars.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_scalars.h new file mode 100644 index 0000000000000000000000000000000000000000..29ac9daf6016667b4143153dd637163bafa19f31 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_scalars.h @@ -0,0 +1,173 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include +#include + +namespace torch::utils { + +template +inline T unpackIntegral(PyObject* obj, const char* type) { + // In Python-3.10 floats can no longer be silently converted to integers + // Keep backward compatible behavior for now + if (PyFloat_Check(obj)) { + return c10::checked_convert(THPUtils_unpackDouble(obj), type); + } + return c10::checked_convert(THPUtils_unpackLong(obj), type); +} + +inline void store_scalar(void* data, at::ScalarType scalarType, PyObject* obj) { + switch (scalarType) { + case at::kByte: + *(uint8_t*)data = unpackIntegral(obj, "uint8"); + break; + case at::kUInt16: + *(uint16_t*)data = unpackIntegral(obj, "uint16"); + break; + case at::kUInt32: + *(uint32_t*)data = unpackIntegral(obj, "uint32"); + break; + case at::kUInt64: + // NB: This doesn't allow implicit conversion of float to int + *(uint64_t*)data = THPUtils_unpackUInt64(obj); + break; + case at::kChar: + *(int8_t*)data = unpackIntegral(obj, "int8"); + break; + case at::kShort: + *(int16_t*)data = unpackIntegral(obj, "int16"); + break; + case at::kInt: + *(int32_t*)data = unpackIntegral(obj, "int32"); + break; + case at::kLong: + *(int64_t*)data = unpackIntegral(obj, "int64"); + break; + case at::kHalf: + *(at::Half*)data = + at::convert(THPUtils_unpackDouble(obj)); + break; + case at::kFloat: + *(float*)data = (float)THPUtils_unpackDouble(obj); + break; + case at::kDouble: + *(double*)data = THPUtils_unpackDouble(obj); + break; + case at::kComplexHalf: + *(c10::complex*)data = + (c10::complex)static_cast>( + THPUtils_unpackComplexDouble(obj)); + break; + case at::kComplexFloat: + *(c10::complex*)data = + (c10::complex)THPUtils_unpackComplexDouble(obj); + break; + case at::kComplexDouble: + *(c10::complex*)data = THPUtils_unpackComplexDouble(obj); + break; + case at::kBool: + *(bool*)data = THPUtils_unpackNumberAsBool(obj); + break; + case at::kBFloat16: + *(at::BFloat16*)data = + at::convert(THPUtils_unpackDouble(obj)); + break; + // TODO(#146647): simplify below with macros + case at::kFloat8_e5m2: + *(at::Float8_e5m2*)data = + at::convert(THPUtils_unpackDouble(obj)); + break; + case at::kFloat8_e5m2fnuz: + *(at::Float8_e5m2fnuz*)data = + at::convert(THPUtils_unpackDouble(obj)); + break; + case at::kFloat8_e4m3fn: + *(at::Float8_e4m3fn*)data = + at::convert(THPUtils_unpackDouble(obj)); + break; + case at::kFloat8_e4m3fnuz: + *(at::Float8_e4m3fnuz*)data = + at::convert(THPUtils_unpackDouble(obj)); + break; + case at::kFloat8_e8m0fnu: + *(at::Float8_e8m0fnu*)data = + at::convert(THPUtils_unpackDouble(obj)); + break; + default: + TORCH_CHECK(false, "store_scalar: invalid type"); + } +} + +inline PyObject* load_scalar(const void* data, at::ScalarType scalarType) { + switch (scalarType) { + case at::kByte: + return THPUtils_packInt64(*(uint8_t*)data); + case at::kUInt16: + return THPUtils_packInt64(*(uint16_t*)data); + case at::kUInt32: + return THPUtils_packUInt32(*(uint32_t*)data); + case at::kUInt64: + return THPUtils_packUInt64(*(uint64_t*)data); + case at::kChar: + return THPUtils_packInt64(*(int8_t*)data); + case at::kShort: + return THPUtils_packInt64(*(int16_t*)data); + case at::kInt: + return THPUtils_packInt64(*(int32_t*)data); + case at::kLong: + return THPUtils_packInt64(*(int64_t*)data); + case at::kHalf: + return PyFloat_FromDouble( + at::convert(*(at::Half*)data)); + case at::kFloat: + return PyFloat_FromDouble(*(float*)data); + case at::kDouble: + return PyFloat_FromDouble(*(double*)data); + case at::kComplexHalf: { + auto data_ = reinterpret_cast*>(data); + return PyComplex_FromDoubles(data_->real(), data_->imag()); + } + case at::kComplexFloat: { + auto data_ = reinterpret_cast*>(data); + return PyComplex_FromDoubles(data_->real(), data_->imag()); + } + case at::kComplexDouble: + return PyComplex_FromCComplex( + *reinterpret_cast((c10::complex*)data)); + case at::kBool: + // Don't use bool*, since it may take out-of-range byte as bool. + // Instead, we cast explicitly to avoid ASAN error. + return PyBool_FromLong(static_cast(*(uint8_t*)data)); + case at::kBFloat16: + return PyFloat_FromDouble( + at::convert(*(at::BFloat16*)data)); + // TODO(#146647): simplify below with macros + case at::kFloat8_e5m2: + return PyFloat_FromDouble( + at::convert(*(at::Float8_e5m2*)data)); + case at::kFloat8_e4m3fn: + return PyFloat_FromDouble( + at::convert(*(at::Float8_e4m3fn*)data)); + case at::kFloat8_e5m2fnuz: + return PyFloat_FromDouble(at::convert( + *(at::Float8_e5m2fnuz*)data)); + case at::kFloat8_e4m3fnuz: + return PyFloat_FromDouble(at::convert( + *(at::Float8_e4m3fnuz*)data)); + case at::kFloat8_e8m0fnu: + return PyFloat_FromDouble( + at::convert(*(at::Float8_e8m0fnu*)data)); + default: + TORCH_CHECK(false, "load_scalar: invalid type"); + } +} + +} // namespace torch::utils + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_strings.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_strings.h new file mode 100644 index 0000000000000000000000000000000000000000..bd4f0c88607cc0ad66f35162efe4433a7eb2ee99 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_strings.h @@ -0,0 +1,140 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include + +// Utilities for handling Python strings. Note that PyString, when defined, is +// the same as PyBytes. + +// Returns true if obj is a bytes/str or unicode object +// As of Python 3.6, this does not require the GIL +inline bool THPUtils_checkString(PyObject* obj) { + return PyBytes_Check(obj) || PyUnicode_Check(obj); +} + +// Unpacks PyBytes (PyString) or PyUnicode as std::string +// PyBytes are unpacked as-is. PyUnicode is unpacked as UTF-8. +// NOTE: this method requires the GIL +inline std::string THPUtils_unpackString(PyObject* obj) { + if (PyBytes_Check(obj)) { + size_t size = PyBytes_GET_SIZE(obj); + return std::string(PyBytes_AS_STRING(obj), size); + } + if (PyUnicode_Check(obj)) { + Py_ssize_t size = 0; + const char* data = PyUnicode_AsUTF8AndSize(obj, &size); + TORCH_CHECK(data, "error unpacking string as utf-8"); + return std::string(data, (size_t)size); + } + TORCH_CHECK(false, "unpackString: expected bytes or unicode object"); +} + +// Unpacks PyBytes (PyString) or PyUnicode as std::string_view +// PyBytes are unpacked as-is. PyUnicode is unpacked as UTF-8. +// NOTE: If `obj` is destroyed, then the non-owning std::string_view will +// become invalid. If the string needs to be accessed at any point after +// `obj` is destroyed, then the std::string_view should be copied into +// a std::string, or another owning object, and kept alive. For an example, +// look at how IValue and autograd nodes handle std::string_view arguments. +// NOTE: this method requires the GIL +inline std::string_view THPUtils_unpackStringView(PyObject* obj) { + if (PyBytes_Check(obj)) { + size_t size = PyBytes_GET_SIZE(obj); + return std::string_view(PyBytes_AS_STRING(obj), size); + } + if (PyUnicode_Check(obj)) { + Py_ssize_t size = 0; + const char* data = PyUnicode_AsUTF8AndSize(obj, &size); + TORCH_CHECK(data, "error unpacking string as utf-8"); + return std::string_view(data, (size_t)size); + } + TORCH_CHECK(false, "unpackString: expected bytes or unicode object"); +} + +inline PyObject* THPUtils_packString(const char* str) { + return PyUnicode_FromString(str); +} + +inline PyObject* THPUtils_packString(const std::string& str) { + return PyUnicode_FromStringAndSize( + str.c_str(), static_cast(str.size())); +} + +inline PyObject* THPUtils_internString(const std::string& str) { + return PyUnicode_InternFromString(str.c_str()); +} + +// Precondition: THPUtils_checkString(obj) must be true +inline bool THPUtils_isInterned(PyObject* obj) { + return PyUnicode_CHECK_INTERNED(obj); +} + +// Precondition: THPUtils_checkString(obj) must be true +inline void THPUtils_internStringInPlace(PyObject** obj) { + PyUnicode_InternInPlace(obj); +} + +/* + * Reference: + * https://github.com/numpy/numpy/blob/f4c497c768e0646df740b647782df463825bfd27/numpy/core/src/common/get_attr_string.h#L42 + * + * Stripped down version of PyObject_GetAttrString, + * avoids lookups for None, tuple, and List objects, + * and doesn't create a PyErr since this code ignores it. + * + * This can be much faster then PyObject_GetAttrString where + * exceptions are not used by caller. + * + * 'obj' is the object to search for attribute. + * + * 'name' is the attribute to search for. + * + * Returns a py::object wrapping the return value. If the attribute lookup + * failed the value will be NULL. + * + */ + +inline py::object PyObject_FastGetAttrString(PyObject* obj, const char* name) { +#if IS_PYTHON_3_13_PLUS + PyObject* res = (PyObject*)nullptr; + int result_code = PyObject_GetOptionalAttrString(obj, name, &res); + if (result_code == -1) { + PyErr_Clear(); + } + return py::reinterpret_steal(res); +#else + PyTypeObject* tp = Py_TYPE(obj); + PyObject* res = (PyObject*)nullptr; + + /* Attribute referenced by (char *)name */ + if (tp->tp_getattr != nullptr) { + // This is OK per https://bugs.python.org/issue39620 + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast) + res = (*tp->tp_getattr)(obj, const_cast(name)); + if (res == nullptr) { + PyErr_Clear(); + } + } + /* Attribute referenced by (PyObject *)name */ + else if (tp->tp_getattro != nullptr) { + auto w = py::reinterpret_steal(PyUnicode_FromString(name)); + if (w.ptr() == nullptr) { + return py::object(); + } + res = (*tp->tp_getattro)(obj, w.ptr()); + if (res == nullptr) { + PyErr_Clear(); + } + } + return py::reinterpret_steal(res); +#endif +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_stub.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_stub.h new file mode 100644 index 0000000000000000000000000000000000000000..f457be5949a775e9ce3f4b8b39d8c4bbe95985b8 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_stub.h @@ -0,0 +1,9 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +struct _object; +using PyObject = _object; + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_symnode.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_symnode.h new file mode 100644 index 0000000000000000000000000000000000000000..793f050d3c1ec3faaab1ee97c4e8b2c5e8f38192 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_symnode.h @@ -0,0 +1,332 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include +#include +#include + +namespace torch { + +TORCH_PYTHON_API py::handle get_symint_class(); +TORCH_PYTHON_API py::handle get_symfloat_class(); +TORCH_PYTHON_API py::handle get_symbool_class(); +TORCH_PYTHON_API py::handle get_dynint_class(); + +// NB: These functions must not be called too early, otherwise torch not setup. +// Alternate design is to have torch "register" the object to us +inline bool is_symint(py::handle obj) { + return py::isinstance(obj, get_symint_class()); +} +inline bool is_symfloat(py::handle obj) { + return py::isinstance(obj, get_symfloat_class()); +} +inline bool is_symbool(py::handle obj) { + return py::isinstance(obj, get_symbool_class()); +} +inline bool is_dynint(py::handle obj) { + return py::isinstance(obj, get_dynint_class()); +} + +namespace impl { + +// This c10::SymNodeImpl simply backends to a Python object that +// implements the API. The Python object is the source of truth, +// this is just an adapter so C++ calls can get to the object. +class PythonSymNodeImpl : public c10::SymNodeImpl { + public: + PythonSymNodeImpl(py::object pyobj) : c10::SymNodeImpl() { + pyobj_ = std::make_shared( + pyobj.release().ptr(), getPyInterpreter()); + } + + c10::SymNode wrap_int(int64_t num) override { + py::gil_scoped_acquire acquire; + auto r = getPyObj().attr("wrap_int")(num); + return c10::make_intrusive(std::move(r)); + } + + c10::SymNode wrap_float(double num) override { + py::gil_scoped_acquire acquire; + auto r = getPyObj().attr("wrap_float")(num); + return c10::make_intrusive(std::move(r)); + } + + c10::SymNode wrap_bool(bool num) override { + py::gil_scoped_acquire acquire; + auto r = getPyObj().attr("wrap_bool")(num); + return c10::make_intrusive(std::move(r)); + } + +#define TORCH_SYMNODE_SIZES_STRIDES(n) \ + c10::SymNode n( \ + c10::ArrayRef sizes, c10::ArrayRef strides) \ + override { \ + py::gil_scoped_acquire acquire; \ + auto r = getPyObj().attr(#n)(sizes, strides); \ + return c10::make_intrusive(std::move(r)); \ + } + + // clang-format off + TORCH_SYMNODE_SIZES_STRIDES(is_contiguous) + TORCH_SYMNODE_SIZES_STRIDES(is_channels_last_contiguous_2d) + TORCH_SYMNODE_SIZES_STRIDES(is_channels_last_contiguous_3d) + TORCH_SYMNODE_SIZES_STRIDES(is_channels_last_strides_2d) + TORCH_SYMNODE_SIZES_STRIDES(is_channels_last_strides_3d) + TORCH_SYMNODE_SIZES_STRIDES(is_non_overlapping_and_dense) + // clang-format on + +#undef TORCH_SYMNODE_SIZES_STRIDES + + bool bool_() override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("bool_")().is(py::handle(Py_True)); + } + + bool is_int() override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("is_int")().is(py::handle(Py_True)); + } + + bool is_float() override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("is_float")().is(py::handle(Py_True)); + } + + bool is_bool() override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("is_bool")().is(py::handle(Py_True)); + } + + bool is_nested_int() const override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("is_nested_int")().is(py::handle(Py_True)); + } + + bool has_hint() override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("has_hint")().is(py::handle(Py_True)); + } + + int64_t guard_int(const char* file, int64_t line) override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("guard_int")(file, line).cast(); + } + + double guard_float(const char* file, int64_t line) override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("guard_float")(file, line).cast(); + } + + bool guard_bool(const char* file, int64_t line) override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("guard_bool")(file, line).cast(); + } + + bool expect_true(const char* file, int64_t line) override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("expect_true")(file, line).cast(); + } + + bool guard_size_oblivious(const char* file, int64_t line) override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("guard_size_oblivious")(file, line).cast(); + } + + bool guard_or_false(const char* file, int64_t line) override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("guard_or_false")(file, line).cast(); + } + + bool statically_known_true(const char* file, int64_t line) override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("statically_known_true")(file, line).cast(); + } + + bool guard_or_true(const char* file, int64_t line) override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("guard_or_true")(file, line).cast(); + } + + int64_t int_() override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("int_")().cast(); + } + + std::optional maybe_as_int() override { + py::gil_scoped_acquire acquire; + const auto& r = getPyObj().attr("maybe_as_int")(); + if (r.is_none()) { + return std::nullopt; + } else { + return r.cast(); + } + } + + std::string str() override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("str")().cast(); + } + + std::string _graph_repr() override { + py::gil_scoped_acquire acquire; + return getPyObj().attr("_graph_repr")().cast(); + } + + c10::SymNode dispatch_sym_ite_( + const char* fname, + const c10::SymNode& other, + const c10::SymNode& third) { + auto pother = dynamic_cast(other.get()); + auto pthird = dynamic_cast(third.get()); + TORCH_CHECK(pother); + TORCH_CHECK(pthird); + py::gil_scoped_acquire acquire; + auto r = getPyObj().attr(fname)(pother->getPyObj(), pthird->getPyObj()); + return c10::make_intrusive(r); + } + + c10::SymNode dispatch_common_(const char* fname, const c10::SymNode& other) { + auto pother = dynamic_cast(other.get()); + TORCH_CHECK(pother); + py::gil_scoped_acquire acquire; + auto r = getPyObj().attr(fname)(pother->getPyObj()); + return c10::make_intrusive(r); + } + + c10::SymNode dispatch_common_(const char* fname) { + py::gil_scoped_acquire acquire; + auto r = getPyObj().attr(fname)(); + return c10::make_intrusive(r); + } + + c10::SymNode add(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode sub(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode mul(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode truediv(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode float_truediv(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode int_truediv(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode pow(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode float_pow(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode pow_by_natural(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode floordiv(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode int_floordiv(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode mod(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode eq(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode ne(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode gt(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode lt(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode le(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode ge(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode sym_min(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + c10::SymNode sym_max(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode sym_and(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode sym_or(const c10::SymNode& other) override { + return dispatch_common_(__func__, other); + } + + c10::SymNode sym_ite(const c10::SymNode& other, const c10::SymNode& third) + override { + return dispatch_sym_ite_(__func__, other, third); + } + + c10::SymNode sym_not() override { + return dispatch_common_(__func__); + } + + c10::SymNode ceil() override { + return dispatch_common_(__func__); + } + + c10::SymNode floor() override { + return dispatch_common_(__func__); + } + + c10::SymNode neg() override { + return dispatch_common_(__func__); + } + + c10::SymNode clone() override { + return dispatch_common_(__func__); + } + + c10::SymNode sym_float() override { + return dispatch_common_(__func__); + } + + py::handle getPyObj() const { + return py::handle(pyobj_->ptr(getPyInterpreter())); + } + std::shared_ptr pyobj_ = nullptr; +}; + +} // namespace impl +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_torch_function_mode.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_torch_function_mode.h new file mode 100644 index 0000000000000000000000000000000000000000..32fbbeb84b814e0c13d1203efa80d4d5362d14eb --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_torch_function_mode.h @@ -0,0 +1,34 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::overrides { + +struct StashTorchFunctionModeGuard { + StashTorchFunctionModeGuard() { + cur_mode_ = at::impl::PythonTorchFunctionTLS::pop_stack(); + } + ~StashTorchFunctionModeGuard() { + at::impl::PythonTorchFunctionTLS::push_onto_stack(cur_mode_); + } + StashTorchFunctionModeGuard(const StashTorchFunctionModeGuard&) = delete; + StashTorchFunctionModeGuard(StashTorchFunctionModeGuard&&) = delete; + StashTorchFunctionModeGuard& operator=(const StashTorchFunctionModeGuard&) = + delete; + StashTorchFunctionModeGuard& operator=(StashTorchFunctionModeGuard&&) = + delete; + + const std::shared_ptr& get_cur_mode() { + return cur_mode_; + } + + private: + std::shared_ptr cur_mode_; +}; + +} // namespace torch::overrides + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_tuples.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_tuples.h new file mode 100644 index 0000000000000000000000000000000000000000..8a35c34d5d9ed11af34d2871b906a1f2582ff47c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/python_tuples.h @@ -0,0 +1,32 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +inline void THPUtils_packInt64Array( + PyObject* tuple, + size_t size, + const int64_t* sizes) { + for (size_t i = 0; i != size; ++i) { + PyObject* i64 = THPUtils_packInt64(sizes[i]); + if (!i64) { + throw python_error(); + } + PyTuple_SET_ITEM(tuple, i, i64); + } +} + +inline PyObject* THPUtils_packInt64Array(size_t size, const int64_t* sizes) { + THPObjectPtr tuple(PyTuple_New(static_cast(size))); + if (!tuple) + throw python_error(); + THPUtils_packInt64Array(tuple.get(), size, sizes); + return tuple.release(); +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/pythoncapi_compat.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/pythoncapi_compat.h new file mode 100644 index 0000000000000000000000000000000000000000..2d107ad578a7850c2a7ceb5448687ce8361743a1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/pythoncapi_compat.h @@ -0,0 +1,2671 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +// Header file providing new C API functions to old Python versions. +// +// File distributed under the Zero Clause BSD (0BSD) license. +// Copyright Contributors to the pythoncapi_compat project. +// +// Homepage: +// https://github.com/python/pythoncapi_compat +// +// Latest version: +// https://raw.githubusercontent.com/python/pythoncapi-compat/main/pythoncapi_compat.h +// +// SPDX-License-Identifier: 0BSD + +#ifndef PYTHONCAPI_COMPAT +#define PYTHONCAPI_COMPAT + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include // offsetof() + +// Python 3.11.0b4 added PyFrame_Back() to Python.h +#if PY_VERSION_HEX < 0x030b00B4 && !defined(PYPY_VERSION) +# include "frameobject.h" // PyFrameObject, PyFrame_GetBack() +#endif + + +#ifndef _Py_CAST +# define _Py_CAST(type, expr) ((type)(expr)) +#endif + +// Static inline functions should use _Py_NULL rather than using directly NULL +// to prevent C++ compiler warnings. On C23 and newer and on C++11 and newer, +// _Py_NULL is defined as nullptr. +#ifndef _Py_NULL +# if (defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L) \ + || (defined(__cplusplus) && __cplusplus >= 201103) +# define _Py_NULL nullptr +# else +# define _Py_NULL NULL +# endif +#endif + +// Cast argument to PyObject* type. +#ifndef _PyObject_CAST +# define _PyObject_CAST(op) _Py_CAST(PyObject*, op) +#endif + +#ifndef Py_BUILD_ASSERT +# define Py_BUILD_ASSERT(cond) \ + do { \ + (void)sizeof(char [1 - 2 * !(cond)]); \ + } while(0) +#endif + + +// bpo-42262 added Py_NewRef() to Python 3.10.0a3 +#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_NewRef) +static inline PyObject* _Py_NewRef(PyObject *obj) +{ + Py_INCREF(obj); + return obj; +} +#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj)) +#endif + + +// bpo-42262 added Py_XNewRef() to Python 3.10.0a3 +#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_XNewRef) +static inline PyObject* _Py_XNewRef(PyObject *obj) +{ + Py_XINCREF(obj); + return obj; +} +#define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj)) +#endif + + +// bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4 +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT) +static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) +{ + ob->ob_refcnt = refcnt; +} +#define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt) +#endif + + +// Py_SETREF() and Py_XSETREF() were added to Python 3.5.2. +// It is excluded from the limited C API. +#if (PY_VERSION_HEX < 0x03050200 && !defined(Py_SETREF)) && !defined(Py_LIMITED_API) +#define Py_SETREF(dst, src) \ + do { \ + PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \ + PyObject *_tmp_dst = (*_tmp_dst_ptr); \ + *_tmp_dst_ptr = _PyObject_CAST(src); \ + Py_DECREF(_tmp_dst); \ + } while (0) + +#define Py_XSETREF(dst, src) \ + do { \ + PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \ + PyObject *_tmp_dst = (*_tmp_dst_ptr); \ + *_tmp_dst_ptr = _PyObject_CAST(src); \ + Py_XDECREF(_tmp_dst); \ + } while (0) +#endif + + +// bpo-43753 added Py_Is(), Py_IsNone(), Py_IsTrue() and Py_IsFalse() +// to Python 3.10.0b1. +#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_Is) +# define Py_Is(x, y) ((x) == (y)) +#endif +#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsNone) +# define Py_IsNone(x) Py_Is(x, Py_None) +#endif +#if (PY_VERSION_HEX < 0x030A00B1 || defined(PYPY_VERSION)) && !defined(Py_IsTrue) +# define Py_IsTrue(x) Py_Is(x, Py_True) +#endif +#if (PY_VERSION_HEX < 0x030A00B1 || defined(PYPY_VERSION)) && !defined(Py_IsFalse) +# define Py_IsFalse(x) Py_Is(x, Py_False) +#endif + + +// bpo-39573 added Py_SET_TYPE() to Python 3.9.0a4 +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE) +static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) +{ + ob->ob_type = type; +} +#define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type) +#endif + + +// bpo-39573 added Py_SET_SIZE() to Python 3.9.0a4 +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE) +static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) +{ + ob->ob_size = size; +} +#define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size) +#endif + + +// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1 +#if PY_VERSION_HEX < 0x030900B1 || defined(PYPY_VERSION) +static inline PyCodeObject* PyFrame_GetCode(PyFrameObject *frame) +{ + assert(frame != _Py_NULL); + assert(frame->f_code != _Py_NULL); + return _Py_CAST(PyCodeObject*, Py_NewRef(frame->f_code)); +} +#endif + +static inline PyCodeObject* _PyFrame_GetCodeBorrow(PyFrameObject *frame) +{ + PyCodeObject *code = PyFrame_GetCode(frame); + Py_DECREF(code); + return code; +} + + +// bpo-40421 added PyFrame_GetBack() to Python 3.9.0b1 +#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION) +static inline PyFrameObject* PyFrame_GetBack(PyFrameObject *frame) +{ + assert(frame != _Py_NULL); + return _Py_CAST(PyFrameObject*, Py_XNewRef(frame->f_back)); +} +#endif + +#if !defined(PYPY_VERSION) +static inline PyFrameObject* _PyFrame_GetBackBorrow(PyFrameObject *frame) +{ + PyFrameObject *back = PyFrame_GetBack(frame); + Py_XDECREF(back); + return back; +} +#endif + + +// bpo-40421 added PyFrame_GetLocals() to Python 3.11.0a7 +#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION) +static inline PyObject* PyFrame_GetLocals(PyFrameObject *frame) +{ +#if PY_VERSION_HEX >= 0x030400B1 + if (PyFrame_FastToLocalsWithError(frame) < 0) { + return NULL; + } +#else + PyFrame_FastToLocals(frame); +#endif + return Py_NewRef(frame->f_locals); +} +#endif + + +// bpo-40421 added PyFrame_GetGlobals() to Python 3.11.0a7 +#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION) +static inline PyObject* PyFrame_GetGlobals(PyFrameObject *frame) +{ + return Py_NewRef(frame->f_globals); +} +#endif + + +// bpo-40421 added PyFrame_GetBuiltins() to Python 3.11.0a7 +#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION) +static inline PyObject* PyFrame_GetBuiltins(PyFrameObject *frame) +{ + return Py_NewRef(frame->f_builtins); +} +#endif + + +// bpo-40421 added PyFrame_GetLasti() to Python 3.11.0b1 +#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION) +static inline int PyFrame_GetLasti(PyFrameObject *frame) +{ +#if PY_VERSION_HEX >= 0x030A00A7 + // bpo-27129: Since Python 3.10.0a7, f_lasti is an instruction offset, + // not a bytes offset anymore. Python uses 16-bit "wordcode" (2 bytes) + // instructions. + if (frame->f_lasti < 0) { + return -1; + } + return frame->f_lasti * 2; +#else + return frame->f_lasti; +#endif +} +#endif + + +// gh-91248 added PyFrame_GetVar() to Python 3.12.0a2 +#if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION) +static inline PyObject* PyFrame_GetVar(PyFrameObject *frame, PyObject *name) +{ + PyObject *locals, *value; + + locals = PyFrame_GetLocals(frame); + if (locals == NULL) { + return NULL; + } +#if PY_VERSION_HEX >= 0x03000000 + value = PyDict_GetItemWithError(locals, name); +#else + value = _PyDict_GetItemWithError(locals, name); +#endif + Py_DECREF(locals); + + if (value == NULL) { + if (PyErr_Occurred()) { + return NULL; + } +#if PY_VERSION_HEX >= 0x03000000 + PyErr_Format(PyExc_NameError, "variable %R does not exist", name); +#else + PyErr_SetString(PyExc_NameError, "variable does not exist"); +#endif + return NULL; + } + return Py_NewRef(value); +} +#endif + + +// gh-91248 added PyFrame_GetVarString() to Python 3.12.0a2 +#if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION) +static inline PyObject* +PyFrame_GetVarString(PyFrameObject *frame, const char *name) +{ + PyObject *name_obj, *value; +#if PY_VERSION_HEX >= 0x03000000 + name_obj = PyUnicode_FromString(name); +#else + name_obj = PyString_FromString(name); +#endif + if (name_obj == NULL) { + return NULL; + } + value = PyFrame_GetVar(frame, name_obj); + Py_DECREF(name_obj); + return value; +} +#endif + + +// bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5 +#if PY_VERSION_HEX < 0x030900A5 || (defined(PYPY_VERSION) && PY_VERSION_HEX < 0x030B0000) +static inline PyInterpreterState * +PyThreadState_GetInterpreter(PyThreadState *tstate) +{ + assert(tstate != _Py_NULL); + return tstate->interp; +} +#endif + + +// bpo-40429 added PyThreadState_GetFrame() to Python 3.9.0b1 +#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION) +static inline PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate) +{ + assert(tstate != _Py_NULL); + return _Py_CAST(PyFrameObject *, Py_XNewRef(tstate->frame)); +} +#endif + +#if !defined(PYPY_VERSION) +static inline PyFrameObject* +_PyThreadState_GetFrameBorrow(PyThreadState *tstate) +{ + PyFrameObject *frame = PyThreadState_GetFrame(tstate); + Py_XDECREF(frame); + return frame; +} +#endif + + +// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5 +#if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION) +static inline PyInterpreterState* PyInterpreterState_Get(void) +{ + PyThreadState *tstate; + PyInterpreterState *interp; + + tstate = PyThreadState_GET(); + if (tstate == _Py_NULL) { + Py_FatalError("GIL released (tstate is NULL)"); + } + interp = tstate->interp; + if (interp == _Py_NULL) { + Py_FatalError("no current interpreter"); + } + return interp; +} +#endif + + +// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a6 +#if 0x030700A1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION) +static inline uint64_t PyThreadState_GetID(PyThreadState *tstate) +{ + assert(tstate != _Py_NULL); + return tstate->id; +} +#endif + +// bpo-43760 added PyThreadState_EnterTracing() to Python 3.11.0a2 +#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION) +static inline void PyThreadState_EnterTracing(PyThreadState *tstate) +{ + tstate->tracing++; +#if PY_VERSION_HEX >= 0x030A00A1 + tstate->cframe->use_tracing = 0; +#else + tstate->use_tracing = 0; +#endif +} +#endif + +// bpo-43760 added PyThreadState_LeaveTracing() to Python 3.11.0a2 +#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION) +static inline void PyThreadState_LeaveTracing(PyThreadState *tstate) +{ + int use_tracing = (tstate->c_tracefunc != _Py_NULL + || tstate->c_profilefunc != _Py_NULL); + tstate->tracing--; +#if PY_VERSION_HEX >= 0x030A00A1 + tstate->cframe->use_tracing = use_tracing; +#else + tstate->use_tracing = use_tracing; +#endif +} +#endif + + +// bpo-37194 added PyObject_CallNoArgs() to Python 3.9.0a1 +// PyObject_CallNoArgs() added to PyPy 3.9.16-v7.3.11 +#if !defined(PyObject_CallNoArgs) && PY_VERSION_HEX < 0x030900A1 +static inline PyObject* PyObject_CallNoArgs(PyObject *func) +{ + return PyObject_CallFunctionObjArgs(func, NULL); +} +#endif + + +// bpo-39245 made PyObject_CallOneArg() public (previously called +// _PyObject_CallOneArg) in Python 3.9.0a4 +// PyObject_CallOneArg() added to PyPy 3.9.16-v7.3.11 +#if !defined(PyObject_CallOneArg) && PY_VERSION_HEX < 0x030900A4 +static inline PyObject* PyObject_CallOneArg(PyObject *func, PyObject *arg) +{ + return PyObject_CallFunctionObjArgs(func, arg, NULL); +} +#endif + + +// bpo-1635741 added PyModule_AddObjectRef() to Python 3.10.0a3 +#if PY_VERSION_HEX < 0x030A00A3 +static inline int +PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value) +{ + int res; + + if (!value && !PyErr_Occurred()) { + // PyModule_AddObject() raises TypeError in this case + PyErr_SetString(PyExc_SystemError, + "PyModule_AddObjectRef() must be called " + "with an exception raised if value is NULL"); + return -1; + } + + Py_XINCREF(value); + res = PyModule_AddObject(module, name, value); + if (res < 0) { + Py_XDECREF(value); + } + return res; +} +#endif + + +// bpo-40024 added PyModule_AddType() to Python 3.9.0a5 +#if PY_VERSION_HEX < 0x030900A5 +static inline int PyModule_AddType(PyObject *module, PyTypeObject *type) +{ + const char *name, *dot; + + if (PyType_Ready(type) < 0) { + return -1; + } + + // inline _PyType_Name() + name = type->tp_name; + assert(name != _Py_NULL); + dot = strrchr(name, '.'); + if (dot != _Py_NULL) { + name = dot + 1; + } + + return PyModule_AddObjectRef(module, name, _PyObject_CAST(type)); +} +#endif + + +// bpo-40241 added PyObject_GC_IsTracked() to Python 3.9.0a6. +// bpo-4688 added _PyObject_GC_IS_TRACKED() to Python 2.7.0a2. +#if PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION) +static inline int PyObject_GC_IsTracked(PyObject* obj) +{ + return (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj)); +} +#endif + +// bpo-40241 added PyObject_GC_IsFinalized() to Python 3.9.0a6. +// bpo-18112 added _PyGCHead_FINALIZED() to Python 3.4.0 final. +#if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0 && !defined(PYPY_VERSION) +static inline int PyObject_GC_IsFinalized(PyObject *obj) +{ + PyGC_Head *gc = _Py_CAST(PyGC_Head*, obj) - 1; + return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(gc)); +} +#endif + + +// bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4 +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE) +static inline int _Py_IS_TYPE(PyObject *ob, PyTypeObject *type) { + return Py_TYPE(ob) == type; +} +#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST(ob), type) +#endif + + +// bpo-46906 added PyFloat_Pack2() and PyFloat_Unpack2() to Python 3.11a7. +// bpo-11734 added _PyFloat_Pack2() and _PyFloat_Unpack2() to Python 3.6.0b1. +// Python 3.11a2 moved _PyFloat_Pack2() and _PyFloat_Unpack2() to the internal +// C API: Python 3.11a2-3.11a6 versions are not supported. +#if 0x030600B1 <= PY_VERSION_HEX && PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION) +static inline int PyFloat_Pack2(double x, char *p, int le) +{ return _PyFloat_Pack2(x, (unsigned char*)p, le); } + +static inline double PyFloat_Unpack2(const char *p, int le) +{ return _PyFloat_Unpack2((const unsigned char *)p, le); } +#endif + + +// bpo-46906 added PyFloat_Pack4(), PyFloat_Pack8(), PyFloat_Unpack4() and +// PyFloat_Unpack8() to Python 3.11a7. +// Python 3.11a2 moved _PyFloat_Pack4(), _PyFloat_Pack8(), _PyFloat_Unpack4() +// and _PyFloat_Unpack8() to the internal C API: Python 3.11a2-3.11a6 versions +// are not supported. +#if PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION) +static inline int PyFloat_Pack4(double x, char *p, int le) +{ return _PyFloat_Pack4(x, (unsigned char*)p, le); } + +static inline int PyFloat_Pack8(double x, char *p, int le) +{ return _PyFloat_Pack8(x, (unsigned char*)p, le); } + +static inline double PyFloat_Unpack4(const char *p, int le) +{ return _PyFloat_Unpack4((const unsigned char *)p, le); } + +static inline double PyFloat_Unpack8(const char *p, int le) +{ return _PyFloat_Unpack8((const unsigned char *)p, le); } +#endif + + +// gh-92154 added PyCode_GetCode() to Python 3.11.0b1 +#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION) +static inline PyObject* PyCode_GetCode(PyCodeObject *code) +{ + return Py_NewRef(code->co_code); +} +#endif + + +// gh-95008 added PyCode_GetVarnames() to Python 3.11.0rc1 +#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION) +static inline PyObject* PyCode_GetVarnames(PyCodeObject *code) +{ + return Py_NewRef(code->co_varnames); +} +#endif + +// gh-95008 added PyCode_GetFreevars() to Python 3.11.0rc1 +#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION) +static inline PyObject* PyCode_GetFreevars(PyCodeObject *code) +{ + return Py_NewRef(code->co_freevars); +} +#endif + +// gh-95008 added PyCode_GetCellvars() to Python 3.11.0rc1 +#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION) +static inline PyObject* PyCode_GetCellvars(PyCodeObject *code) +{ + return Py_NewRef(code->co_cellvars); +} +#endif + + +// Py_UNUSED() was added to Python 3.4.0b2. +#if PY_VERSION_HEX < 0x030400B2 && !defined(Py_UNUSED) +# if defined(__GNUC__) || defined(__clang__) +# define Py_UNUSED(name) _unused_ ## name __attribute__((unused)) +# else +# define Py_UNUSED(name) _unused_ ## name +# endif +#endif + + +// gh-105922 added PyImport_AddModuleRef() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A0 +static inline PyObject* PyImport_AddModuleRef(const char *name) +{ + return Py_XNewRef(PyImport_AddModule(name)); +} +#endif + + +// gh-105927 added PyWeakref_GetRef() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D0000 +static inline int PyWeakref_GetRef(PyObject *ref, PyObject **pobj) +{ + PyObject *obj; + if (ref != NULL && !PyWeakref_Check(ref)) { + *pobj = NULL; + PyErr_SetString(PyExc_TypeError, "expected a weakref"); + return -1; + } + obj = PyWeakref_GetObject(ref); + if (obj == NULL) { + // SystemError if ref is NULL + *pobj = NULL; + return -1; + } + if (obj == Py_None) { + *pobj = NULL; + return 0; + } + *pobj = Py_NewRef(obj); + return 1; +} +#endif + + +// bpo-36974 added PY_VECTORCALL_ARGUMENTS_OFFSET to Python 3.8b1 +#ifndef PY_VECTORCALL_ARGUMENTS_OFFSET +# define PY_VECTORCALL_ARGUMENTS_OFFSET (_Py_CAST(size_t, 1) << (8 * sizeof(size_t) - 1)) +#endif + +// bpo-36974 added PyVectorcall_NARGS() to Python 3.8b1 +#if PY_VERSION_HEX < 0x030800B1 +static inline Py_ssize_t PyVectorcall_NARGS(size_t n) +{ + return n & ~PY_VECTORCALL_ARGUMENTS_OFFSET; +} +#endif + + +// gh-105922 added PyObject_Vectorcall() to Python 3.9.0a4 +#if PY_VERSION_HEX < 0x030900A4 +static inline PyObject* +PyObject_Vectorcall(PyObject *callable, PyObject *const *args, + size_t nargsf, PyObject *kwnames) +{ +#if PY_VERSION_HEX >= 0x030800B1 && !defined(PYPY_VERSION) + // bpo-36974 added _PyObject_Vectorcall() to Python 3.8.0b1 + return _PyObject_Vectorcall(callable, args, nargsf, kwnames); +#else + PyObject *posargs = NULL, *kwargs = NULL; + PyObject *res; + Py_ssize_t nposargs, nkwargs, i; + + if (nargsf != 0 && args == NULL) { + PyErr_BadInternalCall(); + goto error; + } + if (kwnames != NULL && !PyTuple_Check(kwnames)) { + PyErr_BadInternalCall(); + goto error; + } + + nposargs = (Py_ssize_t)PyVectorcall_NARGS(nargsf); + if (kwnames) { + nkwargs = PyTuple_GET_SIZE(kwnames); + } + else { + nkwargs = 0; + } + + posargs = PyTuple_New(nposargs); + if (posargs == NULL) { + goto error; + } + if (nposargs) { + for (i=0; i < nposargs; i++) { + PyTuple_SET_ITEM(posargs, i, Py_NewRef(*args)); + args++; + } + } + + if (nkwargs) { + kwargs = PyDict_New(); + if (kwargs == NULL) { + goto error; + } + + for (i = 0; i < nkwargs; i++) { + PyObject *key = PyTuple_GET_ITEM(kwnames, i); + PyObject *value = *args; + args++; + if (PyDict_SetItem(kwargs, key, value) < 0) { + goto error; + } + } + } + else { + kwargs = NULL; + } + + res = PyObject_Call(callable, posargs, kwargs); + Py_DECREF(posargs); + Py_XDECREF(kwargs); + return res; + +error: + Py_DECREF(posargs); + Py_XDECREF(kwargs); + return NULL; +#endif +} +#endif + + +// gh-106521 added PyObject_GetOptionalAttr() and +// PyObject_GetOptionalAttrString() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyObject_GetOptionalAttr(PyObject *obj, PyObject *attr_name, PyObject **result) +{ + // bpo-32571 added _PyObject_LookupAttr() to Python 3.7.0b1 +#if PY_VERSION_HEX >= 0x030700B1 && !defined(PYPY_VERSION) + return _PyObject_LookupAttr(obj, attr_name, result); +#else + *result = PyObject_GetAttr(obj, attr_name); + if (*result != NULL) { + return 1; + } + if (!PyErr_Occurred()) { + return 0; + } + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + return 0; + } + return -1; +#endif +} + +static inline int +PyObject_GetOptionalAttrString(PyObject *obj, const char *attr_name, PyObject **result) +{ + PyObject *name_obj; + int rc; +#if PY_VERSION_HEX >= 0x03000000 + name_obj = PyUnicode_FromString(attr_name); +#else + name_obj = PyString_FromString(attr_name); +#endif + if (name_obj == NULL) { + *result = NULL; + return -1; + } + rc = PyObject_GetOptionalAttr(obj, name_obj, result); + Py_DECREF(name_obj); + return rc; +} +#endif + + +// gh-106307 added PyObject_GetOptionalAttr() and +// PyMapping_GetOptionalItemString() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result) +{ + *result = PyObject_GetItem(obj, key); + if (*result) { + return 1; + } + if (!PyErr_ExceptionMatches(PyExc_KeyError)) { + return -1; + } + PyErr_Clear(); + return 0; +} + +static inline int +PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result) +{ + PyObject *key_obj; + int rc; +#if PY_VERSION_HEX >= 0x03000000 + key_obj = PyUnicode_FromString(key); +#else + key_obj = PyString_FromString(key); +#endif + if (key_obj == NULL) { + *result = NULL; + return -1; + } + rc = PyMapping_GetOptionalItem(obj, key_obj, result); + Py_DECREF(key_obj); + return rc; +} +#endif + +// gh-108511 added PyMapping_HasKeyWithError() and +// PyMapping_HasKeyStringWithError() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyMapping_HasKeyWithError(PyObject *obj, PyObject *key) +{ + PyObject *res; + int rc = PyMapping_GetOptionalItem(obj, key, &res); + Py_XDECREF(res); + return rc; +} + +static inline int +PyMapping_HasKeyStringWithError(PyObject *obj, const char *key) +{ + PyObject *res; + int rc = PyMapping_GetOptionalItemString(obj, key, &res); + Py_XDECREF(res); + return rc; +} +#endif + + +// gh-108511 added PyObject_HasAttrWithError() and +// PyObject_HasAttrStringWithError() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyObject_HasAttrWithError(PyObject *obj, PyObject *attr) +{ + PyObject *res; + int rc = PyObject_GetOptionalAttr(obj, attr, &res); + Py_XDECREF(res); + return rc; +} + +static inline int +PyObject_HasAttrStringWithError(PyObject *obj, const char *attr) +{ + PyObject *res; + int rc = PyObject_GetOptionalAttrString(obj, attr, &res); + Py_XDECREF(res); + return rc; +} +#endif + + +// gh-106004 added PyDict_GetItemRef() and PyDict_GetItemStringRef() +// to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyDict_GetItemRef(PyObject *mp, PyObject *key, PyObject **result) +{ +#if PY_VERSION_HEX >= 0x03000000 + PyObject *item = PyDict_GetItemWithError(mp, key); +#else + PyObject *item = _PyDict_GetItemWithError(mp, key); +#endif + if (item != NULL) { + *result = Py_NewRef(item); + return 1; // found + } + if (!PyErr_Occurred()) { + *result = NULL; + return 0; // not found + } + *result = NULL; + return -1; +} + +static inline int +PyDict_GetItemStringRef(PyObject *mp, const char *key, PyObject **result) +{ + int res; +#if PY_VERSION_HEX >= 0x03000000 + PyObject *key_obj = PyUnicode_FromString(key); +#else + PyObject *key_obj = PyString_FromString(key); +#endif + if (key_obj == NULL) { + *result = NULL; + return -1; + } + res = PyDict_GetItemRef(mp, key_obj, result); + Py_DECREF(key_obj); + return res; +} +#endif + + +// gh-106307 added PyModule_Add() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyModule_Add(PyObject *mod, const char *name, PyObject *value) +{ + int res = PyModule_AddObjectRef(mod, name, value); + Py_XDECREF(value); + return res; +} +#endif + + +// gh-108014 added Py_IsFinalizing() to Python 3.13.0a1 +// bpo-1856 added _Py_Finalizing to Python 3.2.1b1. +// _Py_IsFinalizing() was added to PyPy 7.3.0. +#if (0x030201B1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030D00A1) \ + && (!defined(PYPY_VERSION_NUM) || PYPY_VERSION_NUM >= 0x7030000) +static inline int Py_IsFinalizing(void) +{ +#if PY_VERSION_HEX >= 0x030700A1 + // _Py_IsFinalizing() was added to Python 3.7.0a1. + return _Py_IsFinalizing(); +#else + return (_Py_Finalizing != NULL); +#endif +} +#endif + + +// gh-108323 added PyDict_ContainsString() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int PyDict_ContainsString(PyObject *op, const char *key) +{ + PyObject *key_obj = PyUnicode_FromString(key); + if (key_obj == NULL) { + return -1; + } + int res = PyDict_Contains(op, key_obj); + Py_DECREF(key_obj); + return res; +} +#endif + + +// gh-108445 added PyLong_AsInt() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int PyLong_AsInt(PyObject *obj) +{ +#ifdef PYPY_VERSION + long value = PyLong_AsLong(obj); + if (value == -1 && PyErr_Occurred()) { + return -1; + } + if (value < (long)INT_MIN || (long)INT_MAX < value) { + PyErr_SetString(PyExc_OverflowError, + "Python int too large to convert to C int"); + return -1; + } + return (int)value; +#else + return _PyLong_AsInt(obj); +#endif +} +#endif + + +// gh-107073 added PyObject_VisitManagedDict() to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg) +{ + PyObject **dict = _PyObject_GetDictPtr(obj); + if (dict == NULL || *dict == NULL) { + return -1; + } + Py_VISIT(*dict); + return 0; +} + +static inline void +PyObject_ClearManagedDict(PyObject *obj) +{ + PyObject **dict = _PyObject_GetDictPtr(obj); + if (dict == NULL || *dict == NULL) { + return; + } + Py_CLEAR(*dict); +} +#endif + +// gh-108867 added PyThreadState_GetUnchecked() to Python 3.13.0a1 +// Python 3.5.2 added _PyThreadState_UncheckedGet(). +#if PY_VERSION_HEX >= 0x03050200 && PY_VERSION_HEX < 0x030D00A1 +static inline PyThreadState* +PyThreadState_GetUnchecked(void) +{ + return _PyThreadState_UncheckedGet(); +} +#endif + +// gh-110289 added PyUnicode_EqualToUTF8() and PyUnicode_EqualToUTF8AndSize() +// to Python 3.13.0a1 +#if PY_VERSION_HEX < 0x030D00A1 +static inline int +PyUnicode_EqualToUTF8AndSize(PyObject *unicode, const char *str, Py_ssize_t str_len) +{ + Py_ssize_t len; + const void *utf8; + PyObject *exc_type, *exc_value, *exc_tb; + int res; + + // API cannot report errors so save/restore the exception + PyErr_Fetch(&exc_type, &exc_value, &exc_tb); + + // Python 3.3.0a1 added PyUnicode_AsUTF8AndSize() +#if PY_VERSION_HEX >= 0x030300A1 + if (PyUnicode_IS_ASCII(unicode)) { + utf8 = PyUnicode_DATA(unicode); + len = PyUnicode_GET_LENGTH(unicode); + } + else { + utf8 = PyUnicode_AsUTF8AndSize(unicode, &len); + if (utf8 == NULL) { + // Memory allocation failure. The API cannot report error, + // so ignore the exception and return 0. + res = 0; + goto done; + } + } + + if (len != str_len) { + res = 0; + goto done; + } + res = (memcmp(utf8, str, (size_t)len) == 0); +#else + PyObject *bytes = PyUnicode_AsUTF8String(unicode); + if (bytes == NULL) { + // Memory allocation failure. The API cannot report error, + // so ignore the exception and return 0. + res = 0; + goto done; + } + +#if PY_VERSION_HEX >= 0x03000000 + len = PyBytes_GET_SIZE(bytes); + utf8 = PyBytes_AS_STRING(bytes); +#else + len = PyString_GET_SIZE(bytes); + utf8 = PyString_AS_STRING(bytes); +#endif + if (len != str_len) { + Py_DECREF(bytes); + res = 0; + goto done; + } + + res = (memcmp(utf8, str, (size_t)len) == 0); + Py_DECREF(bytes); +#endif + +done: + PyErr_Restore(exc_type, exc_value, exc_tb); + return res; +} + +static inline int +PyUnicode_EqualToUTF8(PyObject *unicode, const char *str) +{ + return PyUnicode_EqualToUTF8AndSize(unicode, str, (Py_ssize_t)strlen(str)); +} +#endif + + +// gh-111138 added PyList_Extend() and PyList_Clear() to Python 3.13.0a2 +#if PY_VERSION_HEX < 0x030D00A2 +static inline int +PyList_Extend(PyObject *list, PyObject *iterable) +{ + return PyList_SetSlice(list, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, iterable); +} + +static inline int +PyList_Clear(PyObject *list) +{ + return PyList_SetSlice(list, 0, PY_SSIZE_T_MAX, NULL); +} +#endif + +// gh-111262 added PyDict_Pop() and PyDict_PopString() to Python 3.13.0a2 +#if PY_VERSION_HEX < 0x030D00A2 +static inline int +PyDict_Pop(PyObject *dict, PyObject *key, PyObject **result) +{ + PyObject *value; + + if (!PyDict_Check(dict)) { + PyErr_BadInternalCall(); + if (result) { + *result = NULL; + } + return -1; + } + + // bpo-16991 added _PyDict_Pop() to Python 3.5.0b2. + // Python 3.6.0b3 changed _PyDict_Pop() first argument type to PyObject*. + // Python 3.13.0a1 removed _PyDict_Pop(). +#if defined(PYPY_VERSION) || PY_VERSION_HEX < 0x030500b2 || PY_VERSION_HEX >= 0x030D0000 + value = PyObject_CallMethod(dict, "pop", "O", key); +#elif PY_VERSION_HEX < 0x030600b3 + value = _PyDict_Pop(_Py_CAST(PyDictObject*, dict), key, NULL); +#else + value = _PyDict_Pop(dict, key, NULL); +#endif + if (value == NULL) { + if (result) { + *result = NULL; + } + if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_KeyError)) { + return -1; + } + PyErr_Clear(); + return 0; + } + if (result) { + *result = value; + } + else { + Py_DECREF(value); + } + return 1; +} + +static inline int +PyDict_PopString(PyObject *dict, const char *key, PyObject **result) +{ + PyObject *key_obj = PyUnicode_FromString(key); + if (key_obj == NULL) { + if (result != NULL) { + *result = NULL; + } + return -1; + } + + int res = PyDict_Pop(dict, key_obj, result); + Py_DECREF(key_obj); + return res; +} +#endif + + +#if PY_VERSION_HEX < 0x030200A4 +// Python 3.2.0a4 added Py_hash_t type +typedef Py_ssize_t Py_hash_t; +#endif + + +// gh-111545 added Py_HashPointer() to Python 3.13.0a3 +#if PY_VERSION_HEX < 0x030D00A3 +static inline Py_hash_t Py_HashPointer(const void *ptr) +{ +#if PY_VERSION_HEX >= 0x030900A4 && !defined(PYPY_VERSION) + return _Py_HashPointer(ptr); +#else + return _Py_HashPointer(_Py_CAST(void*, ptr)); +#endif +} +#endif + + +// Python 3.13a4 added a PyTime API. +// Use the private API added to Python 3.5. +#if PY_VERSION_HEX < 0x030D00A4 && PY_VERSION_HEX >= 0x03050000 +typedef _PyTime_t PyTime_t; +#define PyTime_MIN _PyTime_MIN +#define PyTime_MAX _PyTime_MAX + +static inline double PyTime_AsSecondsDouble(PyTime_t t) +{ return _PyTime_AsSecondsDouble(t); } + +static inline int PyTime_Monotonic(PyTime_t *result) +{ return _PyTime_GetMonotonicClockWithInfo(result, NULL); } + +static inline int PyTime_Time(PyTime_t *result) +{ return _PyTime_GetSystemClockWithInfo(result, NULL); } + +static inline int PyTime_PerfCounter(PyTime_t *result) +{ +#if PY_VERSION_HEX >= 0x03070000 && !defined(PYPY_VERSION) + return _PyTime_GetPerfCounterWithInfo(result, NULL); +#elif PY_VERSION_HEX >= 0x03070000 + // Call time.perf_counter_ns() and convert Python int object to PyTime_t. + // Cache time.perf_counter_ns() function for best performance. + static PyObject *func = NULL; + if (func == NULL) { + PyObject *mod = PyImport_ImportModule("time"); + if (mod == NULL) { + return -1; + } + + func = PyObject_GetAttrString(mod, "perf_counter_ns"); + Py_DECREF(mod); + if (func == NULL) { + return -1; + } + } + + PyObject *res = PyObject_CallNoArgs(func); + if (res == NULL) { + return -1; + } + long long value = PyLong_AsLongLong(res); + Py_DECREF(res); + + if (value == -1 && PyErr_Occurred()) { + return -1; + } + + Py_BUILD_ASSERT(sizeof(value) >= sizeof(PyTime_t)); + *result = (PyTime_t)value; + return 0; +#else + // Call time.perf_counter() and convert C double to PyTime_t. + // Cache time.perf_counter() function for best performance. + static PyObject *func = NULL; + if (func == NULL) { + PyObject *mod = PyImport_ImportModule("time"); + if (mod == NULL) { + return -1; + } + + func = PyObject_GetAttrString(mod, "perf_counter"); + Py_DECREF(mod); + if (func == NULL) { + return -1; + } + } + + PyObject *res = PyObject_CallNoArgs(func); + if (res == NULL) { + return -1; + } + double d = PyFloat_AsDouble(res); + Py_DECREF(res); + + if (d == -1.0 && PyErr_Occurred()) { + return -1; + } + + // Avoid floor() to avoid having to link to libm + *result = (PyTime_t)(d * 1e9); + return 0; +#endif +} + +#endif + +// gh-111389 added hash constants to Python 3.13.0a5. These constants were +// added first as private macros to Python 3.4.0b1 and PyPy 7.3.8. +#if (!defined(PyHASH_BITS) \ + && ((!defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x030400B1) \ + || (defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x03070000 \ + && PYPY_VERSION_NUM >= 0x07030800))) +# define PyHASH_BITS _PyHASH_BITS +# define PyHASH_MODULUS _PyHASH_MODULUS +# define PyHASH_INF _PyHASH_INF +# define PyHASH_IMAG _PyHASH_IMAG +#endif + + +// gh-111545 added Py_GetConstant() and Py_GetConstantBorrowed() +// to Python 3.13.0a6 +#if PY_VERSION_HEX < 0x030D00A6 && !defined(Py_CONSTANT_NONE) + +#define Py_CONSTANT_NONE 0 +#define Py_CONSTANT_FALSE 1 +#define Py_CONSTANT_TRUE 2 +#define Py_CONSTANT_ELLIPSIS 3 +#define Py_CONSTANT_NOT_IMPLEMENTED 4 +#define Py_CONSTANT_ZERO 5 +#define Py_CONSTANT_ONE 6 +#define Py_CONSTANT_EMPTY_STR 7 +#define Py_CONSTANT_EMPTY_BYTES 8 +#define Py_CONSTANT_EMPTY_TUPLE 9 + +static inline PyObject* Py_GetConstant(unsigned int constant_id) +{ + static PyObject* constants[Py_CONSTANT_EMPTY_TUPLE + 1] = {NULL}; + + if (constants[Py_CONSTANT_NONE] == NULL) { + constants[Py_CONSTANT_NONE] = Py_None; + constants[Py_CONSTANT_FALSE] = Py_False; + constants[Py_CONSTANT_TRUE] = Py_True; + constants[Py_CONSTANT_ELLIPSIS] = Py_Ellipsis; + constants[Py_CONSTANT_NOT_IMPLEMENTED] = Py_NotImplemented; + + constants[Py_CONSTANT_ZERO] = PyLong_FromLong(0); + if (constants[Py_CONSTANT_ZERO] == NULL) { + goto fatal_error; + } + + constants[Py_CONSTANT_ONE] = PyLong_FromLong(1); + if (constants[Py_CONSTANT_ONE] == NULL) { + goto fatal_error; + } + + constants[Py_CONSTANT_EMPTY_STR] = PyUnicode_FromStringAndSize("", 0); + if (constants[Py_CONSTANT_EMPTY_STR] == NULL) { + goto fatal_error; + } + + constants[Py_CONSTANT_EMPTY_BYTES] = PyBytes_FromStringAndSize("", 0); + if (constants[Py_CONSTANT_EMPTY_BYTES] == NULL) { + goto fatal_error; + } + + constants[Py_CONSTANT_EMPTY_TUPLE] = PyTuple_New(0); + if (constants[Py_CONSTANT_EMPTY_TUPLE] == NULL) { + goto fatal_error; + } + // goto dance to avoid compiler warnings about Py_FatalError() + goto init_done; + +fatal_error: + // This case should never happen + Py_FatalError("Py_GetConstant() failed to get constants"); + } + +init_done: + if (constant_id <= Py_CONSTANT_EMPTY_TUPLE) { + return Py_NewRef(constants[constant_id]); + } + else { + PyErr_BadInternalCall(); + return NULL; + } +} + +static inline PyObject* Py_GetConstantBorrowed(unsigned int constant_id) +{ + PyObject *obj = Py_GetConstant(constant_id); + Py_XDECREF(obj); + return obj; +} +#endif + + +// gh-114329 added PyList_GetItemRef() to Python 3.13.0a4 +#if PY_VERSION_HEX < 0x030D00A4 +static inline PyObject * +PyList_GetItemRef(PyObject *op, Py_ssize_t index) +{ + PyObject *item = PyList_GetItem(op, index); + Py_XINCREF(item); + return item; +} +#endif + + +// gh-114329 added PyList_GetItemRef() to Python 3.13.0a4 +#if PY_VERSION_HEX < 0x030D00A4 +static inline int +PyDict_SetDefaultRef(PyObject *d, PyObject *key, PyObject *default_value, + PyObject **result) +{ + PyObject *value; + if (PyDict_GetItemRef(d, key, &value) < 0) { + // get error + if (result) { + *result = NULL; + } + return -1; + } + if (value != NULL) { + // present + if (result) { + *result = value; + } + else { + Py_DECREF(value); + } + return 1; + } + + // missing: set the item + if (PyDict_SetItem(d, key, default_value) < 0) { + // set error + if (result) { + *result = NULL; + } + return -1; + } + if (result) { + *result = Py_NewRef(default_value); + } + return 0; +} +#endif + +#if PY_VERSION_HEX < 0x030D00B3 +# define Py_BEGIN_CRITICAL_SECTION(op) { +# define Py_END_CRITICAL_SECTION() } +# define Py_BEGIN_CRITICAL_SECTION2(a, b) { +# define Py_END_CRITICAL_SECTION2() } +#endif + +#if PY_VERSION_HEX < 0x030E0000 && PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION) +typedef struct PyUnicodeWriter PyUnicodeWriter; + +static inline void PyUnicodeWriter_Discard(PyUnicodeWriter *writer) +{ + _PyUnicodeWriter_Dealloc((_PyUnicodeWriter*)writer); + PyMem_Free(writer); +} + +static inline PyUnicodeWriter* PyUnicodeWriter_Create(Py_ssize_t length) +{ + if (length < 0) { + PyErr_SetString(PyExc_ValueError, + "length must be positive"); + return NULL; + } + + const size_t size = sizeof(_PyUnicodeWriter); + PyUnicodeWriter *pub_writer = (PyUnicodeWriter *)PyMem_Malloc(size); + if (pub_writer == _Py_NULL) { + PyErr_NoMemory(); + return _Py_NULL; + } + _PyUnicodeWriter *writer = (_PyUnicodeWriter *)pub_writer; + + _PyUnicodeWriter_Init(writer); + if (_PyUnicodeWriter_Prepare(writer, length, 127) < 0) { + PyUnicodeWriter_Discard(pub_writer); + return NULL; + } + writer->overallocate = 1; + return pub_writer; +} + +static inline PyObject* PyUnicodeWriter_Finish(PyUnicodeWriter *writer) +{ + PyObject *str = _PyUnicodeWriter_Finish((_PyUnicodeWriter*)writer); + assert(((_PyUnicodeWriter*)writer)->buffer == NULL); + PyMem_Free(writer); + return str; +} + +static inline int +PyUnicodeWriter_WriteChar(PyUnicodeWriter *writer, Py_UCS4 ch) +{ + if (ch > 0x10ffff) { + PyErr_SetString(PyExc_ValueError, + "character must be in range(0x110000)"); + return -1; + } + + return _PyUnicodeWriter_WriteChar((_PyUnicodeWriter*)writer, ch); +} + +static inline int +PyUnicodeWriter_WriteStr(PyUnicodeWriter *writer, PyObject *obj) +{ + PyObject *str = PyObject_Str(obj); + if (str == NULL) { + return -1; + } + + int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str); + Py_DECREF(str); + return res; +} + +static inline int +PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj) +{ + PyObject *str = PyObject_Repr(obj); + if (str == NULL) { + return -1; + } + + int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str); + Py_DECREF(str); + return res; +} + +static inline int +PyUnicodeWriter_WriteUTF8(PyUnicodeWriter *writer, + const char *str, Py_ssize_t size) +{ + if (size < 0) { + size = (Py_ssize_t)strlen(str); + } + + PyObject *str_obj = PyUnicode_FromStringAndSize(str, size); + if (str_obj == _Py_NULL) { + return -1; + } + + int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str_obj); + Py_DECREF(str_obj); + return res; +} + +static inline int +PyUnicodeWriter_WriteASCII(PyUnicodeWriter *writer, + const char *str, Py_ssize_t size) +{ + if (size < 0) { + size = (Py_ssize_t)strlen(str); + } + + return _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter*)writer, + str, size); +} + +static inline int +PyUnicodeWriter_WriteWideChar(PyUnicodeWriter *writer, + const wchar_t *str, Py_ssize_t size) +{ + if (size < 0) { + size = (Py_ssize_t)wcslen(str); + } + + PyObject *str_obj = PyUnicode_FromWideChar(str, size); + if (str_obj == _Py_NULL) { + return -1; + } + + int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str_obj); + Py_DECREF(str_obj); + return res; +} + +static inline int +PyUnicodeWriter_WriteSubstring(PyUnicodeWriter *writer, PyObject *str, + Py_ssize_t start, Py_ssize_t end) +{ + if (!PyUnicode_Check(str)) { + PyErr_Format(PyExc_TypeError, "expect str, not %s", + Py_TYPE(str)->tp_name); + return -1; + } + if (start < 0 || start > end) { + PyErr_Format(PyExc_ValueError, "invalid start argument"); + return -1; + } + if (end > PyUnicode_GET_LENGTH(str)) { + PyErr_Format(PyExc_ValueError, "invalid end argument"); + return -1; + } + + return _PyUnicodeWriter_WriteSubstring((_PyUnicodeWriter*)writer, str, + start, end); +} + +static inline int +PyUnicodeWriter_Format(PyUnicodeWriter *writer, const char *format, ...) +{ + va_list vargs; + va_start(vargs, format); + PyObject *str = PyUnicode_FromFormatV(format, vargs); + va_end(vargs); + if (str == _Py_NULL) { + return -1; + } + + int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str); + Py_DECREF(str); + return res; +} +#endif // PY_VERSION_HEX < 0x030E0000 + +// gh-116560 added PyLong_GetSign() to Python 3.14.0a0 +#if PY_VERSION_HEX < 0x030E00A0 +static inline int PyLong_GetSign(PyObject *obj, int *sign) +{ + if (!PyLong_Check(obj)) { + PyErr_Format(PyExc_TypeError, "expect int, got %s", Py_TYPE(obj)->tp_name); + return -1; + } + + *sign = _PyLong_Sign(obj); + return 0; +} +#endif + +// gh-126061 added PyLong_IsPositive/Negative/Zero() to Python in 3.14.0a2 +#if PY_VERSION_HEX < 0x030E00A2 +static inline int PyLong_IsPositive(PyObject *obj) +{ + if (!PyLong_Check(obj)) { + PyErr_Format(PyExc_TypeError, "expected int, got %s", Py_TYPE(obj)->tp_name); + return -1; + } + return _PyLong_Sign(obj) == 1; +} + +static inline int PyLong_IsNegative(PyObject *obj) +{ + if (!PyLong_Check(obj)) { + PyErr_Format(PyExc_TypeError, "expected int, got %s", Py_TYPE(obj)->tp_name); + return -1; + } + return _PyLong_Sign(obj) == -1; +} + +static inline int PyLong_IsZero(PyObject *obj) +{ + if (!PyLong_Check(obj)) { + PyErr_Format(PyExc_TypeError, "expected int, got %s", Py_TYPE(obj)->tp_name); + return -1; + } + return _PyLong_Sign(obj) == 0; +} +#endif + + +// gh-124502 added PyUnicode_Equal() to Python 3.14.0a0 +#if PY_VERSION_HEX < 0x030E00A0 +static inline int PyUnicode_Equal(PyObject *str1, PyObject *str2) +{ + if (!PyUnicode_Check(str1)) { + PyErr_Format(PyExc_TypeError, "first argument must be str, not %s", + Py_TYPE(str1)->tp_name); + return -1; + } + if (!PyUnicode_Check(str2)) { + PyErr_Format(PyExc_TypeError, "second argument must be str, not %s", + Py_TYPE(str2)->tp_name); + return -1; + } + +#if PY_VERSION_HEX >= 0x030d0000 && !defined(PYPY_VERSION) + PyAPI_FUNC(int) _PyUnicode_Equal(PyObject *str1, PyObject *str2); + + return _PyUnicode_Equal(str1, str2); +#elif PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION) + return _PyUnicode_EQ(str1, str2); +#elif PY_VERSION_HEX >= 0x03090000 && defined(PYPY_VERSION) + return _PyUnicode_EQ(str1, str2); +#else + return (PyUnicode_Compare(str1, str2) == 0); +#endif +} +#endif + + +// gh-121645 added PyBytes_Join() to Python 3.14.0a0 +#if PY_VERSION_HEX < 0x030E00A0 +static inline PyObject* PyBytes_Join(PyObject *sep, PyObject *iterable) +{ + return _PyBytes_Join(sep, iterable); +} +#endif + + +#if PY_VERSION_HEX < 0x030E00A0 +static inline Py_hash_t Py_HashBuffer(const void *ptr, Py_ssize_t len) +{ +#if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION) + PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void *src, Py_ssize_t len); + + return _Py_HashBytes(ptr, len); +#else + Py_hash_t hash; + PyObject *bytes = PyBytes_FromStringAndSize((const char*)ptr, len); + if (bytes == NULL) { + return -1; + } + hash = PyObject_Hash(bytes); + Py_DECREF(bytes); + return hash; +#endif +} +#endif + + +#if PY_VERSION_HEX < 0x030E00A0 +static inline int PyIter_NextItem(PyObject *iter, PyObject **item) +{ + iternextfunc tp_iternext; + + assert(iter != NULL); + assert(item != NULL); + + tp_iternext = Py_TYPE(iter)->tp_iternext; + if (tp_iternext == NULL) { + *item = NULL; + PyErr_Format(PyExc_TypeError, "expected an iterator, got '%s'", + Py_TYPE(iter)->tp_name); + return -1; + } + + if ((*item = tp_iternext(iter))) { + return 1; + } + if (!PyErr_Occurred()) { + return 0; + } + if (PyErr_ExceptionMatches(PyExc_StopIteration)) { + PyErr_Clear(); + return 0; + } + return -1; +} +#endif + + +#if PY_VERSION_HEX < 0x030E00A0 +static inline PyObject* PyLong_FromInt32(int32_t value) +{ + Py_BUILD_ASSERT(sizeof(long) >= 4); + return PyLong_FromLong(value); +} + +static inline PyObject* PyLong_FromInt64(int64_t value) +{ + Py_BUILD_ASSERT(sizeof(long long) >= 8); + return PyLong_FromLongLong(value); +} + +static inline PyObject* PyLong_FromUInt32(uint32_t value) +{ + Py_BUILD_ASSERT(sizeof(unsigned long) >= 4); + return PyLong_FromUnsignedLong(value); +} + +static inline PyObject* PyLong_FromUInt64(uint64_t value) +{ + Py_BUILD_ASSERT(sizeof(unsigned long long) >= 8); + return PyLong_FromUnsignedLongLong(value); +} + +static inline int PyLong_AsInt32(PyObject *obj, int32_t *pvalue) +{ + Py_BUILD_ASSERT(sizeof(int) == 4); + int value = PyLong_AsInt(obj); + if (value == -1 && PyErr_Occurred()) { + return -1; + } + *pvalue = (int32_t)value; + return 0; +} + +static inline int PyLong_AsInt64(PyObject *obj, int64_t *pvalue) +{ + Py_BUILD_ASSERT(sizeof(long long) == 8); + long long value = PyLong_AsLongLong(obj); + if (value == -1 && PyErr_Occurred()) { + return -1; + } + *pvalue = (int64_t)value; + return 0; +} + +static inline int PyLong_AsUInt32(PyObject *obj, uint32_t *pvalue) +{ + Py_BUILD_ASSERT(sizeof(long) >= 4); + unsigned long value = PyLong_AsUnsignedLong(obj); + if (value == (unsigned long)-1 && PyErr_Occurred()) { + return -1; + } +#if SIZEOF_LONG > 4 + if ((unsigned long)UINT32_MAX < value) { + PyErr_SetString(PyExc_OverflowError, + "Python int too large to convert to C uint32_t"); + return -1; + } +#endif + *pvalue = (uint32_t)value; + return 0; +} + +static inline int PyLong_AsUInt64(PyObject *obj, uint64_t *pvalue) +{ + Py_BUILD_ASSERT(sizeof(long long) == 8); + unsigned long long value = PyLong_AsUnsignedLongLong(obj); + if (value == (unsigned long long)-1 && PyErr_Occurred()) { + return -1; + } + *pvalue = (uint64_t)value; + return 0; +} +#endif + + +// gh-102471 added import and export API for integers to 3.14.0a2. +#if PY_VERSION_HEX < 0x030E00A2 && PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION) +// Helpers to access PyLongObject internals. +static inline void +_PyLong_SetSignAndDigitCount(PyLongObject *op, int sign, Py_ssize_t size) +{ +#if PY_VERSION_HEX >= 0x030C0000 + op->long_value.lv_tag = (uintptr_t)(1 - sign) | ((uintptr_t)size << 3); +#elif PY_VERSION_HEX >= 0x030900A4 + Py_SET_SIZE(op, sign * size); +#else + Py_SIZE(op) = sign * size; +#endif +} + +static inline Py_ssize_t +_PyLong_DigitCount(const PyLongObject *op) +{ +#if PY_VERSION_HEX >= 0x030C0000 + return (Py_ssize_t)(op->long_value.lv_tag >> 3); +#else + return _PyLong_Sign((PyObject*)op) < 0 ? -Py_SIZE(op) : Py_SIZE(op); +#endif +} + +static inline digit* +_PyLong_GetDigits(const PyLongObject *op) +{ +#if PY_VERSION_HEX >= 0x030C0000 + return (digit*)(op->long_value.ob_digit); +#else + return (digit*)(op->ob_digit); +#endif +} + +typedef struct PyLongLayout { + uint8_t bits_per_digit; + uint8_t digit_size; + int8_t digits_order; + int8_t digit_endianness; +} PyLongLayout; + +typedef struct PyLongExport { + int64_t value; + uint8_t negative; + Py_ssize_t ndigits; + const void *digits; + Py_uintptr_t _reserved; +} PyLongExport; + +typedef struct PyLongWriter PyLongWriter; + +static inline const PyLongLayout* +PyLong_GetNativeLayout(void) +{ + static const PyLongLayout PyLong_LAYOUT = { + PyLong_SHIFT, + sizeof(digit), + -1, // least significant first + PY_LITTLE_ENDIAN ? -1 : 1, + }; + + return &PyLong_LAYOUT; +} + +static inline int +PyLong_Export(PyObject *obj, PyLongExport *export_long) +{ + if (!PyLong_Check(obj)) { + memset(export_long, 0, sizeof(*export_long)); + PyErr_Format(PyExc_TypeError, "expected int, got %s", + Py_TYPE(obj)->tp_name); + return -1; + } + + // Fast-path: try to convert to a int64_t + PyLongObject *self = (PyLongObject*)obj; + int overflow; +#if SIZEOF_LONG == 8 + long value = PyLong_AsLongAndOverflow(obj, &overflow); +#else + // Windows has 32-bit long, so use 64-bit long long instead + long long value = PyLong_AsLongLongAndOverflow(obj, &overflow); +#endif + Py_BUILD_ASSERT(sizeof(value) == sizeof(int64_t)); + // the function cannot fail since obj is a PyLongObject + assert(!(value == -1 && PyErr_Occurred())); + + if (!overflow) { + export_long->value = value; + export_long->negative = 0; + export_long->ndigits = 0; + export_long->digits = 0; + export_long->_reserved = 0; + } + else { + export_long->value = 0; + export_long->negative = _PyLong_Sign(obj) < 0; + export_long->ndigits = _PyLong_DigitCount(self); + if (export_long->ndigits == 0) { + export_long->ndigits = 1; + } + export_long->digits = _PyLong_GetDigits(self); + export_long->_reserved = (Py_uintptr_t)Py_NewRef(obj); + } + return 0; +} + +static inline void +PyLong_FreeExport(PyLongExport *export_long) +{ + PyObject *obj = (PyObject*)export_long->_reserved; + + if (obj) { + export_long->_reserved = 0; + Py_DECREF(obj); + } +} + +static inline PyLongWriter* +PyLongWriter_Create(int negative, Py_ssize_t ndigits, void **digits) +{ + if (ndigits <= 0) { + PyErr_SetString(PyExc_ValueError, "ndigits must be positive"); + return NULL; + } + assert(digits != NULL); + + PyLongObject *obj = _PyLong_New(ndigits); + if (obj == NULL) { + return NULL; + } + _PyLong_SetSignAndDigitCount(obj, negative?-1:1, ndigits); + + *digits = _PyLong_GetDigits(obj); + return (PyLongWriter*)obj; +} + +static inline void +PyLongWriter_Discard(PyLongWriter *writer) +{ + PyLongObject *obj = (PyLongObject *)writer; + + assert(Py_REFCNT(obj) == 1); + Py_DECREF(obj); +} + +static inline PyObject* +PyLongWriter_Finish(PyLongWriter *writer) +{ + PyObject *obj = (PyObject *)writer; + PyLongObject *self = (PyLongObject*)obj; + Py_ssize_t j = _PyLong_DigitCount(self); + Py_ssize_t i = j; + int sign = _PyLong_Sign(obj); + + assert(Py_REFCNT(obj) == 1); + + // Normalize and get singleton if possible + while (i > 0 && _PyLong_GetDigits(self)[i-1] == 0) { + --i; + } + if (i != j) { + if (i == 0) { + sign = 0; + } + _PyLong_SetSignAndDigitCount(self, sign, i); + } + if (i <= 1) { + long val = sign * (long)(_PyLong_GetDigits(self)[0]); + Py_DECREF(obj); + return PyLong_FromLong(val); + } + + return obj; +} +#endif + + +#if PY_VERSION_HEX < 0x030C00A3 +# define Py_T_SHORT 0 +# define Py_T_INT 1 +# define Py_T_LONG 2 +# define Py_T_FLOAT 3 +# define Py_T_DOUBLE 4 +# define Py_T_STRING 5 +# define _Py_T_OBJECT 6 +# define Py_T_CHAR 7 +# define Py_T_BYTE 8 +# define Py_T_UBYTE 9 +# define Py_T_USHORT 10 +# define Py_T_UINT 11 +# define Py_T_ULONG 12 +# define Py_T_STRING_INPLACE 13 +# define Py_T_BOOL 14 +# define Py_T_OBJECT_EX 16 +# define Py_T_LONGLONG 17 +# define Py_T_ULONGLONG 18 +# define Py_T_PYSSIZET 19 + +# if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION) +# define _Py_T_NONE 20 +# endif + +# define Py_READONLY 1 +# define Py_AUDIT_READ 2 +# define _Py_WRITE_RESTRICTED 4 +#endif + + +// gh-127350 added Py_fopen() and Py_fclose() to Python 3.14a4 +#if PY_VERSION_HEX < 0x030E00A4 +static inline FILE* Py_fopen(PyObject *path, const char *mode) +{ +#if 0x030400A2 <= PY_VERSION_HEX && !defined(PYPY_VERSION) + PyAPI_FUNC(FILE*) _Py_fopen_obj(PyObject *path, const char *mode); + + return _Py_fopen_obj(path, mode); +#else + FILE *f; + PyObject *bytes; +#if PY_VERSION_HEX >= 0x03000000 + if (!PyUnicode_FSConverter(path, &bytes)) { + return NULL; + } +#else + if (!PyString_Check(path)) { + PyErr_SetString(PyExc_TypeError, "except str"); + return NULL; + } + bytes = Py_NewRef(path); +#endif + const char *path_bytes = PyBytes_AS_STRING(bytes); + + f = fopen(path_bytes, mode); + Py_DECREF(bytes); + + if (f == NULL) { + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path); + return NULL; + } + return f; +#endif +} + +static inline int Py_fclose(FILE *file) +{ + return fclose(file); +} +#endif + + +#if 0x03080000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030E0000 && !defined(PYPY_VERSION) +PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void); + +static inline PyObject* +PyConfig_Get(const char *name) +{ + typedef enum { + _PyConfig_MEMBER_INT, + _PyConfig_MEMBER_UINT, + _PyConfig_MEMBER_ULONG, + _PyConfig_MEMBER_BOOL, + _PyConfig_MEMBER_WSTR, + _PyConfig_MEMBER_WSTR_OPT, + _PyConfig_MEMBER_WSTR_LIST, + } PyConfigMemberType; + + typedef struct { + const char *name; + size_t offset; + PyConfigMemberType type; + const char *sys_attr; + } PyConfigSpec; + +#define PYTHONCAPI_COMPAT_SPEC(MEMBER, TYPE, sys_attr) \ + {#MEMBER, offsetof(PyConfig, MEMBER), \ + _PyConfig_MEMBER_##TYPE, sys_attr} + + static const PyConfigSpec config_spec[] = { + PYTHONCAPI_COMPAT_SPEC(argv, WSTR_LIST, "argv"), + PYTHONCAPI_COMPAT_SPEC(base_exec_prefix, WSTR_OPT, "base_exec_prefix"), + PYTHONCAPI_COMPAT_SPEC(base_executable, WSTR_OPT, "_base_executable"), + PYTHONCAPI_COMPAT_SPEC(base_prefix, WSTR_OPT, "base_prefix"), + PYTHONCAPI_COMPAT_SPEC(bytes_warning, UINT, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(exec_prefix, WSTR_OPT, "exec_prefix"), + PYTHONCAPI_COMPAT_SPEC(executable, WSTR_OPT, "executable"), + PYTHONCAPI_COMPAT_SPEC(inspect, BOOL, _Py_NULL), +#if 0x030C0000 <= PY_VERSION_HEX + PYTHONCAPI_COMPAT_SPEC(int_max_str_digits, UINT, _Py_NULL), +#endif + PYTHONCAPI_COMPAT_SPEC(interactive, BOOL, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(module_search_paths, WSTR_LIST, "path"), + PYTHONCAPI_COMPAT_SPEC(optimization_level, UINT, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(parser_debug, BOOL, _Py_NULL), +#if 0x03090000 <= PY_VERSION_HEX + PYTHONCAPI_COMPAT_SPEC(platlibdir, WSTR, "platlibdir"), +#endif + PYTHONCAPI_COMPAT_SPEC(prefix, WSTR_OPT, "prefix"), + PYTHONCAPI_COMPAT_SPEC(pycache_prefix, WSTR_OPT, "pycache_prefix"), + PYTHONCAPI_COMPAT_SPEC(quiet, BOOL, _Py_NULL), +#if 0x030B0000 <= PY_VERSION_HEX + PYTHONCAPI_COMPAT_SPEC(stdlib_dir, WSTR_OPT, "_stdlib_dir"), +#endif + PYTHONCAPI_COMPAT_SPEC(use_environment, BOOL, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(verbose, UINT, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(warnoptions, WSTR_LIST, "warnoptions"), + PYTHONCAPI_COMPAT_SPEC(write_bytecode, BOOL, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(xoptions, WSTR_LIST, "_xoptions"), + PYTHONCAPI_COMPAT_SPEC(buffered_stdio, BOOL, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(check_hash_pycs_mode, WSTR, _Py_NULL), +#if 0x030B0000 <= PY_VERSION_HEX + PYTHONCAPI_COMPAT_SPEC(code_debug_ranges, BOOL, _Py_NULL), +#endif + PYTHONCAPI_COMPAT_SPEC(configure_c_stdio, BOOL, _Py_NULL), +#if 0x030D0000 <= PY_VERSION_HEX + PYTHONCAPI_COMPAT_SPEC(cpu_count, INT, _Py_NULL), +#endif + PYTHONCAPI_COMPAT_SPEC(dev_mode, BOOL, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(dump_refs, BOOL, _Py_NULL), +#if 0x030B0000 <= PY_VERSION_HEX + PYTHONCAPI_COMPAT_SPEC(dump_refs_file, WSTR_OPT, _Py_NULL), +#endif +#ifdef Py_GIL_DISABLED + PYTHONCAPI_COMPAT_SPEC(enable_gil, INT, _Py_NULL), +#endif + PYTHONCAPI_COMPAT_SPEC(faulthandler, BOOL, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(filesystem_encoding, WSTR, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(filesystem_errors, WSTR, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(hash_seed, ULONG, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(home, WSTR_OPT, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(import_time, BOOL, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(install_signal_handlers, BOOL, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(isolated, BOOL, _Py_NULL), +#ifdef MS_WINDOWS + PYTHONCAPI_COMPAT_SPEC(legacy_windows_stdio, BOOL, _Py_NULL), +#endif + PYTHONCAPI_COMPAT_SPEC(malloc_stats, BOOL, _Py_NULL), +#if 0x030A0000 <= PY_VERSION_HEX + PYTHONCAPI_COMPAT_SPEC(orig_argv, WSTR_LIST, "orig_argv"), +#endif + PYTHONCAPI_COMPAT_SPEC(parse_argv, BOOL, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(pathconfig_warnings, BOOL, _Py_NULL), +#if 0x030C0000 <= PY_VERSION_HEX + PYTHONCAPI_COMPAT_SPEC(perf_profiling, UINT, _Py_NULL), +#endif + PYTHONCAPI_COMPAT_SPEC(program_name, WSTR, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(run_command, WSTR_OPT, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(run_filename, WSTR_OPT, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(run_module, WSTR_OPT, _Py_NULL), +#if 0x030B0000 <= PY_VERSION_HEX + PYTHONCAPI_COMPAT_SPEC(safe_path, BOOL, _Py_NULL), +#endif + PYTHONCAPI_COMPAT_SPEC(show_ref_count, BOOL, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(site_import, BOOL, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(skip_source_first_line, BOOL, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(stdio_encoding, WSTR, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(stdio_errors, WSTR, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(tracemalloc, UINT, _Py_NULL), +#if 0x030B0000 <= PY_VERSION_HEX + PYTHONCAPI_COMPAT_SPEC(use_frozen_modules, BOOL, _Py_NULL), +#endif + PYTHONCAPI_COMPAT_SPEC(use_hash_seed, BOOL, _Py_NULL), + PYTHONCAPI_COMPAT_SPEC(user_site_directory, BOOL, _Py_NULL), +#if 0x030A0000 <= PY_VERSION_HEX + PYTHONCAPI_COMPAT_SPEC(warn_default_encoding, BOOL, _Py_NULL), +#endif + }; + +#undef PYTHONCAPI_COMPAT_SPEC + + const PyConfigSpec *spec; + int found = 0; + for (size_t i=0; i < sizeof(config_spec) / sizeof(config_spec[0]); i++) { + spec = &config_spec[i]; + if (strcmp(spec->name, name) == 0) { + found = 1; + break; + } + } + if (found) { + if (spec->sys_attr != NULL) { + PyObject *value = PySys_GetObject(spec->sys_attr); + if (value == NULL) { + PyErr_Format(PyExc_RuntimeError, "lost sys.%s", spec->sys_attr); + return NULL; + } + return Py_NewRef(value); + } + + const PyConfig *config = _Py_GetConfig(); + void *member = (char *)config + spec->offset; + switch (spec->type) { + case _PyConfig_MEMBER_INT: + case _PyConfig_MEMBER_UINT: + { + int value = *(int *)member; + return PyLong_FromLong(value); + } + case _PyConfig_MEMBER_BOOL: + { + int value = *(int *)member; + return PyBool_FromLong(value != 0); + } + case _PyConfig_MEMBER_ULONG: + { + unsigned long value = *(unsigned long *)member; + return PyLong_FromUnsignedLong(value); + } + case _PyConfig_MEMBER_WSTR: + case _PyConfig_MEMBER_WSTR_OPT: + { + wchar_t *wstr = *(wchar_t **)member; + if (wstr != NULL) { + return PyUnicode_FromWideChar(wstr, -1); + } + else { + return Py_NewRef(Py_None); + } + } + case _PyConfig_MEMBER_WSTR_LIST: + { + const PyWideStringList *list = (const PyWideStringList *)member; + PyObject *tuple = PyTuple_New(list->length); + if (tuple == NULL) { + return NULL; + } + + for (Py_ssize_t i = 0; i < list->length; i++) { + PyObject *item = PyUnicode_FromWideChar(list->items[i], -1); + if (item == NULL) { + Py_DECREF(tuple); + return NULL; + } + PyTuple_SET_ITEM(tuple, i, item); + } + return tuple; + } + default: + Py_UNREACHABLE(); + } + } + + PyErr_Format(PyExc_ValueError, "unknown config option name: %s", name); + return NULL; +} + +static inline int +PyConfig_GetInt(const char *name, int *value) +{ + PyObject *obj = PyConfig_Get(name); + if (obj == NULL) { + return -1; + } + + if (!PyLong_Check(obj)) { + Py_DECREF(obj); + PyErr_Format(PyExc_TypeError, "config option %s is not an int", name); + return -1; + } + + int as_int = PyLong_AsInt(obj); + Py_DECREF(obj); + if (as_int == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_OverflowError, + "config option %s value does not fit into a C int", name); + return -1; + } + + *value = as_int; + return 0; +} +#endif // PY_VERSION_HEX > 0x03090000 && !defined(PYPY_VERSION) + +// gh-133144 added PyUnstable_Object_IsUniquelyReferenced() to Python 3.14.0b1. +// Adapted from _PyObject_IsUniquelyReferenced() implementation. +#if PY_VERSION_HEX < 0x030E00B0 +static inline int PyUnstable_Object_IsUniquelyReferenced(PyObject *obj) +{ +#if !defined(Py_GIL_DISABLED) + return Py_REFCNT(obj) == 1; +#else + // NOTE: the entire ob_ref_shared field must be zero, including flags, to + // ensure that other threads cannot concurrently create new references to + // this object. + return (_Py_IsOwnedByCurrentThread(obj) && + _Py_atomic_load_uint32_relaxed(&obj->ob_ref_local) == 1 && + _Py_atomic_load_ssize_relaxed(&obj->ob_ref_shared) == 0); +#endif +} +#endif + +// gh-128926 added PyUnstable_TryIncRef() and PyUnstable_EnableTryIncRef() to +// Python 3.14.0a5. Adapted from _Py_TryIncref() and _PyObject_SetMaybeWeakref(). +#if PY_VERSION_HEX < 0x030E00A5 +static inline int PyUnstable_TryIncRef(PyObject *op) +{ +#ifndef Py_GIL_DISABLED + if (Py_REFCNT(op) > 0) { + Py_INCREF(op); + return 1; + } + return 0; +#else + // _Py_TryIncrefFast() + uint32_t local = _Py_atomic_load_uint32_relaxed(&op->ob_ref_local); + local += 1; + if (local == 0) { + // immortal + return 1; + } + if (_Py_IsOwnedByCurrentThread(op)) { + _Py_INCREF_STAT_INC(); + _Py_atomic_store_uint32_relaxed(&op->ob_ref_local, local); +#ifdef Py_REF_DEBUG + _Py_INCREF_IncRefTotal(); +#endif + return 1; + } + + // _Py_TryIncRefShared() + Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&op->ob_ref_shared); + for (;;) { + // If the shared refcount is zero and the object is either merged + // or may not have weak references, then we cannot incref it. + if (shared == 0 || shared == _Py_REF_MERGED) { + return 0; + } + + if (_Py_atomic_compare_exchange_ssize( + &op->ob_ref_shared, + &shared, + shared + (1 << _Py_REF_SHARED_SHIFT))) { +#ifdef Py_REF_DEBUG + _Py_INCREF_IncRefTotal(); +#endif + _Py_INCREF_STAT_INC(); + return 1; + } + } +#endif +} + +static inline void PyUnstable_EnableTryIncRef(PyObject *op) +{ +#ifdef Py_GIL_DISABLED + // _PyObject_SetMaybeWeakref() + if (_Py_IsImmortal(op)) { + return; + } + for (;;) { + Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&op->ob_ref_shared); + if ((shared & _Py_REF_SHARED_FLAG_MASK) != 0) { + // Nothing to do if it's in WEAKREFS, QUEUED, or MERGED states. + return; + } + if (_Py_atomic_compare_exchange_ssize( + &op->ob_ref_shared, &shared, shared | _Py_REF_MAYBE_WEAKREF)) { + return; + } + } +#else + (void)op; // unused argument +#endif +} +#endif + + +#if PY_VERSION_HEX < 0x030F0000 +static inline PyObject* +PySys_GetAttrString(const char *name) +{ +#if PY_VERSION_HEX >= 0x03000000 + PyObject *value = Py_XNewRef(PySys_GetObject(name)); +#else + PyObject *value = Py_XNewRef(PySys_GetObject((char*)name)); +#endif + if (value != NULL) { + return value; + } + if (!PyErr_Occurred()) { + PyErr_Format(PyExc_RuntimeError, "lost sys.%s", name); + } + return NULL; +} + +static inline PyObject* +PySys_GetAttr(PyObject *name) +{ +#if PY_VERSION_HEX >= 0x03000000 + const char *name_str = PyUnicode_AsUTF8(name); +#else + const char *name_str = PyString_AsString(name); +#endif + if (name_str == NULL) { + return NULL; + } + + return PySys_GetAttrString(name_str); +} + +static inline int +PySys_GetOptionalAttrString(const char *name, PyObject **value) +{ +#if PY_VERSION_HEX >= 0x03000000 + *value = Py_XNewRef(PySys_GetObject(name)); +#else + *value = Py_XNewRef(PySys_GetObject((char*)name)); +#endif + if (*value != NULL) { + return 1; + } + return 0; +} + +static inline int +PySys_GetOptionalAttr(PyObject *name, PyObject **value) +{ +#if PY_VERSION_HEX >= 0x03000000 + const char *name_str = PyUnicode_AsUTF8(name); +#else + const char *name_str = PyString_AsString(name); +#endif + if (name_str == NULL) { + *value = NULL; + return -1; + } + + return PySys_GetOptionalAttrString(name_str, value); +} +#endif // PY_VERSION_HEX < 0x030F00A1 + + +#if PY_VERSION_HEX < 0x030F00A1 +typedef struct PyBytesWriter { + char small_buffer[256]; + PyObject *obj; + Py_ssize_t size; +} PyBytesWriter; + +static inline Py_ssize_t +_PyBytesWriter_GetAllocated(PyBytesWriter *writer) +{ + if (writer->obj == NULL) { + return sizeof(writer->small_buffer); + } + else { + return PyBytes_GET_SIZE(writer->obj); + } +} + + +static inline int +_PyBytesWriter_Resize_impl(PyBytesWriter *writer, Py_ssize_t size, + int resize) +{ + int overallocate = resize; + assert(size >= 0); + + if (size <= _PyBytesWriter_GetAllocated(writer)) { + return 0; + } + + if (overallocate) { +#ifdef MS_WINDOWS + /* On Windows, overallocate by 50% is the best factor */ + if (size <= (PY_SSIZE_T_MAX - size / 2)) { + size += size / 2; + } +#else + /* On Linux, overallocate by 25% is the best factor */ + if (size <= (PY_SSIZE_T_MAX - size / 4)) { + size += size / 4; + } +#endif + } + + if (writer->obj != NULL) { + if (_PyBytes_Resize(&writer->obj, size)) { + return -1; + } + assert(writer->obj != NULL); + } + else { + writer->obj = PyBytes_FromStringAndSize(NULL, size); + if (writer->obj == NULL) { + return -1; + } + + if (resize) { + assert((size_t)size > sizeof(writer->small_buffer)); + memcpy(PyBytes_AS_STRING(writer->obj), + writer->small_buffer, + sizeof(writer->small_buffer)); + } + } + return 0; +} + +static inline void* +PyBytesWriter_GetData(PyBytesWriter *writer) +{ + if (writer->obj == NULL) { + return writer->small_buffer; + } + else { + return PyBytes_AS_STRING(writer->obj); + } +} + +static inline Py_ssize_t +PyBytesWriter_GetSize(PyBytesWriter *writer) +{ + return writer->size; +} + +static inline void +PyBytesWriter_Discard(PyBytesWriter *writer) +{ + if (writer == NULL) { + return; + } + + Py_XDECREF(writer->obj); + PyMem_Free(writer); +} + +static inline PyBytesWriter* +PyBytesWriter_Create(Py_ssize_t size) +{ + if (size < 0) { + PyErr_SetString(PyExc_ValueError, "size must be >= 0"); + return NULL; + } + + PyBytesWriter *writer = (PyBytesWriter*)PyMem_Malloc(sizeof(PyBytesWriter)); + if (writer == NULL) { + PyErr_NoMemory(); + return NULL; + } + + writer->obj = NULL; + writer->size = 0; + + if (size >= 1) { + if (_PyBytesWriter_Resize_impl(writer, size, 0) < 0) { + PyBytesWriter_Discard(writer); + return NULL; + } + writer->size = size; + } + return writer; +} + +static inline PyObject* +PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size) +{ + PyObject *result; + if (size == 0) { + result = PyBytes_FromStringAndSize("", 0); + } + else if (writer->obj != NULL) { + if (size != PyBytes_GET_SIZE(writer->obj)) { + if (_PyBytes_Resize(&writer->obj, size)) { + goto error; + } + } + result = writer->obj; + writer->obj = NULL; + } + else { + result = PyBytes_FromStringAndSize(writer->small_buffer, size); + } + PyBytesWriter_Discard(writer); + return result; + +error: + PyBytesWriter_Discard(writer); + return NULL; +} + +static inline PyObject* +PyBytesWriter_Finish(PyBytesWriter *writer) +{ + return PyBytesWriter_FinishWithSize(writer, writer->size); +} + +static inline PyObject* +PyBytesWriter_FinishWithPointer(PyBytesWriter *writer, void *buf) +{ + Py_ssize_t size = (char*)buf - (char*)PyBytesWriter_GetData(writer); + if (size < 0 || size > _PyBytesWriter_GetAllocated(writer)) { + PyBytesWriter_Discard(writer); + PyErr_SetString(PyExc_ValueError, "invalid end pointer"); + return NULL; + } + + return PyBytesWriter_FinishWithSize(writer, size); +} + +static inline int +PyBytesWriter_Resize(PyBytesWriter *writer, Py_ssize_t size) +{ + if (size < 0) { + PyErr_SetString(PyExc_ValueError, "size must be >= 0"); + return -1; + } + if (_PyBytesWriter_Resize_impl(writer, size, 1) < 0) { + return -1; + } + writer->size = size; + return 0; +} + +static inline int +PyBytesWriter_Grow(PyBytesWriter *writer, Py_ssize_t size) +{ + if (size < 0 && writer->size + size < 0) { + PyErr_SetString(PyExc_ValueError, "invalid size"); + return -1; + } + if (size > PY_SSIZE_T_MAX - writer->size) { + PyErr_NoMemory(); + return -1; + } + size = writer->size + size; + + if (_PyBytesWriter_Resize_impl(writer, size, 1) < 0) { + return -1; + } + writer->size = size; + return 0; +} + +static inline void* +PyBytesWriter_GrowAndUpdatePointer(PyBytesWriter *writer, + Py_ssize_t size, void *buf) +{ + Py_ssize_t pos = (char*)buf - (char*)PyBytesWriter_GetData(writer); + if (PyBytesWriter_Grow(writer, size) < 0) { + return NULL; + } + return (char*)PyBytesWriter_GetData(writer) + pos; +} + +static inline int +PyBytesWriter_WriteBytes(PyBytesWriter *writer, + const void *bytes, Py_ssize_t size) +{ + if (size < 0) { + size_t len = strlen((const char*)bytes); + if (len > (size_t)PY_SSIZE_T_MAX) { + PyErr_NoMemory(); + return -1; + } + size = (Py_ssize_t)len; + } + + Py_ssize_t pos = writer->size; + if (PyBytesWriter_Grow(writer, size) < 0) { + return -1; + } + char *buf = (char*)PyBytesWriter_GetData(writer); + memcpy(buf + pos, bytes, (size_t)size); + return 0; +} + +static inline int +PyBytesWriter_Format(PyBytesWriter *writer, const char *format, ...) + Py_GCC_ATTRIBUTE((format(printf, 2, 3))); + +static inline int +PyBytesWriter_Format(PyBytesWriter *writer, const char *format, ...) +{ + va_list vargs; + va_start(vargs, format); + PyObject *str = PyBytes_FromFormatV(format, vargs); + va_end(vargs); + + if (str == NULL) { + return -1; + } + int res = PyBytesWriter_WriteBytes(writer, + PyBytes_AS_STRING(str), + PyBytes_GET_SIZE(str)); + Py_DECREF(str); + return res; +} +#endif // PY_VERSION_HEX < 0x030F00A1 + + +#if PY_VERSION_HEX < 0x030F00A1 +static inline PyObject* +PyTuple_FromArray(PyObject *const *array, Py_ssize_t size) +{ + PyObject *tuple = PyTuple_New(size); + if (tuple == NULL) { + return NULL; + } + for (Py_ssize_t i=0; i < size; i++) { + PyObject *item = array[i]; + PyTuple_SET_ITEM(tuple, i, Py_NewRef(item)); + } + return tuple; +} +#endif + + +#if PY_VERSION_HEX < 0x030F00A1 +static inline Py_hash_t +PyUnstable_Unicode_GET_CACHED_HASH(PyObject *op) +{ +#ifdef PYPY_VERSION + (void)op; // unused argument + return -1; +#elif PY_VERSION_HEX >= 0x03000000 + return ((PyASCIIObject*)op)->hash; +#else + return ((PyUnicodeObject*)op)->hash; +#endif +} +#endif + + +#ifdef __cplusplus +} +#endif +#endif // PYTHONCAPI_COMPAT + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/schema_info.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/schema_info.h new file mode 100644 index 0000000000000000000000000000000000000000..e022af2a2a585fabe2c8b8867f0e6034d22fbf84 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/schema_info.h @@ -0,0 +1,121 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::utils { + +using SchemaSpecialCasePair = + std::pair>; +/** + * class SchemaInfo + * + * FunctionSchema wrapper that publicizes argument value specific operator + * behavior (mutation, aliasing, special cases, etc...) + */ + +struct TORCH_API SchemaInfo { + public: + explicit SchemaInfo(c10::FunctionSchema schema) + : schema_(std::move(schema)), + alias_maps_current_(false), + has_init_(false) {} + explicit SchemaInfo(const char* signature) + : schema_(torch::jit::parseSchema(signature)), + alias_maps_current_(false), + has_init_(false) {} + + bool is_mutable(); + + bool is_mutable(const c10::SchemaArgument& argument); + + bool is_mutable(std::string_view name); + + bool has_argument(std::string_view name); + + bool is_nondeterministic() const; + + // Returns whether lhs and rhs may alias directly. + // This does not account for cases where lhs or rhs are a container that + // may contain elements that alias the other argument. + // Besides the checks already included in FunctionSchema::may_alias, this + // method also accounts special aliasing cases causes by aliasing argument + // values supplied from addArgumentValue. + bool may_alias( + const c10::SchemaArgument& lhs, + const c10::SchemaArgument& rhs); + + // Returns whether lhs and rhs may alias directly or whether lhs/rhs are a + // container that may contain elements that alias the other argument. Besides + // the checks already included in FunctionSchema::may_contain_alias, this + // method also accounts for special aliasing cases causes by aliasing argument + // values supplied from addArgumentValue. bidirectional = false only returns + // whether lhs may contain an alias of rhs while bidirectional = true returns + // both directions. + bool may_contain_alias( + const c10::SchemaArgument& lhs, + const c10::SchemaArgument& rhs, + bool bidirectional = true); + + void addArgumentValue(const std::string& name, const at::IValue& value); + + void addArgumentValues( + const std::vector>& value_list); + + void addArgumentValues( + const std::unordered_map& values); + + bool hasInputArgumentNamed(const std::string& name) const; + + private: + // This function enforces more conservative results when the TORCH_WARN is + // triggered from above due to duplicates in an argument list + void ensureConservativity( + const std::unordered_set& duplicates, + const std::vector& arguments_list, + c10::SchemaArgType type); + + void initSchemaInfo(); + + void generateAliasMaps(); + + bool mayContainAliasImpl( + const c10::SchemaArgument& lhs, + const c10::SchemaArgument& rhs); + + static std::vector getNonDeterministicOps(); + + static std::vector getTrainingOps(); + + const std::unordered_set& wildcardSet(); + + const std::unordered_set& containerSet(); + + // Set of all wildcard arguments + std::unordered_set wildcard_set_; + + // Set of all container arguments + std::unordered_set container_set_; + + // Map of argument IValues + std::unordered_map value_map_; + + // Alias map of inputs with each other + std::vector> input_alias_map_; + + // Alias map of outputs to inputs + std::vector> output_alias_map_; + + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) + const c10::FunctionSchema schema_; + + bool alias_maps_current_; + + bool has_init_; +}; +} // namespace torch::utils + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/structseq.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/structseq.h new file mode 100644 index 0000000000000000000000000000000000000000..8d40d6bf4adc54ded2638bf0c67062a733ce9f5e --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/structseq.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::utils { + +PyObject* returned_structseq_repr(PyStructSequence* obj); + +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_apply.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_apply.h new file mode 100644 index 0000000000000000000000000000000000000000..062e093f123e11ee7492cf297b83c8087b336178 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_apply.h @@ -0,0 +1,24 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::utils { + +const at::Tensor& apply_(const at::Tensor& self, PyObject* fn); +const at::Tensor& map_( + const at::Tensor& self, + const at::Tensor& other_, + PyObject* fn); +const at::Tensor& map2_( + const at::Tensor& self, + const at::Tensor& x_, + const at::Tensor& y_, + PyObject* fn); + +} // namespace torch::utils + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_dtypes.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_dtypes.h new file mode 100644 index 0000000000000000000000000000000000000000..978bc25e12052f95b40120ba8c097c0940a955f6 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_dtypes.h @@ -0,0 +1,18 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace torch::utils { + +std::pair getDtypeNames(at::ScalarType scalarType); + +void initializeDtypes(); + +} // namespace torch::utils + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_flatten.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_flatten.h new file mode 100644 index 0000000000000000000000000000000000000000..ea7652eede79d5e40858224f096da4242b8ef41b --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_flatten.h @@ -0,0 +1,89 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace torch::utils { + +/// Generate an ID for a combination of tensor backend + scalar type to be used +/// when ordering tensors ('like' tensors are grouped by pulling out their +/// backend + scalar type, so this function combines that into a single number) +inline size_t type_id(const at::Tensor& tensor) { + return static_cast(tensor.options().backend()) * + static_cast(at::ScalarType::NumOptions) + + static_cast(tensor.scalar_type()); +} + +inline at::Tensor flatten_dense_tensors(at::TensorList tensors) { + return at::flatten_dense_tensors(tensors); +} + +inline std::vector unflatten_dense_tensors( + const at::Tensor& flat, + at::TensorList tensors) { + return at::unflatten_dense_tensors(flat, tensors); +} + +struct TensorGroup { + std::vector tensors; + size_t size = 0; + + size_t type_id() { + AT_ASSERT(!tensors.empty()); + return ::torch::utils::type_id(tensors[0]); + } + + const at::TensorOptions options() { + AT_ASSERT(!tensors.empty()); + return tensors[0].options(); + } +}; + +// Helper function that takes a list of tensors and splits them into tensor +// groups by the size limit and outputs these tensor groups. If the input +// tensors are of different tensor types, they will be split into different +// groups as well. +// +// Two options of splitting provided to the user, +// +// Imagine the size_limit is 256 and the list of input tensors are: +// tensor_a(fp16 - 128 bytes), +// tensor_b(fp32 - 256 bytes), +// tensor_c(fp16 - 128 bytes), +// +// when fine_grained == false: +// The function will read the list of tensors sequentially and accumulate +// enough tensors for each data type until the size_limit, therefore: +// it will output: {{tensor_a, tensor_c}, {tensor_b}} +// +// when fine_grained == true: +// The function will read the list of tensors sequentially and accumulate +// enough tensors for all data types until the size_limit, and then split +// the accumulated tensors into different groups by data types, therefore: +// it will output: {{tensor_a}, {tensor_b}, {tensor_c}} +TORCH_API std::vector take_tensors( + at::TensorList tensors, + size_t size_limit, + bool fine_grained = false); + +TORCH_API void reorder_tensors_like( + std::vector& tensors, + at::TensorList order); + +TORCH_API std::pair flatten_sparse_tensors( + at::TensorList tensors); + +TORCH_API std::vector unflatten_sparse_tensors( + const at::Tensor& flat_indices, + const at::Tensor& flat_values, + at::TensorList tensors); + +} // namespace torch::utils + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_layouts.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_layouts.h new file mode 100644 index 0000000000000000000000000000000000000000..5521d1c4e0b8875c063e1ee14dae951c58e32bba --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_layouts.h @@ -0,0 +1,12 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +namespace torch::utils { + +void initializeLayouts(); + +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_list.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_list.h new file mode 100644 index 0000000000000000000000000000000000000000..8705ab13d1483cb270536d660217527e0c21b308 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_list.h @@ -0,0 +1,18 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace at { +class Tensor; +} + +namespace torch::utils { + +PyObject* tensor_to_list(const at::Tensor& tensor); + +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_memoryformats.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_memoryformats.h new file mode 100644 index 0000000000000000000000000000000000000000..489033081dd89b705f048aba9fbb7f228851868a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_memoryformats.h @@ -0,0 +1,20 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +namespace torch::utils { + +void initializeMemoryFormats(); + +// This methods returns a borrowed reference! +TORCH_PYTHON_API PyObject* getTHPMemoryFormat( + c10::MemoryFormat /*memory_format*/); + +} // namespace torch::utils + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_new.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_new.h new file mode 100644 index 0000000000000000000000000000000000000000..690695179a5462c9b52d45659d738fb97b50eacf --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_new.h @@ -0,0 +1,141 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include + +namespace torch::utils { + +// NOTE: [torch.tensor, lift_fresh, and device movement] +// +// The `only_lift_cpu_tensors` flag controls what happens on torch.tensor([1, 2, +// 3], device="cuda") (or any non-CPU devices). +// +// If false (default): +// - the data gets moved into a CPU Tensor +// - then, it gets moved to cuda (via .to) +// - finally, we call lift_fresh() on it. +// Steps 1 and 2 happen with all modes disabled. +// +// If true: +// - the data gets moved into a CPU Tensor (with correct dtype) +// - we call lift_fresh() on it +// - finally, we move it to cuda (via .to) +// Step 1 happens with all modes disabled. +// +// `only_lift_cpu_tensors=true` is useful to prevent CUDA initialization under +// FakeTensorMode because it avoids moving concrete data to CUDA. +TORCH_API bool only_lift_cpu_tensors(); +TORCH_API void set_only_lift_cpu_tensors(bool value); + +at::Tensor base_tensor_ctor(PyObject* args, PyObject* kwargs); +TORCH_PYTHON_API at::Tensor legacy_tensor_ctor( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PyObject* args, + PyObject* kwargs); +at::Tensor legacy_tensor_new( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PyObject* args, + PyObject* kwargs); +at::Tensor indexing_tensor_from_data( + c10::TensorOptions options, + at::ScalarType scalar_type, + std::optional device, + PyObject* data); +at::Tensor sparse_coo_tensor_ctor( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PythonArgs& r); +void _validate_sparse_coo_tensor_args( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PyObject* args, + PyObject* kwargs); + +at::Tensor sparse_compressed_tensor_ctor( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PythonArgs& r); +at::Tensor sparse_csr_tensor_ctor( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PythonArgs& r); +at::Tensor sparse_csc_tensor_ctor( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PythonArgs& r); +at::Tensor sparse_bsr_tensor_ctor( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PythonArgs& r); +at::Tensor sparse_bsc_tensor_ctor( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PythonArgs& r); + +void _validate_sparse_compressed_tensor_args( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PyObject* args, + PyObject* kwargs); +void _validate_sparse_csr_tensor_args( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PyObject* args, + PyObject* kwargs); +void _validate_sparse_csc_tensor_args( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PyObject* args, + PyObject* kwargs); +void _validate_sparse_bsr_tensor_args( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PyObject* args, + PyObject* kwargs); +void _validate_sparse_bsc_tensor_args( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PyObject* args, + PyObject* kwargs); + +at::Tensor tensor_ctor( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PythonArgs& r); +at::Tensor as_tensor( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PythonArgs& r); +at::Tensor new_tensor( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PyObject* args, + PyObject* kwargs); +at::Tensor new_ones( + c10::DispatchKey dispatch_key, + at::ScalarType scalar_type, + PyObject* args, + PyObject* kwargs); +at::Tensor tensor_frombuffer( + PyObject* buffer, + at::ScalarType dtype, + int64_t count, + int64_t offset, + bool requires_grad); +at::Tensor tensor_fromDLPack(PyObject* data); +at::Tensor asarray( + PyObject* obj, + std::optional dtype, + std::optional device, + std::optional copy, + std::optional requires_grad); +} // namespace torch::utils + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_numpy.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_numpy.h new file mode 100644 index 0000000000000000000000000000000000000000..b43522b8708452c5847be2873908d5c0f57ae6ad --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_numpy.h @@ -0,0 +1,37 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::utils { + +TORCH_API PyObject* tensor_to_numpy( + const at::Tensor& tensor, + bool force = false); + +TORCH_API at::Tensor tensor_from_numpy( + PyObject* obj, + bool warn_if_not_writeable = true); + +TORCH_API int aten_to_numpy_dtype(const at::ScalarType scalar_type); +TORCH_API at::ScalarType numpy_dtype_to_aten(int dtype); + +TORCH_API bool is_numpy_available(); +TORCH_API bool is_numpy_int(PyObject* obj); +TORCH_API bool is_numpy_bool(PyObject* obj); +TORCH_API bool is_numpy_scalar(PyObject* obj); + +void warn_numpy_not_writeable(); +at::Tensor tensor_from_cuda_array_interface( + PyObject* obj, + std::optional device_opt = std::nullopt); + +void validate_numpy_for_dlpack_deleter_bug(); +bool is_numpy_dlpack_deleter_bugged(); + +} // namespace torch::utils + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_qschemes.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_qschemes.h new file mode 100644 index 0000000000000000000000000000000000000000..d7b24333ad63eab535b31d529754b3a4d3b30b82 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_qschemes.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include + +namespace torch::utils { + +PyObject* getTHPQScheme(at::QScheme qscheme); +void initializeQSchemes(); + +} // namespace torch::utils + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_types.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_types.h new file mode 100644 index 0000000000000000000000000000000000000000..d7891fedb997e32d9481613e9cce8c1754c8bd11 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/tensor_types.h @@ -0,0 +1,25 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +namespace torch::utils { + +std::string options_to_string(const at::TensorOptions& options); +std::string type_to_string(const at::DeprecatedTypeProperties& type); +at::TensorOptions options_from_string(const std::string& str); + +// return a vector of all "declared" types, even those that weren't compiled +std::vector> all_declared_types(); + +// return python module name of backend, like torch.cuda, torch.foo +const char* backend_to_string(const at::Backend& backend); + +} // namespace torch::utils + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/throughput_benchmark-inl.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/throughput_benchmark-inl.h new file mode 100644 index 0000000000000000000000000000000000000000..fa267bc1fc3a8ef59b60e5cee3777f696bd6b509 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/throughput_benchmark-inl.h @@ -0,0 +1,176 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace torch::throughput_benchmark::detail { + +template +BenchmarkExecutionStats BenchmarkHelper::benchmark( + const BenchmarkConfig& config) const { + CHECK(initialized_); + TORCH_CHECK( + config.num_worker_threads == 1, + "Only parallelization by callers is supported"); + + LOG(INFO) << at::get_parallel_info(); + + // We pre-generate inputs here for each of the threads. This allows us to + // safely move inputs out for each of the threads independently and thus avoid + // overhead from the benchmark runner itself + std::vector> thread_inputs(config.num_calling_threads); + std::vector input_iters(config.num_calling_threads); + { + std::random_device seeder; + std::mt19937 engine(seeder()); + TORCH_CHECK( + !inputs_.empty(), + "Please provide benchmark inputs." + "Did you forget to call add_input()? "); + std::uniform_int_distribution dist(0, inputs_.size() - 1); + + for (const auto thread_id : c10::irange(config.num_calling_threads)) { + // Just in case we generate num_iters inputs for each of the threads + // This was if one thread does all the work we will be fine + for (const auto i [[maybe_unused]] : + c10::irange(config.num_iters + config.num_warmup_iters)) { + thread_inputs[thread_id].push_back(cloneInput(inputs_[dist(engine)])); + } + input_iters[thread_id] = 0; + } + } + + std::mutex m; + std::condition_variable worker_main_cv; + std::condition_variable main_worker_cv; + // TODO: add GUARDED_BY once it is available + int64_t initialized{0}; + int64_t finished{0}; + bool start{false}; + std::atomic num_attempted_iters{0}; + std::vector callers; + + callers.reserve(config.num_calling_threads); + + static constexpr auto& DEVICES = at::autocast::_AUTOCAST_SUPPORTED_DEVICES; + std::array autocast_enabled; + std::array autocast_dtype; + for (size_t i = 0; i < DEVICES.size(); i++) { + autocast_enabled[i] = at::autocast::is_autocast_enabled(DEVICES[i]); + autocast_dtype[i] = at::autocast::get_autocast_dtype(DEVICES[i]); + } + bool autocast_cache_enabled = at::autocast::is_autocast_cache_enabled(); + bool tls_grad_enabled = c10::GradMode::is_enabled(); + c10::impl::LocalDispatchKeySet tls_key_set = + c10::impl::tls_local_dispatch_key_set(); + + for (const auto thread_id : c10::irange(config.num_calling_threads)) { + callers.emplace_back([&, thread_id]() { + // We use conditional variable as a barrier to make sure each thread + // performs required warmeup iterations before we start measuring + c10::GradMode::set_enabled(tls_grad_enabled); + c10::impl::_force_tls_local_dispatch_key_set(tls_key_set); + for (size_t i = 0; i < DEVICES.size(); i++) { + at::autocast::set_autocast_enabled(DEVICES[i], autocast_enabled[i]); + at::autocast::set_autocast_dtype(DEVICES[i], autocast_dtype[i]); + } + at::autocast::set_autocast_cache_enabled(autocast_cache_enabled); + + for (const auto j : c10::irange(config.num_warmup_iters)) { + (void)j; + runOnce(std::move(thread_inputs[thread_id][input_iters[thread_id]])); + ++input_iters[thread_id]; + } + { + std::unique_lock lock(m); + ++initialized; + worker_main_cv.notify_one(); + // NOLINTNEXTLINE(bugprone-infinite-loop) + while (!start) { + main_worker_cv.wait(lock); + } + } + LOG(INFO) << "Starting forward thread " << thread_id; + while (num_attempted_iters.fetch_add(1) < config.num_iters) { + runOnce(std::move(thread_inputs[thread_id][input_iters[thread_id]])); + ++input_iters[thread_id]; + } + + { + std::unique_lock lock(m); + ++finished; + worker_main_cv.notify_one(); + LOG(INFO) << "Shutting down forward thread " << thread_id + << ". Total number of finished threads: " << finished; + } + }); + } + + using Clock = std::chrono::high_resolution_clock; + using RecordProfile = torch::autograd::profiler::RecordProfile; + using TimePoint = std::chrono::time_point; + TimePoint start_time; + + std::unique_ptr profiler_guard; + { + std::unique_lock lock(m); + while (initialized != config.num_calling_threads) { + worker_main_cv.wait(lock); + } + if (!config.profiler_output_path.empty()) { + LOG(INFO) << "Using Autograd profiler. Trace will be saved to " + << config.profiler_output_path; + profiler_guard = + std::make_unique(config.profiler_output_path); + } + LOG(INFO) << "Starting threads"; + start = true; + start_time = Clock::now(); + } + + main_worker_cv.notify_all(); + { + std::unique_lock lock(m); + worker_main_cv.wait( + lock, [&]() { return finished == config.num_calling_threads; }); + } + auto end_time = std::chrono::high_resolution_clock::now(); + profiler_guard.reset(); + LOG(INFO) << "Finished benchmark"; + + BenchmarkExecutionStats stats; + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + float total_time_ms = std::chrono::duration_cast( + end_time - start_time) + .count() / + 1000.0 / 1000.0; + // We use config.num_iters instead of num_attempted_iters as it is + // repsesatative of the real work done. Last attempted iteration on each + // calling threads doesn't represent the real work (i.e. running the model) + stats.latency_avg_ms = + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + total_time_ms * config.num_calling_threads / config.num_iters; + stats.num_iters = config.num_iters; + + for (auto& t : callers) { + t.join(); + } + return stats; +} + +} // namespace torch::throughput_benchmark::detail + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/throughput_benchmark.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/throughput_benchmark.h new file mode 100644 index 0000000000000000000000000000000000000000..4206d38fa32a08ff661e4686ac6a41a822993770 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/throughput_benchmark.h @@ -0,0 +1,204 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace py = pybind11; + +namespace torch::throughput_benchmark { + +/** + * The struct is used to provide results of a benchmark to the caller + * In the future all additional statistics should be added here. + */ +struct BenchmarkExecutionStats { + float latency_avg_ms{-1}; + int64_t num_iters{-1}; +}; + +std::ostream& operator<<( + std::ostream& os, + const BenchmarkExecutionStats& value); + +/** + * Use this struct in order to configure a throughput benchmark run. + * This struct should include parameters related to threading, batching, number + * of iterations, warm-up, etc. More configs can be added as needed. + * General rule here is that only things that c++ must(!) to be aware of should + * be here. If we can keep other parts in python, we should keep them there. + * This is typical for things that are not perf critical and don't affect + * execution statistics benchmark returns. + */ +struct BenchmarkConfig { + public: + // Calling threads are those threads that are calling into a module in + // parallel. + int num_calling_threads{1}; + // Worker threads are not supported yet. This is just an example that we plan + // to support some sort of multi-threaded forward calls. We may change this + // setting in the future to support different intra and inter op parallelism + // which is not available in PyTorch yet + int num_worker_threads{1}; + // Warmup iters are used to make sure we run a module a few times before + // actually measuring things. This way we avoid cold caches and any other + // similar problems + int num_warmup_iters{1}; + // Number of iterations the benchmark should run with. This number is separate + // from the warmup iterations + int64_t num_iters{100}; + // If set autograd profiler will be enabled. I.e. this variable would be + // created before the main benchmark loop (but after the warmup): + // RecordProfile guard(profiler_output_path); + std::string profiler_output_path; +}; + +namespace detail { + +/** + * A helper class to abstract out different models we test throughput of + */ +template +class BenchmarkHelper { + public: + BenchmarkHelper(); + explicit BenchmarkHelper(Model model) + : model_(std::move(model)), initialized_(true) {} + + // This method to be used in benchmark() method + // Note that there is no result. This way we don't have to call this under GIL + // even when running in the nn.Module mode. Otherwise destructor of the result + // would race with Python + void runOnce(Input&&) const; + // This method is to be used when calling from Python directly + Output runOnce(const py::args&, const py::kwargs&) const; + // Aggregate input in the format Model expects in order to avoid further + // conversions at the benchmark time + void addInput(py::args&&, py::kwargs&&); + void addInput(Input&&); + BenchmarkExecutionStats benchmark(const BenchmarkConfig& config) const; + + bool initialized() const { + return initialized_; + } + + // Destructor doesn't require the GIL because it is going to be executed on + // the PyThon thread + std::vector inputs_; + Model model_; + bool initialized_{false}; +}; + +struct C10_HIDDEN ModuleInput { + ModuleInput(ModuleInput&& other) = default; + + ModuleInput(const ModuleInput&) = delete; + ModuleInput& operator=(ModuleInput& other) = delete; + ModuleInput& operator=(ModuleInput&& other) = delete; + ~ModuleInput() = default; + + ModuleInput(py::args&& args, py::kwargs&& kwargs) + : args(std::move(args)), kwargs(std::move(kwargs)) {} + + py::args args; + py::kwargs kwargs; +}; +typedef py::object ModuleOutput; +typedef std::vector ScriptModuleInput; +typedef at::IValue ScriptModuleOutput; + +template +Input cloneInput(const Input& input); + +typedef BenchmarkHelper + ScriptModuleBenchmark; +template <> +inline BenchmarkHelper:: + BenchmarkHelper() + : model_("Module", std::make_shared()), + initialized_(false) {} +typedef BenchmarkHelper ModuleBenchmark; +template <> +inline BenchmarkHelper::BenchmarkHelper() + : initialized_(false) {} + +template <> +void ScriptModuleBenchmark::runOnce(ScriptModuleInput&& input) const; + +template <> +ScriptModuleOutput ScriptModuleBenchmark::runOnce( + const py::args& args, + const py::kwargs& kwargs) const; + +template <> +void ModuleBenchmark::runOnce(ModuleInput&& input) const; + +template <> +ModuleOutput ModuleBenchmark::runOnce( + const py::args& args, + const py::kwargs& kwargs) const; + +template <> +void ScriptModuleBenchmark::addInput(py::args&& args, py::kwargs&& kwargs); +template <> +void ScriptModuleBenchmark::addInput(ScriptModuleInput&& input); + +template <> +void ModuleBenchmark::addInput(py::args&& args, py::kwargs&& kwargs); + +} // namespace detail + +/** + * This class is a small c++ component responsible for executing a PyTorch + * module under an inference server like load. It can emulate multiple calling + * threads to a single module provided. In the future we plan to enhance this + * component to support inter and intra-op parallelism as well as multiple + * models running in a single process. + * + * For current available configurations refer to the BenchmarkConfig + * documentation + * + * The class supports working with either nn.Module or ScriptModule. + * Under the hood it just dispatches to corresponding specialization of + * class BenchmarkHelper + */ +class C10_HIDDEN ThroughputBenchmark { + public: + explicit ThroughputBenchmark(const jit::Module& module); + explicit ThroughputBenchmark(py::object module); + + // Add one more input example. This input example should be in the exact + // format the module under test expects. It is responsibility of the module to + // perform any such format checks, the benchmark doesn't perform any + // validation of its own + void addInput(py::args args, py::kwargs kwargs); + + // Equivalent to just running the model directly on the given input + py::object runOnce(const py::args& args, const py::kwargs& kwargs); + + // The main method of the class allows to perform a multi-threaded benchmark + // It returns BenchmarkExecutionStats object with a lot of useful statistics + // about runtime execution. We can enhance this class in the future to provide + // more information to the user + BenchmarkExecutionStats benchmark(const BenchmarkConfig& config) const; + + private: + detail::ScriptModuleBenchmark script_module_; + detail::ModuleBenchmark module_; +}; +} // namespace torch::throughput_benchmark + +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/torch_dispatch_mode.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/torch_dispatch_mode.h new file mode 100644 index 0000000000000000000000000000000000000000..1fd554d248bd3b430bf4e54dc8dd74f14e78c64f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/torch_dispatch_mode.h @@ -0,0 +1,73 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +namespace torch::torch_dispatch_mode { + +struct StashTorchDispatchModeGuard { + public: + StashTorchDispatchModeGuard() { + if (c10::impl::TorchDispatchModeTLS::any_modes_set( + /*skip_infra_modes=*/true)) { + saved_mode_ = c10::impl::TorchDispatchModeTLS::pop_stack(); + } else { + auto mode_and_key = + c10::impl::TorchDispatchModeTLS::pop_highest_infra_mode(); + saved_mode_ = std::move(std::get<0>(mode_and_key)); + saved_mode_key_ = std::get<1>(mode_and_key); + } + } + + ~StashTorchDispatchModeGuard() { + if (saved_mode_key_.has_value()) { + c10::impl::TorchDispatchModeTLS::set_mode( + saved_mode_, saved_mode_key_.value()); + } else { + c10::impl::TorchDispatchModeTLS::push_non_infra_mode_onto_stack( + std::move(saved_mode_)); + } + } + StashTorchDispatchModeGuard(const StashTorchDispatchModeGuard&) = delete; + StashTorchDispatchModeGuard(StashTorchDispatchModeGuard&&) = delete; + StashTorchDispatchModeGuard& operator=(const StashTorchDispatchModeGuard&) = + delete; + StashTorchDispatchModeGuard& operator=(StashTorchDispatchModeGuard&&) = + delete; + + const std::shared_ptr& get_cur_mode() { + return saved_mode_; + } + + private: + std::shared_ptr saved_mode_; + std::optional saved_mode_key_; +}; + +struct StashTorchDispatchStackGuard { + public: + StashTorchDispatchStackGuard() { + auto old = c10::impl::TorchDispatchModeTLS::get_state(); + c10::impl::TorchDispatchModeTLS::set_state(std::move(saved_state_)); + saved_state_ = std::move(old); + } + StashTorchDispatchStackGuard(const StashTorchDispatchStackGuard&) = delete; + StashTorchDispatchStackGuard(StashTorchDispatchStackGuard&&) = delete; + StashTorchDispatchStackGuard& operator=(const StashTorchDispatchStackGuard&) = + delete; + StashTorchDispatchStackGuard& operator=(StashTorchDispatchStackGuard&&) = + delete; + + ~StashTorchDispatchStackGuard() { + c10::impl::TorchDispatchModeTLS::set_state(std::move(saved_state_)); + } + + private: + c10::impl::TorchDispatchModeTLS saved_state_; +}; + +} // namespace torch::torch_dispatch_mode + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/variadic.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/variadic.h new file mode 100644 index 0000000000000000000000000000000000000000..e080abdbeb64ab85591aad79431f683743f0aed9 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/variadic.h @@ -0,0 +1,116 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +#include +#include + +namespace torch { + +using at::IterArgs; + +struct CountTensors : IterArgs { + size_t out = 0; + void operator()(const at::Tensor& x) { + out += 1; + } + void operator()(const std::optional& x) { + out += x.has_value(); + } + void operator()(at::ArrayRef xs) { + out += xs.size(); + } +}; + +template +size_t count_tensors(Args&&... args) { + return CountTensors().apply(std::forward(args)...).out; +} + +struct CountVariables : IterArgs { + size_t out = 0; + void operator()(const autograd::Variable& x) { + out += 1; + } + void operator()(at::ArrayRef xs) { + out += xs.size(); + } +}; + +template +inline size_t count_variables(Args&&... args) { + return CountVariables().apply(std::forward(args)...).out; +} + +//===----------------------------------------------------------------------===// +// std::index_sequence shim for C++11 +//===----------------------------------------------------------------------===// + +// A container of type-template parameter indices. +template +struct Indices {}; + +// Decrements the index N, adds N-1 to the list of indices and forwards +// whatever we already have. +template +struct MakeIndices : MakeIndices {}; + +// Partial specialization that forms our base case. When N is zero, we stop +// and define a typedef that will be visible to earlier classes due to +// inheritance. The typedef we define is an index list containing the numbers +// 0 through N-1. +template +struct MakeIndices<0, Is...> { + using indices = Indices; +}; + +//===----------------------------------------------------------------------===// +// Utilities +//===----------------------------------------------------------------------===// + +template +void apply(Function function, Ts&&... ts) { + // https://stackoverflow.com/questions/13978916/inserting-a-variadic-argument-list-into-a-vector + // Creates a dummy array, so that each function call is evaluated in order. + // `(function(), 0)` is because `function` should (!) return `void`, so + // according to the comma operator, it is evaluated and its result (`void`) + // is discarded. Then the zero is evaluated and used as an element in the + // array. The first zero ensures the array is not empty. + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays) + int _[]{0, (function(std::forward(ts)), 0)...}; + (void)_; +} + +template < + typename ReturnType, + typename... Ts, + typename Function, + typename Accessor> +ReturnType unpack(Function function, Accessor accessor) { + return ReturnType(unpack( + std::move(function), + std::move(accessor), + typename MakeIndices::indices())); +} + +template < + typename ReturnType, + typename... Ts, + typename Function, + typename Accessor, + size_t... Is> +ReturnType unpack( + Function function, + Accessor accessor, + Indices /*unused*/) { + return ReturnType(function(accessor.template operator()(Is)...)); +} + +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/verbose.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/verbose.h new file mode 100644 index 0000000000000000000000000000000000000000..54a879f7d456e18a73eade463c9b5b5188f19f33 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/utils/verbose.h @@ -0,0 +1,13 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once +#include + +namespace torch { + +void initVerboseBindings(PyObject* module); + +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/xpu/Event.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/xpu/Event.h new file mode 100644 index 0000000000000000000000000000000000000000..3dc8e69a8758a86e38775d94db140eab22198d8d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/xpu/Event.h @@ -0,0 +1,21 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +struct THXPEvent : THPEvent { + at::xpu::XPUEvent xpu_event; +}; +extern PyObject* THXPEventClass; + +void THXPEvent_init(PyObject* module); + +inline bool THXPEvent_Check(PyObject* obj) { + return THXPEventClass && PyObject_IsInstance(obj, THXPEventClass); +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/xpu/Module.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/xpu/Module.h new file mode 100644 index 0000000000000000000000000000000000000000..1f2eb36ed24981065ffdf7614eb9512f94bb2094 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/xpu/Module.h @@ -0,0 +1,16 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include + +PyMethodDef* THXPModule_methods(); + +namespace torch::xpu { + +void initModule(PyObject* module); + +} // namespace torch::xpu + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/xpu/Stream.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/xpu/Stream.h new file mode 100644 index 0000000000000000000000000000000000000000..de7e8366741469a70ceebb33215e0e13eb7119e3 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/xpu/Stream.h @@ -0,0 +1,22 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include + +// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) +struct THXPStream : THPStream { + at::xpu::XPUStream xpu_stream; +}; +extern PyObject* THXPStreamClass; + +void THXPStream_init(PyObject* module); + +inline bool THXPStream_Check(PyObject* obj) { + return THXPStreamClass && PyObject_IsInstance(obj, THXPStreamClass); +} + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/xpu/XPUPluggableAllocator.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/xpu/XPUPluggableAllocator.h new file mode 100644 index 0000000000000000000000000000000000000000..8a34baba3b47a204e44eb037e0125047487d3aba --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/xpu/XPUPluggableAllocator.h @@ -0,0 +1,85 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include + +namespace torch::xpu::XPUPluggableAllocator { + +struct _AllocationMetadata { + _AllocationMetadata() {} + _AllocationMetadata( + size_t size, + c10::DeviceIndex device_idx, + sycl::queue* queue) + : size(size), device_idx(device_idx), queue(queue) {} + size_t size{0}; + c10::DeviceIndex device_idx{-1}; + sycl::queue* queue{}; +}; + +struct TORCH_PYTHON_API XPUPluggableAllocator + : public c10::xpu::XPUCachingAllocator::XPUAllocator { + XPUPluggableAllocator( + std::function alloc_fn, + std::function free_fn) + : alloc_fn_(std::move(alloc_fn)), free_fn_(std::move(free_fn)) {} + + C10_DISABLE_COPY_AND_ASSIGN(XPUPluggableAllocator); + + ~XPUPluggableAllocator() override = default; + + void* malloc(size_t size, c10::DeviceIndex device, sycl::queue* stream); + + c10::DataPtr allocate(size_t size) override; + c10::DeleterFnPtr raw_deleter() const override; + + void* raw_alloc(size_t nbytes) override; + void raw_delete(void* ptr) override; + void init(c10::DeviceIndex device_count) override; + bool initialized() override; + void copy_data(void* dest, const void* src, std::size_t count) const final; + + void recordStream(const c10::DataPtr&, c10::Stream stream) override; + void emptyCache(c10::MempoolId_t mempool_id = {0, 0}) override; + c10::CachingDeviceAllocator::DeviceStats getDeviceStats( + c10::DeviceIndex device) override; + void resetAccumulatedStats(c10::DeviceIndex device) override; + void resetPeakStats(c10::DeviceIndex device) override; + + void set_init_fn(std::function init_fn) { + init_fn_ = std::move(init_fn); + } + void set_record_stream_fn( + std::function record_stream_fn) { + record_stream_fn_ = std::move(record_stream_fn); + } + + protected: + std::function alloc_fn_; + std::function free_fn_; + std::function init_fn_; + std::function record_stream_fn_; + std::mutex allocator_mutex_; + // We do the bookkeeping here in order to simplify custom allocators + std::unordered_map allocation_metadata_; + bool initialized_ = false; +}; + +TORCH_XPU_API std::shared_ptr +getCurrentAllocator(); + +TORCH_XPU_API std::shared_ptr +createCustomAllocator( + std::function alloc_fn, + std::function free_fn); + +TORCH_XPU_API void changeCurrentAllocator( + const std::shared_ptr& + allocator); + +} // namespace torch::xpu::XPUPluggableAllocator + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/xpu/memory_snapshot.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/xpu/memory_snapshot.h new file mode 100644 index 0000000000000000000000000000000000000000..7966c07aa89b6dcc7dafd48032c52084ba6daa8f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/xpu/memory_snapshot.h @@ -0,0 +1,24 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +namespace torch::xpu { + +TORCH_PYTHON_API void _record_memory_history( + std::optional enabled = "all", + std::optional context = "all", + const std::string& stacks = "all", + size_t max_entries = SIZE_MAX, + bool clear_history = false, + const std::vector& skip_actions = {}); + +} // namespace torch::xpu + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/custom_class.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/custom_class.h new file mode 100644 index 0000000000000000000000000000000000000000..e7177ec77fac0e178e21021e5806e782f223c17c --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/custom_class.h @@ -0,0 +1,523 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace torch { + +/// This function is used in conjunction with `class_::def()` to register +/// a constructor for a given C++ class type. For example, +/// `torch::init()` would register a two-argument constructor +/// taking an `int` and a `std::string` as argument. +template +detail::types init() { + return detail::types{}; +} + +template +struct InitLambda { + Func f; +}; + +template +decltype(auto) init(Func&& f) { + using InitTraits = c10::guts::infer_function_traits_t>; + using ParameterTypeList = typename InitTraits::parameter_types; + + InitLambda init{std::forward(f)}; + return init; +} + +/// Entry point for custom C++ class registration. To register a C++ class +/// in PyTorch, instantiate `torch::class_` with the desired class as the +/// template parameter. Typically, this instantiation should be done in +/// the initialization of a global variable, so that the class will be +/// made available on dynamic library loading without any additional API +/// calls needed. For example, to register a class named Foo, you might +/// create a global variable like so: +/// +/// static auto register_foo = torch::class_("myclasses", "Foo") +/// .def("myMethod", &Foo::myMethod) +/// .def("lambdaMethod", [](const c10::intrusive_ptr& self) { +/// // Do something with `self` +/// }); +/// +/// In addition to registering the class, this registration also chains +/// `def()` calls to register methods. `myMethod()` is registered with +/// a pointer to the Foo class's `myMethod()` method. `lambdaMethod()` +/// is registered with a C++ lambda expression. +template +class class_ : public ::torch::detail::class_base { + static_assert( + std::is_base_of_v, + "torch::class_ requires T to inherit from CustomClassHolder"); + + public: + /// This constructor actually registers the class type. + /// String argument `namespaceName` is an identifier for the + /// namespace you would like this class to appear in. + /// String argument `className` is the name you would like to + /// see this class exposed as in Python and TorchScript. For example, if + /// you pass `foo` as the namespace name and `Bar` as the className, the + /// class will appear as `torch.classes.foo.Bar` in Python and TorchScript + explicit class_( + const std::string& namespaceName, + const std::string& className, + std::string doc_string = "") + : class_base( + namespaceName, + className, + std::move(doc_string), + typeid(c10::intrusive_ptr), + typeid(c10::tagged_capsule)) {} + + /// def() can be used in conjunction with `torch::init()` to register + /// a constructor for a given C++ class type. For example, passing + /// `torch::init()` would register a two-argument + /// constructor taking an `int` and a `std::string` as argument. + template + class_& def( + torch::detail::types /*unused*/, + std::string doc_string = "", + std::initializer_list default_args = + {}) { // Used in combination with + // torch::init<...>() + auto func = [](c10::tagged_capsule self, Types... args) { + auto classObj = c10::make_intrusive(args...); + auto object = self.ivalue.toObject(); + object->setSlot(0, c10::IValue::make_capsule(std::move(classObj))); + }; + + defineMethod( + "__init__", + std::move(func), + std::move(doc_string), + default_args); + return *this; + } + + // Used in combination with torch::init([]lambda(){......}) + template + class_& def( + InitLambda> init, + std::string doc_string = "", + std::initializer_list default_args = {}) { + auto init_lambda_wrapper = [func = std::move(init.f)]( + c10::tagged_capsule self, + ParameterTypes... arg) { + c10::intrusive_ptr classObj = + std::invoke(func, std::forward(arg)...); + auto object = self.ivalue.toObject(); + object->setSlot(0, c10::IValue::make_capsule(classObj)); + }; + + defineMethod( + "__init__", + std::move(init_lambda_wrapper), + std::move(doc_string), + default_args); + + return *this; + } + + /// This is the normal method registration API. `name` is the name that + /// the method will be made accessible by in Python and TorchScript. + /// `f` is a callable object that defines the method. Typically `f` + /// will either be a pointer to a method on `CurClass`, or a lambda + /// expression that takes a `c10::intrusive_ptr` as the first + /// argument (emulating a `this` argument in a C++ method.) + /// + /// Examples: + /// + /// // Exposes method `foo` on C++ class `Foo` as `call_foo()` in + /// // Python and TorchScript + /// .def("call_foo", &Foo::foo) + /// + /// // Exposes the given lambda expression as method `call_lambda()` + /// // in Python and TorchScript. + /// .def("call_lambda", [](const c10::intrusive_ptr& self) { + /// // do something + /// }) + template + class_& def( + std::string name, + Func f, + std::string doc_string = "", + std::initializer_list default_args = {}) { + auto wrapped_f = detail::wrap_func(std::move(f)); + defineMethod( + std::move(name), + std::move(wrapped_f), + std::move(doc_string), + default_args); + return *this; + } + + /// Method registration API for static methods. + template + class_& def_static(std::string name, Func func, std::string doc_string = "") { + auto qualMethodName = qualClassName + "." + name; + auto schema = + c10::inferFunctionSchemaSingleReturn(std::move(name), ""); + + auto wrapped_func = + [func = std::move(func)](jit::Stack& stack) mutable -> void { + using RetType = + typename c10::guts::infer_function_traits_t::return_type; + detail::BoxedProxy()(stack, func); + }; + auto method = std::make_unique( + std::move(qualMethodName), + std::move(schema), + std::move(wrapped_func), + std::move(doc_string)); + + classTypePtr->addStaticMethod(method.get()); + registerCustomClassMethod(std::move(method)); + return *this; + } + + /// Property registration API for properties with both getter and setter + /// functions. + template + class_& def_property( + const std::string& name, + GetterFunc getter_func, + SetterFunc setter_func, + std::string doc_string = "") { + torch::jit::Function* getter{}; + torch::jit::Function* setter{}; + + auto wrapped_getter = + detail::wrap_func(std::move(getter_func)); + getter = defineMethod(name + "_getter", wrapped_getter, doc_string); + + auto wrapped_setter = + detail::wrap_func(std::move(setter_func)); + setter = defineMethod(name + "_setter", wrapped_setter, doc_string); + + classTypePtr->addProperty(name, getter, setter); + return *this; + } + + /// Property registration API for properties with only getter function. + template + class_& def_property( + const std::string& name, + GetterFunc getter_func, + std::string doc_string = "") { + torch::jit::Function* getter{}; + + auto wrapped_getter = + detail::wrap_func(std::move(getter_func)); + getter = defineMethod(name + "_getter", wrapped_getter, doc_string); + + classTypePtr->addProperty(name, getter, nullptr); + return *this; + } + + /// Property registration API for properties with read-write access. + template + class_& def_readwrite(const std::string& name, T CurClass::*field) { + auto getter_func = [field = + field](const c10::intrusive_ptr& self) { + return self.get()->*field; + }; + + auto setter_func = [field = field]( + const c10::intrusive_ptr& self, T value) { + self.get()->*field = value; + }; + + return def_property(name, getter_func, setter_func); + } + + /// Property registration API for properties with read-only access. + template + class_& def_readonly(const std::string& name, T CurClass::*field) { + auto getter_func = + [field = std::move(field)](const c10::intrusive_ptr& self) { + return self.get()->*field; + }; + + return def_property(name, getter_func); + } + + /// This is an unsafe method registration API added for adding custom JIT + /// backend support via custom C++ classes. It is not for general purpose use. + class_& _def_unboxed( + const std::string& name, + std::function func, + c10::FunctionSchema schema, + std::string doc_string = "") { + auto method = std::make_unique( + qualClassName + "." + name, + std::move(schema), + std::move(func), + std::move(doc_string)); + classTypePtr->addMethod(method.get()); + registerCustomClassMethod(std::move(method)); + return *this; + } + + /// def_pickle() is used to define exactly what state gets serialized + /// or deserialized for a given instance of a custom C++ class in + /// Python or TorchScript. This protocol is equivalent to the Pickle + /// concept of `__getstate__` and `__setstate__` from Python + /// (https://docs.python.org/2/library/pickle.html#object.__getstate__) + /// + /// Currently, both the `get_state` and `set_state` callables must be + /// C++ lambda expressions. They should have the following signatures, + /// where `CurClass` is the class you're registering and `T1` is some object + /// that encapsulates the state of the object. + /// + /// __getstate__(intrusive_ptr) -> T1 + /// __setstate__(T2) -> intrusive_ptr + /// + /// `T1` must be an object that is convertible to IValue by the same rules + /// for custom op/method registration. + /// + /// For the common case, T1 == T2. T1 can also be a subtype of T2. An + /// example where it makes sense for T1 and T2 to differ is if __setstate__ + /// handles legacy formats in a backwards compatible way. + /// + /// Example: + /// + /// .def_pickle( + /// // __getstate__ + /// [](const c10::intrusive_ptr>& self) { + /// return self->stack_; + /// }, + /// [](std::vector state) { // __setstate__ + /// return c10::make_intrusive>( + /// std::vector{"i", "was", "deserialized"}); + /// }) + template + class_& def_pickle(GetStateFn&& get_state, SetStateFn&& set_state) { + static_assert( + c10::guts::is_stateless_lambda>::value && + c10::guts::is_stateless_lambda>::value, + "def_pickle() currently only supports lambdas as " + "__getstate__ and __setstate__ arguments."); + def("__getstate__", std::forward(get_state)); + + // __setstate__ needs to be registered with some custom handling: + // We need to wrap the invocation of the user-provided function + // such that we take the return value (i.e. c10::intrusive_ptr) + // and assign it to the `capsule` attribute. + using SetStateTraits = + c10::guts::infer_function_traits_t>; + using SetStateArg = typename c10::guts::typelist::head_t< + typename SetStateTraits::parameter_types>; + auto setstate_wrapper = [set_state = std::forward(set_state)]( + c10::tagged_capsule self, + SetStateArg arg) { + c10::intrusive_ptr classObj = + std::invoke(set_state, std::move(arg)); + auto object = self.ivalue.toObject(); + object->setSlot(0, c10::IValue::make_capsule(classObj)); + }; + defineMethod( + "__setstate__", + detail::wrap_func( + std::move(setstate_wrapper))); + + // type validation + auto getstate_schema = classTypePtr->getMethod("__getstate__").getSchema(); +#ifndef STRIP_ERROR_MESSAGES + auto format_getstate_schema = [&getstate_schema]() { + std::stringstream ss; + ss << getstate_schema; + return ss.str(); + }; +#endif + TORCH_CHECK( + getstate_schema.arguments().size() == 1, + "__getstate__ should take exactly one argument: self. Got: ", + format_getstate_schema()); + auto first_arg_type = getstate_schema.arguments().at(0).type(); + TORCH_CHECK( + *first_arg_type == *classTypePtr, + "self argument of __getstate__ must be the custom class type. Got ", + first_arg_type->repr_str()); + TORCH_CHECK( + getstate_schema.returns().size() == 1, + "__getstate__ should return exactly one value for serialization. Got: ", + format_getstate_schema()); + + auto ser_type = getstate_schema.returns().at(0).type(); + auto setstate_schema = classTypePtr->getMethod("__setstate__").getSchema(); + auto arg_type = setstate_schema.arguments().at(1).type(); + TORCH_CHECK( + ser_type->isSubtypeOf(*arg_type), + "__getstate__'s return type should be a subtype of " + "input argument of __setstate__. Got ", + ser_type->repr_str(), + " but expected ", + arg_type->repr_str()); + + return *this; + } + + private: + template + torch::jit::Function* defineMethod( + std::string name, + Func func, + std::string doc_string = "", + std::initializer_list default_args = {}) { + auto qualMethodName = qualClassName + "." + name; + auto schema = + c10::inferFunctionSchemaSingleReturn(std::move(name), ""); + + // If default values are provided for function arguments, there must be + // none (no default values) or default values for all function + // arguments, except for self. This is because argument names are not + // extracted by inferFunctionSchemaSingleReturn, and so there must be a + // torch::arg instance in default_args even for arguments that do not + // have an actual default value provided. + TORCH_CHECK( + default_args.size() == 0 || + default_args.size() == schema.arguments().size() - 1, + "Default values must be specified for none or all arguments"); + + // If there are default args, copy the argument names and default values to + // the function schema. + if (default_args.size() > 0) { + schema = withNewArguments(schema, default_args); + } + + auto wrapped_func = + [func = std::move(func)](jit::Stack& stack) mutable -> void { + // TODO: we need to figure out how to profile calls to custom functions + // like this! Currently can't do it because the profiler stuff is in + // libtorch and not ATen + using RetType = + typename c10::guts::infer_function_traits_t::return_type; + detail::BoxedProxy()(stack, func); + }; + auto method = std::make_unique( + qualMethodName, + std::move(schema), + std::move(wrapped_func), + std::move(doc_string)); + + // Register the method here to keep the Method alive. + // ClassTypes do not hold ownership of their methods (normally it + // those are held by the CompilationUnit), so we need a proxy for + // that behavior here. + auto method_val = method.get(); + classTypePtr->addMethod(method_val); + registerCustomClassMethod(std::move(method)); + return method_val; + } +}; + +/// make_custom_class() is a convenient way to create an instance of a +/// registered custom class and wrap it in an IValue, for example when you want +/// to pass the object to TorchScript. Its syntax is equivalent to APIs like +/// `std::make_shared<>` or `c10::make_intrusive<>`. +/// +/// For example, if you have a custom C++ class that can be constructed from an +/// `int` and `std::string`, you might use this API like so: +/// +/// IValue custom_class_iv = torch::make_custom_class(3, +/// "foobarbaz"); +template +c10::IValue make_custom_class(CtorArgs&&... args) { + auto userClassInstance = + c10::make_intrusive(std::forward(args)...); + return c10::IValue(std::move(userClassInstance)); +} + +// Alternative api for creating a torchbind class over torch::class_ this api is +// preferred to prevent size regressions on Edge usecases. Must be used in +// conjunction with TORCH_SELECTIVE_CLASS macro aka +// selective_class("foo_namespace", TORCH_SELECTIVE_CLASS("foo")) +template +inline class_ selective_class_( + const std::string& namespace_name, + detail::SelectiveStr className) { + auto class_name = std::string(className.operator const char*()); + return torch::class_(namespace_name, class_name); +} + +template +inline detail::ClassNotSelected selective_class_( + const std::string& /*unused*/, + detail::SelectiveStr /*unused*/) { + return detail::ClassNotSelected(); +} + +// jit namespace for backward-compatibility +// We previously defined everything in torch::jit but moved it out to +// better reflect that these features are not limited only to TorchScript +namespace jit { + +using ::torch::class_; +using ::torch::getCustomClass; +using ::torch::init; +using ::torch::isCustomClass; + +} // namespace jit + +template +inline class_ Library::class_(const std::string& className) { + TORCH_CHECK( + kind_ == DEF || kind_ == FRAGMENT, + "class_(\"", + className, + "\"): Cannot define a class inside of a TORCH_LIBRARY_IMPL block. " + "All class_()s should be placed in the (unique) TORCH_LIBRARY block for their namespace. " + "(Error occurred at ", + file_, + ":", + line_, + ")"); + TORCH_INTERNAL_ASSERT(ns_.has_value(), file_, ":", line_); + return torch::class_(*ns_, className); +} + +const std::unordered_set getAllCustomClassesNames(); + +template +inline class_ Library::class_(detail::SelectiveStr className) { + auto class_name = std::string(className.operator const char*()); + TORCH_CHECK( + kind_ == DEF || kind_ == FRAGMENT, + "class_(\"", + class_name, + "\"): Cannot define a class inside of a TORCH_LIBRARY_IMPL block. " + "All class_()s should be placed in the (unique) TORCH_LIBRARY block for their namespace. " + "(Error occurred at ", + file_, + ":", + line_, + ")"); + TORCH_INTERNAL_ASSERT(ns_.has_value(), file_, ":", line_); + return torch::class_(*ns_, class_name); +} + +template +inline detail::ClassNotSelected Library::class_(detail::SelectiveStr /*unused*/) { + return detail::ClassNotSelected(); +} + +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/custom_class_detail.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/custom_class_detail.h new file mode 100644 index 0000000000000000000000000000000000000000..9d1356b98fc20038723f0c4ff4cad66a1310382a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/custom_class_detail.h @@ -0,0 +1,247 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace torch { + +namespace detail { +/** + * In the Facebook internal build (using BUCK), this macro is enabled by + * passing in -c pt.enable_record_kernel_dtype=1 when building the tracer + * binary. + */ +#if defined ENABLE_RECORD_KERNEL_FUNCTION_DTYPE +TORCH_API void record_custom_class(std::string name); + +/** + * Record an instance of a custom class being loaded + * grab portion of string after final '.' from qualified name + * as this seemingly aligns with how users name their custom classes + * example: __torch__.torch.classes.xnnpack.Conv2dOpContext + */ +#define RECORD_CUSTOM_CLASS(NAME) \ + auto name = std::string(NAME); \ + detail::record_custom_class(name.substr(name.find_last_of(".") + 1)); +#else +#define RECORD_CUSTOM_CLASS(NAME) +#endif +} // namespace detail + +/// This struct is used to represent default values for arguments +/// when registering methods for custom classes. +/// static auto register_foo = torch::class_("myclasses", "Foo") +/// .def("myMethod", &Foo::myMethod, {torch::arg("name") = name}); +struct arg { + // Static method for representing a default value of None. This is meant to + // be used like so: + // torch::arg("name") = torch::arg::none + // and is identical to: + // torch::arg("name") = IValue() + static c10::IValue none() { + return c10::IValue(); + } + + // Explicit constructor. + explicit arg(std::string name) + : name_(std::move(name)), value_(std::nullopt) {} + // Assignment operator. This enables the pybind-like syntax of + // torch::arg("name") = value. + arg& operator=(const c10::IValue& rhs) { + value_ = rhs; + return *this; + } + + // The name of the argument. This is copied to the schema; argument + // names cannot be extracted from the C++ declaration. + std::string name_; + // IValue's default constructor makes it None, which is not distinguishable + // from an actual, user-provided default value that is None. This boolean + // helps distinguish between the two cases. + std::optional value_; +}; + +namespace detail { + +// Argument type utilities +template +struct types { + using type = types; +}; + +template +struct WrapMethod; + +template +struct WrapMethod { + WrapMethod(R (CurrClass::*m)(Args...)) : m(std::move(m)) {} + + R operator()(c10::intrusive_ptr cur, Args... args) { + return std::invoke(m, *cur, args...); + } + + R (CurrClass::*m)(Args...); +}; + +template +struct WrapMethod { + WrapMethod(R (CurrClass::*m)(Args...) const) : m(std::move(m)) {} + + R operator()(c10::intrusive_ptr cur, Args... args) { + return std::invoke(m, *cur, args...); + } + + R (CurrClass::*m)(Args...) const; +}; + +// Adapter for different callable types +template < + typename CurClass, + typename Func, + std::enable_if_t< + std::is_member_function_pointer_v>, + bool> = false> +WrapMethod wrap_func(Func f) { + return WrapMethod(std::move(f)); +} + +template < + typename CurClass, + typename Func, + std::enable_if_t< + !std::is_member_function_pointer_v>, + bool> = false> +Func wrap_func(Func f) { + return f; +} + +template < + class Functor, + bool AllowDeprecatedTypes, + size_t... ivalue_arg_indices> +typename c10::guts::infer_function_traits_t::return_type +call_torchbind_method_from_stack( + Functor& functor, + jit::Stack& stack, + std::index_sequence /*unused*/) { + (void)stack; // when sizeof...(ivalue_arg_indices) == 0, this argument would + // be unused and we have to silence the compiler warning. + + constexpr size_t num_ivalue_args = sizeof...(ivalue_arg_indices); + + using IValueArgTypes = + typename c10::guts::infer_function_traits_t::parameter_types; + // TODO We shouldn't use c10::impl stuff directly here. We should use the + // KernelFunction API instead. + return functor(c10::impl::ivalue_to_arg< + typename c10::impl::decay_if_not_tensor< + c10::guts::typelist:: + element_t>::type, + AllowDeprecatedTypes>:: + call(torch::jit::peek( + stack, ivalue_arg_indices, num_ivalue_args))...); +} + +template +typename c10::guts::infer_function_traits_t::return_type +call_torchbind_method_from_stack(Functor& functor, jit::Stack& stack) { + constexpr size_t num_ivalue_args = + c10::guts::infer_function_traits_t::number_of_parameters; + return call_torchbind_method_from_stack( + functor, stack, std::make_index_sequence()); +} + +template +struct BoxedProxy; + +template +struct BoxedProxy { + void operator()(jit::Stack& stack, Func& func) { + auto retval = call_torchbind_method_from_stack(func, stack); + constexpr size_t num_ivalue_args = + c10::guts::infer_function_traits_t::number_of_parameters; + torch::jit::drop(stack, num_ivalue_args); + stack.emplace_back(c10::ivalue::from(std::move(retval))); + } +}; + +template +struct BoxedProxy { + void operator()(jit::Stack& stack, Func& func) { + call_torchbind_method_from_stack(func, stack); + constexpr size_t num_ivalue_args = + c10::guts::infer_function_traits_t::number_of_parameters; + torch::jit::drop(stack, num_ivalue_args); + stack.emplace_back(); + } +}; + +inline bool validIdent(size_t i, char n) { + return isalpha(n) || n == '_' || (i > 0 && isdigit(n)); +} + +inline void checkValidIdent(const std::string& str, const char* type) { + for (const auto i : c10::irange(str.size())) { + TORCH_CHECK( + validIdent(i, str[i]), + type, + " must be a valid Python/C++ identifier." + " Character '", + str[i], + "' at index ", + i, + " is illegal."); + } +} + +class TORCH_API class_base { + protected: + explicit class_base( + const std::string& namespaceName, + const std::string& className, + std::string doc_string, + const std::type_info& intrusivePtrClassTypeid, + const std::type_info& taggedCapsuleClass); + + static c10::FunctionSchema withNewArguments( + const c10::FunctionSchema& schema, + std::initializer_list default_args); + std::string qualClassName; + at::ClassTypePtr classTypePtr; +}; + +} // namespace detail + +TORCH_API void registerCustomClass(at::ClassTypePtr class_type); +TORCH_API void registerCustomClassMethod(std::unique_ptr method); + +// Given a qualified name (e.g. __torch__.torch.classes.Foo), return +// the ClassType pointer to the Type that describes that custom class, +// or nullptr if no class by that name was found. +TORCH_API at::ClassTypePtr getCustomClass(const std::string& name); + +// Given an IValue, return true if the object contained in that IValue +// is a custom C++ class, otherwise return false. +// NOLINTNEXTLINE(readability-redundant-declaration) +TORCH_API bool isCustomClass(const c10::IValue& v); + +// This API is for testing purposes ONLY. It should not be used in +// any load-bearing code. +TORCH_API std::vector customClassSchemasForBCCheck(); + +namespace jit { +using ::torch::registerCustomClass; +using ::torch::registerCustomClassMethod; +} // namespace jit + +} // namespace torch + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/extension.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/extension.h new file mode 100644 index 0000000000000000000000000000000000000000..ddce96571507358894d4a5232b0954c3461cc7ac --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/extension.h @@ -0,0 +1,14 @@ +#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) +#pragma once + +#ifndef TORCH_INDUCTOR_CPP_WRAPPER +// All pure C++ headers for the C++ frontend. +#include +#endif + +// Python bindings for the C++ frontend (includes Python.h). +#include + +#else +#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." +#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/DeviceType.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/DeviceType.h new file mode 100644 index 0000000000000000000000000000000000000000..9db3ef2568d341fb9a341a36c02ac91c4dcca30f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/DeviceType.h @@ -0,0 +1,128 @@ +#pragma once + +// This is directly synchronized with caffe2/proto/caffe2.proto, but +// doesn't require me to figure out how to get Protobuf headers into +// ATen/core (which would require a lot more build system hacking.) +// If you modify me, keep me synchronized with that file. + +#include +#include + +#include +#include +#include + +namespace c10 { + +// These contains all device types that also have a BackendComponent +// and therefore participate in per-backend functionality dispatch keys. +// This is most backends except PrivateUse2 and PrivateUse3 +#define C10_FORALL_BACKEND_DEVICE_TYPES(_, extra) \ + _(CPU, extra) \ + _(CUDA, extra) \ + _(HIP, extra) \ + _(XLA, extra) \ + _(MPS, extra) \ + _(IPU, extra) \ + _(XPU, extra) \ + _(HPU, extra) \ + _(VE, extra) \ + _(Lazy, extra) \ + _(Meta, extra) \ + _(MTIA, extra) \ + _(PrivateUse1, extra) + +enum class DeviceType : int8_t { + CPU = 0, + CUDA = 1, // CUDA. + MKLDNN = 2, // Reserved for explicit MKLDNN + OPENGL = 3, // OpenGL + OPENCL = 4, // OpenCL + IDEEP = 5, // IDEEP. + HIP = 6, // AMD HIP + FPGA = 7, // FPGA + MAIA = 8, // ONNX Runtime / Microsoft + XLA = 9, // XLA / TPU + Vulkan = 10, // Vulkan + Metal = 11, // Metal + XPU = 12, // XPU + MPS = 13, // MPS + Meta = 14, // Meta (tensors with no data) + HPU = 15, // HPU / HABANA + VE = 16, // SX-Aurora / NEC + Lazy = 17, // Lazy Tensors + IPU = 18, // Graphcore IPU + MTIA = 19, // Meta training and inference devices + PrivateUse1 = 20, // PrivateUse1 device + // NB: If you add more devices: + // - Change the implementations of DeviceTypeName and isValidDeviceType + // in c10/core/DeviceType.cpp + // - Change the number below + COMPILE_TIME_MAX_DEVICE_TYPES = 21, +}; + +constexpr DeviceType kCPU = DeviceType::CPU; +constexpr DeviceType kCUDA = DeviceType::CUDA; +constexpr DeviceType kHIP = DeviceType::HIP; +constexpr DeviceType kFPGA = DeviceType::FPGA; +constexpr DeviceType kMAIA = DeviceType::MAIA; +constexpr DeviceType kXLA = DeviceType::XLA; +constexpr DeviceType kMPS = DeviceType::MPS; +constexpr DeviceType kMeta = DeviceType::Meta; +constexpr DeviceType kVulkan = DeviceType::Vulkan; +constexpr DeviceType kMetal = DeviceType::Metal; +constexpr DeviceType kXPU = DeviceType::XPU; +constexpr DeviceType kHPU = DeviceType::HPU; +constexpr DeviceType kVE = DeviceType::VE; +constexpr DeviceType kLazy = DeviceType::Lazy; +constexpr DeviceType kIPU = DeviceType::IPU; +constexpr DeviceType kMTIA = DeviceType::MTIA; +constexpr DeviceType kPrivateUse1 = DeviceType::PrivateUse1; + +// define explicit int constant +constexpr int COMPILE_TIME_MAX_DEVICE_TYPES = + static_cast(DeviceType::COMPILE_TIME_MAX_DEVICE_TYPES); + +static_assert( + COMPILE_TIME_MAX_DEVICE_TYPES <= 21, + "Hey! You seem to be adding a lot of new DeviceTypes. The intent was " + "for this constant to reflect the actual number of DeviceTypes we support " + "in PyTorch; it's important that this number is not too large as we " + "use this to allocate stack arrays in some places in our code. If you " + "are indeed just adding the 20th device type, feel free to change " + "the check to 32; but if you are adding some sort of extensible device " + "types registration, please be aware that you are affecting code that " + "this number is small. Try auditing uses of this constant."); + +} // namespace c10 + +namespace std { +template <> +struct hash { + std::size_t operator()(c10::DeviceType k) const { + return std::hash()(static_cast(k)); + } +}; +} // namespace std + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly) +using c10::COMPILE_TIME_MAX_DEVICE_TYPES; +using c10::DeviceType; +using c10::kCPU; +using c10::kCUDA; +using c10::kFPGA; +using c10::kHIP; +using c10::kHPU; +using c10::kIPU; +using c10::kLazy; +using c10::kMAIA; +using c10::kMeta; +using c10::kMetal; +using c10::kMPS; +using c10::kMTIA; +using c10::kPrivateUse1; +using c10::kVE; +using c10::kVulkan; +using c10::kXLA; +using c10::kXPU; +HIDDEN_NAMESPACE_END(torch, headeronly) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/Dispatch.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/Dispatch.h new file mode 100644 index 0000000000000000000000000000000000000000..43293ef701ddac509c51abd9a4c1f923e61118f9 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/Dispatch.h @@ -0,0 +1,73 @@ +#pragma once + +#include +#include + +// THO_PRIVATE_CASE_TYPE_USING_HINT_TMPL is same as +// AT_PRIVATE_CASE_TYPE_USING_HINT but with a custom PRELUDE macro: +#define THO_PRIVATE_CASE_TYPE_USING_HINT_TMPL(PRELUDE, enum_type, HINT, ...) \ + case enum_type: { \ + PRELUDE(enum_type); \ + using HINT [[maybe_unused]] = \ + torch::headeronly::impl::ScalarTypeToCPPTypeT; \ + return __VA_ARGS__(); \ + } + +// THO_DISPATCH_CASE_TMPL is same as AT_DISPATCH_CASE but with a +// custom CASE_TYPE_USING_HINT macro: +#define THO_DISPATCH_CASE_TMPL(CASE_TYPE_USING_HINT, enum_type, ...) \ + CASE_TYPE_USING_HINT(enum_type, scalar_t, __VA_ARGS__) + +namespace detail { +inline torch::headeronly::ScalarType scalar_type( + torch::headeronly::ScalarType s) { + return s; +} +} // namespace detail + +// THO_DISPATCH_SWITCH_TMPL is same as AT_DISPATCH_SWITCH but with +// custom PRELUDE and CHECK_NOT_IMPLEMENTED macros: +#define THO_DISPATCH_SWITCH_TMPL( \ + PRELUDE, CHECK_NOT_IMPLEMENTED, TYPE, NAME, ...) \ + [&] { \ + const auto& the_type = TYPE; \ + constexpr const char* at_dispatch_name = NAME; \ + /* don't use TYPE again in case it is an expensive or side-effect op */ \ + torch::headeronly::ScalarType _st = ::detail::scalar_type(the_type); \ + PRELUDE(at_dispatch_name, _st); \ + C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED("-Wswitch-enum") \ + switch (_st) { \ + __VA_ARGS__ \ + default: \ + CHECK_NOT_IMPLEMENTED( \ + false, \ + '"', \ + at_dispatch_name, \ + "\" not implemented for '", \ + torch::headeronly::toString(_st), \ + "'"); \ + } \ + C10_DIAGNOSTIC_POP() \ + }() + +// THO_EMPTY is a helper macro that discards its arguments. +#define THO_EMPTY(...) + +// THO_PRIVATE_CASE_TYPE_USING_HINT is same as +// AT_PRIVATE_CASE_TYPE_USING_HINT with call to macro +// AT_PRIVATE_CHECK_SELECTIVE_BUILD removed. +#define THO_PRIVATE_CASE_TYPE_USING_HINT(enum_type, HINT, ...) \ + THO_PRIVATE_CASE_TYPE_USING_HINT_TMPL(THO_EMPTY, enum_type, HINT, __VA_ARGS__) + +// THO_DISPATCH_SWITCH is same as AT_DISPATCH_SWITCH with call to +// macro RECORD_KERNEL_FUNCTION_DTYPE removed and using +// STD_TORCH_CHECK instead of TORCH_CHECK_NOT_IMPLEMENTED. +#define THO_DISPATCH_SWITCH(TYPE, NAME, ...) \ + THO_DISPATCH_SWITCH_TMPL(THO_EMPTY, STD_TORCH_CHECK, TYPE, NAME, __VA_ARGS__) + +// THO_DISPATCH_CASE is same as AT_DISPATCH_CASE but using +// THO_PRIVATE_CASE_TYPE_USING_HINT instead of +// AT_PRIVATE_CASE_TYPE_USING_HINT. +#define THO_DISPATCH_CASE(enum_type, ...) \ + THO_DISPATCH_CASE_TMPL( \ + THO_PRIVATE_CASE_TYPE_USING_HINT, enum_type, __VA_ARGS__) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/Dispatch_v2.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/Dispatch_v2.h new file mode 100644 index 0000000000000000000000000000000000000000..aa1bc1d9e9f72b1f211c10a313f0b97d94eea0df --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/Dispatch_v2.h @@ -0,0 +1,157 @@ +#pragma once + +#include +#include + +// This file provides THO_DISPATCH_V2_TMPL macro that is a generalized +// version of the original AT_DISPATCH_V2 (see ATen/Dispatch_v2.h for +// documentation): THO_DISPATCH_V2_TMPL extends AT_DISPATCH_V2 with +// extra DISPATCH_SWITCH and DISPATCH_CASE arguments for specifying +// custom implementations of the original AT_DISPATCH_SWITCH and +// AT_DISPATCH_CASE macros. Use the provided macros +// THO_DISPATCH_SWITCH_TMPL and THO_DISPATCH_CASE_TMPL to define the +// custom implementations of the switch and case macros, respectively. + +// Public API macros + +// THO_DISPATCH_V2_TMPL is same as AT_DISPATCH_V2 but with custom +// DISPATCH_SWITCH and DISPATCH_CASE macro arguments: +#define THO_DISPATCH_V2_TMPL( \ + DISPATCH_SWITCH, DISPATCH_CASE, TYPE, NAME, BODY, ...) \ + DISPATCH_SWITCH( \ + TYPE, \ + NAME, \ + THO_AP_VAR_TMPL(DISPATCH_CASE, AT_WRAP(BODY), TYPE, __VA_ARGS__)) + +// THO_DISPATCH_V2 is same as AT_DISPATCH_V2 but using +// THO_DISPATCH_SWITCH and THO_DISPATCH_CASE instead of +// AT_DISPATCH_SWITCH and AT_DISPATCH_CASE, respectively. +#define THO_DISPATCH_V2(TYPE, NAME, BODY, ...) \ + THO_DISPATCH_V2_TMPL( \ + THO_DISPATCH_SWITCH, THO_DISPATCH_CASE, TYPE, NAME, BODY, __VA_ARGS__) + +// Type collection macros + +// This macro lets you pass an arbitrary expression that may contain internal +// commas to another macro without having the commas causing the expression +// to be interpreted as being multiple arguments +#define AT_WRAP(...) __VA_ARGS__ + +#define AT_FLOAT8_TYPES \ + torch::headeronly::ScalarType::Float8_e5m2, \ + torch::headeronly::ScalarType::Float8_e5m2fnuz, \ + torch::headeronly::ScalarType::Float8_e4m3fn, \ + torch::headeronly::ScalarType::Float8_e4m3fnuz, \ + torch::headeronly::ScalarType::Float8_e8m0fnu + +#define AT_INTEGRAL_TYPES \ + torch::headeronly::ScalarType::Byte, torch::headeronly::ScalarType::Char, \ + torch::headeronly::ScalarType::Int, torch::headeronly::ScalarType::Long, \ + torch::headeronly::ScalarType::Short +#define AT_FLOATING_TYPES \ + torch::headeronly::ScalarType::Double, torch::headeronly::ScalarType::Float +#define AT_BAREBONES_UNSIGNED_TYPES \ + torch::headeronly::ScalarType::UInt16, \ + torch::headeronly::ScalarType::UInt32, \ + torch::headeronly::ScalarType::UInt64 +#define AT_OPAQUE_TYPES \ + torch::headeronly::ScalarType::Byte, torch::headeronly::ScalarType::UInt16, \ + torch::headeronly::ScalarType::UInt32, \ + torch::headeronly::ScalarType::UInt64, \ + torch::headeronly::ScalarType::ComplexDouble +#define AT_INTEGRAL_TYPES_V2 \ + AT_EXPAND(AT_INTEGRAL_TYPES), AT_EXPAND(AT_BAREBONES_UNSIGNED_TYPES) +#define AT_COMPLEX_TYPES \ + torch::headeronly::ScalarType::ComplexDouble, \ + torch::headeronly::ScalarType::ComplexFloat +#define AT_QINT_TYPES \ + torch::headeronly::ScalarType::QInt8, torch::headeronly::ScalarType::QUInt8, \ + torch::headeronly::ScalarType::QInt32 +// NB: not *actually* all types +#define AT_ALL_TYPES AT_EXPAND(AT_INTEGRAL_TYPES), AT_EXPAND(AT_FLOATING_TYPES) +#define AT_ALL_TYPES_AND_COMPLEX \ + AT_EXPAND(AT_ALL_TYPES), AT_EXPAND(AT_COMPLEX_TYPES) + +// Helper macros + +// THO_AP_VAR_TMPL is same as AT_AP_VAR but with a custom +// DISPATCH_CASE macro argument: +#define THO_AP_VAR_TMPL(C, N, T, ...) \ + AT_EXPAND( \ + AT_CONCAT(THO_AP, AT_NUM_ARGS(__VA_ARGS__))(C, AT_WRAP(N), __VA_ARGS__)) +#define AT_CONCAT(a, b) AT_CONCAT_AUX(a, b) +#define AT_CONCAT_AUX(a, b) a##b +#define AT_EXPAND(X) X + +// Ensure we never have too many scalar types for the expansion here to +// support. To bump this, you must regenerate the macros below. +static_assert(static_cast(torch::headeronly::ScalarType::NumOptions) < 60); + +// Begin generated code +// clang-format off + +#define AT_NUM_ARGS(...) AT_EXPAND(AT_NUM_ARGS_AUX(__VA_ARGS__, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)) +#define AT_NUM_ARGS_AUX(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, N, ...) N +#define THO_AP1(C, N, _1) C(_1, N) +#define THO_AP2(C, N, _1, _2) C(_1, N) C(_2, N) +#define THO_AP3(C, N, _1, _2, _3) C(_1, N) C(_2, N) C(_3, N) +#define THO_AP4(C, N, _1, _2, _3, _4) C(_1, N) C(_2, N) C(_3, N) C(_4, N) +#define THO_AP5(C, N, _1, _2, _3, _4, _5) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) +#define THO_AP6(C, N, _1, _2, _3, _4, _5, _6) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) +#define THO_AP7(C, N, _1, _2, _3, _4, _5, _6, _7) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) +#define THO_AP8(C, N, _1, _2, _3, _4, _5, _6, _7, _8) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) +#define THO_AP9(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) +#define THO_AP10(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) +#define THO_AP11(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) +#define THO_AP12(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) +#define THO_AP13(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) +#define THO_AP14(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) +#define THO_AP15(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) +#define THO_AP16(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) +#define THO_AP17(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) +#define THO_AP18(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) +#define THO_AP19(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) +#define THO_AP20(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) +#define THO_AP21(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) +#define THO_AP22(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) +#define THO_AP23(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) +#define THO_AP24(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) +#define THO_AP25(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) +#define THO_AP26(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) +#define THO_AP27(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) +#define THO_AP28(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) +#define THO_AP29(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) +#define THO_AP30(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) +#define THO_AP31(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) +#define THO_AP32(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) +#define THO_AP33(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) +#define THO_AP34(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) +#define THO_AP35(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) +#define THO_AP36(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) +#define THO_AP37(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) +#define THO_AP38(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) +#define THO_AP39(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) +#define THO_AP40(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) +#define THO_AP41(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) +#define THO_AP42(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) +#define THO_AP43(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) +#define THO_AP44(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) +#define THO_AP45(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) +#define THO_AP46(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) C(_46, N) +#define THO_AP47(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) C(_46, N) C(_47, N) +#define THO_AP48(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) C(_46, N) C(_47, N) C(_48, N) +#define THO_AP49(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) C(_46, N) C(_47, N) C(_48, N) C(_49, N) +#define THO_AP50(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) C(_46, N) C(_47, N) C(_48, N) C(_49, N) C(_50, N) +#define THO_AP51(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) C(_46, N) C(_47, N) C(_48, N) C(_49, N) C(_50, N) C(_51, N) +#define THO_AP52(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) C(_46, N) C(_47, N) C(_48, N) C(_49, N) C(_50, N) C(_51, N) C(_52, N) +#define THO_AP53(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) C(_46, N) C(_47, N) C(_48, N) C(_49, N) C(_50, N) C(_51, N) C(_52, N) C(_53, N) +#define THO_AP54(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) C(_46, N) C(_47, N) C(_48, N) C(_49, N) C(_50, N) C(_51, N) C(_52, N) C(_53, N) C(_54, N) +#define THO_AP55(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) C(_46, N) C(_47, N) C(_48, N) C(_49, N) C(_50, N) C(_51, N) C(_52, N) C(_53, N) C(_54, N) C(_55, N) +#define THO_AP56(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) C(_46, N) C(_47, N) C(_48, N) C(_49, N) C(_50, N) C(_51, N) C(_52, N) C(_53, N) C(_54, N) C(_55, N) C(_56, N) +#define THO_AP57(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) C(_46, N) C(_47, N) C(_48, N) C(_49, N) C(_50, N) C(_51, N) C(_52, N) C(_53, N) C(_54, N) C(_55, N) C(_56, N) C(_57, N) +#define THO_AP58(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) C(_46, N) C(_47, N) C(_48, N) C(_49, N) C(_50, N) C(_51, N) C(_52, N) C(_53, N) C(_54, N) C(_55, N) C(_56, N) C(_57, N) C(_58, N) +#define THO_AP59(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) C(_46, N) C(_47, N) C(_48, N) C(_49, N) C(_50, N) C(_51, N) C(_52, N) C(_53, N) C(_54, N) C(_55, N) C(_56, N) C(_57, N) C(_58, N) C(_59, N) +#define THO_AP60(C, N, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60) C(_1, N) C(_2, N) C(_3, N) C(_4, N) C(_5, N) C(_6, N) C(_7, N) C(_8, N) C(_9, N) C(_10, N) C(_11, N) C(_12, N) C(_13, N) C(_14, N) C(_15, N) C(_16, N) C(_17, N) C(_18, N) C(_19, N) C(_20, N) C(_21, N) C(_22, N) C(_23, N) C(_24, N) C(_25, N) C(_26, N) C(_27, N) C(_28, N) C(_29, N) C(_30, N) C(_31, N) C(_32, N) C(_33, N) C(_34, N) C(_35, N) C(_36, N) C(_37, N) C(_38, N) C(_39, N) C(_40, N) C(_41, N) C(_42, N) C(_43, N) C(_44, N) C(_45, N) C(_46, N) C(_47, N) C(_48, N) C(_49, N) C(_50, N) C(_51, N) C(_52, N) C(_53, N) C(_54, N) C(_55, N) C(_56, N) C(_57, N) C(_58, N) C(_59, N) C(_60, N) + +// End generated code +// clang-format on diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/Layout.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/Layout.h new file mode 100644 index 0000000000000000000000000000000000000000..62e34ff67b457ae3b6fb5ff4d804d85b3da9cb7a --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/Layout.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +#include +#include + +namespace c10 { + +enum class Layout : int8_t { + Strided, + Sparse, + SparseCsr, + Mkldnn, + SparseCsc, + SparseBsr, + SparseBsc, + Jagged, + NumOptions +}; + +constexpr auto kStrided = Layout::Strided; +constexpr auto kSparse = Layout::Sparse; +constexpr auto kSparseCsr = Layout::SparseCsr; +constexpr auto kMkldnn = Layout::Mkldnn; +constexpr auto kSparseCsc = Layout::SparseCsc; +constexpr auto kSparseBsr = Layout::SparseBsr; +constexpr auto kSparseBsc = Layout::SparseBsc; +constexpr auto kJagged = Layout::Jagged; + +} // namespace c10 + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly) +using c10::kJagged; +using c10::kMkldnn; +using c10::kSparse; +using c10::kSparseBsc; +using c10::kSparseBsr; +using c10::kSparseCsc; +using c10::kSparseCsr; +using c10::kStrided; +using c10::Layout; +HIDDEN_NAMESPACE_END(torch, headeronly) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/MemoryFormat.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/MemoryFormat.h new file mode 100644 index 0000000000000000000000000000000000000000..ad02a901e0169ad6c2e2169a90c72c88fb609097 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/MemoryFormat.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include + +#include +#include + +// Memory format is not the property of a Tensor. It is the way to tell an +// operator how the result should be organized in memory and nothing more. That +// means memory format should never be used as return value for any tensor state +// interrogation functions (internally and externally). +// +// Possible options are: +// Preserve: +// If any of the input tensors is in channels_last format, operator output +// should be in channels_last format +// +// Contiguous: +// Regardless of input tensors format, the output should be contiguous +// Tensor. +// +// ChannelsLast: +// Regardless of input tensors format, the output should be in channels_last +// format. + +namespace c10 { + +enum class MemoryFormat : int8_t { + Contiguous, + Preserve, + ChannelsLast, + ChannelsLast3d, + NumOptions +}; + +inline MemoryFormat get_contiguous_memory_format() { + return MemoryFormat::Contiguous; +} + +} // namespace c10 + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly) +using c10::get_contiguous_memory_format; +using c10::MemoryFormat; +HIDDEN_NAMESPACE_END(torch, headeronly) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/ScalarType.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/ScalarType.h new file mode 100644 index 0000000000000000000000000000000000000000..ce43ce6866cd954adc778cec54c3405d2d1569a1 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/ScalarType.h @@ -0,0 +1,381 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED("-Wswitch-enum") + +namespace c10 { + +// dummy struct for uint1 to uint7, actual functionality +// of these dtypes will be implemented in python with Tensor subclass +template +struct dummy_uint1_7_t {}; + +// dummy struct for int1 to int7, actual functionality +// of these dtypes will be implemented in python with Tensor subclass +template +struct dummy_int1_7_t {}; + +// [dtype Macros note] For the macros below: +// +// For users: If you want to macro some code for all non-QInt scalar types +// (i.e. types with complete information, you probably want one of the +// AT_FORALL_SCALAR_TYPES / AT_FORALL_SCALAR_TYPES_AND macros below, which are +// designed to behave similarly to the Dispatch macros with the same name. +// +// For adding a new dtype: In the beginning, we had an idea that there was a +// list of all scalar types, and you could use AT_FORALL_SCALAR_TYPES to +// iterate over them. But over the years we added weird types which couldn't +// be handled uniformly everywhere and so in the end we ended up with some +// mish-mosh of some helper macros, but mostly use sites making a call about +// what dtypes they can or can't support. So if you want to add a new dtype, +// the preferred resolution is to find a dtype similar to what you want, +// grep for it and edit all the sites you find this way. If you need to add +// a completely new kind of dtype, you're going to have to laboriously audit +// all of the sites everywhere to figure out how it should work. Consulting +// some old PRs where we added new dtypes (check history of this file) can +// help give you an idea where to start. + +// If you want to support ComplexHalf for real, add ComplexHalf +// into this macro (and change the name). But beware: convert() +// doesn't work for all the conversions you need... +// +// TODO: To add unsigned int types here, we must define accumulate type. +// But uint8 currently accumulates into int64, so we would have to make +// an inconsistent choice for the larger types. Difficult. +#define AT_FORALL_SCALAR_TYPES_WITH_COMPLEX_EXCEPT_COMPLEX_HALF_F8NZ(_) \ + _(uint8_t, Byte) \ + _(int8_t, Char) \ + _(int16_t, Short) \ + _(int, Int) \ + _(int64_t, Long) \ + _(c10::Half, Half) \ + _(float, Float) \ + _(double, Double) \ + _(c10::complex, ComplexFloat) \ + _(c10::complex, ComplexDouble) \ + _(bool, Bool) \ + _(c10::BFloat16, BFloat16) \ + _(c10::Float8_e5m2, Float8_e5m2) \ + _(c10::Float8_e4m3fn, Float8_e4m3fn) + +// This macro controls many of our C++ APIs, including constructors +// for Scalar as well as the data() and item() accessors on Tensor +#define AT_FORALL_SCALAR_TYPES_WITH_COMPLEX(_) \ + _(uint8_t, Byte) \ + _(int8_t, Char) \ + _(int16_t, Short) \ + _(int, Int) \ + _(int64_t, Long) \ + _(c10::Half, Half) \ + _(float, Float) \ + _(double, Double) \ + _(c10::complex, ComplexHalf) \ + _(c10::complex, ComplexFloat) \ + _(c10::complex, ComplexDouble) \ + _(bool, Bool) \ + _(c10::BFloat16, BFloat16) \ + _(c10::Float8_e5m2, Float8_e5m2) \ + _(c10::Float8_e4m3fn, Float8_e4m3fn) \ + _(c10::Float8_e5m2fnuz, Float8_e5m2fnuz) \ + _(c10::Float8_e4m3fnuz, Float8_e4m3fnuz) \ + _(c10::Float8_e8m0fnu, Float8_e8m0fnu) + +// NB: Order matters for this macro; it is relied upon in +// _promoteTypesLookup and the serialization format. +#define AT_FORALL_SCALAR_TYPES_WITH_COMPLEX_AND_QINTS(_) \ + _(uint8_t, Byte) /* 0 */ \ + _(int8_t, Char) /* 1 */ \ + _(int16_t, Short) /* 2 */ \ + _(int, Int) /* 3 */ \ + _(int64_t, Long) /* 4 */ \ + _(c10::Half, Half) /* 5 */ \ + _(float, Float) /* 6 */ \ + _(double, Double) /* 7 */ \ + _(c10::complex, ComplexHalf) /* 8 */ \ + _(c10::complex, ComplexFloat) /* 9 */ \ + _(c10::complex, ComplexDouble) /* 10 */ \ + _(bool, Bool) /* 11 */ \ + _(c10::qint8, QInt8) /* 12 */ \ + _(c10::quint8, QUInt8) /* 13 */ \ + _(c10::qint32, QInt32) /* 14 */ \ + _(c10::BFloat16, BFloat16) /* 15 */ \ + _(c10::quint4x2, QUInt4x2) /* 16 */ \ + _(c10::quint2x4, QUInt2x4) /* 17 */ \ + _(c10::bits1x8, Bits1x8) /* 18 */ \ + _(c10::bits2x4, Bits2x4) /* 19 */ \ + _(c10::bits4x2, Bits4x2) /* 20 */ \ + _(c10::bits8, Bits8) /* 21 */ \ + _(c10::bits16, Bits16) /* 22 */ \ + _(c10::Float8_e5m2, Float8_e5m2) /* 23 */ \ + _(c10::Float8_e4m3fn, Float8_e4m3fn) /* 24 */ \ + _(c10::Float8_e5m2fnuz, Float8_e5m2fnuz) /* 25 */ \ + _(c10::Float8_e4m3fnuz, Float8_e4m3fnuz) /* 26 */ \ + _(uint16_t, UInt16) /* 27 */ \ + _(uint32_t, UInt32) /* 28 */ \ + _(uint64_t, UInt64) /* 29 */ \ + _(c10::dummy_uint1_7_t<1>, UInt1) /* 30 */ \ + _(c10::dummy_uint1_7_t<2>, UInt2) /* 31 */ \ + _(c10::dummy_uint1_7_t<3>, UInt3) /* 32 */ \ + _(c10::dummy_uint1_7_t<4>, UInt4) /* 33 */ \ + _(c10::dummy_uint1_7_t<5>, UInt5) /* 34 */ \ + _(c10::dummy_uint1_7_t<6>, UInt6) /* 35 */ \ + _(c10::dummy_uint1_7_t<7>, UInt7) /* 36 */ \ + _(c10::dummy_int1_7_t<1>, Int1) /* 37 */ \ + _(c10::dummy_int1_7_t<2>, Int2) /* 38 */ \ + _(c10::dummy_int1_7_t<3>, Int3) /* 39 */ \ + _(c10::dummy_int1_7_t<4>, Int4) /* 40 */ \ + _(c10::dummy_int1_7_t<5>, Int5) /* 41 */ \ + _(c10::dummy_int1_7_t<6>, Int6) /* 42 */ \ + _(c10::dummy_int1_7_t<7>, Int7) /* 43 */ \ + _(c10::Float8_e8m0fnu, Float8_e8m0fnu) /* 44 */ \ + _(c10::Float4_e2m1fn_x2, Float4_e2m1fn_x2) /* 45 */ + +// NB: despite its generic sounding name, the macros that don't take _AND +// are mostly only used by tensorexpr +#define AT_FORALL_INT_TYPES(_) \ + _(uint8_t, Byte) \ + _(int8_t, Char) \ + _(int16_t, Short) \ + _(int, Int) \ + _(int64_t, Long) + +#define AT_FORALL_SCALAR_TYPES(_) \ + _(uint8_t, Byte) \ + _(int8_t, Char) \ + _(int16_t, Short) \ + _(int, Int) \ + _(int64_t, Long) \ + _(float, Float) \ + _(double, Double) + +// These macros are often controlling how many template instantiations we +// create for kernels. It is typically inappropriate to add new dtypes here, +// instead, new types should be added to use sites on a case-by-case basis. +// We generally are not accepting new dtypes due to binary size concerns. + +#define AT_FORALL_SCALAR_TYPES_AND(SCALARTYPE, _) \ + _(uint8_t, Byte) \ + _(int8_t, Char) \ + _(int16_t, Short) \ + _(int, Int) \ + _(int64_t, Long) \ + _(float, Float) \ + _(double, Double) \ + _(c10::impl::ScalarTypeToCPPTypeT, SCALARTYPE) + +#define AT_FORALL_SCALAR_TYPES_AND2(SCALARTYPE1, SCALARTYPE2, _) \ + _(uint8_t, Byte) \ + _(int8_t, Char) \ + _(int16_t, Short) \ + _(int, Int) \ + _(int64_t, Long) \ + _(float, Float) \ + _(double, Double) \ + _(c10::impl::ScalarTypeToCPPTypeT, \ + SCALARTYPE1) \ + _(c10::impl::ScalarTypeToCPPTypeT, SCALARTYPE2) + +#define AT_FORALL_SCALAR_TYPES_AND3(SCALARTYPE1, SCALARTYPE2, SCALARTYPE3, _) \ + _(uint8_t, Byte) \ + _(int8_t, Char) \ + _(int16_t, Short) \ + _(int, Int) \ + _(int64_t, Long) \ + _(float, Float) \ + _(double, Double) \ + _(c10::impl::ScalarTypeToCPPTypeT, \ + SCALARTYPE1) \ + _(c10::impl::ScalarTypeToCPPTypeT, \ + SCALARTYPE2) \ + _(c10::impl::ScalarTypeToCPPTypeT, SCALARTYPE3) + +#define AT_FORALL_SCALAR_TYPES_AND7( \ + SCALARTYPE1, \ + SCALARTYPE2, \ + SCALARTYPE3, \ + SCALARTYPE4, \ + SCALARTYPE5, \ + SCALARTYPE6, \ + SCALARTYPE7, \ + _) \ + _(uint8_t, Byte) \ + _(int8_t, Char) \ + _(int16_t, Short) \ + _(int, Int) \ + _(int64_t, Long) \ + _(float, Float) \ + _(double, Double) \ + _(c10::impl::ScalarTypeToCPPTypeT, \ + SCALARTYPE1) \ + _(c10::impl::ScalarTypeToCPPTypeT, \ + SCALARTYPE2) \ + _(c10::impl::ScalarTypeToCPPTypeT, \ + SCALARTYPE3) \ + _(c10::impl::ScalarTypeToCPPTypeT, \ + SCALARTYPE4) \ + _(c10::impl::ScalarTypeToCPPTypeT, \ + SCALARTYPE5) \ + _(c10::impl::ScalarTypeToCPPTypeT, \ + SCALARTYPE6) \ + _(c10::impl::ScalarTypeToCPPTypeT, SCALARTYPE7) + +#define AT_FORALL_QINT_TYPES(_) \ + _(c10::qint8, QInt8) \ + _(c10::quint8, QUInt8) \ + _(c10::qint32, QInt32) \ + _(c10::quint4x2, QUInt4x2) \ + _(c10::quint2x4, QUInt2x4) + +#define AT_FORALL_FLOAT8_TYPES(_) \ + _(c10::Float8_e5m2, Float8_e5m2) \ + _(c10::Float8_e4m3fn, Float8_e4m3fn) \ + _(c10::Float8_e5m2fnuz, Float8_e5m2fnuz) \ + _(c10::Float8_e4m3fnuz, Float8_e4m3fnuz) \ + _(c10::Float8_e8m0fnu, Float8_e8m0fnu) + +#define AT_FORALL_COMPLEX_TYPES(_) \ + _(c10::complex, ComplexFloat) \ + _(c10::complex, ComplexDouble) + +enum class ScalarType : int8_t { +#define DEFINE_ST_ENUM_VAL_(_1, n) n, + AT_FORALL_SCALAR_TYPES_WITH_COMPLEX_AND_QINTS(DEFINE_ST_ENUM_VAL_) +#undef DEFINE_ENUM_ST_ENUM_VAL_ + Undefined, + NumOptions +}; + +constexpr uint16_t NumScalarTypes = + static_cast(ScalarType::NumOptions); + +// Map from C++ type to ScalarType enum +template +struct CppTypeToScalarType; + +#define SPECIALIZE_CppTypeToScalarType(cpp_type, scalar_type) \ + template <> \ + struct CppTypeToScalarType \ + : std:: \ + integral_constant { \ + }; + +AT_FORALL_SCALAR_TYPES_WITH_COMPLEX_AND_QINTS(SPECIALIZE_CppTypeToScalarType) + +#undef SPECIALIZE_CppTypeToScalarType + +namespace impl { + +// These are used to map ScalarTypes to C++ types. + +template +struct ScalarTypeToCPPType; + +#define SPECIALIZE_ScalarTypeToCPPType(cpp_type, scalar_type) \ + template <> \ + struct ScalarTypeToCPPType { \ + using type = cpp_type; \ + \ + /* This is a workaround for the CUDA bug which prevents */ \ + /* ::detail::ScalarTypeToCType::type being used directly due to */ \ + /* ambiguous reference which can't to be resolved. For some reason it */ \ + /* can't pick between at::detail and at::cuda::detail. */ \ + /* For repro example, please see: */ \ + /* https://gist.github.com/izdeby/952ae7cf256ddb740a73776d39a7e7ba */ \ + /* UPDATE: while the CUDA bug is fixed, we cannot remove the */ \ + /* workaround as it is BC breaking. However, it is recommended to */ \ + /* update any code that contains */ \ + /* decltype(ScalarTypeToCPPType::t) */ \ + /* with */ \ + /* ScalarTypeToCPPTypeT */ \ + static type t; \ + }; + +AT_FORALL_SCALAR_TYPES_WITH_COMPLEX_AND_QINTS(SPECIALIZE_ScalarTypeToCPPType) + +#undef SPECIALIZE_ScalarTypeToCPPType + +template +using ScalarTypeToCPPTypeT = typename ScalarTypeToCPPType::type; + +} // namespace impl + +inline const char* toString(ScalarType t) { +#define DEFINE_CASE(_, name) \ + case ScalarType::name: \ + return #name; + + switch (t) { + AT_FORALL_SCALAR_TYPES_WITH_COMPLEX_AND_QINTS(DEFINE_CASE) + default: + return "UNKNOWN_SCALAR"; + } +#undef DEFINE_CASE +} + +inline std::ostream& operator<<( + std::ostream& stream, + c10::ScalarType scalar_type) { + return stream << toString(scalar_type); +} + +inline bool isQIntType(ScalarType t) { + // Don't forget to extend this when adding new QInt types + return t == ScalarType::QInt8 || t == ScalarType::QUInt8 || + t == ScalarType::QInt32 || t == ScalarType::QUInt4x2 || + t == ScalarType::QUInt2x4; +} + +inline ScalarType toUnderlying(ScalarType t) { + switch (t) { + case ScalarType::QUInt8: + case ScalarType::QUInt4x2: + [[fallthrough]]; + case ScalarType::QUInt2x4: + return ScalarType::Byte; + case ScalarType::QInt8: + return ScalarType::Char; + case ScalarType::QInt32: + return ScalarType::Int; + default: + return t; + } +} + +} // namespace c10 + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly) +using c10::CppTypeToScalarType; +using c10::dummy_int1_7_t; +using c10::dummy_uint1_7_t; +using c10::NumScalarTypes; +using c10::ScalarType; +using c10::toString; +using c10::operator<<; +using c10::isQIntType; +using c10::toUnderlying; + +namespace impl { +using c10::impl::ScalarTypeToCPPTypeT; +} // namespace impl + +HIDDEN_NAMESPACE_END(torch, headeronly) + +C10_DIAGNOSTIC_POP() diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/TensorAccessor.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/TensorAccessor.h new file mode 100644 index 0000000000000000000000000000000000000000..9019c7ac3104dd90e78b89631e4f011d07786ffd --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/TensorAccessor.h @@ -0,0 +1,462 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include +#include + +namespace torch::headeronly { + +// The PtrTraits argument to the TensorAccessor/GenericPackedTensorAccessor +// is used to enable the __restrict__ keyword/modifier for the data +// passed to cuda. +template +struct DefaultPtrTraits { + typedef T* PtrType; +}; + +#if defined(__CUDACC__) || defined(__HIPCC__) +template +struct RestrictPtrTraits { + typedef T* __restrict__ PtrType; +}; +#endif + +namespace detail { +// Template classes in torch::headeronly::detail namespace are used +// to construct accessor template classes with custom ArrayRef and +// index bound check implementations. For instance, +// at::TensorAccessor and torch::headeronly::TensorAccessor template +// classes use c10::IntArrayRef and +// torch::headeronly::IntHeaderOnlyArrayRef classes, respectively, +// as return value types of sizes() and strides() methods. + +// TensorAccessorBase and TensorAccessor are used for both CPU and CUDA tensors. +// For CUDA tensors it is used in device code (only). This means that we +// restrict ourselves to functions and types available there (e.g. IntArrayRef +// isn't). + +// The PtrTraits argument is only relevant to cuda to support `__restrict__` +// pointers. +template < + class ArrayRefCls, + typename T, + size_t N, + template class PtrTraits = DefaultPtrTraits, + typename index_t = int64_t> +class TensorAccessorBase { + public: + typedef typename PtrTraits::PtrType PtrType; + + C10_HOST_DEVICE TensorAccessorBase( + PtrType data_, + const index_t* sizes_, + const index_t* strides_) + : data_(data_), sizes_(sizes_), strides_(strides_) {} + C10_HOST ArrayRefCls sizes() const { + return ArrayRefCls(sizes_, N); + } + C10_HOST ArrayRefCls strides() const { + return ArrayRefCls(strides_, N); + } + C10_HOST_DEVICE index_t stride(index_t i) const { + return strides_[i]; + } + C10_HOST_DEVICE index_t size(index_t i) const { + return sizes_[i]; + } + C10_HOST_DEVICE PtrType data() { + return data_; + } + C10_HOST_DEVICE const PtrType data() const { + return data_; + } + + protected: + PtrType data_; + const index_t* sizes_; + const index_t* strides_; +}; + +// The `TensorAccessor` is typically instantiated for CPU `Tensor`s using +// `Tensor.accessor()`. +// For CUDA `Tensor`s, `GenericPackedTensorAccessor` is used on the host and +// only indexing on the device uses `TensorAccessor`s. +template < + class ArrayRefCls, + typename T, + size_t N, + template class PtrTraits = DefaultPtrTraits, + typename index_t = int64_t> +class TensorAccessor + : public TensorAccessorBase { + public: + typedef typename PtrTraits::PtrType PtrType; + + C10_HOST_DEVICE TensorAccessor( + PtrType data_, + const index_t* sizes_, + const index_t* strides_) + : TensorAccessorBase( + data_, + sizes_, + strides_) {} + + C10_HOST_DEVICE TensorAccessor + operator[](index_t i) { + return TensorAccessor( + this->data_ + this->strides_[0] * i, + this->sizes_ + 1, + this->strides_ + 1); + } + + C10_HOST_DEVICE const TensorAccessor< + ArrayRefCls, + T, + N - 1, + PtrTraits, + index_t> + operator[](index_t i) const { + return TensorAccessor( + this->data_ + this->strides_[0] * i, + this->sizes_ + 1, + this->strides_ + 1); + } +}; + +template < + class ArrayRefCls, + typename T, + template class PtrTraits, + typename index_t> +class TensorAccessor + : public TensorAccessorBase { + public: + typedef typename PtrTraits::PtrType PtrType; + + C10_HOST_DEVICE TensorAccessor( + PtrType data_, + const index_t* sizes_, + const index_t* strides_) + : TensorAccessorBase( + data_, + sizes_, + strides_) {} + C10_HOST_DEVICE T& operator[](index_t i) { + // NOLINTNEXTLINE(clang-analyzer-core.NullDereference) + return this->data_[this->strides_[0] * i]; + } + C10_HOST_DEVICE const T& operator[](index_t i) const { + return this->data_[this->strides_[0] * i]; + } +}; + +// GenericPackedTensorAccessorBase and GenericPackedTensorAccessor are used on +// for CUDA `Tensor`s on the host and as in contrast to `TensorAccessor`s, they +// copy the strides and sizes on instantiation (on the host) in order to +// transfer them on the device when calling kernels. On the device, indexing of +// multidimensional tensors gives to `TensorAccessor`s. Use RestrictPtrTraits as +// PtrTraits if you want the tensor's data pointer to be marked as __restrict__. +// Instantiation from data, sizes, strides is only needed on the host and +// std::copy isn't available on the device, so those functions are host only. +template < + typename IndexBoundsCheck, + typename T, + size_t N, + template class PtrTraits = DefaultPtrTraits, + typename index_t = int64_t> +class GenericPackedTensorAccessorBase { + public: + typedef typename PtrTraits::PtrType PtrType; + C10_HOST GenericPackedTensorAccessorBase( + PtrType data_, + const index_t* sizes_, + const index_t* strides_) + : data_(data_) { + std::copy(sizes_, sizes_ + N, std::begin(this->sizes_)); + std::copy(strides_, strides_ + N, std::begin(this->strides_)); + } + + // if index_t is not int64_t, we want to have an int64_t constructor + template < + typename source_index_t, + class = std::enable_if_t>> + C10_HOST GenericPackedTensorAccessorBase( + PtrType data_, + const source_index_t* sizes_, + const source_index_t* strides_) + : data_(data_) { + for (size_t i = 0; i < N; ++i) { + this->sizes_[i] = sizes_[i]; + this->strides_[i] = strides_[i]; + } + } + + C10_HOST_DEVICE index_t stride(index_t i) const { + return strides_[i]; + } + C10_HOST_DEVICE index_t size(index_t i) const { + return sizes_[i]; + } + C10_HOST_DEVICE PtrType data() { + return data_; + } + C10_HOST_DEVICE const PtrType data() const { + return data_; + } + + protected: + PtrType data_; + // NOLINTNEXTLINE(*c-arrays*) + index_t sizes_[N]; + // NOLINTNEXTLINE(*c-arrays*) + index_t strides_[N]; + C10_HOST void bounds_check_(index_t i) const { + IndexBoundsCheck _(i); + } +}; + +template < + typename ItemAccessor, + typename IndexBoundsCheck, + typename T, + size_t N, + template class PtrTraits = DefaultPtrTraits, + typename index_t = int64_t> +class GenericPackedTensorAccessor : public GenericPackedTensorAccessorBase< + IndexBoundsCheck, + T, + N, + PtrTraits, + index_t> { + public: + typedef typename PtrTraits::PtrType PtrType; + + C10_HOST GenericPackedTensorAccessor( + PtrType data_, + const index_t* sizes_, + const index_t* strides_) + : GenericPackedTensorAccessorBase< + IndexBoundsCheck, + T, + N, + PtrTraits, + index_t>(data_, sizes_, strides_) {} + + // if index_t is not int64_t, we want to have an int64_t constructor + template < + typename source_index_t, + class = std::enable_if_t>> + C10_HOST GenericPackedTensorAccessor( + PtrType data_, + const source_index_t* sizes_, + const source_index_t* strides_) + : GenericPackedTensorAccessorBase< + IndexBoundsCheck, + T, + N, + PtrTraits, + index_t>(data_, sizes_, strides_) {} + + C10_DEVICE ItemAccessor operator[](index_t i) { + index_t* new_sizes = this->sizes_ + 1; + index_t* new_strides = this->strides_ + 1; + return ItemAccessor( + this->data_ + this->strides_[0] * i, new_sizes, new_strides); + } + + C10_DEVICE const ItemAccessor operator[](index_t i) const { + const index_t* new_sizes = this->sizes_ + 1; + const index_t* new_strides = this->strides_ + 1; + return ItemAccessor( + this->data_ + this->strides_[0] * i, new_sizes, new_strides); + } + + /// Returns a PackedTensorAccessor of the same dimension after transposing the + /// two dimensions given. Does not actually move elements; transposition is + /// made by permuting the size/stride arrays. If the dimensions are not valid, + /// asserts. + C10_HOST GenericPackedTensorAccessor< + ItemAccessor, + IndexBoundsCheck, + T, + N, + PtrTraits, + index_t> + transpose(index_t dim1, index_t dim2) const { + this->bounds_check_(dim1); + this->bounds_check_(dim2); + GenericPackedTensorAccessor< + ItemAccessor, + IndexBoundsCheck, + T, + N, + PtrTraits, + index_t> + result(this->data_, this->sizes_, this->strides_); + std::swap(result.strides_[dim1], result.strides_[dim2]); + std::swap(result.sizes_[dim1], result.sizes_[dim2]); + return result; + } +}; + +template < + typename ItemAccessor, + typename IndexBoundsCheck, + typename T, + template class PtrTraits, + typename index_t> +class GenericPackedTensorAccessor< + ItemAccessor, + IndexBoundsCheck, + T, + 1, + PtrTraits, + index_t> + : public GenericPackedTensorAccessorBase< + IndexBoundsCheck, + T, + 1, + PtrTraits, + index_t> { + public: + typedef typename PtrTraits::PtrType PtrType; + C10_HOST GenericPackedTensorAccessor( + PtrType data_, + const index_t* sizes_, + const index_t* strides_) + : GenericPackedTensorAccessorBase< + IndexBoundsCheck, + T, + 1, + PtrTraits, + index_t>(data_, sizes_, strides_) {} + + // if index_t is not int64_t, we want to have an int64_t constructor + template < + typename source_index_t, + class = std::enable_if_t>> + C10_HOST GenericPackedTensorAccessor( + PtrType data_, + const source_index_t* sizes_, + const source_index_t* strides_) + : GenericPackedTensorAccessorBase< + IndexBoundsCheck, + T, + 1, + PtrTraits, + index_t>(data_, sizes_, strides_) {} + + C10_DEVICE T& operator[](index_t i) { + return this->data_[this->strides_[0] * i]; + } + C10_DEVICE const T& operator[](index_t i) const { + return this->data_[this->strides_[0] * i]; + } + + // Same as in the general N-dimensional case, but note that in the + // 1-dimensional case the returned PackedTensorAccessor will always be an + // identical copy of the original + C10_HOST GenericPackedTensorAccessor< + ItemAccessor, + IndexBoundsCheck, + T, + 1, + PtrTraits, + index_t> + transpose(index_t dim1, index_t dim2) const { + this->bounds_check_(dim1); + this->bounds_check_(dim2); + return GenericPackedTensorAccessor< + ItemAccessor, + IndexBoundsCheck, + T, + 1, + PtrTraits, + index_t>(this->data_, this->sizes_, this->strides_); + } +}; + +template +struct HeaderOnlyIndexBoundsCheck { + HeaderOnlyIndexBoundsCheck(index_t i) { + STD_TORCH_CHECK( + 0 <= i && i < index_t{N}, + "Index ", + i, + " is not within bounds of a tensor of dimension ", + N); + } +}; + +} // namespace detail + +// HeaderOnlyTensorAccessorBase is same as at::TensorAccessorBase +// except sizes() and strides() return IntHeaderOnlyArrayRef instead +// of IntArrayRef. +template < + typename T, + size_t N, + template class PtrTraits = DefaultPtrTraits, + typename index_t = int64_t> +using HeaderOnlyTensorAccessorBase = detail::TensorAccessorBase< + torch::headeronly::IntHeaderOnlyArrayRef, + T, + N, + PtrTraits, + index_t>; + +// HeaderOnlyTensorAccessor is same as at::TensorAccessor except +// sizes() and strides() return IntHeaderOnlyArrayRef instead of +// IntArrayRef. +template < + typename T, + size_t N, + template class PtrTraits = DefaultPtrTraits, + typename index_t = int64_t> +using HeaderOnlyTensorAccessor = detail::TensorAccessor< + torch::headeronly::IntHeaderOnlyArrayRef, + T, + N, + PtrTraits, + index_t>; + +// HeaderOnlyGenericPackedTensorAccessorBase is same as +// at::GenericPackedTensorAccessorBase except sizes() and strides() +// return IntHeaderOnlyArrayRef instead of IntArrayRef. +template < + typename T, + size_t N, + template class PtrTraits = DefaultPtrTraits, + typename index_t = int64_t> +using HeaderOnlyGenericPackedTensorAccessorBase = + detail::GenericPackedTensorAccessorBase< + detail::HeaderOnlyIndexBoundsCheck, + T, + N, + PtrTraits, + index_t>; + +// HeaderOnlyGenericPackedTensorAccessor is same as +// at::GenericPackedTensorAccessor except sizes() and strides() return +// IntHeaderOnlyArrayRef instead of IntArrayRef, and bounds check uses +// STD_TORCH_CHECK instead of TORCH_CHECK_INDEX. +template < + typename T, + size_t N, + template class PtrTraits = DefaultPtrTraits, + typename index_t = int64_t> +using HeaderOnlyGenericPackedTensorAccessor = + detail::GenericPackedTensorAccessor< + HeaderOnlyTensorAccessor, + detail::HeaderOnlyIndexBoundsCheck, + T, + N, + PtrTraits, + index_t>; + +} // namespace torch::headeronly diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/enum_tag.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/enum_tag.h new file mode 100644 index 0000000000000000000000000000000000000000..f45f3f49e86fb315e6afd58c79d75141447e9395 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/core/enum_tag.h @@ -0,0 +1,36 @@ +#pragma once + +// @generated by torchgen/gen.py from enum_tag.h + +#include + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly) + +// Enum of valid tags obtained from the entries in tags.yaml +enum class Tag { + core, + cudagraph_unsafe, + data_dependent_output, + dynamic_output_shape, + flexible_layout, + generated, + inplace_view, + maybe_aliasing_or_mutating, + needs_contiguous_strides, + needs_exact_strides, + needs_fixed_stride_order, + nondeterministic_bitwise, + nondeterministic_seeded, + out_variant, + pointwise, + pt2_compliant_tag, + reduction, + view_copy +}; + +HIDDEN_NAMESPACE_END(torch, headeronly) + +// Re-expose in the at:: namespace for backward compatibility +namespace at { + using torch::headeronly::Tag; +} diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/cpu/vec/intrinsics.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/cpu/vec/intrinsics.h new file mode 100644 index 0000000000000000000000000000000000000000..3cf427dae64bce378f9c284e0db6dd452cb0e3d5 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/cpu/vec/intrinsics.h @@ -0,0 +1,50 @@ +#pragma once +#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) +/* GCC or clang-compatible compiler, targeting x86/x86-64 */ +#include +#elif defined(__clang__) && (defined(__ARM_NEON__) || defined(__aarch64__)) +/* Clang-compatible compiler, targeting arm neon */ +#include +#if defined(__ARM_FEATURE_SVE) +/* CLANG-compatible compiler, targeting ARM with SVE */ +#include +#endif +#elif defined(_MSC_VER) +/* Microsoft C/C++-compatible compiler */ +#include +#if _MSC_VER <= 1900 +#define _mm256_extract_epi64(X, Y) \ + (_mm_extract_epi64(_mm256_extractf128_si256(X, Y >> 1), Y % 2)) +#define _mm256_extract_epi32(X, Y) \ + (_mm_extract_epi32(_mm256_extractf128_si256(X, Y >> 2), Y % 4)) +#define _mm256_extract_epi16(X, Y) \ + (_mm_extract_epi16(_mm256_extractf128_si256(X, Y >> 3), Y % 8)) +#define _mm256_extract_epi8(X, Y) \ + (_mm_extract_epi8(_mm256_extractf128_si256(X, Y >> 4), Y % 16)) +#endif +#elif defined(__GNUC__) && (defined(__ARM_NEON__) || defined(__aarch64__)) +/* GCC-compatible compiler, targeting ARM with NEON */ +#include +#if defined(__ARM_FEATURE_SVE) +/* GCC-compatible compiler, targeting ARM with SVE */ +#include +#endif +#elif defined(__GNUC__) && defined(__IWMMXT__) +/* GCC-compatible compiler, targeting ARM with WMMX */ +#include +#elif defined(__s390x__) +// targets Z/architecture +// we will include vecintrin later +#elif (defined(__GNUC__) || defined(__xlC__)) && \ + (defined(__VEC__) || defined(__ALTIVEC__)) +/* XLC or GCC-compatible compiler, targeting PowerPC with VMX/VSX */ +#include +/* We need to undef those tokens defined by to avoid conflicts + with the C++ types. => Can still use __bool/__vector */ +#undef bool +#undef vector +#undef pixel +#elif defined(__GNUC__) && defined(__SPE__) +/* GCC-compatible compiler, targeting PowerPC with SPE */ +#include +#endif diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/cpu/vec/vec_half.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/cpu/vec/vec_half.h new file mode 100644 index 0000000000000000000000000000000000000000..6ad37b1948306903ea4f92c64d8402ffa3423b23 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/cpu/vec/vec_half.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly, vec) +// See Note [CPU_CAPABILITY namespace] +inline namespace CPU_CAPABILITY { + +#if (defined(CPU_CAPABILITY_AVX2) || defined(CPU_CAPABILITY_AVX512)) && \ + !defined(__APPLE__) +static inline uint16_t float2half_scalar(float val) { +#if defined(CPU_CAPABILITY_AVX2) +#if defined(_MSC_VER) + __m256 v = _mm256_set1_ps(val); + __m128i o = + _mm256_cvtps_ph(v, (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)); + return static_cast(_mm_cvtsi128_si32(o)); +#else + return _cvtss_sh(val, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); +#endif +#elif defined(CPU_CAPABILITY_AVX512) + __m512 v = _mm512_set1_ps(val); + __m256i o = + _mm512_cvtps_ph(v, (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)); + return static_cast( + _mm_cvtsi128_si32(_mm256_castsi256_si128(o))); +#endif +} + +static inline float half2float_scalar(uint16_t val) { +#if defined(CPU_CAPABILITY_AVX2) +#if defined(_MSC_VER) + __m128i v = _mm_cvtsi32_si128(val); + __m256 o = _mm256_cvtph_ps(v); + return _mm256_cvtss_f32(o); +#else + return _cvtsh_ss(val); +#endif +#elif defined(CPU_CAPABILITY_AVX512) + __m256i v = + _mm256_setr_epi16(val, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + __m512 o = _mm512_cvtph_ps(v); + return _mm512_cvtss_f32(o); +#endif +} + +#endif + +} // namespace CPU_CAPABILITY +HIDDEN_NAMESPACE_END(torch, headeronly, vec) + +namespace at::vec { +#if (defined(CPU_CAPABILITY_AVX2) || defined(CPU_CAPABILITY_AVX512)) && \ + !defined(__APPLE__) +using torch::headeronly::vec::float2half_scalar; +using torch::headeronly::vec::half2float_scalar; +#endif +} // namespace at::vec diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/macros/Export.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/macros/Export.h new file mode 100644 index 0000000000000000000000000000000000000000..14b26c18e7b1b702d2ecd1522e95001aaeb18d60 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/macros/Export.h @@ -0,0 +1,145 @@ +#pragma once + +#ifndef C10_MACROS_EXPORT_H_ +#define C10_MACROS_EXPORT_H_ + +#ifndef C10_USING_CUSTOM_GENERATED_MACROS +#include +#endif // C10_USING_CUSTOM_GENERATED_MACROS + +/* Header file to define the common scaffolding for exported symbols. + * + * Export is by itself a quite tricky situation to deal with, and if you are + * hitting this file, make sure you start with the background here: + * - Linux: https://gcc.gnu.org/wiki/Visibility + * - Windows: + * https://docs.microsoft.com/en-us/cpp/cpp/dllexport-dllimport?view=vs-2017 + * + * Do NOT include this file directly. Instead, use c10/macros/Macros.h + */ + +// You do not need to edit this part of file unless you are changing the core +// pytorch export abstractions. +// +// This part defines the C10 core export and import macros. This is controlled +// by whether we are building shared libraries or not, which is determined +// during build time and codified in c10/core/cmake_macros.h. +// When the library is built as a shared lib, EXPORT and IMPORT will contain +// visibility attributes. If it is being built as a static lib, then EXPORT +// and IMPORT basically have no effect. + +// As a rule of thumb, you should almost NEVER mix static and shared builds for +// libraries that depend on c10. AKA, if c10 is built as a static library, we +// recommend everything dependent on c10 to be built statically. If c10 is built +// as a shared library, everything dependent on it should be built as shared. In +// the PyTorch project, all native libraries shall use the macro +// C10_BUILD_SHARED_LIB to check whether pytorch is building shared or static +// libraries. + +// For build systems that do not directly depend on CMake and directly build +// from the source directory (such as Buck), one may not have a cmake_macros.h +// file at all. In this case, the build system is responsible for providing +// correct macro definitions corresponding to the cmake_macros.h.in file. +// +// In such scenarios, one should define the macro +// C10_USING_CUSTOM_GENERATED_MACROS +// to inform this header that it does not need to include the cmake_macros.h +// file. + +#ifdef _WIN32 +#define C10_HIDDEN +#if defined(C10_BUILD_SHARED_LIBS) +#define C10_EXPORT __declspec(dllexport) +#define C10_IMPORT __declspec(dllimport) +#else +#define C10_EXPORT +#define C10_IMPORT +#endif +#else // _WIN32 +#if defined(__GNUC__) +#define C10_EXPORT __attribute__((__visibility__("default"))) +#define C10_HIDDEN __attribute__((__visibility__("hidden"))) +#else // defined(__GNUC__) +#define C10_EXPORT +#define C10_HIDDEN +#endif // defined(__GNUC__) +#define C10_IMPORT C10_EXPORT +#endif // _WIN32 + +#ifdef NO_EXPORT +#undef C10_EXPORT +#define C10_EXPORT +#endif + +// Definition of an adaptive XX_API macro, that depends on whether you are +// building the library itself or not, routes to XX_EXPORT and XX_IMPORT. +// Basically, you will need to do this for each shared library that you are +// building, and the instruction is as follows: assuming that you are building +// a library called libawesome.so. You should: +// (1) for your cmake target (usually done by "add_library(awesome, ...)"), +// define a macro called AWESOME_BUILD_MAIN_LIB using +// target_compile_options. +// (2) define the AWESOME_API macro similar to the one below. +// And in the source file of your awesome library, use AWESOME_API to +// annotate public symbols. + +// Here, for the C10 library, we will define the macro C10_API for both import +// and export. + +// This one is being used by libc10.so +#ifdef C10_BUILD_MAIN_LIB +#define C10_API C10_EXPORT +#else +#define C10_API C10_IMPORT +#endif + +// This one is being used by libtorch.so +#ifdef CAFFE2_BUILD_MAIN_LIB +#define TORCH_API C10_EXPORT +#else +#define TORCH_API C10_IMPORT +#endif + +// You may be wondering why we have TORCH_CUDA_CPP_API and TORCH_CUDA_CU_API +// belonging to the same library instead of just one TORCH_CUDA_API. Well, it +// can indeed just be one TORCH_CUDA_API (and used to be)! TORCH_CUDA_CPP_API +// and TORCH_CUDA_CU_API are artifacts of when we needed a split build to +// avoid relocation marker linking errors. The context is as follows: +// +// Once upon a time, there _was_ only TORCH_CUDA_API. All was happy until we +// tried to compile PyTorch for CUDA 11.1, which ran into relocation marker +// issues when linking big binaries. +// (https://github.com/pytorch/pytorch/issues/39968) We had two choices: +// (1) Stop supporting so many GPU architectures +// (2) Do something else +// We chose #2 and decided to split the behemoth that was torch_cuda into two +// smaller libraries, one with most of the core kernel functions (torch_cuda_cu) +// and the other that had..well..everything else (torch_cuda_cpp). The idea was +// this: instead of linking our static libraries (like the hefty +// libcudnn_static.a) with another huge library, torch_cuda, and run into pesky +// relocation marker issues, we could link our static libraries to a smaller +// part of torch_cuda (torch_cuda_cpp) and avoid the issues. + +// libtorch_cuda.so (where torch_cuda_cu and torch_cuda_cpp are a part of the +// same api) +#ifdef TORCH_CUDA_BUILD_MAIN_LIB +#define TORCH_CUDA_CPP_API C10_EXPORT +#define TORCH_CUDA_CU_API C10_EXPORT +#else +#define TORCH_CUDA_CPP_API C10_IMPORT +#define TORCH_CUDA_CU_API C10_IMPORT +#endif + +#if defined(TORCH_XPU_BUILD_MAIN_LIB) +#define TORCH_XPU_API C10_EXPORT +#else +#define TORCH_XPU_API C10_IMPORT +#endif + +// Enums only need to be exported on windows for non-CUDA files +#if defined(_WIN32) && defined(__CUDACC__) +#define C10_API_ENUM C10_API +#else +#define C10_API_ENUM +#endif +#endif // C10_MACROS_EXPORT_H_ diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/macros/Macros.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/macros/Macros.h new file mode 100644 index 0000000000000000000000000000000000000000..cef99df3f566fbbe091f9b5932ba00523fc3c127 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/macros/Macros.h @@ -0,0 +1,741 @@ +#ifndef C10_MACROS_MACROS_H_ +#define C10_MACROS_MACROS_H_ + +#ifdef __cplusplus +#include +#else +#include +#endif + +/* Main entry for torch/headeronly/macros (used to be c10/macros). + * + * In your code, include torch/headeronly/macros/Macros.h directly, instead of + * individual files in this folder. + */ + +// For build systems that do not directly depend on CMake and directly build +// from the source directory (such as Buck), one may not have a cmake_macros.h +// file at all. In this case, the build system is responsible for providing +// correct macro definitions corresponding to the cmake_macros.h.in file. +// +// In such scenarios, one should define the macro +// C10_USING_CUSTOM_GENERATED_MACROS +// to inform this header that it does not need to include the cmake_macros.h +// file. + +#ifndef C10_USING_CUSTOM_GENERATED_MACROS +#include +#endif // C10_USING_CUSTOM_GENERATED_MACROS + +#include + +#if defined(__clang__) +#define __ubsan_ignore_float_divide_by_zero__ \ + __attribute__((no_sanitize("float-divide-by-zero"))) +#define __ubsan_ignore_undefined__ __attribute__((no_sanitize("undefined"))) +#define __ubsan_ignore_signed_int_overflow__ \ + __attribute__((no_sanitize("signed-integer-overflow"))) +#define __ubsan_ignore_pointer_overflow__ \ + __attribute__((no_sanitize("pointer-overflow"))) +#define __ubsan_ignore_function__ __attribute__((no_sanitize("function"))) +#define __ubsan_ignore_float_cast_overflow__ \ + __attribute__((no_sanitize("float-cast-overflow"))) +#else +#define __ubsan_ignore_float_divide_by_zero__ +#define __ubsan_ignore_undefined__ +#define __ubsan_ignore_signed_int_overflow__ +#define __ubsan_ignore_pointer_overflow__ +#define __ubsan_ignore_function__ +#define __ubsan_ignore_float_cast_overflow__ +#endif + +// Detect address sanitizer as some stuff doesn't work with it +#undef C10_ASAN_ENABLED + +// for clang +#if defined(__has_feature) +#if ((__has_feature(address_sanitizer))) +#define C10_ASAN_ENABLED 1 +#endif +#endif + +// for gcc +#if defined(__SANITIZE_ADDRESS__) +#if __SANITIZE_ADDRESS__ +#if !defined(C10_ASAN_ENABLED) +#define C10_ASAN_ENABLED 1 +#endif +#endif +#endif + +#if !defined(C10_ASAN_ENABLED) +#define C10_ASAN_ENABLED 0 +#endif + +// Detect undefined-behavior sanitizer (UBSAN) +#undef C10_UBSAN_ENABLED + +// for clang or gcc >= 14 +// NB: gcc 14 adds support for Clang's __has_feature +// https://gcc.gnu.org/gcc-14/changes.html +// gcc < 14 doesn't have a macro for UBSAN +// (e.g. __SANITIZE_UNDEFINED__ does not exist in gcc) +// https://github.com/google/sanitizers/issues/765 +#if defined(__has_feature) +#if ((__has_feature(undefined_behavior_sanitizer))) +#define C10_UBSAN_ENABLED 1 +#endif +#endif + +#if !defined(C10_UBSAN_ENABLED) +#define C10_UBSAN_ENABLED 0 +#endif + +// Disable the copy and assignment operator for a class. Note that this will +// disable the usage of the class in std containers. +#define C10_DISABLE_COPY_AND_ASSIGN(classname) \ + classname(const classname&) = delete; \ + classname& operator=(const classname&) = delete + +#define C10_CONCATENATE_IMPL(s1, s2) s1##s2 +#define C10_CONCATENATE(s1, s2) C10_CONCATENATE_IMPL(s1, s2) + +#define C10_MACRO_EXPAND(args) args + +#define C10_STRINGIZE_IMPL(x) #x +#define C10_STRINGIZE(x) C10_STRINGIZE_IMPL(x) + +/** + * C10_ANONYMOUS_VARIABLE(str) introduces a new identifier which starts with + * str and ends with a unique number. + */ +#ifdef __COUNTER__ +#define C10_UID __COUNTER__ +#define C10_ANONYMOUS_VARIABLE(str) C10_CONCATENATE(str, __COUNTER__) +#else +#define C10_UID __LINE__ +#define C10_ANONYMOUS_VARIABLE(str) C10_CONCATENATE(str, __LINE__) +#endif + +#ifdef __has_cpp_attribute +#define C10_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +#define C10_HAS_CPP_ATTRIBUTE(x) (0) +#endif + +#ifndef FBCODE_CAFFE2 +/// DEPRECATED: Warn if a type or return value is discarded. +#define C10_NODISCARD [[nodiscard]] + +/// DEPRECATED: Suppress an unused variable. +#define C10_UNUSED [[maybe_unused]] +#endif + +#if !defined(__has_attribute) +#define __has_attribute(x) 0 +#endif + +// Direct port of LLVM_ATTRIBUTE_USED. +#if __has_attribute(used) +#define C10_USED __attribute__((__used__)) +#else +#define C10_USED +#endif + +#define C10_RESTRICT __restrict + +#ifdef __cplusplus + +// Simply define the namespace, in case a dependent library want to refer to +// the c10 namespace but not any nontrivial files. +namespace c10 {} +namespace c10::cuda {} +namespace c10::hip {} +namespace c10::xpu {} + +// Since C10 is the core library for caffe2 (and aten), we will simply reroute +// all abstractions defined in c10 to be available in caffe2 as well. +// This is only for backwards compatibility. Please use the symbols from the +// c10 namespace where possible. +namespace caffe2 { +using namespace c10; +} +namespace at { +using namespace c10; +} +namespace at::cuda { +using namespace c10::cuda; +} // namespace at::cuda + +// WARNING!!! THIS IS A GIANT HACK!!! +// This line means you cannot simultaneously include c10/hip +// and c10/cuda and then use them from the at::cuda namespace. +// This is true in practice, because HIPIFY works inplace on +// files in ATen/cuda, so it assumes that c10::hip is available +// from at::cuda. This namespace makes that happen. When +// HIPIFY is no longer out-of-place, we can switch the cuda +// here to hip and everyone is happy. +namespace at::cuda { +using namespace c10::hip; +} // namespace at::cuda + +namespace at::xpu { +using namespace c10::xpu; +} // namespace at::xpu + +#endif // __cplusplus + +// C10_LIKELY/C10_UNLIKELY +// +// These macros provide parentheses, so you can use these macros as: +// +// if C10_LIKELY(some_expr) { +// ... +// } +// +// NB: static_cast to boolean is mandatory in C++, because __builtin_expect +// takes a long argument, which means you may trigger the wrong conversion +// without it. +// +#if defined(__GNUC__) || defined(__ICL) || defined(__clang__) +#define C10_LIKELY(expr) (__builtin_expect(static_cast(expr), 1)) +#define C10_UNLIKELY(expr) (__builtin_expect(static_cast(expr), 0)) +#else +#define C10_LIKELY(expr) (expr) +#define C10_UNLIKELY(expr) (expr) +#endif + +/// C10_NOINLINE - Functions whose declaration is annotated with this will not +/// be inlined. +#ifdef __GNUC__ +#define C10_NOINLINE __attribute__((noinline)) +#elif _MSC_VER +#define C10_NOINLINE __declspec(noinline) +#else +#define C10_NOINLINE +#endif + +#if defined(_MSC_VER) +#define C10_ALWAYS_INLINE __forceinline +#elif __has_attribute(always_inline) || defined(__GNUC__) +#define C10_ALWAYS_INLINE __attribute__((__always_inline__)) inline +#else +#define C10_ALWAYS_INLINE inline +#endif + +// Unlike C10_ALWAYS_INLINE, C10_ALWAYS_INLINE_ATTRIBUTE can be used +// on a lambda. +#if defined(_MSC_VER) +// MSVC 14.39 is reasonably recent and doesn't like +// [[msvc::forceinline]] on a lambda, so don't try to use it. +#define C10_ALWAYS_INLINE_ATTRIBUTE +#elif __has_attribute(always_inline) || defined(__GNUC__) +#define C10_ALWAYS_INLINE_ATTRIBUTE __attribute__((__always_inline__)) +#else +#define C10_ALWAYS_INLINE_ATTRIBUTE +#endif + +#if defined(_MSC_VER) +#define C10_ATTR_VISIBILITY_HIDDEN +#elif defined(__GNUC__) +#define C10_ATTR_VISIBILITY_HIDDEN __attribute__((__visibility__("hidden"))) +#else +#define C10_ATTR_VISIBILITY_HIDDEN +#endif + +#define C10_ERASE C10_ALWAYS_INLINE C10_ATTR_VISIBILITY_HIDDEN + +#ifdef __cplusplus +#include +#else +#include +#endif + +#ifdef __HIPCC__ +// Unlike CUDA, HIP requires a HIP header to be included for __host__ to work. +// We do this #include here so that C10_HOST_DEVICE and friends will Just Work. +// See https://github.com/ROCm/hip/issues/441 +#include +#endif + +#if defined(__CUDACC__) || defined(__HIPCC__) +// Designates functions callable from the host (CPU) and the device (GPU) +#define C10_HOST_DEVICE __host__ __device__ +#define C10_DEVICE __device__ +#define C10_HOST __host__ +// constants from +// (https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#features-and-technical-specifications) +// The maximum number of threads per multiprocessor is 1024 for Turing +// architecture (7.5), 1536 for Geforce Ampere (8.6)/Jetson Orin (8.7), and +// 2048 for all other architectures. You'll get warnings if you exceed these +// constants. Hence, the following macros adjust the input values from the user +// to resolve potential warnings. +#if __CUDA_ARCH__ == 750 +constexpr uint32_t CUDA_MAX_THREADS_PER_SM = 1024; +#elif __CUDA_ARCH__ == 860 || __CUDA_ARCH__ == 870 || __CUDA_ARCH__ == 890 || \ + __CUDA_ARCH__ == 1200 +constexpr uint32_t CUDA_MAX_THREADS_PER_SM = 1536; +#else +constexpr uint32_t CUDA_MAX_THREADS_PER_SM = 2048; +#endif +// CUDA_MAX_THREADS_PER_BLOCK is same for all architectures currently +constexpr uint32_t CUDA_MAX_THREADS_PER_BLOCK = 1024; +// CUDA_THREADS_PER_BLOCK_FALLBACK is the "canonical fallback" choice of block +// size. 256 is a good number for this fallback and should give good occupancy +// and versatility across all architectures. +constexpr uint32_t CUDA_THREADS_PER_BLOCK_FALLBACK = 256; +// NOTE: if you are thinking of constexpr-ify the inputs to launch bounds, it +// turns out that although __launch_bounds__ can take constexpr, it +// can't take a constexpr that has anything to do with templates. +// Currently we use launch_bounds that depend on template arguments in +// Loops.cuh, Reduce.cuh and LossCTC.cuh. Hence, C10_MAX_THREADS_PER_BLOCK +// and C10_MIN_BLOCKS_PER_SM are kept as macros. +// Suppose you were planning to write __launch_bounds__(a, b), based on your +// performance tuning on a modern GPU. Instead, you should write +// __launch_bounds__(C10_MAX_THREADS_PER_BLOCK(a), C10_MIN_BLOCKS_PER_SM(a, b)), +// which will also properly respect limits on old architectures. +#define C10_MAX_THREADS_PER_BLOCK(val) \ + (((val) <= CUDA_MAX_THREADS_PER_BLOCK) ? (val) \ + : CUDA_THREADS_PER_BLOCK_FALLBACK) +#define C10_MIN_BLOCKS_PER_SM(threads_per_block, blocks_per_sm) \ + ((((threads_per_block) * (blocks_per_sm) <= CUDA_MAX_THREADS_PER_SM) \ + ? (blocks_per_sm) \ + : ((CUDA_MAX_THREADS_PER_SM + (threads_per_block) - 1) / \ + (threads_per_block)))) +// C10_LAUNCH_BOUNDS is analogous to __launch_bounds__ +#define C10_LAUNCH_BOUNDS_0 \ + __launch_bounds__( \ + 256, 4) // default launch bounds that should give good occupancy and + // versatility across all architectures. +#define C10_LAUNCH_BOUNDS_1(max_threads_per_block) \ + __launch_bounds__((C10_MAX_THREADS_PER_BLOCK((max_threads_per_block)))) +#define C10_LAUNCH_BOUNDS_2(max_threads_per_block, min_blocks_per_sm) \ + __launch_bounds__( \ + (C10_MAX_THREADS_PER_BLOCK((max_threads_per_block))), \ + (C10_MIN_BLOCKS_PER_SM((max_threads_per_block), (min_blocks_per_sm)))) +#else +#define C10_HOST_DEVICE +#define C10_HOST +#define C10_DEVICE +#endif + +#if defined(USE_ROCM) +#define C10_HIP_HOST_DEVICE __host__ __device__ +#else +#define C10_HIP_HOST_DEVICE +#endif + +// C10_WARP_SIZE is only allowed for device code. +// Host code dynamically-sized launch configs _must_ use at::cuda::warp_size(). +// Host or device statically-sized arrays _must_ use either +// C10_WARP_SIZE_UPPER_BOUND or C10_WARP_SIZE_LOWER_BOUND, as needed. +// +// HIP header used to define warpSize as a constexpr that was either 32 or 64 +// depending on the target device, and then always set it to 64 for host code. +// For a time, that allowed C10_WARP_SIZE to be defined like so: +// +// #ifdef USE_ROCM +// #define C10_WARP_SIZE warpSize +// #else +// #define C10_WARP_SIZE 32 +// #endif +// +// In ROCm 7, warpSize is no longer constexpr, matching CUDA behavior. +// We can now only use warpSize for C10_WARP_SIZE in device code and this is +// enforced by using __device__ in its definition. In host code where +// C10_WARP_SIZE was previously used as a compile-time constant, this will now +// cause a compile-time error. +// +// If an array was previously expected to be sized at compile-time using +// C10_WARP_SIZE, users must now use either C10_WARP_SIZE_UPPER_BOUND or +// C10_WARP_SIZE_LOWER_BOUND depending on the situation. +// +// If C10_WARP_SIZE was previously used to determine kernel launch sizes, users +// must now use at::cuda::warp_size() for the dynamic runtime query. +// +// Unfortunately, C10_WARP_SIZE has been public and available for both host and +// device since approximately 2019, so forcing it to be device-only would break +// existing code in the wild. +#if defined(USE_ROCM) +namespace at::cuda { +TORCH_CUDA_CPP_API int warp_size(); +} +#if defined(__HIPCC__) +static __host__ inline int C10_WARP_SIZE_INTERNAL() { + return at::cuda::warp_size(); +} +// NOTE: __device__ C10_WARP_SIZE_INTERNAL +// For __SPIRV__, we must use dynamic warpSize. When not targeting __SPIRV__, +// we can use constexpr. This matches prior behavior. We preserve this for +// backward compatibility instead of forcing old code to use dynamic warpSize +// and losing constexpr. However, compiling for --offload-arch=amdgcnspirv +// could expose where C10_WARP_SIZE was used incorrectly where the dynamic +// warpSize is not allowed. +#if defined(__SPIRV__) +static __device__ inline int C10_WARP_SIZE_INTERNAL() { + return warpSize; +} +#else // __SPIRV__ +static __device__ inline constexpr int C10_WARP_SIZE_INTERNAL() { +#if defined(__GFX9__) + return 64; +#else // __GFX9__ + return 32; +#endif // __GFX9__ +} +#endif // __SPIRV__ +#if defined(__SPIRV__) +#define C10_WARP_SIZE_LOWER_BOUND 32 +#define C10_WARP_SIZE_UPPER_BOUND 64 +#elif defined(__GFX9__) +#define C10_WARP_SIZE_LOWER_BOUND 64 +#define C10_WARP_SIZE_UPPER_BOUND 64 +#else +#define C10_WARP_SIZE_LOWER_BOUND 32 +#define C10_WARP_SIZE_UPPER_BOUND 32 +#endif +#else // !__HIPCC__ +static inline int C10_WARP_SIZE_INTERNAL() { + return at::cuda::warp_size(); +} +#define C10_WARP_SIZE_LOWER_BOUND 32 +#define C10_WARP_SIZE_UPPER_BOUND 64 +#endif // __HIPCC__ +#define C10_WARP_SIZE (C10_WARP_SIZE_INTERNAL()) +#else // !USE_ROCM +#define C10_WARP_SIZE 32 +#define C10_WARP_SIZE_LOWER_BOUND 32 +#define C10_WARP_SIZE_UPPER_BOUND 32 +#endif // USE_ROCM + +#if defined(_MSC_VER) && _MSC_VER <= 1900 +#define __func__ __FUNCTION__ +#endif + +// CUDA_KERNEL_ASSERT checks the assertion +// even when NDEBUG is defined. This is useful for important assertions in CUDA +// code that would otherwise be suppressed when building Release. +#if defined(__ANDROID__) || defined(__APPLE__) || defined(__FreeBSD__) +// Those platforms do not support assert() +#define CUDA_KERNEL_ASSERT(cond) +#define CUDA_KERNEL_ASSERT_MSG(cond, msg) +#define CUDA_KERNEL_ASSERT_PRINTF(cond, msg, ...) +#define SYCL_KERNEL_ASSERT(cond) +#elif defined(_MSC_VER) +#if defined(NDEBUG) +extern "C" { +C10_IMPORT +#if defined(__SYCL_DEVICE_ONLY__) +extern SYCL_EXTERNAL void _wassert( + const wchar_t* wexpr, + const wchar_t* wfile, + unsigned line); +#else +#if defined(__CUDA_ARCH__) +__host__ __device__ +#endif // __CUDA_ARCH__ + void + _wassert(wchar_t const* _Message, wchar_t const* _File, unsigned _Line); +#endif // __SYCL_DEVICE_ONLY__ +} +#endif // NDEBUG +#define CUDA_KERNEL_ASSERT(cond) \ + if (C10_UNLIKELY(!(cond))) { \ + (void)(_wassert( \ + _CRT_WIDE(#cond), \ + _CRT_WIDE(__FILE__), \ + static_cast(__LINE__)), \ + 0); \ + } +// TODO: This doesn't assert the message because I (chilli) couldn't figure out +// a nice way to convert a char* to a wchar_t* +#define CUDA_KERNEL_ASSERT_MSG(cond, msg) \ + if (C10_UNLIKELY(!(cond))) { \ + (void)(_wassert( \ + _CRT_WIDE(#cond), \ + _CRT_WIDE(__FILE__), \ + static_cast(__LINE__)), \ + 0); \ + } +#define CUDA_KERNEL_ASSERT_PRINTF(cond, msg, ...) \ + if (C10_UNLIKELY(!(cond))) { \ + (void)(printf( \ + "[CUDA_KERNEL_ASSERT] " __FILE__ ":" C10_STRINGIZE( \ + __LINE__) ": %s: block: [%d,%d,%d], thread: [%d,%d,%d]: " \ + "Assertion failed: `" #cond "`: " msg "\n", \ + __func__, \ + blockIdx.x, \ + blockIdx.y, \ + blockIdx.z, \ + threadIdx.x, \ + threadIdx.y, \ + threadIdx.z, \ + ##__VA_ARGS__)); \ + (void)(_wassert( \ + _CRT_WIDE(#cond), \ + _CRT_WIDE(__FILE__), \ + static_cast(__LINE__)), \ + 0); \ + } +#define SYCL_KERNEL_ASSERT(cond) \ + if (C10_UNLIKELY(!(cond))) { \ + (void)(_wassert( \ + _CRT_WIDE(#cond), \ + _CRT_WIDE(__FILE__), \ + static_cast(__LINE__)), \ + 0); \ + } +#else // __APPLE__, _MSC_VER +#if defined(NDEBUG) +extern "C" { +#if defined(__SYCL_DEVICE_ONLY__) +extern SYCL_EXTERNAL void __assert_fail( + const char* expr, + const char* file, + unsigned int line, + const char* func); +#elif (defined(__EMSCRIPTEN__)) +// As defined in assert.h in the Emscripten stdlib +_Noreturn void __assert_fail( + const char* expr, + const char* file, + int line, + const char* func); +#else // __SYCL_DEVICE_ONLY__ +#if (defined(__CUDA_ARCH__) && !(defined(__clang__) && defined(__CUDA__))) +// CUDA supports __assert_fail function which are common for both device +// and host side code. +__host__ __device__ +#endif + + // This forward declaration matching the declaration of __assert_fail + // exactly how it is in glibc in case parts of the program are compiled with + // different NDEBUG settings. Otherwise we might get 'ambiguous declaration' + // error. Note: On ROCm - this declaration serves for host side compilation. + void + __assert_fail( + const char* assertion, + const char* file, + unsigned int line, + const char* function) noexcept __attribute__((__noreturn__)); + +#endif // __SYCL_DEVICE_ONLY__ +} +#endif // NDEBUG +// ROCm disables kernel assert by default for performance considerations. +// Though ROCm supports __assert_fail, it uses kernel printf which has +// a non-negligible performance impact even if the assert condition is +// never triggered. We choose to use abort() instead which will still +// terminate the application but without a more useful error message. +#if !defined(C10_USE_ROCM_KERNEL_ASSERT) && defined(USE_ROCM) +#define CUDA_KERNEL_ASSERT(cond) \ + if C10_UNLIKELY (!(cond)) { \ + abort(); \ + } +#define CUDA_KERNEL_ASSERT_MSG(cond, msg) \ + if C10_UNLIKELY (!(cond)) { \ + abort(); \ + } +#define CUDA_KERNEL_ASSERT_PRINTF(cond, msg, ...) \ + if C10_UNLIKELY (!(cond)) { \ + abort(); \ + } +#define SYCL_KERNEL_ASSERT(cond) \ + if C10_UNLIKELY (!(cond)) { \ + abort(); \ + } +#else +#define CUDA_KERNEL_ASSERT(cond) \ + if (C10_UNLIKELY(!(cond))) { \ + __assert_fail( \ + #cond, __FILE__, static_cast(__LINE__), __func__); \ + } +#define CUDA_KERNEL_ASSERT_MSG(cond, msg) \ + if (C10_UNLIKELY(!(cond))) { \ + __assert_fail( \ + msg, __FILE__, static_cast(__LINE__), __func__); \ + } +#define CUDA_KERNEL_ASSERT_PRINTF(cond, msg, ...) \ + if (C10_UNLIKELY(!(cond))) { \ + printf( \ + "[CUDA_KERNEL_ASSERT] " __FILE__ ":" C10_STRINGIZE( \ + __LINE__) ": %s: block: [%d,%d,%d], thread: [%d,%d,%d]: " \ + "Assertion failed: `" #cond "`: " msg "\n", \ + __func__, \ + blockIdx.x, \ + blockIdx.y, \ + blockIdx.z, \ + threadIdx.x, \ + threadIdx.y, \ + threadIdx.z, \ + ##__VA_ARGS__); \ + __assert_fail( \ + #cond, __FILE__, static_cast(__LINE__), __func__); \ + } +#define SYCL_KERNEL_ASSERT(cond) \ + if (C10_UNLIKELY(!(cond))) { \ + __assert_fail( \ + #cond, __FILE__, static_cast(__LINE__), __func__); \ + } +#endif // C10_USE_ROCM_KERNEL_ASSERT && USE_ROCM +#endif // __APPLE__ + +// Compile-time switch to control how assertions are logged inside CUDA kernels. +// If C10_CUDA_VERBOSE_ASSERT is defined, CUDA_KERNEL_ASSERT_VERBOSE will +// take addition information passed to the macro and forward them to +// CUDA_KERNEL_ASSERT_PRINTF If C10_CUDA_VERBOSE_ASSERT is not defined, +// CUDA_KERNEL_ASSERT_VERBOSE will behave the same as CUDA_KERNEL_ASSERT. +#ifdef C10_ENABLE_VERBOSE_ASSERT +#define CUDA_KERNEL_ASSERT_VERBOSE(cond, ...) \ + CUDA_KERNEL_ASSERT_PRINTF(cond, __VA_ARGS__) +#else +#define CUDA_KERNEL_ASSERT_VERBOSE(cond, ...) CUDA_KERNEL_ASSERT(cond) +#endif + +#ifdef __APPLE__ +#include +#endif + +#if defined(__ANDROID__) +#define C10_ANDROID 1 +#define C10_MOBILE 1 +#elif ( \ + defined(__APPLE__) && \ + (TARGET_IPHONE_SIMULATOR || TARGET_OS_SIMULATOR || TARGET_OS_IPHONE)) +#define C10_IOS 1 +#define C10_MOBILE 1 +#endif // ANDROID / IOS + +#if defined(C10_MOBILE) && C10_MOBILE +#define C10_ALWAYS_INLINE_UNLESS_MOBILE inline +#else +#define C10_ALWAYS_INLINE_UNLESS_MOBILE C10_ALWAYS_INLINE +#endif + +#if !defined(FBCODE_CAFFE2) && !defined(C10_NODEPRECATED) +#define CONSTEXPR_EXCEPT_WIN_CUDA constexpr +#define C10_HOST_CONSTEXPR_EXCEPT_WIN_CUDA constexpr + +#define STATIC_CONSTEXPR_STR_INL_EXCEPT_WIN_CUDA(field, val) \ + static constexpr const char field[] = val; +#define STATIC_CONST_STR_OUT_OF_LINE_FOR_WIN_CUDA(cls, field, val) +#endif // !defined(FBCODE_CAFFE2) && !defined(C10_NODEPRECATED) + +#ifndef HAS_DEMANGLE +#if defined(__ANDROID__) || defined(_WIN32) || defined(__EMSCRIPTEN__) +#define HAS_DEMANGLE 0 +#elif defined(__APPLE__) && \ + (TARGET_IPHONE_SIMULATOR || TARGET_OS_SIMULATOR || TARGET_OS_IPHONE) +#define HAS_DEMANGLE 0 +#else +#define HAS_DEMANGLE 1 +#endif +#endif // HAS_DEMANGLE + +#define _C10_PRAGMA__(string) _Pragma(#string) +#define _C10_PRAGMA_(string) _C10_PRAGMA__(string) + +#ifdef __clang__ +#define C10_CLANG_DIAGNOSTIC_PUSH() _Pragma("clang diagnostic push") +#define C10_CLANG_DIAGNOSTIC_POP() _Pragma("clang diagnostic pop") +#define C10_CLANG_DIAGNOSTIC_IGNORE(flag) \ + _C10_PRAGMA_(clang diagnostic ignored flag) +#define C10_CLANG_HAS_WARNING(flag) __has_warning(flag) +#else +#define C10_CLANG_DIAGNOSTIC_PUSH() +#define C10_CLANG_DIAGNOSTIC_POP() +#define C10_CLANG_DIAGNOSTIC_IGNORE(flag) +#define C10_CLANG_HAS_WARNING(flag) 0 +#endif + +#ifdef __clang__ + +#define C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED(warning) \ + _C10_PRAGMA_(clang diagnostic push) \ + _C10_PRAGMA_(clang diagnostic ignored "-Wunknown-warning-option") \ + _C10_PRAGMA_(clang diagnostic ignored warning) + +#define C10_DIAGNOSTIC_POP() _C10_PRAGMA_(clang diagnostic pop) + +#elif __GNUC__ + +#define C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED(warning) \ + _C10_PRAGMA_(GCC diagnostic push) \ + _C10_PRAGMA_(GCC diagnostic ignored "-Wpragmas") \ + _C10_PRAGMA_(GCC diagnostic ignored warning) + +#define C10_DIAGNOSTIC_POP() _C10_PRAGMA_(GCC diagnostic pop) + +#else + +#define C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED(warning) +#define C10_DIAGNOSTIC_POP() + +#endif + +// This macro is used to find older C++ compilers +// that don't support move optimization for return values. + +#if (defined(__GNUC__) && __GNUC__ < 13 && __cplusplus < 202002L) || \ + (defined(__clang_major__) && __clang_major__ < 13) +#define C10_RETURN_MOVE_IF_OLD_COMPILER 1 +#else +#define C10_RETURN_MOVE_IF_OLD_COMPILER 0 +#endif + +// The HIDDEN_NAMESPACE_BEGIN and HIDDEN_NAMESPACE_END below +// are needed for maintaining robustness in our header APIs in +// torch/headeronly and torch/csrc/stable under the namespaces +// torch::headeronly and torch::stable respectively. We enforce +// hidden visibility for these APIs because we want to enable +// loading custom extensions compiled against different libtorch +// versions where these APIs may have changed. + +// Helper macros to handle 1-3 hidden namespace levels when not windows +#define _HIDDEN_NS_GET_MACRO(_1, _2, _3, NAME, ...) NAME +#define _HIDDEN_NS_1(n1) namespace n1 __attribute__((visibility("hidden"))) { +#define _HIDDEN_NS_2(n1, n2) \ + namespace n1 { \ + namespace n2 __attribute__((visibility("hidden"))) { +#define _HIDDEN_NS_3(n1, n2, n3) \ + namespace n1::n2 { \ + namespace n3 __attribute__((visibility("hidden"))) { + +// Helper macros to close namespaces when not windows +#define _HIDDEN_NS_END_1(n1) } +#define _HIDDEN_NS_END_N(n1, ...) \ + } \ + } + +// Helper macros to join strs with :: (for win, where symbols are hidden by +// default) +#define _EXPAND(...) __VA_ARGS__ +#define _JOIN_GET_MACRO(_1, _2, _3, NAME, ...) NAME +#define _JOIN_NS1(a) a +#define _JOIN_NS2(a, b) a::b +#define _JOIN_NS3(a, b, c) a::b::c + +#if !defined(HIDDEN_NAMESPACE_BEGIN) +#if defined(__GNUG__) && !defined(_WIN32) +#define HIDDEN_NAMESPACE_BEGIN(...) \ + _HIDDEN_NS_GET_MACRO( \ + __VA_ARGS__, _HIDDEN_NS_3, _HIDDEN_NS_2, _HIDDEN_NS_1)(__VA_ARGS__) +#else +#define HIDDEN_NAMESPACE_BEGIN(...) \ + namespace _EXPAND(_JOIN_GET_MACRO( \ + __VA_ARGS__, _JOIN_NS3, _JOIN_NS2, _JOIN_NS1)(__VA_ARGS__)) { +#endif +#endif + +#if !defined(HIDDEN_NAMESPACE_END) +#if defined(__GNUG__) && !defined(_WIN32) +#define HIDDEN_NAMESPACE_END(...) \ + _HIDDEN_NS_GET_MACRO( \ + __VA_ARGS__, _HIDDEN_NS_END_N, _HIDDEN_NS_END_N, _HIDDEN_NS_END_1)( \ + __VA_ARGS__) +#else +#define HIDDEN_NAMESPACE_END(...) } +#endif +#endif + +#endif // C10_MACROS_MACROS_H_ diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/macros/cmake_macros.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/macros/cmake_macros.h new file mode 100644 index 0000000000000000000000000000000000000000..aafbb2a9ae4381d694e9f12a395ed28c42d5386f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/macros/cmake_macros.h @@ -0,0 +1,14 @@ +#ifndef C10_MACROS_CMAKE_MACROS_H_ +#define C10_MACROS_CMAKE_MACROS_H_ + +// Automatically generated header file for the C10 library. +// Do not include this file directly. Instead, include torch/headeronly/macros/Macros.h. + +#define C10_BUILD_SHARED_LIBS +/* #undef C10_USE_GLOG */ +/* #undef C10_USE_GFLAGS */ +#define C10_USE_NUMA +/* #undef C10_USE_MSVC_STATIC_RUNTIME */ +/* #undef C10_USE_ROCM_KERNEL_ASSERT */ + +#endif // C10_MACROS_CMAKE_MACROS_H_ diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/BFloat16.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/BFloat16.h new file mode 100644 index 0000000000000000000000000000000000000000..9aa08c265bd2c9e67c34fab9838f5bcf010ab912 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/BFloat16.h @@ -0,0 +1,481 @@ +#pragma once + +// Defines the bloat16 type (brain floating-point). This representation uses +// 1 bit for the sign, 8 bits for the exponent and 7 bits for the mantissa. + +#include +#include + +#include +#include +#include +#include +#include + +#if defined(__CUDACC__) && (!defined(USE_ROCM) || (TORCH_HIP_VERSION >= 702)) +#include +#endif + +#if defined(CL_SYCL_LANGUAGE_VERSION) +#include // for SYCL 1.2.1 +#elif defined(SYCL_LANGUAGE_VERSION) +#include // for SYCL 2020 +#endif + +namespace c10 { + +struct alignas(2) BFloat16 { + uint16_t x; + + // HIP wants __host__ __device__ tag, CUDA does not +#if defined(USE_ROCM) && defined(__HIPCC__) + C10_HOST_DEVICE BFloat16() = default; +#else + BFloat16() = default; +#endif + + struct from_bits_t {}; + static constexpr C10_HOST_DEVICE from_bits_t from_bits() { + return from_bits_t(); + } + + constexpr C10_HOST_DEVICE BFloat16( + unsigned short bits, + from_bits_t /*unused*/) + : x(bits) {} + /* implicit */ inline C10_HOST_DEVICE BFloat16(float value); + inline C10_HOST_DEVICE operator float() const; + +#if defined(__CUDACC__) && (!defined(USE_ROCM) || (TORCH_HIP_VERSION >= 702)) + inline C10_HOST_DEVICE BFloat16(const __nv_bfloat16& value); + explicit inline C10_HOST_DEVICE operator __nv_bfloat16() const; +#endif + +#if defined(SYCL_EXT_ONEAPI_BFLOAT16_MATH_FUNCTIONS) + inline C10_HOST_DEVICE BFloat16(const sycl::ext::oneapi::bfloat16& value); + explicit inline C10_HOST_DEVICE operator sycl::ext::oneapi::bfloat16() const; +#endif +}; + +inline std::ostream& operator<<(std::ostream& out, const BFloat16& value) { + out << (float)value; + return out; +} + +namespace detail { +inline C10_HOST_DEVICE float f32_from_bits(uint16_t src) { + float res = 0; + uint32_t tmp = src; + tmp <<= 16; + +#if defined(USE_ROCM) && defined(__HIPCC__) + float* tempRes; + + // We should be using memcpy in order to respect the strict aliasing rule + // but it fails in the HIP environment. + tempRes = reinterpret_cast(&tmp); + res = *tempRes; +#else + std::memcpy(&res, &tmp, sizeof(tmp)); +#endif + + return res; +} + +inline C10_HOST_DEVICE uint16_t bits_from_f32(float src) { + uint32_t res = 0; + +#if defined(USE_ROCM) && defined(__HIPCC__) + // We should be using memcpy in order to respect the strict aliasing rule + // but it fails in the HIP environment. + uint32_t* tempRes = reinterpret_cast(&src); + res = *tempRes; +#else + std::memcpy(&res, &src, sizeof(res)); +#endif + + return res >> 16; +} + +inline C10_HOST_DEVICE uint16_t round_to_nearest_even(float src) { +#if defined(USE_ROCM) && defined(__HIPCC__) + if (src != src) { +#elif defined(_MSC_VER) + if (isnan(src)) { +#else + if (std::isnan(src)) { +#endif + return UINT16_C(0x7FC0); + } else { + const uint32_t U32 = c10::bit_cast(src); + uint32_t rounding_bias = ((U32 >> 16) & 1) + UINT32_C(0x7FFF); + return static_cast((U32 + rounding_bias) >> 16); + } +} + +} // namespace detail + +//-------- the following is copied from c10/util/BFloat16-inl.h ---------// +C10_CLANG_DIAGNOSTIC_PUSH() +#if C10_CLANG_HAS_WARNING("-Wimplicit-int-float-conversion") +C10_CLANG_DIAGNOSTIC_IGNORE("-Wimplicit-int-float-conversion") +#endif + +/// Constructors +inline C10_HOST_DEVICE BFloat16::BFloat16(float value) + : +#if defined(__CUDACC__) && \ + (!defined(USE_ROCM) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 800 || \ + defined(USE_ROCM) && (TORCH_HIP_VERSION >= 702)) + x(__bfloat16_as_ushort(__float2bfloat16(value))) +#elif defined(__SYCL_DEVICE_ONLY__) && \ + defined(SYCL_EXT_ONEAPI_BFLOAT16_MATH_FUNCTIONS) + x(c10::bit_cast(sycl::ext::oneapi::bfloat16(value))) +#else + // RNE by default + x(detail::round_to_nearest_even(value)) +#endif +{ +} + +/// Implicit conversions +inline C10_HOST_DEVICE BFloat16::operator float() const { +#if defined(__CUDACC__) && (!defined(USE_ROCM) || (TORCH_HIP_VERSION >= 702)) + return __bfloat162float(*reinterpret_cast(&x)); +#elif defined(__SYCL_DEVICE_ONLY__) && \ + defined(SYCL_EXT_ONEAPI_BFLOAT16_MATH_FUNCTIONS) + return float(*reinterpret_cast(&x)); +#else + return detail::f32_from_bits(x); +#endif +} + +#if defined(__CUDACC__) && (!defined(USE_ROCM) || (TORCH_HIP_VERSION >= 702)) +inline C10_HOST_DEVICE BFloat16::BFloat16(const __nv_bfloat16& value) { + x = *reinterpret_cast(&value); +} +inline C10_HOST_DEVICE BFloat16::operator __nv_bfloat16() const { + return *reinterpret_cast(&x); +} +#endif + +#if defined(SYCL_EXT_ONEAPI_BFLOAT16_MATH_FUNCTIONS) +inline C10_HOST_DEVICE BFloat16::BFloat16( + const sycl::ext::oneapi::bfloat16& value) { + x = *reinterpret_cast(&value); +} +inline C10_HOST_DEVICE BFloat16::operator sycl::ext::oneapi::bfloat16() const { + return *reinterpret_cast(&x); +} +#endif + +// CUDA intrinsics + +#if defined(__CUDACC__) || defined(__HIPCC__) +inline C10_DEVICE BFloat16 __ldg(const BFloat16* ptr) { +#if !defined(USE_ROCM) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 800 + return __ldg(reinterpret_cast(ptr)); +#else + return *ptr; +#endif +} +#endif + +/// Arithmetic + +inline C10_HOST_DEVICE BFloat16 +operator+(const BFloat16& a, const BFloat16& b) { + return static_cast(a) + static_cast(b); +} + +inline C10_HOST_DEVICE BFloat16 +operator-(const BFloat16& a, const BFloat16& b) { + return static_cast(a) - static_cast(b); +} + +inline C10_HOST_DEVICE BFloat16 +operator*(const BFloat16& a, const BFloat16& b) { + return static_cast(a) * static_cast(b); +} + +inline C10_HOST_DEVICE BFloat16 operator/(const BFloat16& a, const BFloat16& b) + __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / static_cast(b); +} + +inline C10_HOST_DEVICE BFloat16 operator-(const BFloat16& a) { + return -static_cast(a); +} + +inline C10_HOST_DEVICE BFloat16& operator+=(BFloat16& a, const BFloat16& b) { + a = a + b; + return a; +} + +inline C10_HOST_DEVICE BFloat16& operator-=(BFloat16& a, const BFloat16& b) { + a = a - b; + return a; +} + +inline C10_HOST_DEVICE BFloat16& operator*=(BFloat16& a, const BFloat16& b) { + a = a * b; + return a; +} + +inline C10_HOST_DEVICE BFloat16& operator/=(BFloat16& a, const BFloat16& b) { + a = a / b; + return a; +} + +inline C10_HOST_DEVICE BFloat16& operator|(BFloat16& a, const BFloat16& b) { + a.x = a.x | b.x; + return a; +} + +inline C10_HOST_DEVICE BFloat16& operator^(BFloat16& a, const BFloat16& b) { + a.x = a.x ^ b.x; + return a; +} + +inline C10_HOST_DEVICE BFloat16& operator&(BFloat16& a, const BFloat16& b) { + a.x = a.x & b.x; + return a; +} + +/// Arithmetic with floats + +inline C10_HOST_DEVICE float operator+(BFloat16 a, float b) { + return static_cast(a) + b; +} +inline C10_HOST_DEVICE float operator-(BFloat16 a, float b) { + return static_cast(a) - b; +} +inline C10_HOST_DEVICE float operator*(BFloat16 a, float b) { + return static_cast(a) * b; +} +inline C10_HOST_DEVICE float operator/(BFloat16 a, float b) { + return static_cast(a) / b; +} + +inline C10_HOST_DEVICE float operator+(float a, BFloat16 b) { + return a + static_cast(b); +} +inline C10_HOST_DEVICE float operator-(float a, BFloat16 b) { + return a - static_cast(b); +} +inline C10_HOST_DEVICE float operator*(float a, BFloat16 b) { + return a * static_cast(b); +} +inline C10_HOST_DEVICE float operator/(float a, BFloat16 b) { + return a / static_cast(b); +} + +inline C10_HOST_DEVICE float& operator+=(float& a, const BFloat16& b) { + return a += static_cast(b); +} +inline C10_HOST_DEVICE float& operator-=(float& a, const BFloat16& b) { + return a -= static_cast(b); +} +inline C10_HOST_DEVICE float& operator*=(float& a, const BFloat16& b) { + return a *= static_cast(b); +} +inline C10_HOST_DEVICE float& operator/=(float& a, const BFloat16& b) { + return a /= static_cast(b); +} + +/// Arithmetic with doubles + +inline C10_HOST_DEVICE double operator+(BFloat16 a, double b) { + return static_cast(a) + b; +} +inline C10_HOST_DEVICE double operator-(BFloat16 a, double b) { + return static_cast(a) - b; +} +inline C10_HOST_DEVICE double operator*(BFloat16 a, double b) { + return static_cast(a) * b; +} +inline C10_HOST_DEVICE double operator/(BFloat16 a, double b) { + return static_cast(a) / b; +} + +inline C10_HOST_DEVICE double operator+(double a, BFloat16 b) { + return a + static_cast(b); +} +inline C10_HOST_DEVICE double operator-(double a, BFloat16 b) { + return a - static_cast(b); +} +inline C10_HOST_DEVICE double operator*(double a, BFloat16 b) { + return a * static_cast(b); +} +inline C10_HOST_DEVICE double operator/(double a, BFloat16 b) { + return a / static_cast(b); +} + +/// Arithmetic with ints + +inline C10_HOST_DEVICE BFloat16 operator+(BFloat16 a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a + static_cast(b); +} +inline C10_HOST_DEVICE BFloat16 operator-(BFloat16 a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a - static_cast(b); +} +inline C10_HOST_DEVICE BFloat16 operator*(BFloat16 a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a * static_cast(b); +} +inline C10_HOST_DEVICE BFloat16 operator/(BFloat16 a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a / static_cast(b); +} + +inline C10_HOST_DEVICE BFloat16 operator+(int a, BFloat16 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) + b; +} +inline C10_HOST_DEVICE BFloat16 operator-(int a, BFloat16 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) - b; +} +inline C10_HOST_DEVICE BFloat16 operator*(int a, BFloat16 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) * b; +} +inline C10_HOST_DEVICE BFloat16 operator/(int a, BFloat16 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) / b; +} + +//// Arithmetic with int64_t + +inline C10_HOST_DEVICE BFloat16 operator+(BFloat16 a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a + static_cast(b); +} +inline C10_HOST_DEVICE BFloat16 operator-(BFloat16 a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a - static_cast(b); +} +inline C10_HOST_DEVICE BFloat16 operator*(BFloat16 a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a * static_cast(b); +} +inline C10_HOST_DEVICE BFloat16 operator/(BFloat16 a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a / static_cast(b); +} + +inline C10_HOST_DEVICE BFloat16 operator+(int64_t a, BFloat16 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) + b; +} +inline C10_HOST_DEVICE BFloat16 operator-(int64_t a, BFloat16 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) - b; +} +inline C10_HOST_DEVICE BFloat16 operator*(int64_t a, BFloat16 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) * b; +} +inline C10_HOST_DEVICE BFloat16 operator/(int64_t a, BFloat16 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) / b; +} + +// Overloading < and > operators, because std::max and std::min use them. + +inline C10_HOST_DEVICE bool operator>(BFloat16& lhs, BFloat16& rhs) { + return float(lhs) > float(rhs); +} + +inline C10_HOST_DEVICE bool operator<(BFloat16& lhs, BFloat16& rhs) { + return float(lhs) < float(rhs); +} + +C10_CLANG_DIAGNOSTIC_POP() +} // namespace c10 + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly) + +namespace detail { +using c10::detail::bits_from_f32; +using c10::detail::f32_from_bits; +using c10::detail::round_to_nearest_even; +} // namespace detail + +using c10::BFloat16; +using c10::operator+; +using c10::operator-; +using c10::operator*; +using c10::operator/; +using c10::operator+=; +using c10::operator-=; +using c10::operator*=; +using c10::operator/=; +using c10::operator<; +using c10::operator>; +using c10::operator<<; +HIDDEN_NAMESPACE_END(torch, headeronly) + +namespace std { + +template <> +class numeric_limits { + public: + static constexpr bool is_signed = true; + static constexpr bool is_specialized = true; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = true; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = true; + static constexpr auto has_denorm = numeric_limits::has_denorm; + static constexpr auto has_denorm_loss = + numeric_limits::has_denorm_loss; + static constexpr auto round_style = numeric_limits::round_style; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 8; + static constexpr int digits10 = 2; + static constexpr int max_digits10 = 4; + static constexpr int radix = 2; + static constexpr int min_exponent = -125; + static constexpr int min_exponent10 = -37; + static constexpr int max_exponent = 128; + static constexpr int max_exponent10 = 38; + static constexpr auto traps = numeric_limits::traps; + static constexpr auto tinyness_before = + numeric_limits::tinyness_before; + + static constexpr c10::BFloat16 min() { + return c10::BFloat16(0x0080, c10::BFloat16::from_bits()); + } + static constexpr c10::BFloat16 lowest() { + return c10::BFloat16(0xFF7F, c10::BFloat16::from_bits()); + } + static constexpr c10::BFloat16 max() { + return c10::BFloat16(0x7F7F, c10::BFloat16::from_bits()); + } + static constexpr c10::BFloat16 epsilon() { + return c10::BFloat16(0x3C00, c10::BFloat16::from_bits()); + } + static constexpr c10::BFloat16 round_error() { + return c10::BFloat16(0x3F00, c10::BFloat16::from_bits()); + } + static constexpr c10::BFloat16 infinity() { + return c10::BFloat16(0x7F80, c10::BFloat16::from_bits()); + } + static constexpr c10::BFloat16 quiet_NaN() { + return c10::BFloat16(0x7FC0, c10::BFloat16::from_bits()); + } + static constexpr c10::BFloat16 signaling_NaN() { + return c10::BFloat16(0x7F80, c10::BFloat16::from_bits()); + } + static constexpr c10::BFloat16 denorm_min() { + return c10::BFloat16(0x0001, c10::BFloat16::from_bits()); + } +}; + +} // namespace std diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Deprecated.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Deprecated.h new file mode 100644 index 0000000000000000000000000000000000000000..88440a0242eb4e9e87433278006863fd38c5450d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Deprecated.h @@ -0,0 +1,102 @@ +#pragma once + +/** + * This file provides portable macros for marking declarations + * as deprecated. You should generally use C10_DEPRECATED, + * except when marking 'using' declarations as deprecated, + * in which case you should use C10_DEFINE_DEPRECATED_USING + * (due to portability concerns). + */ + +// Sample usage: +// +// C10_DEPRECATED void bad_func(); +// struct C10_DEPRECATED BadStruct { +// ... +// }; + +// NB: __cplusplus doesn't work for MSVC, so for now MSVC always uses +// the "__declspec(deprecated)" implementation and not the C++14 +// "[[deprecated]]" attribute. We tried enabling "[[deprecated]]" for C++14 on +// MSVC, but ran into issues with some older MSVC versions. +#if (defined(__cplusplus) && __cplusplus >= 201402L) +#define C10_DEPRECATED [[deprecated]] +#define C10_DEPRECATED_MESSAGE(message) [[deprecated(message)]] +#elif defined(__GNUC__) +#define C10_DEPRECATED __attribute__((deprecated)) +// TODO Is there some way to implement this? +#define C10_DEPRECATED_MESSAGE(message) __attribute__((deprecated)) + +#elif defined(_MSC_VER) +#define C10_DEPRECATED __declspec(deprecated) +#define C10_DEPRECATED_MESSAGE(message) __declspec(deprecated(message)) +#else +#warning "You need to implement C10_DEPRECATED for this compiler" +#define C10_DEPRECATED +#endif + +// Sample usage: +// +// C10_DEFINE_DEPRECATED_USING(BadType, int) +// +// which is the portable version of +// +// using BadType [[deprecated]] = int; + +// technically [[deprecated]] syntax is from c++14 standard, but it works in +// many compilers. +#if defined(__has_cpp_attribute) +#if __has_cpp_attribute(deprecated) && !defined(__CUDACC__) +#define C10_DEFINE_DEPRECATED_USING(TypeName, TypeThingy) \ + using TypeName [[deprecated]] = TypeThingy; +#endif +#endif + +#if defined(_MSC_VER) +#if defined(__CUDACC__) +// neither [[deprecated]] nor __declspec(deprecated) work on nvcc on Windows; +// you get the error: +// +// error: attribute does not apply to any entity +// +// So we just turn the macro off in this case. +#if defined(C10_DEFINE_DEPRECATED_USING) +#undef C10_DEFINE_DEPRECATED_USING +#endif +#define C10_DEFINE_DEPRECATED_USING(TypeName, TypeThingy) \ + using TypeName = TypeThingy; +#else +// [[deprecated]] does work in windows without nvcc, though msc doesn't support +// `__has_cpp_attribute` when c++14 is supported, otherwise +// __declspec(deprecated) is used as the alternative. +#ifndef C10_DEFINE_DEPRECATED_USING +#if defined(_MSVC_LANG) && _MSVC_LANG >= 201402L +#define C10_DEFINE_DEPRECATED_USING(TypeName, TypeThingy) \ + using TypeName [[deprecated]] = TypeThingy; +#else +#define C10_DEFINE_DEPRECATED_USING(TypeName, TypeThingy) \ + using TypeName = __declspec(deprecated) TypeThingy; +#endif +#endif +#endif +#endif + +#if !defined(C10_DEFINE_DEPRECATED_USING) && defined(__GNUC__) +// nvcc has a bug where it doesn't understand __attribute__((deprecated)) +// declarations even when the host compiler supports it. We'll only use this gcc +// attribute when not cuda, and when using a GCC compiler that doesn't support +// the c++14 syntax we checked for above (available in __GNUC__ >= 5) +#if !defined(__CUDACC__) +#define C10_DEFINE_DEPRECATED_USING(TypeName, TypeThingy) \ + using TypeName __attribute__((deprecated)) = TypeThingy; +#else +// using cuda + gcc < 5, neither deprecated syntax is available so turning off. +#define C10_DEFINE_DEPRECATED_USING(TypeName, TypeThingy) \ + using TypeName = TypeThingy; +#endif +#endif + +#if !defined(C10_DEFINE_DEPRECATED_USING) +#warning "You need to implement C10_DEFINE_DEPRECATED_USING for this compiler" +#define C10_DEFINE_DEPRECATED_USING +#endif diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Exception.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Exception.h new file mode 100644 index 0000000000000000000000000000000000000000..0e067244a50e15db01d65ecfeb5908c29aecaeba --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Exception.h @@ -0,0 +1,83 @@ +#pragma once + +#include +#include + +#include +#include + +namespace c10 { +// On nvcc, C10_UNLIKELY thwarts missing return statement analysis. In cases +// where the unlikely expression may be a constant, use this macro to ensure +// return statement analysis keeps working (at the cost of not getting the +// likely/unlikely annotation on nvcc). +// https://github.com/pytorch/pytorch/issues/21418 +// +// Currently, this is only used in the error reporting macros below. If you +// want to use it more generally, move me to Macros.h +// +// TODO: Brian Vaughan observed that we might be able to get this to work on +// nvcc by writing some sort of C++ overload that distinguishes constexpr inputs +// from non-constexpr. Since there isn't any evidence that losing C10_UNLIKELY +// in nvcc is causing us perf problems, this is not yet implemented, but this +// might be an interesting piece of C++ code for an intrepid bootcamper to +// write. +#if defined(__CUDACC__) +#define C10_UNLIKELY_OR_CONST(e) e +#else +#define C10_UNLIKELY_OR_CONST(e) C10_UNLIKELY(e) +#endif + +} // namespace c10 + +// STD_TORCH_CHECK throws std::runtime_error instead of c10::Error which is +// useful when certain headers are used in a libtorch-independent way, +// e.g. when Vectorized is used in AOTInductor generated code, or +// for custom ops to have an ABI stable dependency on libtorch. +#ifdef STRIP_ERROR_MESSAGES +#define STD_TORCH_CHECK_MSG(cond, type, ...) \ + (#cond #type " CHECK FAILED at " C10_STRINGIZE(__FILE__)) +#else // so STRIP_ERROR_MESSAGES is not defined +HIDDEN_NAMESPACE_BEGIN(torch, headeronly, detail) +template +std::string stdTorchCheckMsgImpl(const char* /*msg*/, const Args&... args) { + // This is similar to the one in c10/util/Exception.h, but does + // not depend on the more complex c10::str() function. ostringstream + // supports fewer data types than c10::str(), but should be sufficient + // in the headeronly world. + std::ostringstream oss; + ((oss << args), ...); + return oss.str(); +} + +inline const char* stdTorchCheckMsgImpl(const char* msg) { + return msg; +} +// If there is just 1 user-provided C-string argument, use it. +inline const char* stdTorchCheckMsgImpl(const char* /*msg*/, const char* args) { + return args; +} +HIDDEN_NAMESPACE_END(torch, headeronly, detail) + +#define STD_TORCH_CHECK_MSG(cond, type, ...) \ + (torch::headeronly::detail::stdTorchCheckMsgImpl( \ + "Expected " #cond \ + " to be true, but got false. " \ + "(Could this error message be improved? If so, " \ + "please report an enhancement request to PyTorch.)", \ + ##__VA_ARGS__)) +#endif // STRIP_ERROR_MESSAGES + +#define STD_TORCH_CHECK(cond, ...) \ + if (C10_UNLIKELY_OR_CONST(!(cond))) { \ + throw std::runtime_error(STD_TORCH_CHECK_MSG( \ + cond, \ + "", \ + __func__, \ + ", ", \ + __FILE__, \ + ":", \ + __LINE__, \ + ", ", \ + ##__VA_ARGS__)); \ + } diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float4_e2m1fn_x2.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float4_e2m1fn_x2.h new file mode 100644 index 0000000000000000000000000000000000000000..00075914cdc346af4d212f089731c5fea6943873 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float4_e2m1fn_x2.h @@ -0,0 +1,47 @@ +#pragma once +#include + +#include + +/// Defines the Float4_e2m1fn_x2 type (4-bit floating-point, two elements packed +/// into one byte). This is the FP4 dtype from the OCP MX format spec +/// (https://www.opencompute.org/documents/ocp-microscaling-formats-mx-v1-0-spec-final-pdf, +/// Section 5.3.3) +/// +/// Given two high precision values val0 and val1, here is the +/// binary configuration of their packed representation, from MSB to LSB: +/// +/// original value | val1 : val0 +/// ======================================== +/// bit index (MSB==7, LSB==0) | 7654 : 3210 +/// sign/exponent/mantissa | seem : seem +/// + +namespace c10 { + +struct alignas(1) Float4_e2m1fn_x2 { + uint8_t val_; + Float4_e2m1fn_x2() = default; + C10_HOST_DEVICE explicit Float4_e2m1fn_x2(uint8_t val) : val_(val) {} +}; + +/// Comparison operators +inline C10_HOST_DEVICE bool operator==( + const Float4_e2m1fn_x2& a, + const Float4_e2m1fn_x2& b) { + return a.val_ == b.val_; +} + +inline C10_HOST_DEVICE bool operator!=( + const Float4_e2m1fn_x2& a, + const Float4_e2m1fn_x2& b) { + return a.val_ != b.val_; +} + +} // namespace c10 + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly) +using c10::Float4_e2m1fn_x2; +using c10::operator==; +using c10::operator!=; +HIDDEN_NAMESPACE_END(torch, headeronly) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_e4m3fn.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_e4m3fn.h new file mode 100644 index 0000000000000000000000000000000000000000..06d70e6b4982c908fd13b54a3530d11381453c72 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_e4m3fn.h @@ -0,0 +1,537 @@ +#pragma once + +/// Defines the Float8_e4m3fn type (8-bit floating-point) including conversions +/// to standard C types and basic arithmetic operations. Note that arithmetic +/// operations are implemented by converting to floating point and +/// performing the operation in float32. +/// Binary configuration: +/// s eeee mmm +/// 1 sign bit +/// 4 exponent bits +/// 3 mantissa bits +/// bias = 7 +/// +/// Implementation based on the paper https://arxiv.org/pdf/2209.05433.pdf +/// and inspired by Half implementation from pytorch/c10/util/Half.h + +#include +#include + +#if defined(__cplusplus) +#include +#include +#elif !defined(__OPENCL_VERSION__) +#include +#include +#endif + +#ifdef _MSC_VER +#include +#endif + +#include +#include + +namespace c10 { + +struct alignas(1) Float8_e4m3fn { + uint8_t x; + + struct from_bits_t {}; + C10_HOST_DEVICE static constexpr from_bits_t from_bits() { + return from_bits_t(); + } + + Float8_e4m3fn() = default; + + constexpr C10_HOST_DEVICE Float8_e4m3fn(uint8_t bits, from_bits_t /*unused*/) + : x(bits) {} + inline C10_HOST_DEVICE Float8_e4m3fn(float value); + inline C10_HOST_DEVICE operator float() const; + inline C10_HOST_DEVICE bool isnan() const; + inline C10_HOST_DEVICE bool isinf() const; +}; + +inline std::ostream& operator<<(std::ostream& out, const Float8_e4m3fn& value) { + out << (float)value; + return out; +} + +namespace detail { + +/* + * Convert a 8-bit floating-point number in fp8 E4M3FN format, in bit + * representation, to a 32-bit floating-point number in IEEE single-precision + * format, in bit representation. + * + * @note The implementation doesn't use any floating-point operations. + */ +inline C10_HOST_DEVICE float fp8e4m3fn_to_fp32_value(uint8_t input) { + /* + * Extend the fp8 E4M3FN number to 32 bits and shift to the + * upper part of the 32-bit word: + * +---+----+---+-----------------------------+ + * | S |EEEE|MMM|0000 0000 0000 0000 0000 0000| + * +---+----+---+-----------------------------+ + * Bits 31 27-30 24-26 0-23 + * + * S - sign bit, E - bits of the biased exponent, M - bits of the mantissa, 0 + * - zero bits. + */ + const uint32_t w = (uint32_t)input << 24; + /* + * Extract the sign of the input number into the high bit of the 32-bit word: + * + * +---+----------------------------------+ + * | S |0000000 00000000 00000000 00000000| + * +---+----------------------------------+ + * Bits 31 0-31 + */ + const uint32_t sign = w & UINT32_C(0x80000000); + /* + * Extract mantissa and biased exponent of the input number into the bits 0-30 + * of the 32-bit word: + * + * +---+----+---+-----------------------------+ + * | S |EEEE|MMM|0000 0000 0000 0000 0000 0000| + * +---+----+---+-----------------------------+ + * Bits 31 27-30 24-26 0-23 + */ + const uint32_t nonsign = w & UINT32_C(0x7FFFFFFF); + /* + * Renorm shift is the number of bits to shift mantissa left to make the + * half-precision number normalized. If the initial number is normalized, some + * of its high 5 bits (sign == 0 and 4-bit exponent) equals one. In this case + * renorm_shift == 0. If the number is denormalize, renorm_shift > 0. Note + * that if we shift denormalized nonsign by renorm_shift, the unit bit of + * mantissa will shift into exponent, turning the biased exponent into 1, and + * making mantissa normalized (i.e. without leading 1). + */ +#if defined(__CUDA_ARCH__) || defined(__HIP_DEVICE_COMPILE__) + uint32_t renorm_shift = __clz(nonsign); +#elif defined(__SYCL_DEVICE_ONLY__) + // Note: zero is not a supported input into `__builtin_clz` + uint32_t renorm_shift = + nonsign != 0 ? __builtin_clz(nonsign) : sizeof(uint32_t) * CHAR_BIT; +#elif defined(_MSC_VER) && !defined(__clang__) + unsigned long nonsign_bsr; + _BitScanReverse(&nonsign_bsr, (unsigned long)nonsign); + uint32_t renorm_shift = (uint32_t)nonsign_bsr ^ 31; +#else + // Note: zero is not a supported input into `__builtin_clz` + uint32_t renorm_shift = + nonsign != 0 ? __builtin_clz(nonsign) : sizeof(uint32_t) * CHAR_BIT; +#endif + renorm_shift = renorm_shift > 4 ? renorm_shift - 4 : 0; + /* + * Iff fp8e4m3fn number has all exponent and mantissa bits set to 1, + * the addition overflows it into bit 31, and the subsequent shift turns the + * high 9 bits into 1. Thus inf_nan_mask == 0x7F800000 if the fp8e4m3fn number + * is Nan, 0x00000000 otherwise + */ + const int32_t inf_nan_mask = + ((int32_t)(nonsign + 0x01000000) >> 8) & INT32_C(0x7F800000); + /* + * Iff nonsign is 0, it overflows into 0xFFFFFFFF, turning bit 31 + * into 1. Otherwise, bit 31 remains 0. The signed shift right by 31 + * broadcasts bit 31 into all bits of the zero_mask. Thus zero_mask == + * 0xFFFFFFFF if the half-precision number was zero (+0.0h or -0.0h) + * 0x00000000 otherwise + */ + const int32_t zero_mask = (int32_t)(nonsign - 1) >> 31; + /* + * 1. Shift nonsign left by renorm_shift to normalize it (if the input + * was denormal) + * 2. Shift nonsign right by 4 so the exponent (4 bits originally) + * becomes an 8-bit field and 3-bit mantissa shifts into the 3 high + * bits of the 23-bit mantissa of IEEE single-precision number. + * 3. Add 0x78 to the exponent (starting at bit 23) to compensate the + * different in exponent bias (0x7F for single-precision number less 0x07 + * for fp8e4m3fn number). + * 4. Subtract renorm_shift from the exponent (starting at bit 23) to + * account for renormalization. As renorm_shift is less than 0x78, this + * can be combined with step 3. + * 5. Binary OR with inf_nan_mask to turn the exponent into 0xFF if the + * input was NaN or infinity. + * 6. Binary ANDNOT with zero_mask to turn the mantissa and exponent + * into zero if the input was zero. + * 7. Combine with the sign of the input number. + */ + uint32_t result = sign | + ((((nonsign << renorm_shift >> 4) + ((0x78 - renorm_shift) << 23)) | + inf_nan_mask) & + ~zero_mask); + return fp32_from_bits(result); +} + +/* + * Convert a 32-bit floating-point number in IEEE single-precision format to a + * 8-bit floating-point number in fp8 E4M3FN format, in bit representation. + */ +inline C10_HOST_DEVICE uint8_t fp8e4m3fn_from_fp32_value(float f) { + /* + * Binary representation of 480.0f, which is the first value + * not representable in fp8e4m3fn range: + * 0 1111 111 - fp8e4m3fn + * 0 10000111 11100000000000000000000 - fp32 + */ + constexpr uint32_t fp8_max = UINT32_C(1087) << 20; + + /* + * A mask for converting fp32 numbers lower than fp8e4m3fn normal range + * into denorm representation + * magic number: ((127 - 7) + (23 - 3) + 1) + */ + constexpr uint32_t denorm_mask = UINT32_C(141) << 23; + + uint32_t f_bits = fp32_to_bits(f); + + uint8_t result = 0u; + + /* + * Extract the sign of the input number into the high bit of the 32-bit word: + * + * +---+----------------------------------+ + * | S |0000000 00000000 00000000 00000000| + * +---+----------------------------------+ + * Bits 31 0-31 + */ + const uint32_t sign = f_bits & UINT32_C(0x80000000); + + /* + * Set sign bit to 0 + */ + f_bits ^= sign; + + if (f_bits >= fp8_max) { + // NaN - all exponent and mantissa bits set to 1 + result = 0x7f; + } else { + if (f_bits < (UINT32_C(121) << 23)) { + // Input number is smaller than 2^(-6), which is the smallest + // fp8e4m3fn normal number + f_bits = + fp32_to_bits(fp32_from_bits(f_bits) + fp32_from_bits(denorm_mask)); + result = static_cast(f_bits - denorm_mask); + } else { + // resulting mantissa is odd + uint8_t mant_odd = (f_bits >> 20) & 1; + + // update exponent, rounding bias part 1 + f_bits += ((uint32_t)(7 - 127) << 23) + 0x7FFFF; + + // rounding bias part 2 + f_bits += mant_odd; + + // take the bits! + result = static_cast(f_bits >> 20); + } + } + + result |= static_cast(sign >> 24); + return result; +} + +} // namespace detail + +// -------- below is copied from c10/util/Float8_e4m3fn-inl.h --------// +C10_CLANG_DIAGNOSTIC_PUSH() +#if C10_CLANG_HAS_WARNING("-Wimplicit-int-float-conversion") +C10_CLANG_DIAGNOSTIC_IGNORE("-Wimplicit-int-float-conversion") +#endif + +/// Constructors + +inline C10_HOST_DEVICE Float8_e4m3fn::Float8_e4m3fn(float value) + : x(detail::fp8e4m3fn_from_fp32_value(value)) {} + +/// Implicit conversions + +inline C10_HOST_DEVICE Float8_e4m3fn::operator float() const { + return detail::fp8e4m3fn_to_fp32_value(x); +} + +/// Special values helper + +inline C10_HOST_DEVICE bool Float8_e4m3fn::isnan() const { + return (x & 0b01111111) == 0b01111111; +} + +inline C10_HOST_DEVICE bool Float8_e4m3fn::isinf() const { + // Note: fp8e4m3fn does not have infinity, so this always returns false. + return false; +} + +/// Arithmetic + +inline C10_HOST_DEVICE Float8_e4m3fn +operator+(const Float8_e4m3fn& a, const Float8_e4m3fn& b) { + return static_cast(a) + static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e4m3fn +operator-(const Float8_e4m3fn& a, const Float8_e4m3fn& b) { + return static_cast(a) - static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e4m3fn +operator*(const Float8_e4m3fn& a, const Float8_e4m3fn& b) { + return static_cast(a) * static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e4m3fn operator/( + const Float8_e4m3fn& a, + const Float8_e4m3fn& b) __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e4m3fn operator-(const Float8_e4m3fn& a) { + return -static_cast(a); +} + +inline C10_HOST_DEVICE Float8_e4m3fn& operator+=( + Float8_e4m3fn& a, + const Float8_e4m3fn& b) { + a = a + b; + return a; +} + +inline C10_HOST_DEVICE Float8_e4m3fn& operator-=( + Float8_e4m3fn& a, + const Float8_e4m3fn& b) { + a = a - b; + return a; +} + +inline C10_HOST_DEVICE Float8_e4m3fn& operator*=( + Float8_e4m3fn& a, + const Float8_e4m3fn& b) { + a = a * b; + return a; +} + +inline C10_HOST_DEVICE Float8_e4m3fn& operator/=( + Float8_e4m3fn& a, + const Float8_e4m3fn& b) { + a = a / b; + return a; +} + +/// Arithmetic with floats + +inline C10_HOST_DEVICE float operator+(Float8_e4m3fn a, float b) { + return static_cast(a) + b; +} +inline C10_HOST_DEVICE float operator-(Float8_e4m3fn a, float b) { + return static_cast(a) - b; +} +inline C10_HOST_DEVICE float operator*(Float8_e4m3fn a, float b) { + return static_cast(a) * b; +} +inline C10_HOST_DEVICE float operator/(Float8_e4m3fn a, float b) + __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / b; +} + +inline C10_HOST_DEVICE float operator+(float a, Float8_e4m3fn b) { + return a + static_cast(b); +} +inline C10_HOST_DEVICE float operator-(float a, Float8_e4m3fn b) { + return a - static_cast(b); +} +inline C10_HOST_DEVICE float operator*(float a, Float8_e4m3fn b) { + return a * static_cast(b); +} +inline C10_HOST_DEVICE float operator/(float a, Float8_e4m3fn b) + __ubsan_ignore_float_divide_by_zero__ { + return a / static_cast(b); +} + +inline C10_HOST_DEVICE float& operator+=(float& a, const Float8_e4m3fn& b) { + return a += static_cast(b); +} +inline C10_HOST_DEVICE float& operator-=(float& a, const Float8_e4m3fn& b) { + return a -= static_cast(b); +} +inline C10_HOST_DEVICE float& operator*=(float& a, const Float8_e4m3fn& b) { + return a *= static_cast(b); +} +inline C10_HOST_DEVICE float& operator/=(float& a, const Float8_e4m3fn& b) { + return a /= static_cast(b); +} + +/// Arithmetic with doubles + +inline C10_HOST_DEVICE double operator+(Float8_e4m3fn a, double b) { + return static_cast(a) + b; +} +inline C10_HOST_DEVICE double operator-(Float8_e4m3fn a, double b) { + return static_cast(a) - b; +} +inline C10_HOST_DEVICE double operator*(Float8_e4m3fn a, double b) { + return static_cast(a) * b; +} +inline C10_HOST_DEVICE double operator/(Float8_e4m3fn a, double b) + __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / b; +} + +inline C10_HOST_DEVICE double operator+(double a, Float8_e4m3fn b) { + return a + static_cast(b); +} +inline C10_HOST_DEVICE double operator-(double a, Float8_e4m3fn b) { + return a - static_cast(b); +} +inline C10_HOST_DEVICE double operator*(double a, Float8_e4m3fn b) { + return a * static_cast(b); +} +inline C10_HOST_DEVICE double operator/(double a, Float8_e4m3fn b) + __ubsan_ignore_float_divide_by_zero__ { + return a / static_cast(b); +} + +/// Arithmetic with ints + +inline C10_HOST_DEVICE Float8_e4m3fn operator+(Float8_e4m3fn a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a + static_cast(b); +} +inline C10_HOST_DEVICE Float8_e4m3fn operator-(Float8_e4m3fn a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a - static_cast(b); +} +inline C10_HOST_DEVICE Float8_e4m3fn operator*(Float8_e4m3fn a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a * static_cast(b); +} +inline C10_HOST_DEVICE Float8_e4m3fn operator/(Float8_e4m3fn a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a / static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e4m3fn operator+(int a, Float8_e4m3fn b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) + b; +} +inline C10_HOST_DEVICE Float8_e4m3fn operator-(int a, Float8_e4m3fn b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) - b; +} +inline C10_HOST_DEVICE Float8_e4m3fn operator*(int a, Float8_e4m3fn b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) * b; +} +inline C10_HOST_DEVICE Float8_e4m3fn operator/(int a, Float8_e4m3fn b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) / b; +} + +//// Arithmetic with int64_t + +inline C10_HOST_DEVICE Float8_e4m3fn operator+(Float8_e4m3fn a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a + static_cast(b); +} +inline C10_HOST_DEVICE Float8_e4m3fn operator-(Float8_e4m3fn a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a - static_cast(b); +} +inline C10_HOST_DEVICE Float8_e4m3fn operator*(Float8_e4m3fn a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a * static_cast(b); +} +inline C10_HOST_DEVICE Float8_e4m3fn operator/(Float8_e4m3fn a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a / static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e4m3fn operator+(int64_t a, Float8_e4m3fn b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) + b; +} +inline C10_HOST_DEVICE Float8_e4m3fn operator-(int64_t a, Float8_e4m3fn b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) - b; +} +inline C10_HOST_DEVICE Float8_e4m3fn operator*(int64_t a, Float8_e4m3fn b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) * b; +} +inline C10_HOST_DEVICE Float8_e4m3fn operator/(int64_t a, Float8_e4m3fn b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) / b; +} + +/// NOTE: we do not define comparisons directly and instead rely on the implicit +/// conversion from c10::Float8_e4m3fn to float. + +C10_CLANG_DIAGNOSTIC_POP() + +} // namespace c10 + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly) +using c10::Float8_e4m3fn; +using c10::operator<<; +using c10::operator+; +using c10::operator-; +using c10::operator*; +using c10::operator/; +using c10::operator+=; +using c10::operator-=; +using c10::operator*=; +using c10::operator/=; +HIDDEN_NAMESPACE_END(torch, headeronly) + +namespace std { + +template <> +class numeric_limits { + public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = false; + static constexpr auto has_denorm = true; + static constexpr auto has_denorm_loss = true; + static constexpr auto round_style = numeric_limits::round_style; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 4; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 3; + static constexpr int radix = 2; + static constexpr int min_exponent = -5; + static constexpr int min_exponent10 = -1; + static constexpr int max_exponent = 8; + static constexpr int max_exponent10 = 2; + static constexpr auto traps = numeric_limits::traps; + static constexpr auto tinyness_before = false; + + static constexpr c10::Float8_e4m3fn min() { + return c10::Float8_e4m3fn(0x08, c10::Float8_e4m3fn::from_bits()); + } + static constexpr c10::Float8_e4m3fn lowest() { + return c10::Float8_e4m3fn(0xFE, c10::Float8_e4m3fn::from_bits()); + } + static constexpr c10::Float8_e4m3fn max() { + return c10::Float8_e4m3fn(0x7E, c10::Float8_e4m3fn::from_bits()); + } + static constexpr c10::Float8_e4m3fn epsilon() { + return c10::Float8_e4m3fn(0x20, c10::Float8_e4m3fn::from_bits()); + } + static constexpr c10::Float8_e4m3fn round_error() { + return c10::Float8_e4m3fn(0x30, c10::Float8_e4m3fn::from_bits()); + } + static constexpr c10::Float8_e4m3fn quiet_NaN() { + return c10::Float8_e4m3fn(0x7F, c10::Float8_e4m3fn::from_bits()); + } + static constexpr c10::Float8_e4m3fn denorm_min() { + return c10::Float8_e4m3fn(0x01, c10::Float8_e4m3fn::from_bits()); + } +}; + +} // namespace std diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_e4m3fnuz.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_e4m3fnuz.h new file mode 100644 index 0000000000000000000000000000000000000000..4c11b3be05593fe3f9a2d8787750f546bd875bff --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_e4m3fnuz.h @@ -0,0 +1,450 @@ +#pragma once + +/// Defines the Float8_e4m3fnuz type (8-bit floating-point) including +/// conversions to standard C types and basic arithmetic operations. Note that +/// arithmetic operations are implemented by converting to floating point and +/// performing the operation in float32. +/// Binary configuration remains the same as Float8_e4m3fn: +/// s eeee mmm +/// 1 sign bit +/// 4 exponent bits +/// 3 mantissa bits +/// The key differences versus Float8_e4m3fn are: +/// bias = 8 +/// no infinities or negative zero +/// NaN only when sign bit is 1, rest all 0s +/// +/// Implementation based on the paper https://arxiv.org/pdf/2206.02915.pdf and +/// the existing Float8_e4m3fn implementation. + +#include +#include +#include + +#include + +#if defined(__cplusplus) +#include +#elif !defined(__OPENCL_VERSION__) +#include +#include +#endif + +#include +#include + +namespace c10 { + +struct alignas(1) Float8_e4m3fnuz { + uint8_t x; + + struct from_bits_t {}; + C10_HOST_DEVICE static constexpr from_bits_t from_bits() { + return from_bits_t(); + } + + Float8_e4m3fnuz() = default; + + constexpr C10_HOST_DEVICE Float8_e4m3fnuz( + uint8_t bits, + from_bits_t /*unused*/) + : x(bits) {} + inline C10_HOST_DEVICE Float8_e4m3fnuz(float value); + inline C10_HOST_DEVICE operator float() const; + inline C10_HOST_DEVICE bool isnan() const; + inline C10_HOST_DEVICE bool isinf() const; +}; + +inline std::ostream& operator<<( + std::ostream& out, + const Float8_e4m3fnuz& value) { + out << (float)value; + return out; +} + +namespace detail { + +/* + * Convert a 32-bit floating-point number in IEEE single-precision format to a + * 8-bit floating-point number in fp8 E4M3FNUZ format, in bit representation. + */ +inline C10_HOST_DEVICE uint8_t fp8e4m3fnuz_from_fp32_value(float f) { + /* + * Binary representation of 256.0f, which is the first value not representable + * (i.e. the first value which would overflow in to the sign bit, resulting in + * a NaN) in fp8e4m3fnuz range: + * 1 0000 000 - fp8e4m3fnuz + * 0 10000111 00000000000000000000000 - fp32 + */ + constexpr uint32_t fnuz_max = UINT32_C(0x87) << 23; + + /* + * A mask for converting fp32 numbers lower than fp8e4m3fnuz normal range + * into denorm representation + * magic number: ((127 - 8) + (23 - 3) + 1) + */ + constexpr uint32_t denorm_mask = UINT32_C(0x8C) << 23; + + uint32_t f_bits = fp32_to_bits(f); + + uint32_t result = 0u; + + /* + * Extract the sign of the input number into the high bit of the 32-bit word: + * + * +---+----------------------------------+ + * | S |0000000 00000000 00000000 00000000| + * +---+----------------------------------+ + * Bits 31 0-31 + */ + const uint32_t sign = f_bits & UINT32_C(0x80000000); + + /* + * Set sign bit to 0 + */ + f_bits ^= sign; + + if (f_bits >= fnuz_max) { + // NaN -- sign bit set to 1, rest 0s. + return 0x80; + } + + if (f_bits < (UINT32_C(0x78) << 23) /* 2^-7 in float32 */) { + // Input exponent is less than -7, the smallest e4m3fnuz exponent, so the + // number will become subnormal. + f_bits = fp32_to_bits(fp32_from_bits(f_bits) + fp32_from_bits(denorm_mask)); + result = static_cast(f_bits - denorm_mask); + if (result == 0) { + // fnuz types don't have negative zero. + return 0; + } + } else { + // resulting mantissa is odd + uint8_t mant_odd = (f_bits >> 20) & 1; + + // update exponent, rounding bias part 1 + f_bits += ((uint32_t)(8 - 127) << 23) + 0x7FFFF; + + // rounding bias part 2 + f_bits += mant_odd; + + // take the bits! + result = static_cast(f_bits >> 20); + } + + result |= sign >> 24; + return result; +} + +} // namespace detail + +//------ below is copied from c10/util/Float8_e4m3fnuz-inl.h ------// +C10_CLANG_DIAGNOSTIC_PUSH() +#if C10_CLANG_HAS_WARNING("-Wimplicit-int-float-conversion") +C10_CLANG_DIAGNOSTIC_IGNORE("-Wimplicit-int-float-conversion") +#endif + +/// Constructors + +inline C10_HOST_DEVICE Float8_e4m3fnuz::Float8_e4m3fnuz(float value) + : x(detail::fp8e4m3fnuz_from_fp32_value(value)) {} + +/// Implicit conversions + +inline C10_HOST_DEVICE Float8_e4m3fnuz::operator float() const { + return torch::headeronly::detail::fp8_fnuz_to_fp32_value<4, 3>(x); +} + +/// Special values helper + +inline C10_HOST_DEVICE bool Float8_e4m3fnuz::isnan() const { + return x == 0b10000000; +} + +inline C10_HOST_DEVICE bool Float8_e4m3fnuz::isinf() const { + // Note: fp8e4m3fnuz does not have infinity, so this always returns false. + return false; +} + +/// Arithmetic + +inline C10_HOST_DEVICE Float8_e4m3fnuz +operator+(const Float8_e4m3fnuz& a, const Float8_e4m3fnuz& b) { + return static_cast(a) + static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e4m3fnuz +operator-(const Float8_e4m3fnuz& a, const Float8_e4m3fnuz& b) { + return static_cast(a) - static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e4m3fnuz +operator*(const Float8_e4m3fnuz& a, const Float8_e4m3fnuz& b) { + return static_cast(a) * static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e4m3fnuz operator/( + const Float8_e4m3fnuz& a, + const Float8_e4m3fnuz& b) __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e4m3fnuz operator-(const Float8_e4m3fnuz& a) { + return -static_cast(a); +} + +inline C10_HOST_DEVICE Float8_e4m3fnuz& operator+=( + Float8_e4m3fnuz& a, + const Float8_e4m3fnuz& b) { + a = a + b; + return a; +} + +inline C10_HOST_DEVICE Float8_e4m3fnuz& operator-=( + Float8_e4m3fnuz& a, + const Float8_e4m3fnuz& b) { + a = a - b; + return a; +} + +inline C10_HOST_DEVICE Float8_e4m3fnuz& operator*=( + Float8_e4m3fnuz& a, + const Float8_e4m3fnuz& b) { + a = a * b; + return a; +} + +inline C10_HOST_DEVICE Float8_e4m3fnuz& operator/=( + Float8_e4m3fnuz& a, + const Float8_e4m3fnuz& b) { + a = a / b; + return a; +} + +/// Arithmetic with floats + +inline C10_HOST_DEVICE float operator+(Float8_e4m3fnuz a, float b) { + return static_cast(a) + b; +} +inline C10_HOST_DEVICE float operator-(Float8_e4m3fnuz a, float b) { + return static_cast(a) - b; +} +inline C10_HOST_DEVICE float operator*(Float8_e4m3fnuz a, float b) { + return static_cast(a) * b; +} +inline C10_HOST_DEVICE float operator/(Float8_e4m3fnuz a, float b) + __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / b; +} + +inline C10_HOST_DEVICE float operator+(float a, Float8_e4m3fnuz b) { + return a + static_cast(b); +} +inline C10_HOST_DEVICE float operator-(float a, Float8_e4m3fnuz b) { + return a - static_cast(b); +} +inline C10_HOST_DEVICE float operator*(float a, Float8_e4m3fnuz b) { + return a * static_cast(b); +} +inline C10_HOST_DEVICE float operator/(float a, Float8_e4m3fnuz b) + __ubsan_ignore_float_divide_by_zero__ { + return a / static_cast(b); +} + +inline C10_HOST_DEVICE float& operator+=(float& a, const Float8_e4m3fnuz& b) { + return a += static_cast(b); +} +inline C10_HOST_DEVICE float& operator-=(float& a, const Float8_e4m3fnuz& b) { + return a -= static_cast(b); +} +inline C10_HOST_DEVICE float& operator*=(float& a, const Float8_e4m3fnuz& b) { + return a *= static_cast(b); +} +inline C10_HOST_DEVICE float& operator/=(float& a, const Float8_e4m3fnuz& b) { + return a /= static_cast(b); +} + +/// Arithmetic with doubles + +inline C10_HOST_DEVICE double operator+(Float8_e4m3fnuz a, double b) { + return static_cast(a) + b; +} +inline C10_HOST_DEVICE double operator-(Float8_e4m3fnuz a, double b) { + return static_cast(a) - b; +} +inline C10_HOST_DEVICE double operator*(Float8_e4m3fnuz a, double b) { + return static_cast(a) * b; +} +inline C10_HOST_DEVICE double operator/(Float8_e4m3fnuz a, double b) + __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / b; +} + +inline C10_HOST_DEVICE double operator+(double a, Float8_e4m3fnuz b) { + return a + static_cast(b); +} +inline C10_HOST_DEVICE double operator-(double a, Float8_e4m3fnuz b) { + return a - static_cast(b); +} +inline C10_HOST_DEVICE double operator*(double a, Float8_e4m3fnuz b) { + return a * static_cast(b); +} +inline C10_HOST_DEVICE double operator/(double a, Float8_e4m3fnuz b) + __ubsan_ignore_float_divide_by_zero__ { + return a / static_cast(b); +} + +/// Arithmetic with ints + +inline C10_HOST_DEVICE Float8_e4m3fnuz operator+(Float8_e4m3fnuz a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a + static_cast(b); +} +inline C10_HOST_DEVICE Float8_e4m3fnuz operator-(Float8_e4m3fnuz a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a - static_cast(b); +} +inline C10_HOST_DEVICE Float8_e4m3fnuz operator*(Float8_e4m3fnuz a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a * static_cast(b); +} +inline C10_HOST_DEVICE Float8_e4m3fnuz operator/(Float8_e4m3fnuz a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a / static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e4m3fnuz operator+(int a, Float8_e4m3fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) + b; +} +inline C10_HOST_DEVICE Float8_e4m3fnuz operator-(int a, Float8_e4m3fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) - b; +} +inline C10_HOST_DEVICE Float8_e4m3fnuz operator*(int a, Float8_e4m3fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) * b; +} +inline C10_HOST_DEVICE Float8_e4m3fnuz operator/(int a, Float8_e4m3fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) / b; +} + +//// Arithmetic with int64_t + +inline C10_HOST_DEVICE Float8_e4m3fnuz operator+(Float8_e4m3fnuz a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a + static_cast(b); +} +inline C10_HOST_DEVICE Float8_e4m3fnuz operator-(Float8_e4m3fnuz a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a - static_cast(b); +} +inline C10_HOST_DEVICE Float8_e4m3fnuz operator*(Float8_e4m3fnuz a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a * static_cast(b); +} +inline C10_HOST_DEVICE Float8_e4m3fnuz operator/(Float8_e4m3fnuz a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a / static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e4m3fnuz operator+(int64_t a, Float8_e4m3fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) + b; +} +inline C10_HOST_DEVICE Float8_e4m3fnuz operator-(int64_t a, Float8_e4m3fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) - b; +} +inline C10_HOST_DEVICE Float8_e4m3fnuz operator*(int64_t a, Float8_e4m3fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) * b; +} +inline C10_HOST_DEVICE Float8_e4m3fnuz operator/(int64_t a, Float8_e4m3fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) / b; +} + +/// NOTE: we do not define comparisons directly and instead rely on the implicit +/// conversion from c10::Float8_e4m3fnuz to float. + +C10_CLANG_DIAGNOSTIC_POP() + +} // namespace c10 + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly) +using c10::Float8_e4m3fnuz; +using c10::operator+; +using c10::operator-; +using c10::operator*; +using c10::operator/; +using c10::operator+=; +using c10::operator-=; +using c10::operator*=; +using c10::operator/=; +using c10::operator<<; + +namespace detail { +using c10::detail::fp8e4m3fnuz_from_fp32_value; +} // namespace detail + +HIDDEN_NAMESPACE_END(torch, headeronly) + +namespace std { + +template <> +class numeric_limits { + public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = false; + static constexpr auto has_denorm = true; + static constexpr auto has_denorm_loss = true; + static constexpr auto round_style = numeric_limits::round_style; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 4; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 3; + static constexpr int radix = 2; + static constexpr int min_exponent = -6; + static constexpr int min_exponent10 = -1; + static constexpr int max_exponent = 8; + static constexpr int max_exponent10 = 2; + static constexpr auto traps = numeric_limits::traps; + static constexpr auto tinyness_before = false; + + static constexpr c10::Float8_e4m3fnuz min() { + return c10::Float8_e4m3fnuz(0x08, c10::Float8_e4m3fnuz::from_bits()); + } + static constexpr c10::Float8_e4m3fnuz lowest() { + return c10::Float8_e4m3fnuz(0xFF, c10::Float8_e4m3fnuz::from_bits()); + } + static constexpr c10::Float8_e4m3fnuz max() { + return c10::Float8_e4m3fnuz(0x7F, c10::Float8_e4m3fnuz::from_bits()); + } + static constexpr c10::Float8_e4m3fnuz epsilon() { + return c10::Float8_e4m3fnuz(0x28, c10::Float8_e4m3fnuz::from_bits()); + } + static constexpr c10::Float8_e4m3fnuz round_error() { + return c10::Float8_e4m3fnuz(0x38, c10::Float8_e4m3fnuz::from_bits()); + } + static constexpr c10::Float8_e4m3fnuz infinity() { + // NaN (no infinities) + return c10::Float8_e4m3fnuz(0x80, c10::Float8_e4m3fnuz::from_bits()); + } + static constexpr c10::Float8_e4m3fnuz quiet_NaN() { + return c10::Float8_e4m3fnuz(0x80, c10::Float8_e4m3fnuz::from_bits()); + } + static constexpr c10::Float8_e4m3fnuz denorm_min() { + return c10::Float8_e4m3fnuz(0x01, c10::Float8_e4m3fnuz::from_bits()); + } +}; + +} // namespace std diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_e5m2.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_e5m2.h new file mode 100644 index 0000000000000000000000000000000000000000..0aa856d0d5546fc53b7bf7148fefef72c563b262 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_e5m2.h @@ -0,0 +1,458 @@ +#pragma once + +/// Defines the Float8_e5m2 type (8-bit floating-point) including conversions +/// to standard C types and basic arithmetic operations. Note that arithmetic +/// operations are implemented by converting to floating point and +/// performing the operation in float32. +/// Binary configuration: +/// s eeeee mm +/// 1 sign bit +/// 5 exponent bits +/// 2 mantissa bits +/// bias = 15 +/// +/// Implementation based on the paper https://arxiv.org/pdf/2209.05433.pdf +/// and inspired by Half implementation from pytorch/c10/util/Half.h + +#include +#include + +#include + +namespace c10 { + +struct alignas(1) Float8_e5m2 { + uint8_t x; + + struct from_bits_t {}; + C10_HOST_DEVICE static constexpr from_bits_t from_bits() { + return from_bits_t(); + } + + Float8_e5m2() = default; + + constexpr C10_HOST_DEVICE Float8_e5m2(uint8_t bits, from_bits_t /*unused*/) + : x(bits) {} + inline C10_HOST_DEVICE Float8_e5m2(float value); + inline C10_HOST_DEVICE operator float() const; + inline C10_HOST_DEVICE bool isnan() const; + inline C10_HOST_DEVICE bool isinf() const; +}; + +inline std::ostream& operator<<(std::ostream& out, const Float8_e5m2& value) { + out << (float)value; + return out; +} + +namespace detail { + +/* + * Convert a 8-bit floating-point number in fp8 E5M2 format, in bit + * representation, to a 32-bit floating-point number in IEEE single-precision + * format, in bit representation. + * + * @note The implementation doesn't use any floating-point operations. + */ +inline C10_HOST_DEVICE float fp8e5m2_to_fp32_value(uint8_t input) { + /* + * Extend the fp8 E5M2 number to 32 bits and shift to the + * upper part of the 32-bit word: + * +---+----+---+-----------------------------+ + * | S |EEEEE|MM|0000 0000 0000 0000 0000 0000| + * +---+----+---+-----------------------------+ + * Bits 31 26-30 24-25 0-23 + * + * S - sign bit, E - bits of the biased exponent, M - bits of the mantissa, 0 + * - zero bits. + */ + uint16_t half_representation = input; + half_representation <<= 8; + return fp16_ieee_to_fp32_value(half_representation); +} + +/* + * Convert a 32-bit floating-point number in IEEE single-precision format to a + * 8-bit floating-point number in fp8 E5M2 format, in bit representation. + */ +inline C10_HOST_DEVICE uint8_t fp8e5m2_from_fp32_value(float f) { + /* + * Binary representation of fp32 infinity + * 0 11111111 00000000000000000000000 + */ + constexpr uint32_t fp32_inf = UINT32_C(255) << 23; + + /* + * Binary representation of 65536.0f, which is the first value + * not representable in fp8e5m2 range: + * 0 11111 00 - fp8e5m2 + * 0 10001111 00000000000000000000000 - fp32 + */ + constexpr uint32_t fp8_max = UINT32_C(143) << 23; + + /* + * A mask for converting fp32 numbers lower than fp8e5m2 normal range + * into denorm representation + * magic number: ((127 - 15) + (23 - 2) + 1) + */ + constexpr uint32_t denorm_mask = UINT32_C(134) << 23; + + uint32_t f_bits = fp32_to_bits(f); + uint8_t result = 0u; + + /* + * Extract the sign of the input number into the high bit of the 32-bit word: + * + * +---+----------------------------------+ + * | S |0000000 00000000 00000000 00000000| + * +---+----------------------------------+ + * Bits 31 0-31 + */ + const uint32_t sign = f_bits & UINT32_C(0x80000000); + + /* + * Set sign bit to 0 + */ + f_bits ^= sign; + + if (f_bits >= fp8_max) { + // NaN - all exponent and mantissa bits set to 1 + result = f_bits > fp32_inf ? UINT8_C(0x7F) : UINT8_C(0x7C); + } else { + if (f_bits < (UINT32_C(113) << 23)) { + // Input number is smaller than 2^(-14), which is the smallest + // fp8e5m2 normal number + f_bits = + fp32_to_bits(fp32_from_bits(f_bits) + fp32_from_bits(denorm_mask)); + result = static_cast(f_bits - denorm_mask); + } else { + // resulting mantissa is odd + uint32_t mant_odd = (f_bits >> 21) & 1; + + // update exponent, rounding bias part 1 + f_bits += ((uint32_t)(15 - 127) << 23) + 0xFFFFF; + + // rounding bias part 2 + f_bits += mant_odd; + + // take the bits! + result = static_cast(f_bits >> 21); + } + } + + result |= static_cast(sign >> 24); + return result; +} + +} // namespace detail + +// -------- below is copied from c10/util/Float8_e5m2-inl.h --------// +C10_CLANG_DIAGNOSTIC_PUSH() +#if C10_CLANG_HAS_WARNING("-Wimplicit-int-float-conversion") +C10_CLANG_DIAGNOSTIC_IGNORE("-Wimplicit-int-float-conversion") +#endif + +#define EXP_WIDTH_FP8 5 +#define MAN_WIDTH_FP8 2 +#define EXP_BIAS_FP8 15 + +/// Constructors + +inline C10_HOST_DEVICE Float8_e5m2::Float8_e5m2(float value) + : x(detail::fp8e5m2_from_fp32_value(value)) {} + +/// Implicit conversions + +inline C10_HOST_DEVICE Float8_e5m2::operator float() const { + return detail::fp8e5m2_to_fp32_value(x); +} + +/// Special values helpers + +inline C10_HOST_DEVICE bool Float8_e5m2::isnan() const { + return (x & 0b01111111) > 0b01111100; +} + +inline C10_HOST_DEVICE bool Float8_e5m2::isinf() const { + return (x & 0b01111111) == 0b01111100; +} + +/// Arithmetic + +inline C10_HOST_DEVICE Float8_e5m2 +operator+(const Float8_e5m2& a, const Float8_e5m2& b) { + return static_cast(a) + static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e5m2 +operator-(const Float8_e5m2& a, const Float8_e5m2& b) { + return static_cast(a) - static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e5m2 +operator*(const Float8_e5m2& a, const Float8_e5m2& b) { + return static_cast(a) * static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e5m2 operator/( + const Float8_e5m2& a, + const Float8_e5m2& b) __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e5m2 operator-(const Float8_e5m2& a) { + return -static_cast(a); +} + +inline C10_HOST_DEVICE Float8_e5m2& operator+=( + Float8_e5m2& a, + const Float8_e5m2& b) { + a = a + b; + return a; +} + +inline C10_HOST_DEVICE Float8_e5m2& operator-=( + Float8_e5m2& a, + const Float8_e5m2& b) { + a = a - b; + return a; +} + +inline C10_HOST_DEVICE Float8_e5m2& operator*=( + Float8_e5m2& a, + const Float8_e5m2& b) { + a = a * b; + return a; +} + +inline C10_HOST_DEVICE Float8_e5m2& operator/=( + Float8_e5m2& a, + const Float8_e5m2& b) { + a = a / b; + return a; +} + +/// Arithmetic with floats + +inline C10_HOST_DEVICE float operator+(Float8_e5m2 a, float b) { + return static_cast(a) + b; +} +inline C10_HOST_DEVICE float operator-(Float8_e5m2 a, float b) { + return static_cast(a) - b; +} +inline C10_HOST_DEVICE float operator*(Float8_e5m2 a, float b) { + return static_cast(a) * b; +} +inline C10_HOST_DEVICE float operator/(Float8_e5m2 a, float b) + __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / b; +} + +inline C10_HOST_DEVICE float operator+(float a, Float8_e5m2 b) { + return a + static_cast(b); +} +inline C10_HOST_DEVICE float operator-(float a, Float8_e5m2 b) { + return a - static_cast(b); +} +inline C10_HOST_DEVICE float operator*(float a, Float8_e5m2 b) { + return a * static_cast(b); +} +inline C10_HOST_DEVICE float operator/(float a, Float8_e5m2 b) + __ubsan_ignore_float_divide_by_zero__ { + return a / static_cast(b); +} + +inline C10_HOST_DEVICE float& operator+=(float& a, const Float8_e5m2& b) { + return a += static_cast(b); +} +inline C10_HOST_DEVICE float& operator-=(float& a, const Float8_e5m2& b) { + return a -= static_cast(b); +} +inline C10_HOST_DEVICE float& operator*=(float& a, const Float8_e5m2& b) { + return a *= static_cast(b); +} +inline C10_HOST_DEVICE float& operator/=(float& a, const Float8_e5m2& b) { + return a /= static_cast(b); +} + +/// Arithmetic with doubles + +inline C10_HOST_DEVICE double operator+(Float8_e5m2 a, double b) { + return static_cast(a) + b; +} +inline C10_HOST_DEVICE double operator-(Float8_e5m2 a, double b) { + return static_cast(a) - b; +} +inline C10_HOST_DEVICE double operator*(Float8_e5m2 a, double b) { + return static_cast(a) * b; +} +inline C10_HOST_DEVICE double operator/(Float8_e5m2 a, double b) + __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / b; +} + +inline C10_HOST_DEVICE double operator+(double a, Float8_e5m2 b) { + return a + static_cast(b); +} +inline C10_HOST_DEVICE double operator-(double a, Float8_e5m2 b) { + return a - static_cast(b); +} +inline C10_HOST_DEVICE double operator*(double a, Float8_e5m2 b) { + return a * static_cast(b); +} +inline C10_HOST_DEVICE double operator/(double a, Float8_e5m2 b) + __ubsan_ignore_float_divide_by_zero__ { + return a / static_cast(b); +} + +/// Arithmetic with ints + +inline C10_HOST_DEVICE Float8_e5m2 operator+(Float8_e5m2 a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a + static_cast(b); +} +inline C10_HOST_DEVICE Float8_e5m2 operator-(Float8_e5m2 a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a - static_cast(b); +} +inline C10_HOST_DEVICE Float8_e5m2 operator*(Float8_e5m2 a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a * static_cast(b); +} +inline C10_HOST_DEVICE Float8_e5m2 operator/(Float8_e5m2 a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a / static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e5m2 operator+(int a, Float8_e5m2 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) + b; +} +inline C10_HOST_DEVICE Float8_e5m2 operator-(int a, Float8_e5m2 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) - b; +} +inline C10_HOST_DEVICE Float8_e5m2 operator*(int a, Float8_e5m2 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) * b; +} +inline C10_HOST_DEVICE Float8_e5m2 operator/(int a, Float8_e5m2 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) / b; +} + +//// Arithmetic with int64_t + +inline C10_HOST_DEVICE Float8_e5m2 operator+(Float8_e5m2 a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a + static_cast(b); +} +inline C10_HOST_DEVICE Float8_e5m2 operator-(Float8_e5m2 a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a - static_cast(b); +} +inline C10_HOST_DEVICE Float8_e5m2 operator*(Float8_e5m2 a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a * static_cast(b); +} +inline C10_HOST_DEVICE Float8_e5m2 operator/(Float8_e5m2 a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a / static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e5m2 operator+(int64_t a, Float8_e5m2 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) + b; +} +inline C10_HOST_DEVICE Float8_e5m2 operator-(int64_t a, Float8_e5m2 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) - b; +} +inline C10_HOST_DEVICE Float8_e5m2 operator*(int64_t a, Float8_e5m2 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) * b; +} +inline C10_HOST_DEVICE Float8_e5m2 operator/(int64_t a, Float8_e5m2 b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) / b; +} + +/// NOTE: we do not define comparisons directly and instead rely on the implicit +/// conversion from c10::Float8_e5m2 to float. +C10_CLANG_DIAGNOSTIC_POP() +} // namespace c10 + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly) +using c10::Float8_e5m2; +using c10::operator<<; +using c10::operator+; +using c10::operator-; +using c10::operator*; +using c10::operator/; +using c10::operator+=; +using c10::operator-=; +using c10::operator*=; +using c10::operator/=; + +namespace detail { +using c10::detail::fp8e5m2_from_fp32_value; +using c10::detail::fp8e5m2_to_fp32_value; +} // namespace detail +HIDDEN_NAMESPACE_END(torch, headeronly) + +namespace std { + +template <> +class numeric_limits { + public: + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_specialized = true; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = true; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = false; + static constexpr auto has_denorm = true; + static constexpr auto has_denorm_loss = true; + static constexpr auto round_style = numeric_limits::round_style; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 3; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 2; + static constexpr int radix = 2; + static constexpr int min_exponent = -13; + static constexpr int min_exponent10 = -4; + static constexpr int max_exponent = 16; + static constexpr int max_exponent10 = 4; + static constexpr auto traps = numeric_limits::traps; + static constexpr auto tinyness_before = + numeric_limits::tinyness_before; + + static constexpr c10::Float8_e5m2 min() { + return c10::Float8_e5m2(0x4, c10::Float8_e5m2::from_bits()); + } + static constexpr c10::Float8_e5m2 max() { + return c10::Float8_e5m2(0x7B, c10::Float8_e5m2::from_bits()); + } + static constexpr c10::Float8_e5m2 lowest() { + return c10::Float8_e5m2(0xFB, c10::Float8_e5m2::from_bits()); + } + static constexpr c10::Float8_e5m2 epsilon() { + return c10::Float8_e5m2(0x34, c10::Float8_e5m2::from_bits()); + } + static constexpr c10::Float8_e5m2 round_error() { + return c10::Float8_e5m2(0x38, c10::Float8_e5m2::from_bits()); + } + static constexpr c10::Float8_e5m2 infinity() { + return c10::Float8_e5m2(0x7C, c10::Float8_e5m2::from_bits()); + } + static constexpr c10::Float8_e5m2 quiet_NaN() { + return c10::Float8_e5m2(0x7F, c10::Float8_e5m2::from_bits()); + } + static constexpr c10::Float8_e5m2 denorm_min() { + return c10::Float8_e5m2(0x01, c10::Float8_e5m2::from_bits()); + } +}; + +} // namespace std diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_e5m2fnuz.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_e5m2fnuz.h new file mode 100644 index 0000000000000000000000000000000000000000..6b0f79b75adea4a994a3c44e666b73767b68c66d --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_e5m2fnuz.h @@ -0,0 +1,448 @@ +#pragma once + +/// Defines the Float8_e5m2fnuz type (8-bit floating-point) including +/// conversions to standard C types and basic arithmetic operations. Note that +/// arithmetic operations are implemented by converting to floating point and +/// performing the operation in float32. +/// Binary configuration remains the same as e5m2: +/// s eeeee mm +/// 1 sign bit +/// 5 exponent bits +/// 2 mantissa bits +/// The key differences that e5m2fnuz brings are: +/// bias = 16 +/// no infinities or negative zero +/// NaN only when sign bit is 1, rest all 0s +/// +/// Implementation based on the paper https://arxiv.org/pdf/2206.02915.pdf and +/// the existing Float8_e4m3fn implementation. + +#include +#include +#include +#include + +#if defined(__cplusplus) +#include +#elif !defined(__OPENCL_VERSION__) +#include +#include +#endif + +#include +#include + +namespace c10 { + +struct alignas(1) Float8_e5m2fnuz { + uint8_t x; + + struct from_bits_t {}; + C10_HOST_DEVICE static constexpr from_bits_t from_bits() { + return from_bits_t(); + } + + Float8_e5m2fnuz() = default; + + constexpr C10_HOST_DEVICE Float8_e5m2fnuz( + uint8_t bits, + from_bits_t /*unused*/) + : x(bits) {} + inline C10_HOST_DEVICE Float8_e5m2fnuz(float value); + inline C10_HOST_DEVICE operator float() const; + inline C10_HOST_DEVICE bool isnan() const; + inline C10_HOST_DEVICE bool isinf() const; +}; + +inline std::ostream& operator<<( + std::ostream& out, + const Float8_e5m2fnuz& value) { + out << (float)value; + return out; +} + +namespace detail { + +/* + * Convert a 32-bit floating-point number in IEEE single-precision format to a + * 8-bit floating-point number in fp8 E5M2 format, in bit representation. + */ +inline C10_HOST_DEVICE uint8_t fp8e5m2fnuz_from_fp32_value(float f) { + /* + * Binary representation of 65536.0f, which is the first value not + * representable (i.e. the first value which would overflow in to the sign + * bit, resulting in a NaN) in fp8e4m3fnuz range: + * 1 00000 00 - fp8e5m2fnuz + * 0 10001111 00000000000000000000000 - fp32 + */ + constexpr uint32_t fnuz_max = UINT32_C(0x8F) << 23; + + /* + * A mask for converting fp32 numbers lower than fp8e5m2fnuz normal range + * into denormalized representation. + * magic number: ((127 - 16) + (23 - 2) + 1) + */ + constexpr uint32_t denorm_mask = UINT32_C(0x85) << 23; + + uint32_t f_bits = fp32_to_bits(f); + uint32_t result = 0u; + + /* + * Extract the sign of the input number into the high bit of the 32-bit word: + * + * +---+----------------------------------+ + * | S |0000000 00000000 00000000 00000000| + * +---+----------------------------------+ + * Bits 31 0-31 + */ + const uint32_t sign = f_bits & UINT32_C(0x80000000); + + /* + * Set sign bit to 0 + */ + f_bits ^= sign; + + if (f_bits >= fnuz_max) { + // NaN -- sign bit set to 1, rest 0s + return 0x80; + } + + if (f_bits < (UINT32_C(0x70) << 23) /* 2^-15 in float32 */) { + // Input exponent is less than -15, the smallest e5m2fnuz exponent, so the + // number will become subnormal. + f_bits = fp32_to_bits(fp32_from_bits(f_bits) + fp32_from_bits(denorm_mask)); + result = static_cast(f_bits - denorm_mask); + if (result == 0) { + // fnuz types don't have negative zero. + return 0; + } + } else { + // resulting mantissa is odd + uint8_t mant_odd = (f_bits >> 21) & 1; + + // update exponent, rounding bias part 1 + f_bits += ((uint32_t)(16 - 127) << 23) + 0xFFFFF; + + // rounding bias part 2 + f_bits += mant_odd; + + // take the bits! + result = static_cast(f_bits >> 21); + } + + result |= sign >> 24; + return result; +} + +} // namespace detail + +//------ below is copied from c10/util/Float8_e5m2fnuz-inl.h ------// +C10_CLANG_DIAGNOSTIC_PUSH() +#if C10_CLANG_HAS_WARNING("-Wimplicit-int-float-conversion") +C10_CLANG_DIAGNOSTIC_IGNORE("-Wimplicit-int-float-conversion") +#endif + +/// Constructors + +inline C10_HOST_DEVICE Float8_e5m2fnuz::Float8_e5m2fnuz(float value) + : x(detail::fp8e5m2fnuz_from_fp32_value(value)) {} + +/// Implicit conversions + +inline C10_HOST_DEVICE Float8_e5m2fnuz::operator float() const { + return torch::headeronly::detail::fp8_fnuz_to_fp32_value<5, 2>(x); +} + +/// Special values helpers + +inline C10_HOST_DEVICE bool Float8_e5m2fnuz::isnan() const { + return x == 0b10000000; +} + +inline C10_HOST_DEVICE bool Float8_e5m2fnuz::isinf() const { + return false; +} + +/// Arithmetic + +inline C10_HOST_DEVICE Float8_e5m2fnuz +operator+(const Float8_e5m2fnuz& a, const Float8_e5m2fnuz& b) { + return static_cast(a) + static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e5m2fnuz +operator-(const Float8_e5m2fnuz& a, const Float8_e5m2fnuz& b) { + return static_cast(a) - static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e5m2fnuz +operator*(const Float8_e5m2fnuz& a, const Float8_e5m2fnuz& b) { + return static_cast(a) * static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e5m2fnuz operator/( + const Float8_e5m2fnuz& a, + const Float8_e5m2fnuz& b) __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e5m2fnuz operator-(const Float8_e5m2fnuz& a) { + return -static_cast(a); +} + +inline C10_HOST_DEVICE Float8_e5m2fnuz& operator+=( + Float8_e5m2fnuz& a, + const Float8_e5m2fnuz& b) { + a = a + b; + return a; +} + +inline C10_HOST_DEVICE Float8_e5m2fnuz& operator-=( + Float8_e5m2fnuz& a, + const Float8_e5m2fnuz& b) { + a = a - b; + return a; +} + +inline C10_HOST_DEVICE Float8_e5m2fnuz& operator*=( + Float8_e5m2fnuz& a, + const Float8_e5m2fnuz& b) { + a = a * b; + return a; +} + +inline C10_HOST_DEVICE Float8_e5m2fnuz& operator/=( + Float8_e5m2fnuz& a, + const Float8_e5m2fnuz& b) { + a = a / b; + return a; +} + +/// Arithmetic with floats + +inline C10_HOST_DEVICE float operator+(Float8_e5m2fnuz a, float b) { + return static_cast(a) + b; +} +inline C10_HOST_DEVICE float operator-(Float8_e5m2fnuz a, float b) { + return static_cast(a) - b; +} +inline C10_HOST_DEVICE float operator*(Float8_e5m2fnuz a, float b) { + return static_cast(a) * b; +} +inline C10_HOST_DEVICE float operator/(Float8_e5m2fnuz a, float b) + __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / b; +} + +inline C10_HOST_DEVICE float operator+(float a, Float8_e5m2fnuz b) { + return a + static_cast(b); +} +inline C10_HOST_DEVICE float operator-(float a, Float8_e5m2fnuz b) { + return a - static_cast(b); +} +inline C10_HOST_DEVICE float operator*(float a, Float8_e5m2fnuz b) { + return a * static_cast(b); +} +inline C10_HOST_DEVICE float operator/(float a, Float8_e5m2fnuz b) + __ubsan_ignore_float_divide_by_zero__ { + return a / static_cast(b); +} + +inline C10_HOST_DEVICE float& operator+=(float& a, const Float8_e5m2fnuz& b) { + return a += static_cast(b); +} +inline C10_HOST_DEVICE float& operator-=(float& a, const Float8_e5m2fnuz& b) { + return a -= static_cast(b); +} +inline C10_HOST_DEVICE float& operator*=(float& a, const Float8_e5m2fnuz& b) { + return a *= static_cast(b); +} +inline C10_HOST_DEVICE float& operator/=(float& a, const Float8_e5m2fnuz& b) { + return a /= static_cast(b); +} + +/// Arithmetic with doubles + +inline C10_HOST_DEVICE double operator+(Float8_e5m2fnuz a, double b) { + return static_cast(a) + b; +} +inline C10_HOST_DEVICE double operator-(Float8_e5m2fnuz a, double b) { + return static_cast(a) - b; +} +inline C10_HOST_DEVICE double operator*(Float8_e5m2fnuz a, double b) { + return static_cast(a) * b; +} +inline C10_HOST_DEVICE double operator/(Float8_e5m2fnuz a, double b) + __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / b; +} + +inline C10_HOST_DEVICE double operator+(double a, Float8_e5m2fnuz b) { + return a + static_cast(b); +} +inline C10_HOST_DEVICE double operator-(double a, Float8_e5m2fnuz b) { + return a - static_cast(b); +} +inline C10_HOST_DEVICE double operator*(double a, Float8_e5m2fnuz b) { + return a * static_cast(b); +} +inline C10_HOST_DEVICE double operator/(double a, Float8_e5m2fnuz b) + __ubsan_ignore_float_divide_by_zero__ { + return a / static_cast(b); +} + +/// Arithmetic with ints + +inline C10_HOST_DEVICE Float8_e5m2fnuz operator+(Float8_e5m2fnuz a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a + static_cast(b); +} +inline C10_HOST_DEVICE Float8_e5m2fnuz operator-(Float8_e5m2fnuz a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a - static_cast(b); +} +inline C10_HOST_DEVICE Float8_e5m2fnuz operator*(Float8_e5m2fnuz a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a * static_cast(b); +} +inline C10_HOST_DEVICE Float8_e5m2fnuz operator/(Float8_e5m2fnuz a, int b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a / static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e5m2fnuz operator+(int a, Float8_e5m2fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) + b; +} +inline C10_HOST_DEVICE Float8_e5m2fnuz operator-(int a, Float8_e5m2fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) - b; +} +inline C10_HOST_DEVICE Float8_e5m2fnuz operator*(int a, Float8_e5m2fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) * b; +} +inline C10_HOST_DEVICE Float8_e5m2fnuz operator/(int a, Float8_e5m2fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) / b; +} + +//// Arithmetic with int64_t + +inline C10_HOST_DEVICE Float8_e5m2fnuz operator+(Float8_e5m2fnuz a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a + static_cast(b); +} +inline C10_HOST_DEVICE Float8_e5m2fnuz operator-(Float8_e5m2fnuz a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a - static_cast(b); +} +inline C10_HOST_DEVICE Float8_e5m2fnuz operator*(Float8_e5m2fnuz a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a * static_cast(b); +} +inline C10_HOST_DEVICE Float8_e5m2fnuz operator/(Float8_e5m2fnuz a, int64_t b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return a / static_cast(b); +} + +inline C10_HOST_DEVICE Float8_e5m2fnuz operator+(int64_t a, Float8_e5m2fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) + b; +} +inline C10_HOST_DEVICE Float8_e5m2fnuz operator-(int64_t a, Float8_e5m2fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) - b; +} +inline C10_HOST_DEVICE Float8_e5m2fnuz operator*(int64_t a, Float8_e5m2fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) * b; +} +inline C10_HOST_DEVICE Float8_e5m2fnuz operator/(int64_t a, Float8_e5m2fnuz b) { + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + return static_cast(a) / b; +} + +/// NOTE: we do not define comparisons directly and instead rely on the implicit +/// conversion from c10::Float8_e5m2fnuz to float. + +C10_CLANG_DIAGNOSTIC_POP() + +} // namespace c10 + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly) +using c10::Float8_e5m2fnuz; +using c10::operator<<; +using c10::operator+; +using c10::operator-; +using c10::operator*; +using c10::operator/; +using c10::operator+=; +using c10::operator-=; +using c10::operator*=; +using c10::operator/=; + +namespace detail { +using c10::detail::fp8e5m2fnuz_from_fp32_value; +} +HIDDEN_NAMESPACE_END(torch, headeronly) + +namespace std { + +template <> +class numeric_limits { + public: + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_specialized = true; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = false; + static constexpr auto has_denorm = true; + static constexpr auto has_denorm_loss = true; + static constexpr auto round_style = numeric_limits::round_style; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 3; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 2; + static constexpr int radix = 2; + static constexpr int min_exponent = -14; + static constexpr int min_exponent10 = -4; + static constexpr int max_exponent = 16; + static constexpr int max_exponent10 = 4; + static constexpr auto traps = numeric_limits::traps; + static constexpr auto tinyness_before = + numeric_limits::tinyness_before; + + static constexpr c10::Float8_e5m2fnuz min() { + return c10::Float8_e5m2fnuz(0x04, c10::Float8_e5m2fnuz::from_bits()); + } + static constexpr c10::Float8_e5m2fnuz max() { + return c10::Float8_e5m2fnuz(0x7F, c10::Float8_e5m2fnuz::from_bits()); + } + static constexpr c10::Float8_e5m2fnuz lowest() { + return c10::Float8_e5m2fnuz(0xFF, c10::Float8_e5m2fnuz::from_bits()); + } + static constexpr c10::Float8_e5m2fnuz epsilon() { + return c10::Float8_e5m2fnuz(0x34, c10::Float8_e5m2fnuz::from_bits()); + } + static constexpr c10::Float8_e5m2fnuz round_error() { + return c10::Float8_e5m2fnuz(0x38, c10::Float8_e5m2fnuz::from_bits()); + } + static constexpr c10::Float8_e5m2fnuz infinity() { + return c10::Float8_e5m2fnuz(0x80, c10::Float8_e5m2fnuz::from_bits()); + } + // TODO(future): we are mapping neg_zero to both inf and NaN, this is + // surprising and we should figure out what to do about it. + static constexpr c10::Float8_e5m2fnuz quiet_NaN() { + return c10::Float8_e5m2fnuz(0x80, c10::Float8_e5m2fnuz::from_bits()); + } + static constexpr c10::Float8_e5m2fnuz denorm_min() { + return c10::Float8_e5m2fnuz(0x01, c10::Float8_e5m2fnuz::from_bits()); + } +}; + +} // namespace std diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_e8m0fnu.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_e8m0fnu.h new file mode 100644 index 0000000000000000000000000000000000000000..80d89439c90b939259e1ec20b0b0c0256d3ced84 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_e8m0fnu.h @@ -0,0 +1,226 @@ +#pragma once + +/// Defines the Float8_e8m0fnu type (8-bit floating-point) including +/// conversions to standard C types +/// Binary configuration : +/// eeeeeeee +/// no sign bits +/// 8 exponent bits +/// no mantissa bits +/// +/// This is the E8M0 dtype from the OCP MX format spec +/// (https://www.opencompute.org/documents/ocp-microscaling-formats-mx-v1-0-spec-final-pdf, +/// Section 5.4.1) + +#include +#include + +// TODO(#146647): do we need to special case OPENCL? +#if defined(__cplusplus) +#include +#elif !defined(__OPENCL_VERSION__) +#include +#include +#endif + +#include +#include +#include + +namespace c10 { + +struct alignas(1) Float8_e8m0fnu { + uint8_t x; + + struct from_bits_t {}; + C10_HOST_DEVICE static constexpr from_bits_t from_bits() { + return from_bits_t(); + } + + Float8_e8m0fnu() = default; + + constexpr C10_HOST_DEVICE Float8_e8m0fnu(uint8_t bits, from_bits_t /*unused*/) + : x(bits) {} + inline C10_HOST_DEVICE Float8_e8m0fnu(float value); + inline C10_HOST_DEVICE operator float() const; + inline C10_HOST_DEVICE bool isnan() const; +}; + +inline std::ostream& operator<<( + std::ostream& out, + const Float8_e8m0fnu& value) { + out << (float)value; + return out; +} + +namespace detail { +/* + * Convert a 32-bit floating-point number in IEEE single-precision format to a + * 8-bit floating-point number in fp8 e8m0fnu format, in bit representation. + */ +inline C10_HOST_DEVICE uint8_t fp8e8m0fnu_from_fp32_value(float f) { + // TODO(#146647): maybe rewrite without control flow + + uint32_t f_bits = c10::detail::fp32_to_bits(f); + + // extract the exponent + uint32_t exponent = (f_bits >> 23) & 0b11111111; + + // special case float32 NaN and +-inf to map to e8m0 nan + if (exponent == 0b11111111) { + return exponent; + } + + // next, we use guard, round, sticky bits and the LSB to implement round to + // nearest, with ties to even + + // guard bit - bit 23, or 22 zero-indexed + uint8_t g = (f_bits & 0x400000) > 0; + // round bit - bit 22, or 21 zero-indexed + uint8_t r = (f_bits & 0x200000) > 0; + // sticky bit - bits 21 to 1, or 20 to 0 zero-indexed + uint8_t s = (f_bits & 0x1FFFFF) > 0; + // in casting to e8m0, LSB is the implied mantissa bit. It equals to 0 if the + // original float32 is denormal, and to 1 if the original float32 is normal. + uint8_t lsb = exponent > 0; + + // implement the RNE logic + bool round_up = false; + + // if g == 0, round down (no-op) + if (g == 1) { + if ((r == 1) || (s == 1)) { + // round up + round_up = true; + } else { + if (lsb == 1) { + // round up + round_up = true; + } + // if lsb == 0, round down (no-op) + } + } + + if (round_up) { + // adjust exponent + // note that if exponent was 255 we would have already returned earlier, so + // we know we can add one safely without running out of bounds + exponent++; + } + + return exponent; +} + +} // namespace detail + +//------- the below is from c10/util/Float8_e8m0fnu-inl.h ------// +// TODO(#146647): Can we remove the below warning? +C10_CLANG_DIAGNOSTIC_PUSH() +#if C10_CLANG_HAS_WARNING("-Wimplicit-int-float-conversion") +C10_CLANG_DIAGNOSTIC_IGNORE("-Wimplicit-int-float-conversion") +#endif + +/// Constructors +inline C10_HOST_DEVICE Float8_e8m0fnu::Float8_e8m0fnu(float value) + : x(detail::fp8e8m0fnu_from_fp32_value(value)) {} + +/// Implicit conversions + +inline C10_HOST_DEVICE Float8_e8m0fnu::operator float() const { + // TODO(#146647): maybe rewrite without control flow + + // if exponent is zero, need to special case to return 2^-127 instead of zero + if (x == 0) { + return c10::detail::fp32_from_bits(0x00400000); + } + + // if exponent is NaN, need to special case to return properly encoded NaN + if (isnan()) { + return c10::detail::fp32_from_bits(0x7f800001); + } + + // leave sign at 0, set the exponent bits, leave stored mantissa at 0 + uint32_t res = x << 23; + + return c10::detail::fp32_from_bits(res); +} + +/// Special values helper + +inline C10_HOST_DEVICE bool Float8_e8m0fnu::isnan() const { + return x == 0b11111111; +} + +/// NOTE: we do not define comparisons directly and instead rely on the implicit +/// conversion from c10::Float8_e8m0fnu to float. +C10_CLANG_DIAGNOSTIC_POP() + +} // namespace c10 + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly) +using c10::Float8_e8m0fnu; +using c10::operator<<; + +namespace detail { +using c10::detail::fp8e8m0fnu_from_fp32_value; +} // namespace detail +HIDDEN_NAMESPACE_END(torch, headeronly) + +namespace std { + +template <> +class numeric_limits { + public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = false; + static constexpr auto has_denorm = false; + static constexpr auto has_denorm_loss = false; + static constexpr auto round_style = numeric_limits::round_style; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 1; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 1; // just a 2! + static constexpr int radix = 2; + static constexpr int min_exponent = -126; + static constexpr int min_exponent10 = -38; + static constexpr int max_exponent = 128; + static constexpr int max_exponent10 = 38; + static constexpr auto traps = numeric_limits::traps; + static constexpr auto tinyness_before = false; + + static constexpr c10::Float8_e8m0fnu min() { + // 2^-127 + return c10::Float8_e8m0fnu(0b00000000, c10::Float8_e8m0fnu::from_bits()); + } + static constexpr c10::Float8_e8m0fnu lowest() { + // 2^-127 + return c10::Float8_e8m0fnu(0b00000000, c10::Float8_e8m0fnu::from_bits()); + } + static constexpr c10::Float8_e8m0fnu max() { + // 254 biased, which is 127 unbiased, so 2^127 + return c10::Float8_e8m0fnu(0b11111110, c10::Float8_e8m0fnu::from_bits()); + } + static constexpr c10::Float8_e8m0fnu epsilon() { + // according to https://en.cppreference.com/w/cpp/types/numeric_limits, this + // is "the difference between 1.0 and the next representable value of the + // given floating-point type". The next representable value is 2.0, so the + // difference is 1.0 which is 2^0. 0 unbiased is 127 biased. + return c10::Float8_e8m0fnu(0b01111111, c10::Float8_e8m0fnu::from_bits()); + } + static constexpr c10::Float8_e8m0fnu round_error() { + // 0.5 in float, which is 2^-1, and -1 + 127 = 126 + return c10::Float8_e8m0fnu(0b01111110, c10::Float8_e8m0fnu::from_bits()); + } + static constexpr c10::Float8_e8m0fnu quiet_NaN() { + return c10::Float8_e8m0fnu(0b11111111, c10::Float8_e8m0fnu::from_bits()); + } +}; + +} // namespace std diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_fnuz_cvt.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_fnuz_cvt.h new file mode 100644 index 0000000000000000000000000000000000000000..59fab8cc28dbfb2c9c8cb4951deaf2bb06dd06ec --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Float8_fnuz_cvt.h @@ -0,0 +1,69 @@ +#pragma once + +#include +#include + +#include + +#if defined(SYCL_LANGUAGE_VERSION) +#include +#endif + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly, detail) + +/* + * Convert a 8-bit floating-point number in either f8 E4M3FNUZ or bf8 E5M2FNUZ + * format, in bit representation, to a 32-bit floating-point number. + */ +template +inline C10_HOST_DEVICE float fp8_fnuz_to_fp32_value(uint8_t x) { + static_assert((we == 4 && wm == 3) || (we == 5 && wm == 2)); + constexpr uint32_t weo = 8; + constexpr uint32_t wmo = 23; + + if (x == 0) { + return 0; + } + + if (x == 0x80) { + constexpr uint32_t ifNaN = 0x7F800001; + return fp32_from_bits(ifNaN); + } + + uint32_t mantissa = x & ((1 << wm) - 1); + uint32_t exponent = (x & 0x7F) >> wm; + + // subnormal input + if (exponent == 0) { + // guaranteed mantissa!=0 since cases 0x0 and 0x80 are handled above +#if defined(__CUDA_ARCH__) || defined(__HIP_DEVICE_COMPILE__) + uint32_t renorm_shift = __clz(mantissa); +#elif defined(__SYCL_DEVICE_ONLY__) + uint32_t renorm_shift = sycl::clz(mantissa); +#elif defined(_MSC_VER) + unsigned long nonsign_bsr; + _BitScanReverse(&nonsign_bsr, (unsigned long)mantissa); + uint32_t renorm_shift = (uint32_t)nonsign_bsr ^ 31; +#else + uint32_t renorm_shift = __builtin_clz(mantissa); +#endif + uint32_t sh = 1 + renorm_shift - (32 - wm); + mantissa <<= sh; + exponent += 1 - sh; + mantissa &= ((1 << wm) - 1); + } + + const uint32_t exp_low_cutoff = (1 << (weo - 1)) - (1 << (we - 1)); + exponent += exp_low_cutoff - 1; + mantissa <<= wmo - wm; + + uint32_t sign = x >> 7; + uint32_t retval = (sign << 31) | (exponent << 23) | mantissa; + return fp32_from_bits(retval); +} + +HIDDEN_NAMESPACE_END(torch, headeronly, detail) + +namespace c10::detail { +using torch::headeronly::detail::fp8_fnuz_to_fp32_value; +} diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Half.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Half.h new file mode 100644 index 0000000000000000000000000000000000000000..a9c0b166ba2ea825ee8c2933e519de40112dae6f --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Half.h @@ -0,0 +1,788 @@ +#pragma once + +/// Defines the Half type (half-precision floating-point) including conversions +/// to standard C types and basic arithmetic operations. Note that arithmetic +/// operations are implemented by converting to floating point and +/// performing the operation in float32, instead of using CUDA half intrinsics. +/// Most uses of this type within ATen are memory bound, including the +/// element-wise kernels, and the half intrinsics aren't efficient on all GPUs. +/// If you are writing a compute bound kernel, you can use the CUDA half +/// intrinsics directly on the Half type from device code. + +#include +#include +#include + +#if defined(__cplusplus) +#include +#elif !defined(__OPENCL_VERSION__) +#include +#endif + +#ifdef _MSC_VER +#include +#endif + +#include +#include +#include + +#ifdef __CUDACC__ +#include +#endif + +#ifdef __HIPCC__ +#include +#endif + +#if defined(CL_SYCL_LANGUAGE_VERSION) +#include // for SYCL 1.2.1 +#elif defined(SYCL_LANGUAGE_VERSION) +#include // for SYCL 2020 +#endif + +#if (defined(CPU_CAPABILITY_AVX2) || defined(CPU_CAPABILITY_AVX512)) && \ + !defined(__APPLE__) +#include +#endif + +#if defined(__aarch64__) && !defined(__CUDACC__) +#include +#endif + +#if defined(__GNUC__) || defined(__clang__) +#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || \ + defined(_M_IX86) +#if defined(__F16C__) && \ + !(defined(__CUDA_ARCH__) || defined(__CUDACC__) || \ + defined(__HIP_DEVICE_COMPILE__)) +#define C10_X86_F16 1 +#include // import conversion ops from f16cintrin.h +#endif // defined(__F16C__) && !(defined(__CUDA_ARCH__) || defined(__CUDACC__) + // || defined(__HIP_DEVICE_COMPILE__)) +#endif // __x86_64__ || _M_X64 || __i386 || _M_IX86 +#endif // __GNUC__ || __clang__ + +namespace c10 { + +struct alignas(2) Half { + unsigned short x; + + struct from_bits_t {}; + C10_HOST_DEVICE static constexpr from_bits_t from_bits() { + return from_bits_t(); + } + + // HIP wants __host__ __device__ tag, CUDA does not +#if defined(USE_ROCM) + C10_HOST_DEVICE Half() = default; +#else + Half() = default; +#endif + + constexpr C10_HOST_DEVICE Half(unsigned short bits, from_bits_t /*unused*/) + : x(bits) {} +#if defined(__aarch64__) && !defined(__CUDACC__) + inline Half(float16_t value); + inline operator float16_t() const; +#else + inline C10_HOST_DEVICE Half(float value); + inline C10_HOST_DEVICE operator float() const; +#endif + +#if defined(__CUDACC__) || defined(__HIPCC__) + inline C10_HOST_DEVICE Half(const __half& value); + inline C10_HOST_DEVICE operator __half() const; +#endif +#ifdef SYCL_LANGUAGE_VERSION + inline C10_HOST_DEVICE Half(const sycl::half& value); + inline C10_HOST_DEVICE operator sycl::half() const; +#endif +}; + +inline std::ostream& operator<<(std::ostream& out, const Half& value) { + out << (float)value; + return out; +} + +namespace detail { +/* + * Convert a 16-bit floating-point number in IEEE half-precision format, in bit + * representation, to a 32-bit floating-point number in IEEE single-precision + * format. + * + * @note The implementation relies on IEEE-like (no assumption about rounding + * mode and no operations on denormals) floating-point operations and bitcasts + * between integer and floating-point variables. + */ +C10_HOST_DEVICE inline float fp16_ieee_to_fp32_value(uint16_t h) { +#ifdef C10_X86_F16 + return _cvtsh_ss(h); +#else + /* + * Extend the half-precision floating-point number to 32 bits and shift to the + * upper part of the 32-bit word: + * +---+-----+------------+-------------------+ + * | S |EEEEE|MM MMMM MMMM|0000 0000 0000 0000| + * +---+-----+------------+-------------------+ + * Bits 31 26-30 16-25 0-15 + * + * S - sign bit, E - bits of the biased exponent, M - bits of the mantissa, 0 + * - zero bits. + */ + const uint32_t w = (uint32_t)h << 16; + /* + * Extract the sign of the input number into the high bit of the 32-bit word: + * + * +---+----------------------------------+ + * | S |0000000 00000000 00000000 00000000| + * +---+----------------------------------+ + * Bits 31 0-31 + */ + const uint32_t sign = w & UINT32_C(0x80000000); + /* + * Extract mantissa and biased exponent of the input number into the high bits + * of the 32-bit word: + * + * +-----+------------+---------------------+ + * |EEEEE|MM MMMM MMMM|0 0000 0000 0000 0000| + * +-----+------------+---------------------+ + * Bits 27-31 17-26 0-16 + */ + const uint32_t two_w = w + w; + + /* + * Shift mantissa and exponent into bits 23-28 and bits 13-22 so they become + * mantissa and exponent of a single-precision floating-point number: + * + * S|Exponent | Mantissa + * +-+---+-----+------------+----------------+ + * |0|000|EEEEE|MM MMMM MMMM|0 0000 0000 0000| + * +-+---+-----+------------+----------------+ + * Bits | 23-31 | 0-22 + * + * Next, there are some adjustments to the exponent: + * - The exponent needs to be corrected by the difference in exponent bias + * between single-precision and half-precision formats (0x7F - 0xF = 0x70) + * - Inf and NaN values in the inputs should become Inf and NaN values after + * conversion to the single-precision number. Therefore, if the biased + * exponent of the half-precision input was 0x1F (max possible value), the + * biased exponent of the single-precision output must be 0xFF (max possible + * value). We do this correction in two steps: + * - First, we adjust the exponent by (0xFF - 0x1F) = 0xE0 (see exp_offset + * below) rather than by 0x70 suggested by the difference in the exponent bias + * (see above). + * - Then we multiply the single-precision result of exponent adjustment by + * 2**(-112) to reverse the effect of exponent adjustment by 0xE0 less the + * necessary exponent adjustment by 0x70 due to difference in exponent bias. + * The floating-point multiplication hardware would ensure than Inf and + * NaN would retain their value on at least partially IEEE754-compliant + * implementations. + * + * Note that the above operations do not handle denormal inputs (where biased + * exponent == 0). However, they also do not operate on denormal inputs, and + * do not produce denormal results. + */ + constexpr uint32_t exp_offset = UINT32_C(0xE0) << 23; + // const float exp_scale = 0x1.0p-112f; + constexpr uint32_t scale_bits = (uint32_t)15 << 23; + float exp_scale_val = 0; +#if defined(_MSC_VER) && defined(__clang__) + __builtin_memcpy(&exp_scale_val, &scale_bits, sizeof(exp_scale_val)); +#else + std::memcpy(&exp_scale_val, &scale_bits, sizeof(exp_scale_val)); +#endif + + const float exp_scale = exp_scale_val; + const float normalized_value = + fp32_from_bits((two_w >> 4) + exp_offset) * exp_scale; + + /* + * Convert denormalized half-precision inputs into single-precision results + * (always normalized). Zero inputs are also handled here. + * + * In a denormalized number the biased exponent is zero, and mantissa has + * on-zero bits. First, we shift mantissa into bits 0-9 of the 32-bit word. + * + * zeros | mantissa + * +---------------------------+------------+ + * |0000 0000 0000 0000 0000 00|MM MMMM MMMM| + * +---------------------------+------------+ + * Bits 10-31 0-9 + * + * Now, remember that denormalized half-precision numbers are represented as: + * FP16 = mantissa * 2**(-24). + * The trick is to construct a normalized single-precision number with the + * same mantissa and thehalf-precision input and with an exponent which would + * scale the corresponding mantissa bits to 2**(-24). A normalized + * single-precision floating-point number is represented as: FP32 = (1 + + * mantissa * 2**(-23)) * 2**(exponent - 127) Therefore, when the biased + * exponent is 126, a unit change in the mantissa of the input denormalized + * half-precision number causes a change of the constructed single-precision + * number by 2**(-24), i.e. the same amount. + * + * The last step is to adjust the bias of the constructed single-precision + * number. When the input half-precision number is zero, the constructed + * single-precision number has the value of FP32 = 1 * 2**(126 - 127) = + * 2**(-1) = 0.5 Therefore, we need to subtract 0.5 from the constructed + * single-precision number to get the numerical equivalent of the input + * half-precision number. + */ + constexpr uint32_t magic_mask = UINT32_C(126) << 23; + constexpr float magic_bias = 0.5f; + const float denormalized_value = + fp32_from_bits((two_w >> 17) | magic_mask) - magic_bias; + + /* + * - Choose either results of conversion of input as a normalized number, or + * as a denormalized number, depending on the input exponent. The variable + * two_w contains input exponent in bits 27-31, therefore if its smaller than + * 2**27, the input is either a denormal number, or zero. + * - Combine the result of conversion of exponent and mantissa with the sign + * of the input number. + */ + constexpr uint32_t denormalized_cutoff = UINT32_C(1) << 27; + const uint32_t result = sign | + (two_w < denormalized_cutoff ? fp32_to_bits(denormalized_value) + : fp32_to_bits(normalized_value)); + return fp32_from_bits(result); +#endif // C10_X86_F16 +} + +/* + * Convert a 32-bit floating-point number in IEEE single-precision format to a + * 16-bit floating-point number in IEEE half-precision format, in bit + * representation. + * + * @note The implementation relies on IEEE-like (no assumption about rounding + * mode and no operations on denormals) floating-point operations and bitcasts + * between integer and floating-point variables. + */ +inline uint16_t fp16_ieee_from_fp32_value(float f) { +#ifdef C10_X86_F16 + return _cvtss_sh(f, _MM_FROUND_TO_NEAREST_INT); +#else + // const float scale_to_inf = 0x1.0p+112f; + // const float scale_to_zero = 0x1.0p-110f; + constexpr uint32_t scale_to_inf_bits = (uint32_t)239 << 23; + constexpr uint32_t scale_to_zero_bits = (uint32_t)17 << 23; + float scale_to_inf_val = 0, scale_to_zero_val = 0; + std::memcpy(&scale_to_inf_val, &scale_to_inf_bits, sizeof(scale_to_inf_val)); + std::memcpy( + &scale_to_zero_val, &scale_to_zero_bits, sizeof(scale_to_zero_val)); + const float scale_to_inf = scale_to_inf_val; + const float scale_to_zero = scale_to_zero_val; + +#if defined(_MSC_VER) && _MSC_VER == 1916 + float base = ((signbit(f) != 0 ? -f : f) * scale_to_inf) * scale_to_zero; +#else + float base = (fabsf(f) * scale_to_inf) * scale_to_zero; +#endif + + const uint32_t w = fp32_to_bits(f); + const uint32_t shl1_w = w + w; + const uint32_t sign = w & UINT32_C(0x80000000); + uint32_t bias = shl1_w & UINT32_C(0xFF000000); + if (bias < UINT32_C(0x71000000)) { + bias = UINT32_C(0x71000000); + } + + base = fp32_from_bits((bias >> 1) + UINT32_C(0x07800000)) + base; + const uint32_t bits = fp32_to_bits(base); + const uint32_t exp_bits = (bits >> 13) & UINT32_C(0x00007C00); + const uint32_t mantissa_bits = bits & UINT32_C(0x00000FFF); + const uint32_t nonsign = exp_bits + mantissa_bits; + return static_cast( + (sign >> 16) | + (shl1_w > UINT32_C(0xFF000000) ? UINT16_C(0x7E00) : nonsign)); +#endif // C10_X86_F16 +} + +/* + * Convert a 16-bit floating-point number in IEEE half-precision format, in bit + * representation, to a 32-bit floating-point number in IEEE single-precision + * format, in bit representation. + * + * @note The implementation doesn't use any floating-point operations. + */ +inline uint32_t fp16_ieee_to_fp32_bits(uint16_t h) { + /* + * Extend the half-precision floating-point number to 32 bits and shift to the + * upper part of the 32-bit word: + * +---+-----+------------+-------------------+ + * | S |EEEEE|MM MMMM MMMM|0000 0000 0000 0000| + * +---+-----+------------+-------------------+ + * Bits 31 26-30 16-25 0-15 + * + * S - sign bit, E - bits of the biased exponent, M - bits of the mantissa, 0 + * - zero bits. + */ + const uint32_t w = (uint32_t)h << 16; + /* + * Extract the sign of the input number into the high bit of the 32-bit word: + * + * +---+----------------------------------+ + * | S |0000000 00000000 00000000 00000000| + * +---+----------------------------------+ + * Bits 31 0-31 + */ + const uint32_t sign = w & UINT32_C(0x80000000); + /* + * Extract mantissa and biased exponent of the input number into the bits 0-30 + * of the 32-bit word: + * + * +---+-----+------------+-------------------+ + * | 0 |EEEEE|MM MMMM MMMM|0000 0000 0000 0000| + * +---+-----+------------+-------------------+ + * Bits 30 27-31 17-26 0-16 + */ + const uint32_t nonsign = w & UINT32_C(0x7FFFFFFF); + /* + * Renorm shift is the number of bits to shift mantissa left to make the + * half-precision number normalized. If the initial number is normalized, some + * of its high 6 bits (sign == 0 and 5-bit exponent) equals one. In this case + * renorm_shift == 0. If the number is denormalize, renorm_shift > 0. Note + * that if we shift denormalized nonsign by renorm_shift, the unit bit of + * mantissa will shift into exponent, turning the biased exponent into 1, and + * making mantissa normalized (i.e. without leading 1). + */ +#ifdef _MSC_VER + unsigned long nonsign_bsr; + _BitScanReverse(&nonsign_bsr, (unsigned long)nonsign); + uint32_t renorm_shift = (uint32_t)nonsign_bsr ^ 31; +#else + uint32_t renorm_shift = __builtin_clz(nonsign); +#endif + renorm_shift = renorm_shift > 5 ? renorm_shift - 5 : 0; + /* + * Iff half-precision number has exponent of 15, the addition overflows + * it into bit 31, and the subsequent shift turns the high 9 bits + * into 1. Thus inf_nan_mask == 0x7F800000 if the half-precision number + * had exponent of 15 (i.e. was NaN or infinity) 0x00000000 otherwise + */ + const int32_t inf_nan_mask = + ((int32_t)(nonsign + 0x04000000) >> 8) & INT32_C(0x7F800000); + /* + * Iff nonsign is 0, it overflows into 0xFFFFFFFF, turning bit 31 + * into 1. Otherwise, bit 31 remains 0. The signed shift right by 31 + * broadcasts bit 31 into all bits of the zero_mask. Thus zero_mask == + * 0xFFFFFFFF if the half-precision number was zero (+0.0h or -0.0h) + * 0x00000000 otherwise + */ + const int32_t zero_mask = (int32_t)(nonsign - 1) >> 31; + /* + * 1. Shift nonsign left by renorm_shift to normalize it (if the input + * was denormal) + * 2. Shift nonsign right by 3 so the exponent (5 bits originally) + * becomes an 8-bit field and 10-bit mantissa shifts into the 10 high + * bits of the 23-bit mantissa of IEEE single-precision number. + * 3. Add 0x70 to the exponent (starting at bit 23) to compensate the + * different in exponent bias (0x7F for single-precision number less 0xF + * for half-precision number). + * 4. Subtract renorm_shift from the exponent (starting at bit 23) to + * account for renormalization. As renorm_shift is less than 0x70, this + * can be combined with step 3. + * 5. Binary OR with inf_nan_mask to turn the exponent into 0xFF if the + * input was NaN or infinity. + * 6. Binary ANDNOT with zero_mask to turn the mantissa and exponent + * into zero if the input was zero. + * 7. Combine with the sign of the input number. + */ + return sign | + ((((nonsign << renorm_shift >> 3) + ((0x70 - renorm_shift) << 23)) | + inf_nan_mask) & + ~zero_mask); +} + +#ifdef C10_X86_F16 +#undef C10_X86_F16 +#endif // C10_X86_F16 + +#if defined(__aarch64__) && !defined(__CUDACC__) +inline float16_t fp16_from_bits(uint16_t h) { + return c10::bit_cast(h); +} + +inline uint16_t fp16_to_bits(float16_t f) { + return c10::bit_cast(f); +} + +// According to https://godbolt.org/z/frExdbsWG it would translate to single +// fcvt s0, h0 +inline float native_fp16_to_fp32_value(uint16_t h) { + return static_cast(fp16_from_bits(h)); +} + +inline uint16_t native_fp16_from_fp32_value(float f) { + return fp16_to_bits(static_cast(f)); +} +#endif + +} // namespace detail + +//---------- below is copied from c10/util/Half-inl.h ----------------// +C10_CLANG_DIAGNOSTIC_PUSH() +#if C10_CLANG_HAS_WARNING("-Wimplicit-int-float-conversion") +C10_CLANG_DIAGNOSTIC_IGNORE("-Wimplicit-int-float-conversion") +#endif + +#if defined(__aarch64__) && !defined(__CUDACC__) +/// Constructors +inline Half::Half(float16_t value) : x(detail::fp16_to_bits(value)) {} +inline Half::operator float16_t() const { + return detail::fp16_from_bits(x); +} +#else + +inline C10_HOST_DEVICE Half::Half(float value) + : +#if defined(__CUDA_ARCH__) || defined(__HIP_DEVICE_COMPILE__) + x(__half_as_short(__float2half(value))) +#elif defined(__SYCL_DEVICE_ONLY__) + x(c10::bit_cast(sycl::half(value))) +#elif (defined(CPU_CAPABILITY_AVX2) || defined(CPU_CAPABILITY_AVX512)) && \ + !defined(__APPLE__) + x(at::vec::float2half_scalar(value)) +#else + x(detail::fp16_ieee_from_fp32_value(value)) +#endif +{ +} + +/// Implicit conversions + +inline C10_HOST_DEVICE Half::operator float() const { +#if defined(__CUDA_ARCH__) || defined(__HIP_DEVICE_COMPILE__) + return __half2float(*reinterpret_cast(&x)); +#elif defined(__SYCL_DEVICE_ONLY__) + return float(c10::bit_cast(x)); +#elif (defined(CPU_CAPABILITY_AVX2) || defined(CPU_CAPABILITY_AVX512)) && \ + !defined(__APPLE__) + return at::vec::half2float_scalar(x); +#elif defined(__aarch64__) && !defined(__CUDACC__) + return detail::native_fp16_to_fp32_value(x); +#else + return detail::fp16_ieee_to_fp32_value(x); +#endif +} + +#endif /* !defined(__aarch64__) || defined(__CUDACC__) \ + */ + +#if defined(__CUDACC__) || defined(__HIPCC__) +inline C10_HOST_DEVICE Half::Half(const __half& value) { + x = *reinterpret_cast(&value); +} +inline C10_HOST_DEVICE Half::operator __half() const { + return *reinterpret_cast(&x); +} +#endif + +#ifdef SYCL_LANGUAGE_VERSION +inline C10_HOST_DEVICE Half::Half(const sycl::half& value) { + x = *reinterpret_cast(&value); +} +inline C10_HOST_DEVICE Half::operator sycl::half() const { + return *reinterpret_cast(&x); +} +#endif + +// CUDA intrinsics + +#if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 350)) || \ + (defined(__clang__) && defined(__CUDA__)) +inline __device__ Half __ldg(const Half* ptr) { + return __ldg(reinterpret_cast(ptr)); +} +#endif + +/// Arithmetic + +inline C10_HOST_DEVICE Half operator+(const Half& a, const Half& b) { + return static_cast(a) + static_cast(b); +} + +inline C10_HOST_DEVICE Half operator-(const Half& a, const Half& b) { + return static_cast(a) - static_cast(b); +} + +inline C10_HOST_DEVICE Half operator*(const Half& a, const Half& b) { + return static_cast(a) * static_cast(b); +} + +inline C10_HOST_DEVICE Half operator/(const Half& a, const Half& b) + __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / static_cast(b); +} + +inline C10_HOST_DEVICE Half operator-(const Half& a) { +#if (defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530) || \ + defined(__HIP_DEVICE_COMPILE__) + return __hneg(a); +#elif defined(__SYCL_DEVICE_ONLY__) + return -c10::bit_cast(a); +#else + return -static_cast(a); +#endif +} + +inline C10_HOST_DEVICE Half& operator+=(Half& a, const Half& b) { + a = a + b; + return a; +} + +inline C10_HOST_DEVICE Half& operator-=(Half& a, const Half& b) { + a = a - b; + return a; +} + +inline C10_HOST_DEVICE Half& operator*=(Half& a, const Half& b) { + a = a * b; + return a; +} + +inline C10_HOST_DEVICE Half& operator/=(Half& a, const Half& b) { + a = a / b; + return a; +} + +/// Arithmetic with floats + +inline C10_HOST_DEVICE float operator+(Half a, float b) { + return static_cast(a) + b; +} +inline C10_HOST_DEVICE float operator-(Half a, float b) { + return static_cast(a) - b; +} +inline C10_HOST_DEVICE float operator*(Half a, float b) { + return static_cast(a) * b; +} +inline C10_HOST_DEVICE float operator/(Half a, float b) + __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / b; +} + +inline C10_HOST_DEVICE float operator+(float a, Half b) { + return a + static_cast(b); +} +inline C10_HOST_DEVICE float operator-(float a, Half b) { + return a - static_cast(b); +} +inline C10_HOST_DEVICE float operator*(float a, Half b) { + return a * static_cast(b); +} +inline C10_HOST_DEVICE float operator/(float a, Half b) + __ubsan_ignore_float_divide_by_zero__ { + return a / static_cast(b); +} + +inline C10_HOST_DEVICE float& operator+=(float& a, const Half& b) { + return a += static_cast(b); +} +inline C10_HOST_DEVICE float& operator-=(float& a, const Half& b) { + return a -= static_cast(b); +} +inline C10_HOST_DEVICE float& operator*=(float& a, const Half& b) { + return a *= static_cast(b); +} +inline C10_HOST_DEVICE float& operator/=(float& a, const Half& b) { + return a /= static_cast(b); +} + +/// Arithmetic with doubles + +inline C10_HOST_DEVICE double operator+(Half a, double b) { + return static_cast(a) + b; +} +inline C10_HOST_DEVICE double operator-(Half a, double b) { + return static_cast(a) - b; +} +inline C10_HOST_DEVICE double operator*(Half a, double b) { + return static_cast(a) * b; +} +inline C10_HOST_DEVICE double operator/(Half a, double b) + __ubsan_ignore_float_divide_by_zero__ { + return static_cast(a) / b; +} + +inline C10_HOST_DEVICE double operator+(double a, Half b) { + return a + static_cast(b); +} +inline C10_HOST_DEVICE double operator-(double a, Half b) { + return a - static_cast(b); +} +inline C10_HOST_DEVICE double operator*(double a, Half b) { + return a * static_cast(b); +} +inline C10_HOST_DEVICE double operator/(double a, Half b) + __ubsan_ignore_float_divide_by_zero__ { + return a / static_cast(b); +} + +/// Arithmetic with ints + +inline C10_HOST_DEVICE Half operator+(Half a, int b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return a + static_cast(b); +} +inline C10_HOST_DEVICE Half operator-(Half a, int b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return a - static_cast(b); +} +inline C10_HOST_DEVICE Half operator*(Half a, int b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return a * static_cast(b); +} +inline C10_HOST_DEVICE Half operator/(Half a, int b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return a / static_cast(b); +} + +inline C10_HOST_DEVICE Half operator+(int a, Half b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return static_cast(a) + b; +} +inline C10_HOST_DEVICE Half operator-(int a, Half b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return static_cast(a) - b; +} +inline C10_HOST_DEVICE Half operator*(int a, Half b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return static_cast(a) * b; +} +inline C10_HOST_DEVICE Half operator/(int a, Half b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return static_cast(a) / b; +} + +//// Arithmetic with int64_t + +inline C10_HOST_DEVICE Half operator+(Half a, int64_t b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return a + static_cast(b); +} +inline C10_HOST_DEVICE Half operator-(Half a, int64_t b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return a - static_cast(b); +} +inline C10_HOST_DEVICE Half operator*(Half a, int64_t b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return a * static_cast(b); +} +inline C10_HOST_DEVICE Half operator/(Half a, int64_t b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return a / static_cast(b); +} + +inline C10_HOST_DEVICE Half operator+(int64_t a, Half b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return static_cast(a) + b; +} +inline C10_HOST_DEVICE Half operator-(int64_t a, Half b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return static_cast(a) - b; +} +inline C10_HOST_DEVICE Half operator*(int64_t a, Half b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return static_cast(a) * b; +} +inline C10_HOST_DEVICE Half operator/(int64_t a, Half b) { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions) + return static_cast(a) / b; +} + +/// NOTE: we do not define comparisons directly and instead rely on the implicit +/// conversion from c10::Half to float. + +C10_CLANG_DIAGNOSTIC_POP() + +} // namespace c10 + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly) + +using c10::Half; +using c10::operator+; +using c10::operator-; +using c10::operator*; +using c10::operator/; +using c10::operator+=; +using c10::operator-=; +using c10::operator*=; +using c10::operator/=; +using c10::operator<<; + +namespace detail { +#if defined(__aarch64__) && !defined(__CUDACC__) +using c10::detail::fp16_from_bits; +using c10::detail::fp16_to_bits; +using c10::detail::native_fp16_from_fp32_value; +using c10::detail::native_fp16_to_fp32_value; +#endif + +using c10::detail::fp16_ieee_from_fp32_value; +using c10::detail::fp16_ieee_to_fp32_bits; +using c10::detail::fp16_ieee_to_fp32_value; +} // namespace detail + +HIDDEN_NAMESPACE_END(torch, headeronly) + +namespace std { + +template <> +class numeric_limits { + public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = true; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = true; + static constexpr auto has_denorm = numeric_limits::has_denorm; + static constexpr auto has_denorm_loss = + numeric_limits::has_denorm_loss; + static constexpr auto round_style = numeric_limits::round_style; + static constexpr bool is_iec559 = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 11; + static constexpr int digits10 = 3; + static constexpr int max_digits10 = 5; + static constexpr int radix = 2; + static constexpr int min_exponent = -13; + static constexpr int min_exponent10 = -4; + static constexpr int max_exponent = 16; + static constexpr int max_exponent10 = 4; + static constexpr auto traps = numeric_limits::traps; + static constexpr auto tinyness_before = + numeric_limits::tinyness_before; + static constexpr c10::Half min() { + return c10::Half(0x0400, c10::Half::from_bits()); + } + static constexpr c10::Half lowest() { + return c10::Half(0xFBFF, c10::Half::from_bits()); + } + static constexpr c10::Half max() { + return c10::Half(0x7BFF, c10::Half::from_bits()); + } + static constexpr c10::Half epsilon() { + return c10::Half(0x1400, c10::Half::from_bits()); + } + static constexpr c10::Half round_error() { + return c10::Half(0x3800, c10::Half::from_bits()); + } + static constexpr c10::Half infinity() { + return c10::Half(0x7C00, c10::Half::from_bits()); + } + static constexpr c10::Half quiet_NaN() { + return c10::Half(0x7E00, c10::Half::from_bits()); + } + static constexpr c10::Half signaling_NaN() { + return c10::Half(0x7D00, c10::Half::from_bits()); + } + static constexpr c10::Half denorm_min() { + return c10::Half(0x0001, c10::Half::from_bits()); + } +}; + +} // namespace std diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/HeaderOnlyArrayRef.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/HeaderOnlyArrayRef.h new file mode 100644 index 0000000000000000000000000000000000000000..751ffef32bb1da3a00f3735f9f7200d805f3f9d2 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/HeaderOnlyArrayRef.h @@ -0,0 +1,248 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace c10 { + +/// HeaderOnlyArrayRef - A subset of ArrayRef that is implemented only +/// in headers. This will be a base class from which ArrayRef inherits, so that +/// we can keep much of the implementation shared. +/// +/// [HeaderOnlyArrayRef vs ArrayRef note] +/// As HeaderOnlyArrayRef is a subset of ArrayRef, it has slightly less +/// functionality than ArrayRef. We document the minor differences below: +/// 1. ArrayRef has an extra convenience constructor for SmallVector. +/// 2. ArrayRef uses TORCH_CHECK. HeaderOnlyArrayRef uses header-only +/// STD_TORCH_CHECK, which will output a std::runtime_error vs a +/// c10::Error. Consequently, you should use ArrayRef when possible +/// and HeaderOnlyArrayRef only when necessary to support headeronly code. +/// In all other aspects, HeaderOnlyArrayRef is identical to ArrayRef, with the +/// positive benefit of being header-only and thus independent of libtorch.so. +template +class HeaderOnlyArrayRef { + public: + using iterator = const T*; + using const_iterator = const T*; + using size_type = size_t; + using value_type = T; + + using reverse_iterator = std::reverse_iterator; + + protected: + /// The start of the array, in an external buffer. + const T* Data; + + /// The number of elements. + size_type Length; + + public: + /// @name Constructors + /// @{ + + /// Construct an empty HeaderOnlyArrayRef. + /* implicit */ constexpr HeaderOnlyArrayRef() : Data(nullptr), Length(0) {} + + /// Construct a HeaderOnlyArrayRef from a single element. + // TODO Make this explicit + constexpr HeaderOnlyArrayRef(const T& OneElt) : Data(&OneElt), Length(1) {} + + /// Construct a HeaderOnlyArrayRef from a pointer and length. + constexpr HeaderOnlyArrayRef(const T* data, size_t length) + : Data(data), Length(length) {} + + /// Construct a HeaderOnlyArrayRef from a range. + constexpr HeaderOnlyArrayRef(const T* begin, const T* end) + : Data(begin), Length(end - begin) {} + + template < + typename Container, + typename U = decltype(std::declval().data()), + typename = std::enable_if_t< + (std::is_same_v || std::is_same_v)>> + /* implicit */ HeaderOnlyArrayRef(const Container& container) + : Data(container.data()), Length(container.size()) {} + + /// Construct a HeaderOnlyArrayRef from a std::vector. + // The enable_if stuff here makes sure that this isn't used for + // std::vector, because ArrayRef can't work on a std::vector + // bitfield. + template + /* implicit */ HeaderOnlyArrayRef(const std::vector& Vec) + : Data(Vec.data()), Length(Vec.size()) { + static_assert( + !std::is_same_v, + "HeaderOnlyArrayRef cannot be constructed from a std::vector bitfield."); + } + + /// Construct a HeaderOnlyArrayRef from a std::array + template + /* implicit */ constexpr HeaderOnlyArrayRef(const std::array& Arr) + : Data(Arr.data()), Length(N) {} + + /// Construct a HeaderOnlyArrayRef from a C array. + template + // NOLINTNEXTLINE(*c-arrays*) + /* implicit */ constexpr HeaderOnlyArrayRef(const T (&Arr)[N]) + : Data(Arr), Length(N) {} + + /// Construct a HeaderOnlyArrayRef from a std::initializer_list. + /* implicit */ constexpr HeaderOnlyArrayRef( + const std::initializer_list& Vec) + : Data( + std::begin(Vec) == std::end(Vec) ? static_cast(nullptr) + : std::begin(Vec)), + Length(Vec.size()) {} + + /// @} + /// @name Simple Operations + /// @{ + + constexpr iterator begin() const { + return this->Data; + } + constexpr iterator end() const { + return this->Data + this->Length; + } + + // These are actually the same as iterator, since ArrayRef only + // gives you const iterators. + constexpr const_iterator cbegin() const { + return this->Data; + } + constexpr const_iterator cend() const { + return this->Data + this->Length; + } + + constexpr reverse_iterator rbegin() const { + return reverse_iterator(end()); + } + constexpr reverse_iterator rend() const { + return reverse_iterator(begin()); + } + + /// Check if all elements in the array satisfy the given expression + constexpr bool allMatch(const std::function& pred) const { + return std::all_of(cbegin(), cend(), pred); + } + + /// empty - Check if the array is empty. + constexpr bool empty() const { + return this->Length == 0; + } + + constexpr const T* data() const { + return this->Data; + } + + /// size - Get the array size. + constexpr size_t size() const { + return this->Length; + } + + /// front - Get the first element. + constexpr const T& front() const { + STD_TORCH_CHECK( + !this->empty(), + "HeaderOnlyArrayRef: attempted to access front() of empty list"); + return this->Data[0]; + } + + /// back - Get the last element. + constexpr const T& back() const { + STD_TORCH_CHECK( + !this->empty(), + "HeaderOnlyArrayRef: attempted to access back() of empty list"); + return this->Data[this->Length - 1]; + } + + /// equals - Check for element-wise equality. + constexpr bool equals(HeaderOnlyArrayRef RHS) const { + return this->Length == RHS.Length && + std::equal(begin(), end(), RHS.begin()); + } + + /// slice(n, m) - Take M elements of the array starting at element N + constexpr HeaderOnlyArrayRef slice(size_t N, size_t M) const { + STD_TORCH_CHECK( + N + M <= this->size(), + "HeaderOnlyArrayRef: invalid slice, N = ", + N, + "; M = ", + M, + "; size = ", + this->size()); + return HeaderOnlyArrayRef(this->data() + N, M); + } + + /// slice(n) - Chop off the first N elements of the array. + constexpr HeaderOnlyArrayRef slice(size_t N) const { + STD_TORCH_CHECK( + N <= this->size(), + "HeaderOnlyArrayRef: invalid slice, N = ", + N, + "; size = ", + this->size()); + return slice(N, this->size() - N); + } + + /// @} + /// @name Operator Overloads + /// @{ + constexpr const T& operator[](size_t Index) const { + return this->Data[Index]; + } + + /// Vector compatibility + constexpr const T& at(size_t Index) const { + STD_TORCH_CHECK( + Index < this->Length, + "HeaderOnlyArrayRef: invalid index Index = ", + Index, + "; Length = ", + this->Length); + return this->Data[Index]; + } + + /// Disallow accidental assignment from a temporary. + /// + /// The declaration here is extra complicated so that "arrayRef = {}" + /// continues to select the move assignment operator. + template + std::enable_if_t, HeaderOnlyArrayRef>& operator=( + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) + U&& Temporary) = delete; + + /// Disallow accidental assignment from a temporary. + /// + /// The declaration here is extra complicated so that "arrayRef = {}" + /// continues to select the move assignment operator. + template + std::enable_if_t, HeaderOnlyArrayRef>& operator=( + std::initializer_list) = delete; + + /// @} + /// @name Expensive Operations + /// @{ + std::vector vec() const { + return std::vector(this->Data, this->Data + this->Length); + } + + /// @} +}; + +} // namespace c10 + +namespace torch::headeronly { +using c10::HeaderOnlyArrayRef; +using IntHeaderOnlyArrayRef = HeaderOnlyArrayRef; +} // namespace torch::headeronly diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Metaprogramming.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Metaprogramming.h new file mode 100644 index 0000000000000000000000000000000000000000..2589f338d35dbcf569e15966a788dd16130c0681 --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/Metaprogramming.h @@ -0,0 +1,237 @@ +#pragma once + +#include +#include +#include + +namespace c10::guts { + +/** + * Access information about result type or arguments from a function type. + * Example: + * using A = function_traits::return_type // A == int + * using A = function_traits::parameter_types::tuple_type + * // A == tuple + */ +template +struct function_traits { + static_assert( + !std::is_same_v, + "In function_traits, Func must be a plain function type."); +}; +template +struct function_traits { + using func_type = Result(Args...); + using return_type = Result; + using parameter_types = typelist::typelist; + static constexpr auto number_of_parameters = sizeof...(Args); +}; + +/** + * infer_function_traits: creates a `function_traits` type for a simple + * function (pointer) or functor (lambda/struct). Currently does not support + * class methods. + */ + +template +struct infer_function_traits { + using type = function_traits< + c10::guts::detail::strip_class_t>; +}; + +template +struct infer_function_traits { + using type = function_traits; +}; + +template +struct infer_function_traits { + using type = function_traits; +}; + +template +using infer_function_traits_t = typename infer_function_traits::type; + +/** + * make_function_traits: creates a `function_traits` type given a Return type + * and a typelist of Argument types + * + * Example: + * bool f(int, int); + * + * infer_function_traits_t == make_function_traits_t> + */ +template +struct make_function_traits { + static_assert( + false_t::value, + "In guts::make_function_traits, the ArgList argument must be typelist<...>."); +}; + +template +struct make_function_traits> { + using type = function_traits; +}; + +template +using make_function_traits_t = + typename make_function_traits::type; + +/** + * make_offset_index_sequence + * Like make_index_sequence, but starting from Start instead of 0. + * + * Example: + * make_offset_index_sequence<10, 3> == std::index_sequence<10, 11, 12> + */ +template +struct make_offset_index_sequence_impl + : make_offset_index_sequence_impl { + static_assert( + static_cast(Start) >= 0, + "make_offset_index_sequence: Start < 0"); + static_assert(static_cast(N) >= 0, "make_offset_index_sequence: N < 0"); +}; + +template +struct make_offset_index_sequence_impl { + typedef std::index_sequence type; +}; + +template +using make_offset_index_sequence = + typename make_offset_index_sequence_impl::type; + +/** + * Use tuple_elements to extract a position-indexed subset of elements + * from the argument tuple into a result tuple. + * + * Example: + * std::tuple t = std::make_tuple(0, "HEY", 2.0); + * std::tuple result = tuple_elements(t, std::index_sequence<0, + * 2>()); + */ +template +constexpr auto tuple_elements(Tuple t, std::index_sequence /*unused*/) { + return std::tuple...>(std::get(t)...); +} + +/** + * Use tuple_take to extract the first or last n elements from the argument + * tuple into a result tuple. + * + * Example: + * std::tuple t = std::make_tuple(0, "HEY", 2.0); + * std::tuple first_two = tuple_take(t); + * std::tuple last_two = tuple_take(t); + */ +template +struct TupleTake {}; + +template +struct TupleTake= 0, void>> { + static auto call(Tuple t) { + constexpr size_t size = std::tuple_size(); + static_assert(N <= size, "tuple_take: N > size"); + return tuple_elements(t, std::make_index_sequence{}); + } +}; + +template + struct TupleTake < Tuple, + N, std::enable_if_t> { + static auto call(Tuple t) { + constexpr size_t size = std::tuple_size(); + static_assert(-N <= size, "tuple_take: -N > size"); + return tuple_elements(t, make_offset_index_sequence{}); + } +}; + +template +auto tuple_take(Tuple t) { + return TupleTake::call(t); +} + +/** + * Use tuple_slice to extract a contiguous subtuple from the argument. + * + * Example: + * std::tuple t = std::make_tuple(0, + * "HEY", 2.0, false); std::tuple middle_two = + * tuple_slice(t); + */ +template +constexpr auto tuple_slice(Tuple t) { + constexpr size_t size = std::tuple_size(); + static_assert(Start + N <= size, "tuple_slice: Start + N > size"); + return tuple_elements(t, make_offset_index_sequence{}); +} + +/** + * Use tuple_map to run a mapping function over a tuple to get a new tuple. + * + * Example 1: + * auto result = tuple_map(std::tuple(3, 4, 5), [] + * (int32_t a) -> int16_t {return a+1;}); + * // result == std::tuple(4, 5, 6) + * + * Example 2: + * struct Mapper { + * std::string operator()(int32_t a) const { + * return std::to_string(a); + * } + * int64_t operator()(const std::string& a) const { + * return atoi(a.c_str()); + * } + * }; + * auto result = tuple_map(std::tuple(3, "4"), + * Mapper()); + * // result == std::tuple("3", 4) + * + * Example 3: + * struct A final { + * int32_t func() { + * return 5; + * } + * }; + * struct B final { + * std::string func() { + * return "5"; + * } + * }; + * auto result = tuple_map(std::make_tuple(A(), B()), [] (auto a) { return + * a.func(); }); + * // result == std::tuple(5, "5"); + */ +namespace detail { +template +auto tuple_map( + // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved) + std::tuple&& tuple, + const Mapper& mapper, + std::index_sequence /*unused*/) { + return std::tuple(std::get( + tuple))))...>(mapper(std::forward(std::get(tuple)))...); +} +} // namespace detail + +template +auto tuple_map(std::tuple&& tuple, const Mapper& mapper) { + return detail::tuple_map( + std::move(tuple), mapper, std::index_sequence_for()); +} + +} // namespace c10::guts + +HIDDEN_NAMESPACE_BEGIN(torch, headeronly, guts) + +using c10::guts::function_traits; +using c10::guts::infer_function_traits_t; +using c10::guts::make_function_traits_t; +using c10::guts::tuple_elements; +using c10::guts::tuple_map; +using c10::guts::tuple_slice; +using c10::guts::tuple_take; + +HIDDEN_NAMESPACE_END(torch, headeronly, guts) diff --git a/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/TypeList.h b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/TypeList.h new file mode 100644 index 0000000000000000000000000000000000000000..cd81f0cc1dcf97e0444ace259be265693c2935ec --- /dev/null +++ b/workspace/outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/headeronly/util/TypeList.h @@ -0,0 +1,548 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace c10::guts { + +template +struct false_t : std::false_type {}; +template