Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Numpy reader changes #5

Open
wants to merge 5 commits into
base: param_vx_changes
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions rocAL/include/api/rocal_api_data_loaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,46 @@ extern "C" RocalTensor ROCAL_API_CALL rocalRawTFRecordSourceSingleShard(RocalCon
unsigned out_width = 0, unsigned out_height = 0,
const char* record_name_prefix = "");

/*! \brief Creates Numpy raw data reader and loader. It allocates the resources and objects required to read raw data stored on the numpy arrays.
* \ingroup group_rocal_data_loaders
* \param [in] context Rocal context
* \param [in] source_path A NULL terminated char string pointing to the location on the disk
* \param [in] internal_shard_count Defines the parallelism level by internally sharding the input dataset and load/decode using multiple decoder/loader instances. Using shard counts bigger than 1 improves the load/decode performance if compute resources (CPU cores) are available.
* \param [in] tensor_layout The tensor layout for the numpy loader tensor specified by the user.
* \param [in] is_output Determines if the user wants the loaded numpy arrays to be part of the output or not.
* \param [in] shuffle Determines if the user wants to shuffle the dataset or not.
* \param [in] loop Determines if the user wants to indefinitely loops through images or not.
* \return Reference to the output tensor
*/
extern "C" RocalTensor ROCAL_API_CALL rocalNumpyFileSource(RocalContext p_context,
const char* source_path,
unsigned internal_shard_count,
RocalTensorLayout tensor_layout = ROCAL_NONE,
bool is_output = false,
bool shuffle = false,
bool loop = false);

/*! \brief Creates Numpy raw data reader and loader. It allocates the resources and objects required to read raw data stored on the numpy arrays.
* \ingroup group_rocal_data_loaders
* \param [in] context Rocal context
* \param [in] source_path A NULL terminated char string pointing to the location on the disk
* \param [in] tensor_layout The tensor layout for the numpy loader tensor specified by the user.
* \param [in] is_output Determines if the user wants the loaded numpy arrays to be part of the output or not.
* \param [in] shuffle Determines if the user wants to shuffle the dataset or not.
* \param [in] loop Determines if the user wants to indefinitely loops through images or not.
* \param [in] shard_id Shard id for this loader
* \param [in] shard_count Total shard count
* \return Reference to the output tensor
*/
extern "C" RocalTensor rocalNumpyFileSourceSingleShard(RocalContext p_context,
const char* source_path,
RocalTensorLayout tensor_layout = ROCAL_NONE,
bool is_output = false,
bool shuffle = false,
bool loop = false,
unsigned shard_id = 0,
unsigned shard_count = 1);

/*!
* \brief Creates a video reader and decoder as a source. It allocates the resources and objects required to read and decode mp4 videos stored on the file systems.
* \ingroup group_rocal_data_loaders
Expand Down
8 changes: 7 additions & 1 deletion rocAL/include/api/rocal_api_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,15 @@ enum RocalTensorLayout {
/*! \brief AMD ROCAL_NFCHW
*/
ROCAL_NFCHW = 3,
/*! \brief AMD ROCAL_NDHWC
*/
ROCAL_NDHWC = 4,
/*! \brief AMD ROCAL_NCDHW
*/
ROCAL_NCDHW = 5,
/*! \brief AMD ROCAL_NONE
*/
ROCAL_NONE = 4 // Layout for generic tensors (Non-Image or Non-Video)
ROCAL_NONE = 6 // Layout for generic tensors (Non-Image or Non-Video)
};

