Skip to content

Commit

Permalink
Add initial nvtiff support (#831)
Browse files Browse the repository at this point in the history
  • Loading branch information
tmartin-gh authored Jan 16, 2025
1 parent a394c29 commit 9eafdfa
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 15 deletions.
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,16 @@ if (MATX_EN_COVERAGE)
target_link_options(matx INTERFACE -lgcov --coverage)
endif()

# Add nvtiff support if installed
find_library(NVTIFF_LIBRARY nvtiff)
if (NOT NVTIFF_LIBRARY)
message(STATUS "Cannot find nvtiff library. Disabling MatX nvtiff features.")
else()
message(STATUS "Found nvtiff library at ${NVTIFF_LIBRARY}. Enabling MatX nvtiff features.")
target_compile_definitions(matx INTERFACE MATX_ENABLE_NVTIFF)
endif()


# Get the tensor libraries if we need them
if (MATX_EN_CUTENSOR)
set(CUTENSORNET_VERSION 24.03.0.4)
Expand Down
2 changes: 1 addition & 1 deletion include/matx.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

#include "matx/core/defines.h"
#include "matx/core/error.h"
#include "matx/core/file_io.h"
#include "matx/file_io/file_io.h"
#include "matx/core/half_complex.h"
#include "matx/core/half.h"
#include "matx/core/nvtx.h"
Expand Down
28 changes: 14 additions & 14 deletions include/matx/core/file_io.h → include/matx/file_io/file_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
#include "matx/core/pybind.h"
#include "matx/core/tensor.h"


#include "tiff.h"

#if defined(MATX_ENABLE_FILEIO) || defined(DOXYGEN_ONLY)

Expand Down Expand Up @@ -124,7 +124,7 @@ using namespace pybind11::literals;
* This has a startup performance hit, but CSV reading is intended to be a
* slow-path function, so this is not a critical component to speed up. Currently
* 1D and 2D tensors are supported only.
*
*
* @tparam TensorType
* Data type of tensor
* @param t
Expand All @@ -141,7 +141,7 @@ void read_csv(TensorType &t, const std::string fname,
const std::string delimiter, bool skip_header = true)
{
MATX_NVTX_START("", matx::MATX_NVTX_LOG_API)

if (TensorType::Rank() != 1 && TensorType::Rank() != 2) {
MATX_THROW(matxInvalidDim,
"CSV reading limited to tensors of rank 1 and 2");
Expand All @@ -152,7 +152,7 @@ void read_csv(TensorType &t, const std::string fname,
const std::string errorMessage = "Failed to read [" + fname + "], Does not Exist";
MATX_THROW(matxIOError, errorMessage.c_str());
}

auto pb = std::make_unique<detail::MatXPybind>();

auto np = pybind11::module_::import("numpy");
Expand All @@ -169,7 +169,7 @@ void read_csv(TensorType &t, const std::string fname,
* This has a startup performance hit, but CSV writing is intended to be a
* slow-path function, so this is not a critical component to speed up. Currently
* 1D and 2D tensors are supported only.
*
*
* @tparam TensorType
* Data type of tensor
* @param t
Expand All @@ -184,7 +184,7 @@ void write_csv(const TensorType &t, const std::string fname,
const std::string delimiter)
{
MATX_NVTX_START("", matx::MATX_NVTX_LOG_API)

if (TensorType::Rank() != 1 && TensorType::Rank() != 2) {
MATX_THROW(matxInvalidDim,
"CSV reading limited to tensors of rank 1 and 2");
Expand Down Expand Up @@ -220,15 +220,15 @@ void read_mat(TensorType &t, const std::string fname,
const std::string var)
{


if (!std::filesystem::exists(fname)) {
const std::string errorMessage = "Failed to read [" + fname + "], Does not Exist";
MATX_THROW(matxIOError, errorMessage.c_str());
}


MATX_NVTX_START("", matx::MATX_NVTX_LOG_API)


auto pb = std::make_unique<detail::MatXPybind>();

Expand Down Expand Up @@ -295,7 +295,7 @@ void write_mat(const TensorType &t, const std::string fname,
const std::string var)
{
MATX_NVTX_START("", matx::MATX_NVTX_LOG_API)

auto pb = std::make_unique<detail::MatXPybind>();
auto np = pybind11::module_::import("numpy");
auto sp = pybind11::module_::import("scipy.io");
Expand Down Expand Up @@ -323,12 +323,12 @@ template <typename TensorType>
void read_npy(TensorType &t, const std::string& fname)
{
MATX_NVTX_START("", matx::MATX_NVTX_LOG_API)

if (!std::filesystem::exists(fname)) {
const std::string errorMessage = "Failed to read [" + fname + "], Does not Exist";
MATX_THROW(matxIOError, errorMessage.c_str());
}

auto pb = std::make_unique<detail::MatXPybind>();

auto np = pybind11::module_::import("numpy");
Expand All @@ -339,7 +339,7 @@ void read_npy(TensorType &t, const std::string& fname)

/**
* @brief Write a NPY file from a tensor view
*
*
* NPY files are a simple binary format for storing arrays of numbers.
*
* @tparam TensorType
Expand All @@ -353,7 +353,7 @@ template <typename TensorType>
void write_npy(const TensorType &t, const std::string& fname)
{
MATX_NVTX_START("", matx::MATX_NVTX_LOG_API)

auto pb = std::make_unique<detail::MatXPybind>();
auto np = pybind11::module_::import("numpy");

Expand Down
144 changes: 144 additions & 0 deletions include/matx/file_io/tiff.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
////////////////////////////////////////////////////////////////////////////////
// BSD 3-Clause License
//
// Copyright (c) 2021, NVIDIA Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/////////////////////////////////////////////////////////////////////////////////

#pragma once

#ifdef MATX_ENABLE_NVTIFF

#include <vector>
#include <nvtiff.h>
#define MATX_CHECK_NVTIFF(call) do { \
nvtiffStatus_t _e = (call); \
if (_e != NVTIFF_STATUS_SUCCESS) { \
fprintf(stderr, "nvtiff error code %d in file '%s' in line %i\n", _e, __FILE__, __LINE__); \
MATX_THROW(matx::matxCudaError, "nvTIFF error"); \
} \
} while (0)

namespace matx {
namespace io {

class Tiff
{
public:
Tiff(cudaStream_t stream=0, int NUM_DECODERS=1)
: stream_(stream), NUM_DECODERS_(NUM_DECODERS), decoder_idx(0)
{
events.resize(NUM_DECODERS_);
tiff_streams.resize(NUM_DECODERS_);
decoders.resize(NUM_DECODERS_);
for (int k=0; k<NUM_DECODERS_; k++)
{
MATX_CUDA_CHECK(cudaEventCreate(&events[k]));
MATX_CUDA_CHECK(cudaEventRecord(events[k],stream_));
MATX_CHECK_NVTIFF(nvtiffStreamCreate(&tiff_streams[k]));
MATX_CHECK_NVTIFF(nvtiffDecoderCreate(&decoders[k], nullptr, nullptr, stream_));
}
}

~Tiff()
{
for (int k=0; k<NUM_DECODERS_; k++)
{
nvtiffDecoderDestroy(decoders[k],stream_);
nvtiffStreamDestroy(tiff_streams[k]);
cudaEventDestroy(events[k]);
}
}

template<typename T>
void load(const char* filename, uint32_t image_id, T& t)
{
nvtiffFileInfo_t file_info;
nvtiffImageInfo_t image_info;

MATX_CUDA_CHECK(cudaEventSynchronize(events[decoder_idx]));
MATX_CHECK_NVTIFF(nvtiffStreamParseFromFile(filename, tiff_streams[decoder_idx]));
MATX_CHECK_NVTIFF(nvtiffStreamGetFileInfo(tiff_streams[decoder_idx], &file_info));
MATX_CHECK_NVTIFF(nvtiffStreamGetImageInfo(tiff_streams[decoder_idx], image_id, &image_info));
make_tensor(t, {image_info.image_height, image_info.image_width});
uint8_t* data[1] {reinterpret_cast<uint8_t*>(t.Data())};
MATX_CHECK_NVTIFF(nvtiffDecodeRange(tiff_streams[decoder_idx], decoders[decoder_idx], image_id, 1, data, stream_));
MATX_CUDA_CHECK(cudaEventRecord(events[decoder_idx],stream_));
decoder_idx++;
if (decoder_idx >= NUM_DECODERS_) {
decoder_idx = 0;
}
}

void load_toptr(const char* filename, uint32_t image_id, uint8_t* t_data)
{
MATX_CUDA_CHECK(cudaEventSynchronize(events[decoder_idx]));
MATX_CHECK_NVTIFF(nvtiffStreamParseFromFile(filename, tiff_streams[decoder_idx]));
uint8_t* data[1] {reinterpret_cast<uint8_t*>(t_data)};
MATX_CHECK_NVTIFF(nvtiffDecodeRange(tiff_streams[decoder_idx], decoders[decoder_idx], image_id, 1, data, stream_));
MATX_CUDA_CHECK(cudaEventRecord(events[decoder_idx],stream_));
decoder_idx++;
if (decoder_idx >= NUM_DECODERS_) {
decoder_idx = 0;
}
}

void info(const char* filename, uint32_t image_id)
{
nvtiffFileInfo_t file_info;
nvtiffImageInfo_t image_info;

MATX_CUDA_CHECK(cudaEventSynchronize(events[decoder_idx]));
MATX_CHECK_NVTIFF(nvtiffStreamParseFromFile(filename, tiff_streams[decoder_idx]));
MATX_CHECK_NVTIFF(nvtiffStreamGetFileInfo(tiff_streams[decoder_idx], &file_info));
printf("%s:\n",filename);
for (uint32_t k=0; k<file_info.num_images; k++)
{
MATX_CHECK_NVTIFF(nvtiffStreamGetImageInfo(tiff_streams[decoder_idx], image_id, &image_info));
printf(" image %u\n",k);
printf(" image_width: %u\n",image_info.image_width);
printf(" image_height: %u\n",image_info.image_height);
printf(" samples_per_pixel: %u\n",image_info.samples_per_pixel);
printf(" bits_per_pixel: %u\n",image_info.bits_per_pixel);
printf(" sample_format[0]: %u\n",image_info.sample_format[0]);
}
}

private:
int NUM_DECODERS_;
int decoder_idx;
cudaStream_t stream_;
std::vector<cudaEvent_t> events;
std::vector<nvtiffStream_t> tiff_streams;
std::vector<nvtiffDecoder_t> decoders;
};

}
}

#endif // MATX_ENABLE_NVTIFF defined

0 comments on commit 9eafdfa

Please sign in to comment.