Re: [eigen] Malloc-free dynamic matrices

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]


On 3/5/10, Gael Guennebaud <gael.guennebaud@xxxxxxxxx> wrote:
> yes there are hundreds of way to achieve these goals without touching
> Matrix, but none of the solutions will be as convenient as having it by
> default directly inside Matrix. For instance, nobody would ever think about
> removing reserve from std::vector! I really don't see any valuable argument
> against doing so.

I am not quite sure if we are talking about the 100% same thing here.

The original poster's very goal (and his code examples) for
'NeverRealloc' appear to be semantically different from the concept of
"reserve".

In fact:

::std::vector<float> v1, v2;
v1.reserve(10), v2.reserve(100);

// populate v1 and v2 with 10 and 100 elements respectively

v1 = v2; // the original poster wants an assertion/error to be
generated -- i.e. by *design* he wants to *never* reallocate -- hence
the "NeverRealloc" option name... -- as per his own code example...

I know that you, later in your email, re-qualify this as an optional
feature -- but if so, to me, this is rather different w.r.t. the
concept of just reserving/caching the memory.

For instance, if we have already started comparing/justifying concepts
of "reserve" in eigen's matrix based on reservation semantics in
::std::vector -- should then one also, conversely, consider having the
'assert/error' option (when re-growth may be needed at the target obj)
for the ::std::vector as well? Of course not... :-)

"Reservation != reallocation" and clumping both into the same context
is not real clear to me.

So, if we are talking about "reservation"  -- then *yes*, of course,
such a feature would be convenient in the Matrix obj. -- and it can
lead one on the path for more elaborate caching later on (e.g. not
just reserving-ahead via "reserve" but also having heuristics for
keeping the memory-size from previously-used large resize state
(similar to growth-control for large strings in Mozilla browser
afaik), etc. etc. etc. -- be those ideas reasonable/needed or not :-)

.... but this would be a rather different context for the conversation
as compared to the original's idea of *never* realloc and generating
assertions for the matrix re-growth...

[...]

> And finally, remains the question whether resizing above the pre allocated
> size should be allowed or not. Here it is pretty clear that the default must
> allows that.
[...]
> What do you think?

I agree indeed -- if one does go ahead with the "reserve", then
asserting is not a good idea (at least with a default state... if
ever) -- as "reserve" and "never-realloc" are two *distinct*
*different* semantic points -- otherwise ::std::vector would have
these assertions enforced as well :-)

leon.

> On Thu, Mar 4, 2010 at 3:58 AM, leon zadorin <leonleon77@xxxxxxxxx> wrote:
>
>> On 3/4/10, Márton Danóczy <marton78@xxxxxxxxx> wrote:
>> > On 3 March 2010 15:44, leon zadorin <leonleon77@xxxxxxxxx> wrote:
>> >> double * reserved(aligned_alloc(8192));
>> >>
>> >> // 3x3
>> >> Map<double> m(reserved, 3, 3);
>> >>
>> >> // 10x10 -- resize w/o reallocation -- equivalent to NeverRealloc w/o
>> >> much repatching(?)
>> >> m.remap(reserved, 10, 10);
>> >
>> [...]
>> > Matrix<float, Dynamic, Dynamic, NoRealloc> A, B, C;
>> >
>> > A.reserve(16); A.resize(4,4);
>> > B.reserve(25); B.resize(5,5);
>> > C.reserve(81); C.resize(9,9);
>> >
>> > B=A; //this should work and resize B to 4x4
>> > B=C; //this should raise an assertion failure
>> >
>> > To achieve this behaviour, we do need a dedicated class -- or an
>> > option, such as in the patch.
>>
>> Sure... but not quite -- if we are talking about adding extra
>> "sanity-checking" in the debug builds of an app, and if current API
>> has no such assertions, then some form of changes would be needed.
>>
>> But in such a case, still -- I don't think Benoit was arguing against
>> any changes -- only in favor of smaller/more-elegant ones...
>>
>> Map<> obj. ctor could indeed have an additional arg denoting the max
>> size of the (re)mappable mem (on which it is mapping)... or indeed, as
>> others have alluded to, one could pass an 'array object' instead of
>> just 'float/double *' (given that what you are really trying to
>> 'sanity-check' is the boundary -- and such is not meant to
>> auto-reallocate but to assert -- implying that this should not be
>> happening 'by design') -- so a logical conclusion would be for Map<>
>> to be able to map from a vector/array type (e.g. ::boost::array
>> semantics), then:
>>
>> array a1(25);
>> array a2(81);
>>
>> Map m1(a1, 5, 5);
>>
>> Map m2(a2, 9, 9);
>>
>> m1 = m2; // assertion due to boundary-checking of 'intelligent' arrays....
>>
>> or if constructing/mapping explicitly from "double/float *"
>>
>> double *a1(alloc(25));
>> Map m1(a1, 5, 5, 25); // i.e. additional arg denoting max mappable mem.
>>
>> double *a2(alloc(81));
>> Map m2(a2, 9, 9, 81);
>>
>> m1 = m2; // the same assertion... (ifndef NDEBUG of course)
>>
>> In fact, given that you are only requiring an assertion (not exception
>> throwing), then the actual presence of the above fields (e.g. in the
>> Map class, the 'bounds-keeping' variable could, itself, exist only
>> #ifndef NDEBUG
>> size_t max_mappable_size;
>> #endif
>>
>> Alternatively, as you mentioned -- another class may be used... but,
>> if such is to be the case, then what I was trying to say was that this
>> class feels like being more of a facade design-pattern, not a patch to
>> the existing class:
>>
>> struct blah {
>> double * data;
>> Map m;
>> blah()
>> : data(allocate), m(data, x, y)
>> {
>> }
>> etc. etc. -- like op= with checking for memory-bounds violations...
>> };
>>
>> ... but only if one wants it...
>>
>> from your code-example it looks to me like it really should be subject
>> to an "array" object... or a Map object... as memory-bounds checking
>> is really a question of abstracting the c-style 'arrays' in the first
>> place... ideally...
>>
>> kind regards
>> Leon.
>>
>>
>>
>



Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/