So, i've been thinking for hours, i'm hoping that there's a way to get
d-pointers to work without a binary library, but i won't finish
studying this tonight.
Why does a binary shared library seem so useful? Because if we put all
the implementation of the data layout in such a shared library, we
ensure that if application A links to library B and both use Eigen,
then both are using the same data layout.
Why do I think that having a shared library is perhaps actually not
essential? Because since A and B both use Eigen already, both can
already have their own implementation of the Eigen data layout code.
The problem is that if they were compiled with different versions of
Eigen, these layouts may not be the same. We would like both to use
the most recent of the two versions of the Eigen data layout. Thus
this just a problem about "versioning" functions and selecting at
link-time or at run-time the the most "recent" one. I'm hoping that
there's a way to implement that... but it's a bit too much for my
brain tonight. Random keywords floating in my mind: extern template...
linking of virtual functions....
Benoit
2010/3/4 Gael Guennebaud <gael.guennebaud@xxxxxxxxx>:
>
> Ok, let me try to summarize. As far as I understood, the led us to two
> options:
>
> Option1: we add a tiny shared library implementing the
> creation/initialization of the D_structure and a method to get the
> D_structure. Then where and how it is store is a detail. This approach
> offers full flexibility in the future but requires a shared lib.
>
> Option2: if we don't want a shared lib, then there is no way we can change
> the size of the D_structure and/or the way it is initialized. So we can
> still keep some flexibility (~10% ?) by deciding for 3.0 to reserve some
> extra bytes for future uses. Those bytes will be initialized to 0, and in
> the future their default values must still be zero. In this case, there is
> indeed no need to store them on the heap, and we can store them on the stack
> as members of Matrix.
>
> gael.
>
>
> On Thu, Mar 4, 2010 at 10:43 PM, Benoit Jacob <jacob.benoit.1@xxxxxxxxx>
> wrote:
>>
>> 2010/3/4 Gael Guennebaud <gael.guennebaud@xxxxxxxxx>:
>> >> >> > alloc:
>> >> >> > m_data = ei_aligned_new(size+<16 bytes>) + <16 bytes>;
>> >> >> > allocatedSize() = size;
>> >> >> >
>> >> >> > dealloc:
>> >> >> > ei_aligned_delete(m_data-<16bytes>);
>> >> >> >
>> >> >> > int& allocatedSize() {return (m_data-<16bytes>);}
>> >> >> >
>> >> >> > Disclaimer: yes the above is not C++, it is just to picture the
>> >> >> > idea!
>> >> >>
>> >> >> This looks like going only halfway toward heap-stored data. Instead,
>> >> >> why not take the bolder move of adding a d-pointer? We would put
>> >> >> there
>> >> >> any additional data that is OK to access with non-inline functions..
>> >> >> So
>> >> >> we would keep directly as data members the array pointer m_data and
>> >> >> the dimensions m_rows and m_cols so we can still call
>> >> >> rows()/cols()/data() at zero cost (useful as they are used all the
>> >> >> time) but other less frequently used data could be deferred onto the
>> >> >> d-pointer and accessed through no-inline accessors.
>> >> >
>> >> > To be honest I don't see how adding a d-pointer can offer more
>> >> > flexibility.
>> >>
>> >> With your approach, any additional member data that we may want to add
>> >> in the future, has to fit in the fixed number of bytes that were
>> >> reserved, like 8 bytes or 16 bytes. We have to decide once and for all
>> >> how much space we reserve for additional members. Moreover, once we've
>> >> added a member, we have to keep its offset fixed forever. All of that
>> >> can theoretically be overcome by using a d-pointer.
>> >
>> > hm... maybe I've been clear but as "my proposal" I was referring to the
>> > solution of storing the D_structure in the dynamically allocated memory,
>> > i.e., with the data.
>>
>> Well let's look at your pseudo code:
>>
>> m_data = ei_aligned_new(size+<16 bytes>) + <16 bytes>;
>> allocatedSize() = size;
>>
>> dealloc:
>> ei_aligned_delete(m_data-<16bytes>);
>>
>> If I understand correctly, you're reserving a fixed amount of memory
>> (here 16 bytes) for the D_structure just before the location pointed
>> to by m_data. So yes it's on the heap, that's what I understood, but
>> you still hardcode the number of bytes that your D_structure may have.
>>
>> >> > My proposal affords the same with less memory and runtime overhead: a
>> >> > true
>> >> > d-pointer would requires in addition one pointer, one call to malloc,
>> >>
>> >> Yep, I thought about that just after sending the e-mail. The solution
>> >> might be to merge this idea with your idea: allocate at once the
>> >> matrix array and the D_structure. But in order to allow the
>> >> D_structure to grow in the future, place it after the array, not
>> >> before, and access it only with non-inline accessors .... now here's
>> >> the catch... that must be compiled into a shared library :( I didn't
>> >> think about that in my previous e-mail, but the d-pointer approach can
>> >> only work if we have a binary shared library :( Though at that point,
>> >> having such a tiny library would solve a bunch of problems at once
>> >> (cache size parameters, etc). I don't know what to think about that.
>> >
>> > You cannot easily put it at the end because ideally we would store the
>> > allocatedSize variable in the D_structure, and if you put it at the end
>> > of
>> > the data, you need the allocatedSize to access to the D_structure...
>>
>> Well yes, in my proposal of putting the D_structure at the end, we
>> have to add a new data member to Matrix, which can be either the
>> offset or why not directly the pointer to the D_structure. But I don't
>> think that it should be the allocatedSize that we should store, and
>> actually it still wouldn't be too convenient to address the
>> D_structure (need to take padding into account...)
>>
>> Then, from the moment we're storing 2 pointers, m_data and m_d, it
>> doesn't matter anymore which one is at the beginning and which one is
>> at the end of the buffer.
>>
>> Is that a big deal to add one more data member to MatrixXf...?
>>
>> Though in that vein, one might go further and ask why we're preferring
>> to put stuff on the heap at all, why not just add plain data members
>> to MatrixXf...? I'm not sure why sizeof(MatrixXf) matters more than
>> the size of the allocated buffer.
>>
>> > Since
>> > this whole approach can only work via a shared library,
>>
>> ...if we want a real d-pointer. Without a shared lib, we can still
>> have a D_structure, it's just that the application using Eigen
>> hardcodes the D_structure data layout at compile time, so we don't get
>> the flexibility of a d-pointer.
>>
>> >> I'm completely hesitating, I can't make a decision on that. I guess
>> >> that if we treat this issue simultaneously with other issues that
>> >> would benefit from a binary lib, such as cache size runtime
>> >> parameters, then the case for a binary lib gets quite strong. On the
>> >> other hand it will require good communication and documentation, it
>> >> would be great to keep it optional (maybe make its code optionally
>> >> available as a header file...), and it should be WTFPL-licensed.
>> >
>> > Same here, though I become more and more in favor to a shared library as
>> > it
>> > might solve many issues.
>>
>> i don't know... above we're discussing a very good solution without a
>> binary lib, and below you have a great idea for the cache size problem
>> too:
>>
>> >
>> > Regarding runtime settings without a shared lib, I was thinking about
>> > using
>> > a static variable inside a function:
>> >
>> > // internal
>> > int manage_cache_size(enum action,int v=0)
>> > {
>> > static int value = EIGEN_DEFAULT_CACHE_SIZE;
>> > if(action==set) value = v;
>> > if(action==get) return value;
>> > return value;
>> >
>> > }
>> >
>> > // public:
>> > int cacheSize() { return manage_cache_size(get); }
>> > void setCacheSize(int v) { manage_cache_size(set,v); }
>> >
>> > but I'm really unsure about that...
>>
>> wow, that looks like a great idea!
>>
>> Such a static variable in a function, works exactly like a global
>> variable from a library as far as we're concerned... as far as I can
>> see.
>>
>> Benoit
>>
>>
>
>