// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "tensor.h" #include "engine.h" #include OIDN_NAMESPACE_BEGIN std::ostream& operator <<(std::ostream& sm, const TensorDims& dims) { sm << "["; for (size_t i = 0; i < dims.size(); ++i) { if (i > 0) sm << ", "; sm << dims[i]; } sm << "]"; return sm; } // ----------------------------------------------------------------------------------------------- // Tensor // ----------------------------------------------------------------------------------------------- Tensor::Tensor(const TensorDesc& desc) : TensorDesc(desc) { if (!desc.isValid()) throw std::invalid_argument("invalid tensor descriptor"); } Tensor::Tensor(const Ref& buffer, const TensorDesc& desc, size_t byteOffset) : Memory(buffer, byteOffset), TensorDesc(desc) { if (!desc.isValid()) throw std::invalid_argument("invalid tensor descriptor"); } Ref Tensor::toDevice(Engine* engine, Storage storage) { return this; } #if 0 uint32_t Tensor::getHash() const { std::vector hostBytes; const uint8_t* bytes; if (buffer && buffer->getStorage() == Storage::Device) { // Copy the tensor to the host hostBytes.resize(getByteSize()); getBuffer()->getEngine()->usmCopy(hostBytes.data(), getPtr(), getByteSize()); bytes = hostBytes.data(); } else { bytes = static_cast(getPtr()); } const size_t numBytes = getByteSize(); uint32_t hash = 0x811c9dc5; for (size_t i = 0; i < numBytes; ++i) { hash ^= bytes[i]; hash *= 0x1000193; } return hash; } void Tensor::dump(const std::string& filenamePrefix) { if (dataType == DataType::Float32 && layout == TensorLayout::chw) dumpImpl(filenamePrefix); else if (dataType == DataType::Float32 && layout == TensorLayout::Chw8c) dumpImpl(filenamePrefix); else if (dataType == DataType::Float32 && layout == TensorLayout::Chw16c) dumpImpl(filenamePrefix); else if (dataType == DataType::Float16 && layout == TensorLayout::chw) dumpImpl(filenamePrefix); else if (dataType == DataType::Float16 && layout == TensorLayout::Chw16c) dumpImpl(filenamePrefix); else if (dataType == DataType::Float16 && layout == TensorLayout::hwc) dumpImpl(filenamePrefix); else throw std::runtime_error("tensor dump not implemented"); } template void Tensor::dumpImpl(const std::string& filenamePrefix) { if (buffer && buffer->getStorage() == Storage::Device) throw std::runtime_error("tensor dump not implemented for device storage"); TensorAccessor3D acc = *this; for (int c = 0; c < acc.C; ++c) { // Open the file const std::string filename = filenamePrefix + toString(c) + ".pfm"; std::ofstream file(filename, std::ios::binary); if (file.fail()) throw std::runtime_error("cannot open image file: " + std::string(filename)); // Write the header file << "Pf" << std::endl; file << acc.W << " " << acc.H << std::endl; file << "-1.0" << std::endl; // Write the pixels for (int h = acc.H-1; h >= 0; --h) { for (int w = 0; w < acc.W; ++w) { const float x = acc(c, h, w); file.write((char*)&x, sizeof(float)); } } } } #endif // ----------------------------------------------------------------------------------------------- // HostTensor // ----------------------------------------------------------------------------------------------- HostTensor::HostTensor(const TensorDesc& desc) : Tensor(desc), ptr(alignedMalloc(getByteSize())), shared(false) {} HostTensor::HostTensor(const TensorDesc& desc, void* data) : Tensor(desc), ptr(data), shared(true) {} HostTensor::~HostTensor() { if (!shared) alignedFree(ptr); } Ref HostTensor::toDevice(Engine* engine, Storage storage) { const size_t byteSize = getByteSize(); auto bufferCopy = engine->newBuffer(byteSize, storage); bufferCopy->write(0, byteSize, getPtr()); return engine->newTensor(bufferCopy, getDesc()); } // ----------------------------------------------------------------------------------------------- // DeviceTensor // ----------------------------------------------------------------------------------------------- DeviceTensor::DeviceTensor(Engine* engine, const TensorDesc& desc, Storage storage) : Tensor(desc) { buffer = engine->newBuffer(getByteSize(), storage); ptr = buffer->getPtr(); } DeviceTensor::DeviceTensor(const Ref& buffer, const TensorDesc& desc, size_t byteOffset) : Tensor(buffer, desc, byteOffset) { if (byteOffset + getByteSize() > buffer->getByteSize()) throw Exception(Error::InvalidArgument, "buffer region is out of bounds"); ptr = static_cast(buffer->getPtr()) + byteOffset; } void DeviceTensor::postRealloc() { if (buffer) ptr = static_cast(buffer->getPtr()) + byteOffset; } OIDN_NAMESPACE_END