Files
paddlepaddle--paddle/paddle/fluid/pybind/place.cc
T
2026-07-13 12:40:42 +08:00

742 lines
32 KiB
C++

/* Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
Copyright (c) 2022 NVIDIA Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
#include <Python.h>
#include <algorithm>
#include <cctype>
#include <cstdlib>
#include <iterator>
#include <map>
#include <memory>
#include <mutex> // NOLINT // for call_once
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#include "paddle/fluid/framework/convert_utils.h"
#include "paddle/fluid/framework/custom_operator.h"
#include "paddle/fluid/framework/data_layout.h"
#include "paddle/fluid/framework/data_type_transform.h"
#include "paddle/fluid/framework/dense_tensor_array.h"
#include "paddle/fluid/framework/dlpack_tensor.h"
#include "paddle/fluid/framework/executor.h"
#include "paddle/fluid/framework/executor_cache.h"
#include "paddle/fluid/framework/executor_gc_helper.h"
#include "paddle/fluid/framework/feed_fetch_method.h"
#include "paddle/fluid/framework/feed_fetch_type.h"
#include "paddle/fluid/framework/garbage_collector.h"
#include "paddle/fluid/framework/io/fs.h"
#include "paddle/fluid/framework/ir/coalesce_grad_tensor_pass.h"
#include "paddle/fluid/framework/ir/cost_model.h"
#include "paddle/fluid/framework/ir/generate_pass.h"
#include "paddle/fluid/framework/ir/pass_builder.h"
#include "paddle/fluid/framework/new_executor/executor_statistics.h"
#include "paddle/fluid/framework/new_executor/standalone_executor.h"
#include "paddle/fluid/framework/op_info.h"
#include "paddle/fluid/framework/op_registry.h"
#include "paddle/fluid/framework/op_version_registry.h"
#include "paddle/fluid/framework/phi_utils.h"
#include "paddle/fluid/framework/prune.h"
#include "paddle/fluid/framework/scope_pool.h"
#include "paddle/fluid/framework/selected_rows_utils.h"
#include "paddle/fluid/framework/tensor_util.h"
#include "paddle/fluid/framework/trainer.h"
#include "paddle/fluid/framework/type_defs.h"
#include "paddle/fluid/framework/version.h"
#include "paddle/fluid/imperative/amp_auto_cast.h"
#include "paddle/fluid/imperative/layer.h"
#include "paddle/phi/core/framework/reader.h"
#include "paddle/phi/core/memory/allocation/allocator_strategy.h"
#ifdef PADDLE_WITH_CUDA
#include "paddle/phi/core/memory/allocation/cuda_ipc_allocator.h"
#endif
#include "paddle/fluid/platform/enforce.h"
#include "paddle/fluid/platform/init.h"
#include "paddle/fluid/platform/profiler/event_python.h"
#include "paddle/fluid/platform/profiler/profiler.h"
#include "paddle/fluid/pybind/bind_cost_model.h"
#include "paddle/fluid/pybind/communication.h"
#include "paddle/fluid/pybind/compatible.h"
#include "paddle/fluid/pybind/const_value.h"
#include "paddle/fluid/pybind/cuda_streams_py.h"
#include "paddle/fluid/pybind/data_set_py.h"
#include "paddle/fluid/pybind/distributed_py.h"
#include "paddle/fluid/pybind/eager.h"
#include "paddle/fluid/pybind/exception.h"
#include "paddle/fluid/pybind/fleet_wrapper_py.h"
#include "paddle/fluid/pybind/generator_py.h"
#include "paddle/fluid/pybind/global_value_getter_setter.h"
#include "paddle/fluid/pybind/gloo_context_py.h"
#include "paddle/fluid/pybind/gloo_wrapper_py.h"
#include "paddle/fluid/pybind/graph.h"
#include "paddle/fluid/pybind/imperative.h"
#include "paddle/fluid/pybind/inference_api.h"
#include "paddle/fluid/pybind/io.h"
#include "paddle/fluid/pybind/pybind_variant_caster.h"
#include "paddle/phi/backends/cpu/cpu_info.h"
#include "paddle/phi/backends/device_manager.h"
#include "paddle/phi/backends/dynload/dynamic_loader.h"
#include "paddle/phi/common/place.h"
#include "paddle/phi/core/compat/convert_utils.h"
#include "paddle/phi/core/lod_utils.h"
#include "paddle/phi/core/memory/allocation/mmap_allocator.h"
#include "paddle/phi/core/platform/cpu_helper.h"
#include "paddle/phi/core/platform/device/device_wrapper.h"
#include "paddle/phi/core/platform/device_context.h"
#include "paddle/phi/core/platform/monitor.h"
#include "paddle/phi/core/platform/profiler.h"
#include "paddle/phi/core/platform/profiler/event_tracing.h"
#include "paddle/utils/none.h"
#if defined(PADDLE_WITH_NCCL) || defined(PADDLE_WITH_RCCL)
#include "paddle/fluid/pybind/nccl_wrapper_py.h"
#endif
#include "paddle/fluid/framework/data_type.h"
#include "paddle/fluid/pybind/protobuf.h"
#include "paddle/fluid/pybind/pybind.h" // NOLINT
#include "paddle/fluid/pybind/reader_py.h"
#include "paddle/fluid/pybind/tensor_py.h"
#include "paddle/utils/string/to_string.h"
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
#if defined(PADDLE_WITH_NCCL) || defined(PADDLE_WITH_RCCL)
#include "paddle/fluid/operators/nccl/nccl_gpu_common.h"
#endif
#ifndef PADDLE_WITH_HIP
#include "paddle/phi/core/platform/device/gpu/cuda/cuda_profiler.h"
#endif
#include "paddle/phi/core/platform/device/gpu/gpu_info.h"
#endif
#ifdef PADDLE_WITH_XPU
#include "paddle/phi/core/platform/device/xpu/xpu_info.h"
#include "paddle/phi/core/platform/device/xpu/xpu_op_list.h"
#endif
#ifdef PADDLE_WITH_CUSTOM_DEVICE
#include "paddle/phi/capi/capi.h"
#endif
#include "paddle/phi/core/platform/cuda_graph_with_memory_pool.h"
#ifdef PADDLE_WITH_IPU
#include "paddle/fluid/platform/device/ipu/ipu_backend.h"
#include "paddle/fluid/platform/device/ipu/ipu_info.h"
#endif
#ifdef PADDLE_WITH_CRYPTO
#include "paddle/fluid/pybind/crypto.h"
#endif
#include "paddle/common/flags.h"
#include "paddle/fluid/eager/api/utils/global_utils.h"
#include "paddle/fluid/imperative/layout_autotune.h"
#include "paddle/fluid/pybind/eager_utils.h"
#include "paddle/fluid/pybind/place.h"
#include "paddle/phi/api/ext/op_meta_info.h"
#include "paddle/phi/kernels/autotune/cache.h"
#include "paddle/phi/kernels/autotune/switch_autotune.h"
#include "pybind11/stl.h"
COMMON_DECLARE_bool(use_mkldnn);
COMMON_DECLARE_bool(use_onednn);
// disable auto conversion to list in Python
PYBIND11_MAKE_OPAQUE(phi::TensorArray);
PYBIND11_MAKE_OPAQUE(paddle::framework::FetchUnmergedList);
PYBIND11_MAKE_OPAQUE(paddle::framework::FetchList);
PYBIND11_MAKE_OPAQUE(paddle::framework::FetchType);
namespace paddle::pybind {
PyTypeObject *g_place_pytype = nullptr;
PyTypeObject *g_customplace_pytype = nullptr;
PyTypeObject *g_cudaplace_pytype = nullptr;
PyTypeObject *g_cpuplace_pytype = nullptr;
PyTypeObject *g_xpuplace_pytype = nullptr;
PyTypeObject *g_cudapinnedplace_pytype = nullptr;
PyTypeObject *g_xpupinnedplace_pytype = nullptr;
PyTypeObject *g_ipuplace_pytype = nullptr;
template <typename PlaceType>
static inline int PlaceIndex(const PlaceType &p) { // NOLINT
return static_cast<int>(Place(p).GetType());
}
template <typename PlaceType1, typename PlaceType2>
static inline bool IsSamePlace(const PlaceType1 &p1, const PlaceType2 &p2) {
if (std::is_same_v<PlaceType1, Place> || std::is_same_v<PlaceType2, Place> ||
std::is_same_v<PlaceType1, PlaceType2>) {
return Place(p1) == Place(p2);
}
return false;
}
void BindPlace(pybind11::module &m) { // NOLINT
using namespace paddle::framework; // NOLINT
py::class_<Place> platformplace(m, "Place");
g_place_pytype = reinterpret_cast<PyTypeObject *>(platformplace.ptr());
platformplace.def(py::init<>())
.def("_type", &PlaceIndex<Place>)
.def("_equals", &IsSamePlace<Place, Place>)
.def("_equals", &IsSamePlace<Place, GPUPlace>)
.def("_equals", &IsSamePlace<Place, CPUPlace>)
.def("_equals", &IsSamePlace<Place, phi::XPUPlace>)
.def("_equals", &IsSamePlace<Place, phi::IPUPlace>)
.def("_equals", &IsSamePlace<Place, phi::GPUPinnedPlace>)
.def("_equals", &IsSamePlace<Place, phi::XPUPinnedPlace>)
.def("_equals", &IsSamePlace<Place, phi::CustomPlace>)
.def("__eq__",
[](const py::object &self, const py::object &other) -> bool {
if (py::isinstance<Place>(other)) {
return self.attr("_equals")(other).cast<bool>();
}
return false;
})
.def("__hash__", [](const Place &self) { return Place::Hash()(self); })
.def("is_gpu_place", [](Place &self) { return phi::is_gpu_place(self); })
.def("is_cpu_place", [](Place &self) { return phi::is_cpu_place(self); })
.def("is_xpu_place", [](Place &self) { return phi::is_xpu_place(self); })
.def("is_ipu_place", [](Place &self) { return phi::is_ipu_place(self); })
.def("is_cuda_pinned_place",
[](Place &self) { return phi::is_cuda_pinned_place(self); })
.def("is_xpu_pinned_place",
[](Place &self) { return phi::is_xpu_pinned_place(self); })
.def("is_custom_place",
[](Place &self) { return phi::is_custom_place(self); })
.def("gpu_device_id", [](Place &self) { return self.device; })
.def("xpu_device_id", [](Place &self) { return self.device; })
.def("ipu_device_id", [](Place &self) { return self.device; })
.def("custom_device_id", [](Place &self) { return self.device; })
.def("custom_device_type",
[](Place &self) { return self.GetDeviceType(); })
.def("set_place", [](Place &self, const Place &other) { self = other; })
.def("set_place",
[](Place &self, const CPUPlace &cpu_place) { self = cpu_place; })
.def(
"set_place",
[](Place &self, const phi::XPUPlace &xpu_place) { self = xpu_place; })
.def("set_place",
[](Place &self, const GPUPlace &gpu_place) { self = gpu_place; })
.def("set_place",
[](Place &self, const phi::GPUPinnedPlace &cuda_pinned_place) {
self = cuda_pinned_place;
})
.def("set_place",
[](Place &self, const phi::XPUPinnedPlace &xpu_pinned_place) {
self = xpu_pinned_place;
})
.def(
"set_place",
[](Place &self, const phi::IPUPlace &ipu_place) { self = ipu_place; })
.def("set_place",
[](Place &self, const phi::CustomPlace &plug_place) {
self = plug_place;
})
.def("__dlpack_device__",
[](const Place &self) {
::DLDevice dl_device = paddle::framework::PlaceToDLDevice(self);
return py::make_tuple(static_cast<int32_t>(dl_device.device_type),
dl_device.device_id);
})
.def("__repr__", string::to_string<const Place &>)
.def("__str__", string::to_string<const Place &>);
py::class_<phi::CustomPlace, Place> customplace(m,
"CustomPlace",
R"DOC(
CustomPlace is a descriptor of a device.
It represents a custom device on which a tensor will be allocated and a model will run.
Examples:
.. code-block:: pycon
>>> # doctest: +REQUIRES(env:CUSTOM_DEVICE)
>>> import paddle
>>> fake_cpu_place = paddle.CustomPlace("FakeCPU", 0)
)DOC");
g_customplace_pytype = reinterpret_cast<PyTypeObject *>(customplace.ptr());
customplace
.def("__init__",
[](phi::CustomPlace &self,
const std::string &device_type,
int dev_id) {
#ifdef PADDLE_WITH_CUSTOM_DEVICE
if (UNLIKELY(dev_id < 0)) {
LOG(ERROR) << string::Sprintf(
"Invalid CustomPlace(%s, %d), device id must be 0 "
"or "
"positive integer",
device_type,
dev_id);
PADDLE_THROW(::common::errors::InvalidArgument(
"use wrong place, Please check."));
}
if (LIKELY(phi::DeviceManager::HasDeviceType(device_type) &&
phi::DeviceManager::IsCustom(device_type))) {
int dev_count = static_cast<int>(
phi::DeviceManager::GetDeviceCount(device_type));
if (UNLIKELY(dev_id >= dev_count)) {
if (dev_count == 0) {
#if defined(PADDLE_WITH_CUDA)
LOG(ERROR)
<< "Cannot use " << device_type
<< " because there is no " << device_type
<< " detected on your machine."
<< "Please check your environment variables "
"and device configuration. "
<< "Device type: " << device_type
<< ", CUDA_VISIBLE_DEVICES: "
<< std::getenv("CUDA_VISIBLE_DEVICES")
#else
LOG(ERROR) << "Cannot use " << device_type
<< " because there is no " << device_type
<< " detected on your machine.";
#endif
PADDLE_THROW(::common::errors::InvalidArgument(
"use wrong place, Please check."));
} else {
LOG(ERROR) << string::Sprintf(
"Invalid CustomPlace(%s, %d), dev_id must "
"inside "
"[0, %d), because %s "
"number on your machine is %d",
device_type,
dev_id,
dev_count,
device_type,
dev_count);
PADDLE_THROW(::common::errors::InvalidArgument(
"use wrong place, Please check."));
}
}
new (&self) phi::CustomPlace(device_type, dev_id);
} else {
LOG(ERROR) << string::Sprintf(
"Invalid CustomPlace(%s, %d), the device type is "
"not registered "
"as a custom device.",
device_type,
dev_id);
PADDLE_THROW(::common::errors::InvalidArgument(
"use wrong place, Please check."));
}
#else
LOG(ERROR) << string::Sprintf(
"Cannot use CustomDevice because you have installed CPU/GPU "
"version PaddlePaddle.\n"
"If you want to use CustomDevice, please try to install "
"CustomDevice version "
"PaddlePaddle by: pip install paddlepaddle\n"
"If you only have CPU, please change "
"CustomPlace(%s, %d) to be CPUPlace().\n",
device_type, dev_id);
PADDLE_THROW(::common::errors::InvalidArgument(
"use wrong place, Please check."));
#endif
})
.def("_type", &PlaceIndex<phi::CustomPlace>)
.def("get_device_id",
[](const phi::CustomPlace &self) { return self.GetDeviceId(); })
.def("get_device_type",
[](const phi::CustomPlace &self) { return self.GetDeviceType(); })
.def("__repr__", string::to_string<const phi::CustomPlace &>)
.def("__str__", string::to_string<const phi::CustomPlace &>);
#if defined(PADDLE_WITH_CUSTOM_DEVICE)
m.def("is_float16_supported", [](const phi::CustomPlace &place) -> bool {
return phi::DeviceManager::IsFloat16Supported(place);
});
m.def("is_bfloat16_supported", [](const phi::CustomPlace &place) -> bool {
return phi::DeviceManager::IsBFloat16Supported(place);
});
#endif
py::class_<GPUPlace, Place> cudaplace(m, "CUDAPlace", R"DOC(
CUDAPlace is a descriptor of a device.
It represents a GPU device allocated or to be allocated with Tensor.
Each CUDAPlace has a dev_id to indicate the graphics card ID represented by the current CUDAPlace,
staring from 0.
The memory of CUDAPlace with different dev_id is not accessible.
Numbering here refers to the logical ID of the visible graphics card, not the actual ID of the graphics card.
You can set visible GPU devices by setting the `CUDA_VISIBLE_DEVICES` environment variable.
When the program starts, visible GPU devices will be numbered from 0.
If `CUDA_VISIBLE_DEVICES` is not set, all devices are visible by default,
and the logical ID is the same as the actual ID.
Parameters:
id (int): GPU device ID.
Examples:
.. code-block:: pycon
>>> # doctest: +REQUIRES(env:GPU)
>>> import paddle
>>> place = paddle.CUDAPlace(0)
)DOC");
g_cudaplace_pytype = reinterpret_cast<PyTypeObject *>(cudaplace.ptr());
cudaplace
.def("__init__",
[](GPUPlace &self, int dev_id) {
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
if (UNLIKELY(dev_id < 0)) {
LOG(ERROR) << string::Sprintf(
"Invalid CUDAPlace(%d), device id must be 0 or "
"positive integer",
dev_id);
PADDLE_THROW(::common::errors::InvalidArgument(
"use wrong place, Please check."));
}
if (UNLIKELY(dev_id >= platform::GetGPUDeviceCount())) {
if (platform::GetGPUDeviceCount() == 0) {
LOG(ERROR) << "Cannot use GPU because there is no GPU "
"detected on your "
"machine.";
PADDLE_THROW(::common::errors::InvalidArgument(
"use wrong place, Please check."));
} else {
LOG(ERROR) << string::Sprintf(
"Invalid CUDAPlace(%d), must inside [0, %d), because GPU "
"number on your machine is %d",
dev_id,
platform::GetGPUDeviceCount(),
platform::GetGPUDeviceCount());
PADDLE_THROW(::common::errors::InvalidArgument(
"use wrong place, Please check."));
}
}
new (&self) GPUPlace(dev_id);
#else
LOG(ERROR) << string::Sprintf(
"Cannot use GPU because you have installed CPU version "
"PaddlePaddle.\n"
"If you want to use GPU, please try to install GPU version "
"PaddlePaddle by: pip install paddlepaddle-gpu\n"
"If you only have CPU, please change CUDAPlace(%d) to be "
"CPUPlace().\n",
dev_id);
PADDLE_THROW(::common::errors::InvalidArgument(
"use wrong place, Please check."));
#endif
})
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
.def("get_device_id",
[](const GPUPlace &self) { return self.GetDeviceId(); })
.def("_type", &PlaceIndex<GPUPlace>)
.def("_equals", &IsSamePlace<GPUPlace, Place>)
.def("_equals", &IsSamePlace<GPUPlace, GPUPlace>)
.def("_equals", &IsSamePlace<GPUPlace, CPUPlace>)
.def("_equals", &IsSamePlace<GPUPlace, phi::XPUPlace>)
.def("_equals", &IsSamePlace<GPUPlace, phi::GPUPinnedPlace>)
.def("_equals", &IsSamePlace<GPUPlace, phi::XPUPinnedPlace>)
.def("_get_device_id",
[](GPUPlace &self) -> int { return self.GetDeviceId(); })
#endif
.def("__repr__", string::to_string<const GPUPlace &>)
.def("__str__", string::to_string<const GPUPlace &>);
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
m.def("is_float16_supported", [](const GPUPlace &place) -> bool {
// Only GPUs with Compute Capability >= 53 support float16
#ifdef PADDLE_WITH_HIP
return true;
#else
return platform::GetGPUComputeCapability(place.device) >= 53;
#endif
});
m.def("is_bfloat16_supported", [](const GPUPlace &place) -> bool {
// Only GPUs with Compute Capability >= 80 support bfloat16
#ifdef PADDLE_WITH_HIP
return true;
#else
return platform::GetGPUComputeCapability(place.device) >= 80;
#endif
});
#endif
py::class_<phi::XPUPlace, Place> xpuplace(m, "XPUPlace", R"DOC(
Return a Baidu Kunlun Place
Examples:
.. code-block:: pycon
>>> # doctest: +REQUIRES(env:XPU)
>>> import paddle.base as base
>>> xpu_place = base.XPUPlace(0)
)DOC");
g_xpuplace_pytype = reinterpret_cast<PyTypeObject *>(xpuplace.ptr());
xpuplace
.def("__init__",
[](phi::XPUPlace &self, int dev_id) {
#ifdef PADDLE_WITH_XPU
if (UNLIKELY(dev_id < 0)) {
LOG(ERROR) << string::Sprintf(
"Invalid XPUPlace(%d), device id must be 0 or "
"positive integer",
dev_id);
PADDLE_THROW(::common::errors::InvalidArgument(
"use wrong place, Please check."));
}
if (UNLIKELY(dev_id >= platform::GetXPUDeviceCount())) {
if (platform::GetXPUDeviceCount() == 0) {
LOG(ERROR) << "Cannot use XPU because there is no XPU "
"detected on your "
"machine.";
PADDLE_THROW(::common::errors::InvalidArgument(
"use wrong place, Please check."));
} else {
LOG(ERROR) << string::Sprintf(
"Invalid XPUPlace(%d), must inside [0, %d), because XPU "
"number on your machine is %d",
dev_id,
platform::GetXPUDeviceCount(),
platform::GetXPUDeviceCount());
PADDLE_THROW(::common::errors::InvalidArgument(
"use wrong place, Please check."));
}
}
new (&self) phi::XPUPlace(dev_id);
#else
LOG(ERROR) << string::Sprintf(
"Cannot use XPU because you have installed CPU/GPU version "
"PaddlePaddle.\n"
"If you want to use XPU, please try to install XPU version "
"PaddlePaddle by: pip install paddlepaddle-xpu\n"
"If you only have CPU, please change XPUPlace(%d) to be "
"CPUPlace().\n",
dev_id);
PADDLE_THROW(::common::errors::InvalidArgument(
"use wrong place, Please check."));
#endif
})
#ifdef PADDLE_WITH_XPU
.def("_type", &PlaceIndex<phi::XPUPlace>)
.def("_equals", &IsSamePlace<phi::XPUPlace, Place>)
.def("_equals", &IsSamePlace<phi::XPUPlace, GPUPlace>)
.def("_equals", &IsSamePlace<phi::XPUPlace, CPUPlace>)
.def("_equals", &IsSamePlace<phi::XPUPlace, phi::XPUPlace>)
.def("_equals", &IsSamePlace<phi::XPUPlace, phi::GPUPinnedPlace>)
.def("_equals", &IsSamePlace<phi::XPUPlace, phi::XPUPinnedPlace>)
.def("get_device_id",
[](const phi::XPUPlace &self) { return self.GetDeviceId(); })
#endif
.def("__repr__", string::to_string<const phi::XPUPlace &>)
.def("__str__", string::to_string<const phi::XPUPlace &>);
#ifdef PADDLE_WITH_XPU
py::enum_<phi::backends::xpu::XPUVersion>(m, "XPUVersion", py::arithmetic())
.value("XPU1", phi::backends::xpu::XPUVersion::XPU1)
.value("XPU2", phi::backends::xpu::XPUVersion::XPU2)
.value("XPU3", phi::backends::xpu::XPUVersion::XPU3)
.export_values();
m.def("get_xpu_device_count", platform::GetXPUDeviceCount);
m.def("set_xpu_debug_level",
[](int level) { platform::set_xpu_debug_level(level); });
m.def("get_xpu_device_version",
[](int device_id) { return platform::get_xpu_version(device_id); });
#ifdef PADDLE_WITH_XPU_KP
m.def("get_xpu_device_op_support_types",
[](const std::string &op_name, phi::backends::xpu::XPUVersion version) {
return platform::get_xpu_kp_op_support_type(op_name, version);
});
#else
m.def("get_xpu_device_op_support_types",
[](const std::string &op_name, phi::backends::xpu::XPUVersion version) {
return platform::get_xpu_op_support_type(op_name, version);
});
#endif
m.def("get_xpu_device_op_list", [](phi::backends::xpu::XPUVersion version) {
return platform::get_xpu_op_list(version);
});
m.def("is_float16_supported", [](const phi::XPUPlace &place) -> bool {
// XPUs with Compute Capability > xpu1 support float16
return platform::get_xpu_version(place.device) >
phi::backends::xpu::XPUVersion::XPU1;
});
m.def("is_bfloat16_supported", [](const phi::XPUPlace &place) -> bool {
// XPUs with Compute Capability > xpu2 support bfloat16
return platform::get_xpu_version(place.device) >
phi::backends::xpu::XPUVersion::XPU2;
});
#endif
py::class_<CPUPlace, Place> cpuplace(m, "CPUPlace", R"DOC(
CPUPlace is a descriptor of a device.
It represents a CPU device on which a tensor will be allocated and a model will run.
Examples:
.. code-block:: pycon
>>> import paddle
>>> cpu_place = paddle.CPUPlace()
)DOC");
g_cpuplace_pytype = reinterpret_cast<PyTypeObject *>(cpuplace.ptr());
cpuplace.def(py::init<>())
.def("_type", &PlaceIndex<CPUPlace>)
.def("_equals", &IsSamePlace<CPUPlace, Place>)
.def("_equals", &IsSamePlace<CPUPlace, phi::XPUPlace>)
.def("_equals", &IsSamePlace<CPUPlace, GPUPlace>)
.def("_equals", &IsSamePlace<CPUPlace, CPUPlace>)
.def("_equals", &IsSamePlace<CPUPlace, phi::GPUPinnedPlace>)
.def("_equals", &IsSamePlace<CPUPlace, phi::XPUPinnedPlace>)
.def("__repr__", string::to_string<const CPUPlace &>)
.def("__str__", string::to_string<const CPUPlace &>);
m.def("is_float16_supported",
[](const CPUPlace &place) -> bool { return false; });
m.def("is_bfloat16_supported", [](const CPUPlace &place) -> bool {
#ifndef PADDLE_WITH_DNNL
return false;
#else
if (phi::backends::cpu::MayIUse(phi::backends::cpu::cpu_isa_t::avx512_core))
return true;
else
return false;
#endif
});
py::class_<phi::GPUPinnedPlace, Place> cudapinnedplace(
m, "CUDAPinnedPlace", R"DOC(
CUDAPinnedPlace is a descriptor of a device.
It refers to the page locked memory allocated by the CUDA function `cudaHostAlloc()` in the host memory.
The host operating system will not paging and exchanging the memory.
It can be accessed through direct memory access technology to speed up the copy of data between the host and GPU.
For more information on CUDA data transfer and `pinned memory`,
please refer to `official document <https://docs.nvidia.com/cuda/cuda-c-best-practices-guide/index.html#pinned-memory>`_ .
Examples:
.. code-block:: pycon
>>> # doctest: +REQUIRES(env:GPU)
>>> import paddle
>>> place = paddle.CUDAPinnedPlace()
)DOC");
g_cudapinnedplace_pytype =
reinterpret_cast<PyTypeObject *>(cudapinnedplace.ptr());
cudapinnedplace
.def(py::init([]() {
#if !defined(PADDLE_WITH_CUDA) && !defined(PADDLE_WITH_HIP)
PADDLE_THROW(common::errors::PermissionDenied(
"Cannot use CUDAPinnedPlace in CPU only version, "
"Please recompile or reinstall Paddle with CUDA support."));
#endif
return std::make_unique<phi::GPUPinnedPlace>();
}))
.def("_type", &PlaceIndex<phi::GPUPinnedPlace>)
.def("_equals", &IsSamePlace<phi::GPUPinnedPlace, Place>)
.def("_equals", &IsSamePlace<phi::GPUPinnedPlace, GPUPlace>)
.def("_equals", &IsSamePlace<phi::GPUPinnedPlace, phi::XPUPlace>)
.def("_equals", &IsSamePlace<phi::GPUPinnedPlace, CPUPlace>)
.def("_equals", &IsSamePlace<phi::GPUPinnedPlace, phi::GPUPinnedPlace>)
.def("_equals", &IsSamePlace<phi::GPUPinnedPlace, phi::XPUPinnedPlace>)
.def("__repr__", string::to_string<const phi::GPUPinnedPlace &>)
.def("__str__", string::to_string<const phi::GPUPinnedPlace &>);
// XPUPinnedPlace
py::class_<phi::XPUPinnedPlace, Place> xpupinnedplace(
m, "XPUPinnedPlace", R"DOC(
XPUPinnedPlace is a descriptor of a device.
It refers to the page locked memory allocated by the CUDA function `cudaHostAlloc()` in the host memory.
The host operating system will not paging and exchanging the memory.
It can be accessed through direct memory access technology to speed up the copy of data between the host and XPU.
For more information on XPU data transfer and `pinned memory`,
please refer to `official document <https://docs.nvidia.com/cuda/cuda-c-best-practices-guide/index.html#pinned-memory>`_ .
Examples:
.. code-block:: pycon
>>> # doctest: +REQUIRES(env:XPU)
>>> import paddle
>>> place = paddle.XPUPinnedPlace()
)DOC");
g_xpupinnedplace_pytype =
reinterpret_cast<PyTypeObject *>(xpupinnedplace.ptr());
xpupinnedplace
.def(py::init([]() {
#if !defined(PADDLE_WITH_XPU)
PADDLE_THROW(common::errors::PermissionDenied(
"Cannot use XPUPinnedPlace in CPU only version, "
"Please recompile or reinstall Paddle with XPU support."));
#endif
return std::make_unique<phi::XPUPinnedPlace>();
}))
.def("_type", &PlaceIndex<phi::XPUPinnedPlace>)
.def("_equals", &IsSamePlace<phi::XPUPinnedPlace, Place>)
.def("_equals", &IsSamePlace<phi::XPUPinnedPlace, GPUPlace>)
.def("_equals", &IsSamePlace<phi::XPUPinnedPlace, phi::XPUPlace>)
.def("_equals", &IsSamePlace<phi::XPUPinnedPlace, CPUPlace>)
.def("_equals", &IsSamePlace<phi::XPUPinnedPlace, phi::GPUPinnedPlace>)
.def("_equals", &IsSamePlace<phi::XPUPinnedPlace, phi::XPUPinnedPlace>)
.def("__repr__", string::to_string<const phi::XPUPinnedPlace &>)
.def("__str__", string::to_string<const phi::XPUPinnedPlace &>);
// IPUPlace
py::class_<phi::IPUPlace, Place> ipuplace(m, "IPUPlace", R"DOC(
IPUPlace is a descriptor of a device.
It represents a IPU device on which a tensor will be allocated and a model will run.
Examples:
.. code-block:: pycon
>>> # doctest: +REQUIRES(env:IPU)
>>> import paddle
>>> ipu_place = paddle.IPUPlace()
)DOC");
g_ipuplace_pytype = reinterpret_cast<PyTypeObject *>(ipuplace.ptr());
ipuplace
.def("__init__",
[](phi::IPUPlace &self) {
#ifdef PADDLE_WITH_IPU
if (platform::GetIPUDeviceCount() == 0) {
LOG(ERROR) << "Cannot use IPU because there is no IPU "
"detected on your "
"machine.";
PADDLE_THROW(::common::errors::InvalidArgument(
"use wrong place, Please check."));
}
// use ipu(0) to compile, while run with the number user configure
// in sharding and pipeline.
new (&self) phi::IPUPlace(0);
#else
LOG(ERROR) << string::Sprintf(
"Cannot use IPU because you didn't install IPU version "
"PaddlePaddle.\n"
"If you want to use IPU, please try to install IPU version "
"PaddlePaddle by: pip install paddlepaddle*\n"
"If you only have CPU, please change IPUPlace to be "
"CPUPlace().\n");
PADDLE_THROW(::common::errors::InvalidArgument(
"use wrong place, Please check."));
#endif
})
.def("_type", &PlaceIndex<phi::IPUPlace>)
.def("_equals", &IsSamePlace<phi::IPUPlace, Place>)
.def("_equals", &IsSamePlace<phi::IPUPlace, GPUPlace>)
.def("_equals", &IsSamePlace<phi::IPUPlace, CPUPlace>)
.def("_equals", &IsSamePlace<phi::IPUPlace, phi::XPUPlace>)
.def("_equals", &IsSamePlace<phi::IPUPlace, phi::IPUPlace>)
.def("_equals", &IsSamePlace<phi::IPUPlace, phi::GPUPinnedPlace>)
.def("_equals", &IsSamePlace<phi::IPUPlace, phi::XPUPinnedPlace>)
.def("__str__", string::to_string<const phi::IPUPlace &>);
}
} // namespace paddle::pybind