Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2010-04

cmem not aligning memory

17 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

C Western

I notice that the cmem unit does not align memory in the same way as the default unit - removing the cmem unit makes a factor of two difference in the speed of some double precision matrix code. (My system is i386). Inspecting the cmem unit indicates the issue is the extra bytes allocated for the count - is this really needed? Or do we have to allocate more bytes for blocks that are a multiple of 8?

Colin

Reply by email

Jonas Maebe
to C Western
C Western wrote
I notice that the cmem unit does not align memory in the same way as the default unit - removing the cmem unit makes a factor of two difference in the speed of some double precision matrix code. (My system is i386). Inspecting the cmem unit indicates the issue is the extra bytes allocated for the count - is this really needed?

It is to be able to implement the same checking as the Pascal version has (give a run time error in case someone calls freemem(p,size) with the wrong size).

BSD variants have a malloc_size() function that could be used instead, but at least Solaris and Linux don't seem to have something similar.

Or do we have to allocate more bytes for blocks that are a multiple of 8?

FPC's default memory manager even guarantees 16 byte alignment (for vectors).

Jonas

Reply by email

Jonas Maebe
to Micha Nelissen: Do C memory managers guarantee any alignment anyway? Not for SSE (16 bytes) I'm sure, but…
Micha Nelissen wrote
Do C memory managers guarantee any alignment anyway? Not for SSE (16 bytes) I'm sure, but 8 bytes I don't know.

From Linux' malloc man page:

For calloc() and malloc(), the value returned is a pointer to the allo- cated memory, which is suitably aligned for any kind of variable, or NULL if the request fails.

Mac OS X:

The allocated memory is aligned such that it can be used for any data type, including AltiVec- and SSE-related types.

Jonas

Reply by email

Michalis Kamburelis
to Marco van de Voort: In our previous episode, Jonas Maebe said: So a possible solution is to allocate…
Marco van de Voort wrote 10 lines
In our previous episode, Jonas Maebe said: >> Or do we have to allocate more bytes for blocks that are a multiple of 8? > FPC's default memory manager even guarantees 16 byte alignment (for vectors). So a possible solution is to allocate 16-sizeof(ptruint) bytes more? for 32-bit that would mean: <12 bytes slack><size><data>

Note that fftw_getmem and fftw_freemem (packages/fftw/src/fftw_s.pas) already contain the code to allocate always aligned pointer. (They allocate 15 bytes more for 16-bytes aligmnment, and store the value of original unaligned pointer to pass it to free.)

One could use these as a workaround, to get aligned pointers from any GetMem/FreeMem implementation.

Michalis

Reply by email

Michael Schnell
to Jonas Maebe: From Linux' malloc man page: For calloc() and malloc(), the value returned is a pointer…
Jonas Maebe wrote 7 lines
From Linux' malloc man page: For calloc() and malloc(), the value returned is a pointer to the allo- cated memory, which is suitably aligned for any kind of variable, or NULL if the request fails.