/*! \brief rocAL Tensor Output Type enum
Expand Down
49 changes: 49 additions & 0 deletions rocAL/include/loaders/image/node_numpy_loader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
Copyright (c) 2019 - 2024 Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#pragma once
#include "node.h"
#include "numpy_loader_sharded.h"

class NumpyLoaderNode : public Node {
public:
NumpyLoaderNode(Tensor *output, void *device_resources);
~NumpyLoaderNode() override;
NumpyLoaderNode() = delete;

/// \param internal_shard_count Defines the amount of parallelism user wants for the load process to be handled internally.
/// \param source_path Defines the path that includes the numpy array dataset
/// \param load_batch_count Defines the quantum count of the numpy arrays to be loaded. It's usually equal to the user's batch size.
/// The loader will repeat numpy arrays if necessary to be able to have numpy arrays in multiples of the load_batch_count,
/// for example if there are 10 numpy arrays in the dataset and load_batch_count is 3, the loader repeats 2 numpy arrays as if there are 12 numpy arrays available.
void init(unsigned internal_shard_count, const std::string &source_path, StorageType storage_type, DecoderType decoder_type, bool shuffle, bool loop,
size_t load_batch_count, RocalMemType mem_type);

std::shared_ptr<LoaderModule> get_loader_module();

protected:
void create_node() override{};
void update_node() override{};

private:
std::shared_ptr<NumpyLoaderSharded> _loader_module = nullptr;
};
50 changes: 50 additions & 0 deletions rocAL/include/loaders/image/node_numpy_loader_single_shard.h
SundarRajan98 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
Copyright (c) 2019 - 2024 Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#pragma once
#include "node.h"
#include "numpy_loader_sharded.h"

class NumpyLoaderSingleShardNode : public Node {
public:
NumpyLoaderSingleShardNode(Tensor *output, void *device_resources);
~NumpyLoaderSingleShardNode() override;

/// \param user_shard_count shard count from user
/// \param user_shard_id shard id from user
/// \param source_path Defines the path that includes the numpy array dataset
/// \param load_batch_count Defines the quantum count of the numpy arrays to be loaded. It's usually equal to the user's batch size.
/// The loader will repeat numpy arrays if necessary to be able to have numpy arrays in multiples of the load_batch_count,
/// for example if there are 10 numpy arrays in the dataset and load_batch_count is 3, the loader repeats 2 numpy arrays as if there are 12 numpy arrays available.
void init(unsigned shard_id, unsigned shard_count, const std::string &source_path,
StorageType storage_type, DecoderType decoder_type, bool shuffle, bool loop,
size_t load_batch_count, RocalMemType mem_type);

std::shared_ptr<LoaderModule> get_loader_module();

protected:
void create_node() override{};
void update_node() override{};

private:
std::shared_ptr<NumpyLoader> _loader_module = nullptr;
};
90 changes: 90 additions & 0 deletions rocAL/include/loaders/image/numpy_loader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
Copyright (c) 2019 - 2024 Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#pragma once

#include <string>
#include <thread>
#include <vector>

#include "circular_buffer.h"
#include "commons.h"
#include "image_read_and_decode.h"

// NumpyLoader runs an internal thread for loading of numpy arrays asynchronously
// it uses a circular buffer to store loaded numpy arrays for the user
class NumpyLoader : public LoaderModule {
public:
explicit NumpyLoader(void* dev_resources);
~NumpyLoader() override;
LoaderModuleStatus load_next() override;
void initialize(ReaderConfig reader_cfg, DecoderConfig decoder_cfg, RocalMemType mem_type, unsigned batch_size, bool keep_orig_size = false) override;
void set_output(Tensor* output_image) override;
void set_random_bbox_data_reader(std::shared_ptr<RandomBBoxCrop_MetaDataReader> randombboxcrop_meta_data_reader) override;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

void set_random_bbox_data_reader(std::shared_ptr<RandomBBoxCrop_MetaDataReader> randombboxcrop_meta_data_reader) override { THROW("set_random_bbox_data_reader is not compatible with this implementation") };

Please change to THROW err

size_t remaining_count() override; // returns number of remaining items to be loaded
void reset() override; // Resets the loader to load from the beginning of the media
Timing timing() override;
void start_loading() override;
LoaderModuleStatus set_cpu_affinity(cpu_set_t cpu_mask);
LoaderModuleStatus set_cpu_sched_policy(struct sched_param sched_policy);
void set_gpu_device_id(int device_id);
std::vector<std::string> get_id() override;
decoded_image_info get_decode_image_info() override;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to change decoded_image_info and crop_image_info
Please check with @shobana-mcw

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we use this API in numpy reader?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pure virtual functions in loader module and called in output_routine for all loaders

crop_image_info get_crop_image_info() override;
void set_prefetch_queue_depth(size_t prefetch_queue_depth) override;
void shut_down() override;
void feed_external_input(const std::vector<std::string>& input_images_names, const std::vector<unsigned char*>& input_buffer,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will not support this?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Numpy readers were not tested with external source

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need an external source usecase for numpy reader?

const std::vector<ROIxywh>& roi_xywh, unsigned int max_width, unsigned int max_height, unsigned int channels, ExternalSourceFileMode mode, bool eos) override {}

private:
bool is_out_of_data();
void de_init();
void stop_internal_thread();
LoaderModuleStatus update_output_tensor();
LoaderModuleStatus load_routine();
std::shared_ptr<Reader> _reader;
std::shared_ptr<RandomBBoxCrop_MetaDataReader> _randombboxcrop_meta_data_reader = nullptr;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not used

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set_random_bbox_data_reader is a pure virtual func that must be implemented

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fiona-gladwin We might have to remove the _randombboxcrop_meta_data_reader from the reader and enable it only for the class which requires it.

Tensor* _output_tensor;
std::vector<std::string> _output_names; //!< image name/ids that are stores in the _output_image
size_t _output_mem_size;
MetaDataBatch* _meta_data = nullptr; //!< The output of the meta_data_graph,
bool _internal_thread_running;
size_t _batch_size;
size_t _image_size;
std::thread _load_thread;
RocalMemType _mem_type;
decoded_image_info _decoded_img_info;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to change all variables without the word image, since we are referring to numpy arrays here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Address this.

crop_image_info _crop_image_info;
decoded_image_info _output_decoded_img_info;
crop_image_info _output_cropped_img_info;
CircularBuffer _circ_buff;
TimingDBG _file_load_time, _swap_handle_time;
bool _is_initialized;
bool _stopped = false;
bool _loop; //<! If true the reader will wrap around at the end of the media (files/samples/...) and wouldn't stop
size_t _prefetch_queue_depth; // Used for circular buffer's internal buffer
size_t _image_counter = 0; //!< How many samples have been loaded already
size_t _remaining_count; //!< How many samples are there yet to be loaded
bool _decoder_keep_original = false;
SundarRajan98 marked this conversation as resolved.
Show resolved Hide resolved
int _device_id;
std::vector<std::vector<unsigned>> _tensor_roi;
};
61 changes: 61 additions & 0 deletions rocAL/include/loaders/image/numpy_loader_sharded.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
Copyright (c) 2019 - 2024 Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#pragma once

#include "numpy_loader.h"
//
// NumpyLoaderSharded Can be used to run load and decode in multiple shards, each shard by a single loader instance,
// It improves load and decode performance since each loader loads the numpy arrays in parallel using an internal thread
//
class NumpyLoaderSharded : public LoaderModule {
public:
explicit NumpyLoaderSharded(void *dev_resources);
~NumpyLoaderSharded() override;
LoaderModuleStatus load_next() override;
void initialize(ReaderConfig reader_cfg, DecoderConfig decoder_cfg, RocalMemType mem_type, unsigned batch_size, bool keep_orig_size = false) override;
void set_output(Tensor *output_image) override;
void set_random_bbox_data_reader(std::shared_ptr<RandomBBoxCrop_MetaDataReader> randombboxcrop_meta_data_reader) override;
size_t remaining_count() override;
void reset() override;
void start_loading() override;
std::vector<std::string> get_id() override;
decoded_image_info get_decode_image_info() override;
crop_image_info get_crop_image_info() override;
Timing timing() override;
void set_prefetch_queue_depth(size_t prefetch_queue_depth) override;
void shut_down() override;
void feed_external_input(const std::vector<std::string>& input_images_names, const std::vector<unsigned char*>& input_buffer,
const std::vector<ROIxywh>& roi_xywh, unsigned int max_width, unsigned int max_height, unsigned int channels, ExternalSourceFileMode mode, bool eos) override {}

private:
void increment_loader_idx();
void *_dev_resources;
bool _initialized = false;
std::vector<std::shared_ptr<NumpyLoader>> _loaders;
size_t _loader_idx;
size_t _shard_count = 1;
void fast_forward_through_empty_loaders();
size_t _prefetch_queue_depth;
Tensor *_output_tensor;
std::shared_ptr<RandomBBoxCrop_MetaDataReader> _randombboxcrop_meta_data_reader = nullptr;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be removed and add This doesnt the implementation for the function set_random_bbox_data_reader

};
46 changes: 46 additions & 0 deletions rocAL/include/loaders/numpy_source_evaluator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
Copyright (c) 2019 - 2024 Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#pragma once
#include <map>
#include <memory>

#include "loader_module.h"
#include "reader_factory.h"
#include "timing_debug.h"

enum class NumpySourceEvaluatorStatus {
OK = 0,
UNSUPPORTED_STORAGE_TYPE,
};

class NumpySourceEvaluator {
public:
NumpySourceEvaluatorStatus create(ReaderConfig reader_cfg);
void find_max_numpy_dimensions();
std::vector<size_t> max_numpy_dims() { return _max_numpy_dims; }
RocalTensorDataType get_numpy_dtype() { return _numpy_dtype; }

std::vector<size_t> _max_numpy_dims;
RocalTensorDataType _numpy_dtype;
std::shared_ptr<Reader> _reader;
};
13 changes: 13 additions & 0 deletions rocAL/include/pipeline/commons.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ enum class RocalTensorlayout {
NCHW,
NFHWC,
NFCHW,
NDHWC,
NCDHW,
NONE
};

Expand Down Expand Up @@ -105,6 +107,17 @@ enum class RocalROIType {
XYWH
};

/*! \brief Tensor 3D ROI type
*
* currently supports following formats
* LTFRBB - Left-Top-Front-Right-Bottom-Back
* XYZWHD - X-Y-Z-Width-Height-Depth
*/
enum class Rocal3DROIType {
LTFRBB = 0,
SundarRajan98 marked this conversation as resolved.
Show resolved Hide resolved
XYZWHD
};

/*! \brief Tensor ROI in LTRB format
*
*/
Expand Down
Loading