Host-Device Data Transmission
// EngineTransNewT structure typedef struct EngineTransNew { std::shared_ptr<uint8_t> trans_buff = nullptr; // Transfer buffer uint32_t buffer_size = 0; // Transfer buffer size std::shared_ptr<uint8_t> trans_buff_extend = nullptr; uint32_t buffer_size_extend = 0; std::vector<crop_rect> crop_list; // The serialize function is used to serialize a structure. template <class Archive> void serialize(Archive & ar) { ar(buffer_size, buffer_size_extend, crop_list); } }EngineTransNewT; /** * @ingroup hiaiengine * @brief GetTransSearPtr, // Serializes the Trans data. * @param [in]: dataPtr // Structure pointer * @param [out]: structStr // Structure buffer * @param [out]: buffer // Structure data pointer buffer * @param [out]: buffSize // Structure data size */ void GetTransSearPtr(void* data_ptr, std::string& struct_str, uint8_t*& buffer, uint32_t& buffer_size) { EngineTransNewT* engine_trans = (EngineTransNewT*)data_ptr; uint32_t dataLen = engine_trans->buffer_size; uint32_t dataLen_extend = engine_trans->buffer_size_extend; // Obtains the structure buffer and size. buffer_size = dataLen + dataLen_extend; buffer = (uint8_t*)engine_trans->trans_buff.get(); // Serialization std::ostringstream outputStr; cereal::PortableBinaryOutputArchive archive(outputStr); archive((*engine_trans)); struct_str = outputStr.str(); } /** * @ingroup hiaiengine * @brief GetTransSearPtr, // Deserializes the Trans data. * @param [in] : ctrlPtr // Structure pointer * @param [in]: ctrlLen // Control information size of the data structure * @param [in] : dataPtr // Structure data pointer * @param [in]: dataLen // Data storage size of the structure, which is used only for verification and does not represent the original data size * @param [out]: std::shared_ptr<void> // Structure pointer assigned to the engine */ std::shared_ptr<void> GetTransDearPtr( const char* ctrlPtr, const uint32_t& ctrlLen, const uint8_t* dataPtr, const uint32_t& dataLen) { if(ctrlPtr == nullptr) { return nullptr; } std::shared_ptr<EngineTransNewT> engine_trans_ptr = std::make_shared<EngineTransNewT>(); // Assigns a value to engine_trans_ptr. std::istringstream inputStream(std::string(ctrlPtr, ctrlLen)); cereal::PortableBinaryInputArchive archive(inputStream); archive((*engine_trans_ptr)); uint32_t offsetLen = engine_trans_ptr->buffer_size; if(dataPtr != nullptr) { (engine_trans_ptr->trans_buff).reset((const_cast<uint8_t*>(dataPtr)), ReleaseDataBuffer); // trans_buff and trans_buff_extend point to a contiguous memory space whose address starts with dataPtr; // therefore, you only need to bind trans_buff to the destructor, and then the destructor will free the contiguous memory space after being used. (engine_trans_ptr->trans_buff_extend).reset((const_cast<uint8_t*>(dataPtr + offsetLen)), SearDeleteNothing); } return std::static_pointer_cast<void>(engine_trans_ptr); } // Registers EngineTransNewT HIAI_REGISTER_SERIALIZE_FUNC("EngineTransNewT", EngineTransNewT, GetTransSearPtr, GetTransDearPtr);
In the case of a large amount of image data or code stream transmission, HIAI_REGISTER_SERIALIZE_FUNC is used to serialize or deserialize the user-defined data types, which can implement high-performance data transmission and save the transmission time.
The Matrix module describes the data to be transmitted in the form of "control information+data information". The control information refers to a user-defined data type, and the data information refers to content to be transmitted. The Matrix module provides the following mechanism to ensure data transmission between the host and device.
- Before data transmission, you can call the HIAI_REGISTER_SERIALIZE_FUNC macro to register user-defined data types, user-defined serialization functions, and user-defined deserialization functions.
- After you call the SendData API to send data at the local end, the Matrix module performs the operations. Figure 1 shows the processing process.
- Call the user-defined serialization function to serialize the control information and save the serialized control information to the memory (ctrlBuf).
- Copy the control information and store it in the memory of the peer end through the Direct Memory Access (DMA) mapping, and maintain the mapping between the control information of the local end and that of the peer end.
The pointer to the memory (dataBuf) has been transferred through the input parameter of the SendData API. dataBuf is allocated by calling the HIAI_DMalloc/HIAI_DVPP_DMalloc API. After the memory is allocated, the system copies the local data information through DMA mapping and stores it to the memory of the peer end, and maintains the mapping between the local end and the peer end.
- A message including the addresses and sizes of ctrlBuf and dataBuf is sent to the peer end.
- After the peer end receives the message, the Matrix module calls the user-defined deserialization function to parse the control information and data information obtained by the peer end, and sends the parsed data to the corresponding receiving engine for processing.
- After the peer end parses the data, the control information is used out. Therefore, the memory (ctrlBuf) for storing the control information can be freed. This memory is allocated at the local end, so the peer end needs to send the local end a message for freeing ctrlBuf.
- After receiving the message, the local end frees ctrlBuf.
- After the engine receives and processes the data, dataBuf can be freed. The Matrix module does not know when dataBuf is used up. Therefore, when the deserialization function is implemented, dataBuf needs to return a smart pointer and bound to the destructor hiai::Graph::ReleaseDataBuffer. When the smart pointer ends the lifecycle destruction, the destructor is automatically called to send a message to the local end for freeing dataBuf.
- After receiving the message, the local end frees dataBuf.
Example scenario: The following code declares the serialization/deserialization function, defines the data type (struct), and registers the user-defined data type, serialization function, and deserialization function using the HIAI_REGISTER_SERIALIZE_FUNC macro. Before data transmission, the Matrix module calls the registered serialization function. After data transmission, the Matrix module calls the registered deserialization function.
// EngineTransNewT structure struct EngineTransNewT { std::shared_ptr<uint8_t> transBuff; uint32_t bufferSize; // Buffer size std::string url; // The serialize function is used to serialize a structure. template <class Archive> void serialize(Archive & ar) { ar(url); } } /** * @ingroup hiaiengine * @brief GetTransSearPtr, // Serializes the Trans data. * @param [in]: dataPtr // Structure pointer * @param [out]: structStr // Structure buffer * @param [out]: buffer // Structure data pointer buffer * @param [out]: buffSize // Structure data size */ void GetTransSearPtr(void* dataPtr, std::string& structStr, uint8_t*& buffer, uint32_t& bufferSize) { EngineTransNewT* engineTrans = (EngineTransNewT *)dataPtr; std::shared_ptr<uint8_t> transBuff = ((EngineTransNewT *)dataPtr)->transBuff; buffer = (uint8_t*)engineTrans->transBuff.get(); bufferSize = engineTrans->bufferSize; engineTrans->transBuff = nullptr; engineTrans->buffSize = 0; std::ostringstream outputStr; cereal::PortableBinaryOutputArchive archive(outputStr); archive((*engineTrans)); struct_str = outputStr.str(); ((EngineTransNewT*)dataPtr)->transBuff = transBuff; engineTrans->buffSize = bufferSize; } /** * @ingroup hiaiengine * @brief GetTransSearPtr, // Deserializes the Trans data. * @param [in] : ctrlPtr // Structure pointer * @param [in]: ctrlLen // Control information size of the data structure * @param [in] : dataPtr // Structure data pointer * @param [in]: dataLen // Data storage size of the structure, which is used only for verification and does not represent the original data size * @param [out]: std::shared_ptr<void> // Structure pointer assigned to the engine */ std::shared_ptr<void> GetTransDearPtr(char* ctrlPtr, const uint32_t& ctrlLen, uint8_t* dataPtr, const uint32_t& dataLen) { std::shared_ptr<EngineTransNewT> engineTransPtr = std::make_shared<EngineTransNewT>(); std::istringstream inputStream(std::string(ctrlPtr, ctrlLen)); cereal::PortableBinaryInputArchive archive(inputStream); archive((*engineTransPtr)); engineTransPtr->bufferSize = dataLen; engineTransPtr->transBuff.reset(dataPtr, hiai::Graph::ReleaseDataBuffer); return std::static_pointer_cast<void>(engineTransPtr); } // Registers EngineTransNewT HIAI_REGISTER_SERIALIZE_FUNC("EngineTransNewT", EngineTransNewT, GetTransSearPtr, GetTransDearPtr);
Feedback
Was this page helpful?
Provide feedbackThank you very much for your feedback. We will continue working to improve the documentation.See the reply and handling status in My Cloud VOC.
For any further questions, feel free to contact us through the chatbot.
Chatbot