Commit 2c15bb96 authored by Paal Kvamme's avatar Paal Kvamme
Browse files

Calculate up front how many bricks needed for incremental build.

parent 076deb1a
......@@ -205,6 +205,26 @@ GenLodBase::_savestats()
{
}
/**
* Given a starting position and a size, reduce the size if needed so
* it fits inside the survey. The result may be empty. Note that there
* is no need for a correspinding method to adjust the position because
* padding is always added at the end of the survey.
*/
index3_t
GenLodBase::_clipsizetosurvey(std::int32_t lod, const index3_t& pos, const index3_t& size) const
{
const std::int64_t lodfactor = std::int64_t(1) << lod;
const index3_t surveysize =
(this->_surveysize + (lodfactor - 1)) / lodfactor;
// Don't use std::min(index3_t,index3_t). It doesn't do what you think.
return index3_t{
std::max(std::int64_t(0), std::min(pos[0]+size[0], surveysize[0]) - pos[0]),
std::max(std::int64_t(0), std::min(pos[1]+size[1], surveysize[1]) - pos[1]),
std::max(std::int64_t(0), std::min(pos[2]+size[2], surveysize[2]) - pos[2])
};
}
/**
* For debugging and logging only.
*/
......@@ -412,9 +432,11 @@ GenLodImpl::_calculate(const std::array<std::int64_t,3>& readpos_in, std::int32_
<< ", size=" << readsize << ")\n";
std::shared_ptr<const DataBuffer> data;
bool wasread = false;
if(readlod == 0) {
// Fullres bricks are always read, not calculated.
data = this->_read(readlod, readpos, readsize);
wasread = true;
this->_accumulate(data);
}
else if (this->_canread(readlod, readpos, readsize)) {
......@@ -426,6 +448,7 @@ GenLodImpl::_calculate(const std::array<std::int64_t,3>& readpos_in, std::int32_
// requested data is already in file so there is no write back.
// Just like in the LOD 0 case.
data = this->_read(readlod, readpos, readsize);
wasread = true;
}
else {
const std::array<std::int64_t,3> bs = this->_bricksize;
......@@ -461,13 +484,14 @@ GenLodImpl::_calculate(const std::array<std::int64_t,3>& readpos_in, std::int32_
// TODO-Performance: If parallelizing above, needs to have a test
// if (plan != "C" || readlod > 0)
this->_write(readlod, readpos, data);
if (!wasread)
this->_write(readlod, readpos, data);
std::shared_ptr<DataBuffer> result;
if (readlod == this->_nlods - 1) {
result = nullptr; // Caller will discard it anyway.
if (this->_done != this->_total) {
#if 0 // If trusting _willneed()
#if 1 // If trusting _willneed()
throw OpenZGY::Errors::ZgyInternalError
("GenLodImpl: Expected " + std::to_string(this->_total) +
" reads and writes but saw " + std::to_string(this->_done) + ".");
......@@ -837,6 +861,73 @@ GenLodC::_willneed() const
sz = (sz + std::int64_t(1)) / std::int64_t(2);
}
++total; // Loop stopped short of the last level, by definition one brick.
const std::int64_t full_total = total;
// TODO-@@@ This is WAY too complicated and fragile. Consider some
// kind of dry run instead. Or just accept a less accurate progress bar.
// On the positice side this is a good test to see that incremental
// rebuilds touch the data they ought to. Even though only the final
// count is checked.
// TODO-@@@ A virtual method or a data member telling us when an
// incremental buid is in progress. If not, this entire code block
// can be skipped. Knowing about incremental builds might also suggest
// other changes. Such as reducing the block size in _calculate().
// Subtract the bricks skipped because of incremental build.
// If full build then _canread() returns false for all lod>0
// and the code below, even without a short cut, would do nothing.
sz = this->_surveysize;
std::array<std::int64_t,3> max = sz; // Limit imposed by survey size @ lod-1
for (std::int32_t lod = 1; lod < _nlods; ++lod) {
max = sz; // size at (lod-1)
sz = (sz + std::int64_t(1)) / std::int64_t(2);
const index3_t chosensize{2*bs[0], 2*bs[1], sz[2]}; // before clipping.
for (std::int64_t ii = 0; ii < sz[0]; ii += chosensize[0]) {
for (std::int64_t jj = 0; jj < sz[1]; jj += chosensize[1]) {
// Consider 4 brick-columns at (lod), i.e. what _calculate chooses.
// If any of those need to be rebuilt then rebuild all, meaning
// we need to read 16 brick-columns from lod-1.
const index3_t checkpos{ii,jj,0};
const index3_t checksize = _clipsizetosurvey(lod, checkpos, chosensize);
if (_canread(lod, checkpos, checksize)) {
const index3_t subsize = _clipsizetosurvey
(lod-1, checkpos + checkpos, checksize + checksize);
const std::int64_t ibricks = (subsize[0] + bs[0] - 1) / bs[0];
const std::int64_t jbricks = (subsize[1] + bs[1] - 1) / bs[1];
const std::int64_t kbricks = (subsize[2] + bs[2] - 1) / bs[2];
total -= (ibricks * jbricks * kbricks);
if (lod == _nlods - 1)
total -= 1; // final brick won't be read either.
if (this->_verbose) {
std::cout << "@ lod " << lod << " pos " << checkpos
<< " is clean, saving "
<< ibricks << "*" << jbricks << "*" << kbricks
<< " bricks: "
<< " do not read lod " << lod-1
<< " pos (" << checkpos[0]*2
<< ", " << checkpos[1]*2
<< ", " << checkpos[2]*2
<< ") size (" << ibricks * bs[0]
<< ", " << jbricks * bs[1]
<< ", " << kbricks * bs[2]
<< ")\n";
}
}
}
}
}
if (this->_verbose) {
if (full_total == total)
std::cout << "@ Full lowres build needs " << total
<< " bricks" << std::endl;
else
std::cout << "@ Incr lowres build needs " << total
<< " of " << full_total << " bricks" << std::endl;
}
return total;
}
......
......@@ -90,6 +90,7 @@ protected:
std::int32_t lod, const index3_t& pos,
const std::shared_ptr<const DataBuffer>& data) const;
virtual void _savestats();
index3_t _clipsizetosurvey(std::int32_t lod, const index3_t& pos, const index3_t& size) const;
void _report(const DataBuffer* data) const;
void _reporttotal(std::int64_t total) { _total = total; }
std::string _prefix(std::int32_t lod) const;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment