[英]Speeding up boost::iostreams::filtering_streambuf
I am new to the C++ concept of streams and want to ask for some general advice to speed up my code in image processing .我是 C++ 流概念的新手,想寻求一些一般性建议,以加快我在图像处理中的代码。 I use a stream buffer
boost::iostreams::filtering_streambuf
to load and decompress the image from a file, as suggested in this post and another post .我使用流缓冲区
boost::iostreams::filtering_streambuf
从文件中加载和解压缩图像,如本文和另一篇文章中所建议的那样。 The performance is not satisfactory.表现并不令人满意。
The relavent code is the following:相关代码如下:
template <int _NCH>
class MultiChImg {
public:
...
...
private:
std::atomic<bool> __in_operation;
std::atomic<bool> __content_loaded;
char **_IMG[_NCH];
int _W, _H;
void dcmprss ( const std::string & file_name, bool is_decomp = true) {
...
...
// decompress
int counter = 0, iw = -1, ih = -1, _r = 0;
auto _fill_ = [&](const char c){
_r = counter % _NCH ; // was 3 for RGB mindset
if ( _r == 0 ) {
iw++; // fast index
if ( iw%_W==0 ) { iw=0; ih++; } // slow index
}
_IMG[_r][_H-1-ih][iw] = c;
counter ++ ;
} ;
auto EoS = std::istreambuf_iterator<char>() ;
// char buf[4096]; // UPDATE: improved code according to @sehe
if ( is_decomp ) {
// decompress
bio::filtering_streambuf<bio::input> input;
input.push( bio::gzip_decompressor() ); //
input.push( fstrm );
std::basic_istream<char> inflated( &input );
auto T3 = timing(T2, "Timing : dcmprss() prepare decomp ") ;
// assign values to _IMG (0=>R, 1=>G, 2=>B)
// TODO // bottleneck
std::for_each(
std::istreambuf_iterator<char>(inflated), EoS, _fill_ );
// UPDATE: improved code according to @sehe , replace the previous two lines
// while (inflated.read(buf, sizeof(buf)))
// std::for_each(buf, buf + inflated.gcount(), _fill_);
auto T4 = timing(T3, "Timing : dcmprss() decomp+assign ") ;
} else {
// assign values to _IMG (0=>R, 1=>G, 2=>B)
// TODO // bottleneck
std::for_each(
std::istreambuf_iterator<char>(fstrm), EoS, _fill_ ); // different !
// UPDATE: improved code according to @sehe , replace the previous two lines
// while (fstrm.read(buf, sizeof(buf)))
// std::for_each(buf, buf + fstrm.gcount(), _fill_);
auto T3 = timing(T2, "Timing : dcmprss() assign ") ;
}
assert(counter == _NCH*_H*_W);
...
...
};
...
...
}
The bottleneck appears to be the for_each()
part, where I iterate the stream, either inflated
via std::istreambuf_iterator<char>(inflated)
, or fstrm
via std::istreambuf_iterator<char>(fstrm)
, to apply a lambda function _fill_
.瓶颈似乎是
for_each()
部分,我在其中迭代流,通过std::istreambuf_iterator<char>(inflated)
inflated
通过 std:: fstrm
std::istreambuf_iterator<char>(fstrm)
的 fstrm 来应用 lambda 函数_fill_
。 This lambda function transfers the bytes in the stream to the designated place in the multi-dimensional array class member _IMG
.此 lambda 函数将流中的字节传输到多维数组类成员
_IMG
中的指定位置。
UPDATE: the timing was incorrect due to memory leakage.更新:由于内存泄漏,时间不正确。 I've corrected that.
我已经纠正了。
The timing results of the above function dcmprss()
are 450ms for a .gz file of 30MB size, 400ms for uncompressed file.上述函数
dcmprss()
的计时结果对于 30MB 大小的 .gz 文件为 450ms,对于未压缩文件为 400ms。 I think it takes too long.我认为这需要太长时间。 So I am asking the community for some kind advice to improve.
所以我要求社区提供一些改进的建议。
Thanks for your time on my post!感谢您花时间在我的帖子上!
You can use blockwise IO您可以使用分块 IO
char buf[4096];
inflated.read(buf, sizeof(buf));
std::for_each(buf, buf + inflated.gcount(), _fill_);
However, I also think considerable time might be wasted in _fill_
where some dimensions are reshaped.但是,我也认为可能会在
_fill_
中浪费相当多的时间,因为某些维度会被重新塑造。 That feels arbitrary.感觉很随意。
Note that several libraries have the features to transparently re-index multi-dimensional data, so you may potentially save time just linearly copy the source data and accessing that:请注意,有几个库具有透明地重新索引多维数据的功能,因此您可能会节省时间,只需线性复制源数据并访问它:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.