| 84 | using AllocationDeleter = void (*)(phi::Allocation*); |
| 85 | |
| 86 | Tensor FromBlobImpl(void* data, |
| 87 | const phi::DenseTensorMeta& meta, |
| 88 | const phi::Place& place, |
| 89 | const Deleter& deleter) { |
| 90 | PADDLE_ENFORCE_NOT_NULL( |
| 91 | data, common::errors::InvalidArgument("data can not be nullptr.")); |
| 92 | |
| 93 | phi::Place data_place; |
| 94 | if (place.GetType() == phi::AllocationType::UNDEFINED || |
| 95 | place.GetType() == phi::AllocationType::CPU || |
| 96 | place.GetType() == phi::AllocationType::GPU) { |
| 97 | data_place = GetPlaceFromPtr(data); |
| 98 | if (place.GetType() != phi::AllocationType::UNDEFINED) { |
| 99 | PADDLE_ENFORCE_EQ(data_place, |
| 100 | place, |
| 101 | common::errors::InvalidArgument( |
| 102 | "Specified place does not match place of data. ", |
| 103 | "Specified: %s, Expected: %s.", |
| 104 | data_place.DebugString(), |
| 105 | place.DebugString())); |
| 106 | } |
| 107 | } else { |
| 108 | data_place = place; |
| 109 | } |
| 110 | |
| 111 | // Calculate the number of elements of underlying storage |
| 112 | size_t size = 1; |
| 113 | for (auto i = 0; i < meta.dims.size(); ++i) { |
| 114 | if (meta.dims[i] == 0) { |
| 115 | size = 0; |
| 116 | break; |
| 117 | } |
| 118 | size += meta.strides[i] * (meta.dims[i] - 1); |
| 119 | } |
| 120 | |
| 121 | AllocationDeleter alloc_deleter = nullptr; |
| 122 | if (deleter) { |
| 123 | DeleterManager::Instance()->RegisterPtr(data, deleter); |
| 124 | alloc_deleter = [](phi::Allocation* p) { |
| 125 | DeleterManager::Instance()->DeletePtr(p->ptr()); |
| 126 | }; |
| 127 | } |
| 128 | |
| 129 | auto alloc = std::make_shared<phi::Allocation>( |
| 130 | data, size * SizeOf(meta.dtype), alloc_deleter, data_place); |
| 131 | |
| 132 | return Tensor(std::make_shared<phi::DenseTensor>(alloc, meta)); |
| 133 | } |
| 134 | |
| 135 | PADDLE_API Tensor from_blob(void* data, |
| 136 | const phi::IntArray& shape, |
no test coverage detected