Sequential
Sequential can link multiple backends together. In other words, Sequential[DecodeTensor,ResizeTensor,cvtColorTensor,SyncTensor] and Sequential[DecodeMat,ResizeMat] are valid backends.
During the forward execution of Sequential[DecodeMat,ResizeMat], the data (dict) will go through the following process in sequence:
- Execute
DecodeMat:DecodeMatreadsdataand assigns the result toresultandcolor. - Conditional control flow: attempts to assign the value of
resultin the data todataand deletesresult. - Execute
ResizeMat:ResizeMatreadsdataand assigns the result to theresultkey.
Sequential can be abbreviated as S. API reference can be found in Sequential.
Conditional Control Flow Filter
Sequential itself implements support for control flow syntax extensions. In fact, S[DecodeMat,ResizeMat] is equivalent to S[(Run)DecodeMat,(swap)ResizeMat].
The filters in () parentheses can return the following states:
- Run, which means that the current sub-backend can be skipped and wait to enter the next sub-backend (Effective from v0.3.2b1;
Continuecan be used in previous versions.) - Break, which means to exit the execution of
Sequential - Error, which means an error occurred
- SerialSkip, which means that consecutive serial sub-backends can be skipped, equivalent to Break in
Sequential - SubGraphSkip, which means that consecutive subgraphs can be skipped, equivalent to Break in
Sequential
Here are some built-in filter definitions:
- Run
- swap
#include "filter.hpp"
class FilterRun : public Filter {
public:
status forward(dict data) override { return Filter::status::Run; }
};
IPIPE_REGISTER(Filter, FilterRun, "Run,run");
class Filter {
public:
enum struct status { Run, Skip, SerialSkip, SubGraphSkip, Break, Error };
virtual bool init(const std::unordered_map<std::string, std::string>& /*config*/,
dict /*dict_config*/) {
return true;
};
virtual status forward(dict input) {
auto iter = input->find(TASK_RESULT_KEY);
if (iter == input->end()) {
return status::Break;
}
(*input)[TASK_DATA_KEY] = (*input)[TASK_RESULT_KEY];
input->erase(iter);
return status::Run;
}
virtual ~Filter() = default;
};
If four data enter this Sequential at the same time, but one of them fails to decode, then
- One data returns
status::Breakinswap, while the others returnstatus::Run. Sequentialcontinues to send the remaining three data to the next stage, while the data inBreakstate terminates the execution in Sequential.
The above describes the response when encountering Break for some data; similarly, when encountering Skip for some data, the data will be locally processed in a similar way. However, when a data is in Error state, Sequential will consider the overall task status as Error. If this contradicts the user's intention, the user can try to split the sub-backends into different Sequentials to avoid mutual interference. Note that the Error state is generally extremely rare and unexpected.