Hmm. What does "suitable" mean ? With many embedded CPUs alignment is forced to prevent runtime errors. With an X86 any alignment is allowed but performance is different Of course for Integers and Pointers Dword alignment (or QWord for 64 Bit systems) is appropriate (and supposedly provided by malloc. But with Vectors (and long Reals) more strict alignment might be faster. malloc() does not handle this. The C library provides calloc() for this purpose, but I don't know how this exactly works. I suppose it is implementation-depending.

-Michael

Reply by email

Jonas Maebe
to Michael Schnell
Michael Schnell wrote 10 lines
On 04/03/2010 02:12 PM, Jonas Maebe wrote: > > From Linux' malloc man page: > > For calloc() and malloc(), the value returned is a pointer to the > allo- > cated memory, which is suitably aligned for any kind of variable, or > NULL if the request fails. > Hmm. What does "suitable" mean ?

Conforming to the cpu's alignment requirements.

With many embedded CPUs alignment is forced to prevent runtime errors. With an X86 any alignment is allowed but performance is different

Vectors on x86 also require the memory to be aligned (unless you use special instructions, but by default compilers will not do that since that partially defeats the purpose of using vectors).

Show quoted text 6 lines
Of course for Integers and Pointers Dword alignment (or QWord for 64 Bit systems) is appropriate (and supposedly provided by malloc. But with Vectors (and long Reals) more strict alignment might be faster. malloc() does not handle this. The C library provides calloc() for this purpose,

No, calloc simply zeroes the allocated memory.

Jonas

Reply by email

Michael Schnell
to Jonas Maebe
Jonas Maebe wrote
No, calloc simply zeroes the allocated memory.

So why does it provide a size argument ? Just to zero the information it would suffice to give it a byte count as with malloc().

-Michael

Reply by email

Marco van de Voort
to Michael Schnell

In our previous episode, Michael Schnell said:

> No, calloc simply zeroes the allocated memory. So why does it provide a size argument ? Just to zero the information it would suffice to give it a byte count as with malloc().

I don't know, but the FreeBSD manpage says:

The calloc() function allocates space for number objects, each size bytes in length. The result is identical to calling malloc() with an argument
of ``number * size'', with the exception that the allocated memory is explicitly initialized to zero bytes.

Note the .. identical to calling malloc .. except .. initialized to zero bytes,

which is exactly what Jonas says.

Reply by email

Jonas Maebe
to Michael Schnell: So why does it provide a size argument ? Just to zero the information it would suffice to…
Michael Schnell wrote 5 lines
On 04/06/2010 01:07 PM, Jonas Maebe wrote: > > No, calloc simply zeroes the allocated memory. So why does it provide a size argument ?

One argument I know if is to prevent overflows, because size_t is an unsigned type while most multiplications are evaluated using signed arithmetic, but then one could ask why not do the same for malloc (the reply to that is that calloc is more often used for arrays, and arrays more often need to be zero than random data structures --see also dynamic arrays and ansistrings in Pascal vs other types-- but it's not that convincing to me).

Anyway, the reason for the two arguments is definitely completely unrelated to alignment, because
1) size does not define the alignment requirements. A struct containing 16 "1 byte" fields has an alignment requirement of 1, while a 16 byte vector usually has an alignment requi

2) the official standard also says that the result of calloc has to be assignable to any other pointer type: http://www.opengroup.org/onlinepubs/000095399/functions/calloc.html ("The pointer returned if the allocation succeeds shall be suitably aligned so that it may be assigned to a pointer to any type of object")

Jonas

Reply by email

Michael Schnell
to Marco van de Voort: In our previous episode, Michael Schnell said: I don't know, but the FreeBSD manpage says:
Marco van de Voort wrote 9 lines
I don't know, but the FreeBSD manpage says: The calloc() function allocates space for number objects, each size bytes in length. The result is identical to calling malloc() with an argument of ``number * size'', with the exception that the allocated memory is explicitly initialized to zero bytes.

That is why I supposed that it is implementation dependent.

-Michael

Reply by email

Jonas Maebe
to Michael Schnell
Michael Schnell wrote
On 04/06/2010 02:15 PM, Jonas Maebe wrote: > the result of calloc has to be assignable to any other pointer type: Is this not true for malloc(), as well ?

Yes, but I was only trying to illustrate that the "element size" parameter of calloc is unrelated to alignment requirements.

Jonas

Reply by email

C Western
to Jonas Maebe: From Linux' malloc man page: For calloc() and malloc(), the value returned is a pointer…
Jonas Maebe wrote 16 lines
On 03 Apr 2010, at 14:09, Micha Nelissen wrote: > Do C memory managers guarantee any alignment anyway? Not for SSE (16 bytes) I'm sure, but 8 bytes I don't know. From Linux' malloc man page: For calloc() and malloc(), the value returned is a pointer to the allo- cated memory, which is suitably aligned for any kind of variable, or NULL if the request fails. Mac OS X: The allocated memory is aligned such that it can be used for any data type, including AltiVec- and SSE-related types.

This means that the current cmem provides optimally bad alignment for doubles (and possibly invalid on some systems), as the alignment is offset by SizeOf(Integer).

How about an alternative implementation, without the integer recording size? I had a quick try at this - the only use of the MemSize routine in fpc+lazarus seems to be in an optimization in resizing strings. If this routine is adjusted to cope with MemSize returning 0 to indicate "not known" then most applications should work. This implementation as the additional advantage that mixing malloc and free's between C and Pascal then work.

PS: The CFreeMemSize seems to be incorrectly implemented - it does not offset the pointer.

Colin

Reply by email

Jonas Maebe
to C Western
C Western wrote 6 lines
How about an alternative implementation, without the integer recording size? I had a quick try at this - the only use of the MemSize routine in fpc+lazarus seems to be in an optimization in resizing strings. If this routine is adjusted to cope with MemSize returning 0 to indicate "not known" then most applications should work.

Having "most" applications work is a great recipe for annoying bug reports (and annoyed users).

This implementation as the additional advantage that mixing malloc and free's between C and Pascal then work.

That would indeed be nice, but I don't think it is feasible. Someone who values such functionality more than a full implementation of the memory manager can always install their own memory manager.

PS: The CFreeMemSize seems to be incorrectly implemented - it does not offset the pointer.

It calls CFreeMem, which does perform the adjustment.

Jonas

Reply by email

C Western
to Jonas Maebe
Jonas Maebe wrote 11 lines
On 08 Apr 2010, at 15:05, C Western wrote: > How about an alternative implementation, without the integer recording > size? I had a quick try at this - the only use of the MemSize routine > in fpc+lazarus seems to be in an optimization in resizing strings. If > this routine is adjusted to cope with MemSize returning 0 to indicate > "not known" then most applications should work. Having "most" applications work is a great recipe for annoying bug reports (and annoyed users).

True, except that the current implementation has its own problems, as discussed. Fortunately I don't see any need to use cmem for my own application; I think I added it at some point because there was some indication it was faster, but a quick test now suggests not.

Show quoted text 12 lines
> This implementation as the additional advantage that mixing malloc and > free's between C and Pascal then work. That would indeed be nice, but I don't think it is feasible. Someone who values such functionality more than a full implementation of the memory manager can always install their own memory manager. > PS: The CFreeMemSize seems to be incorrectly implemented - it does not > offset the pointer. It calls CFreeMem, which does perform the adjustment.

Sorry - you are quite right.

Colin

Reply by email