copy from pointer to pointer

J

Jason Who

I need to make a quick raw copy of a large block of data from one pointer to
another.
Marshal.Copy let me copy from pointer to array and another call can take it
from aray to pointer. That is obviously not optimal.

I can however not find any way of copying BLOCKS of data from pointer to
pointer... apart from a loop and a load of copy instructions.

What is the method for copying a large block of data from here to there
given two pointers?
....hm.. I guess I could make an unmanaged c++ function and do a memcpy, but
that seems a bit odd
 
M

Mattias Sjögren

I need to make a quick raw copy of a large block of data from one pointer to
another.
Marshal.Copy let me copy from pointer to array and another call can take it
from aray to pointer. That is obviously not optimal.

I can however not find any way of copying BLOCKS of data from pointer to
pointer... apart from a loop and a load of copy instructions.

What is the method for copying a large block of data from here to there
given two pointers?
...hm.. I guess I could make an unmanaged c++ function and do a memcpy, but
that seems a bit odd

You can call RtlMoveMemory in kernel32.dll with PInvoke.

[DllImport("kernel32.dll")]
static extern void RtlMoveMemory(IntPtr dest, IntPtr src, uint len);


Mattias
 
J

Jason Who

You can call RtlMoveMemory in kernel32.dll with PInvoke.
[DllImport("kernel32.dll")]
static extern void RtlMoveMemory(IntPtr dest, IntPtr src, uint len);

Ok.. Not wrapping c++ but invoking win32. It is a little less messy, but
still... Is there really no native way of doing this in c#? When one can
write unsafe code and move data arround through pointers, it seems natural
to have some featurein the language/framework which allows for a block copy
from pointer to pointer?

Oh well... you gave a solution. Thanks. I will try it. After all, it is
clean _enough_ and should work :)
 
M

Michael C

Jason Who said:
Ok.. Not wrapping c++ but invoking win32. It is a little less messy, but
still... Is there really no native way of doing this in c#? When one can
write unsafe code and move data arround through pointers, it seems natural
to have some featurein the language/framework which allows for a block
copy from pointer to pointer?

I thought the same thing but couldn't find anything. I'd wondered if I was
missing something but with 3 people confirming the same thing here I guess
I'm not.

Michael
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

Jason said:
I need to make a quick raw copy of a large block of data from one pointer to
another.
Marshal.Copy let me copy from pointer to array and another call can take it
from aray to pointer. That is obviously not optimal.

I can however not find any way of copying BLOCKS of data from pointer to
pointer... apart from a loop and a load of copy instructions.

What is the method for copying a large block of data from here to there
given two pointers?
...hm.. I guess I could make an unmanaged c++ function and do a memcpy, but
that seems a bit odd

How about a simple loop?

while (count-- > 0) (p2++)* = (p1++)*;
 
W

Willy Denoyette [MVP]

Jason Who said:
You can call RtlMoveMemory in kernel32.dll with PInvoke.

[DllImport("kernel32.dll")]
static extern void RtlMoveMemory(IntPtr dest, IntPtr src, uint len);

Ok.. Not wrapping c++ but invoking win32. It is a little less messy, but
still... Is there really no native way of doing this in c#? When one can
write unsafe code and move data arround through pointers, it seems natural
to have some featurein the language/framework which allows for a block
copy from pointer to pointer?

Oh well... you gave a solution. Thanks. I will try it. After all, it is
clean _enough_ and should work :)

If you want a "pure" managed (but slower) solution, you can always use
Marshal.ReadInt64 and Marshal.WriteInt64 like this:

int bufferSize = ......;
IntPtr dest = Marshal.AllocHGlobal(bufferSize);
IntPtr src = Marshal.AllocHGlobal(bufferSize);
int size1 = bufferSize % 8;
int size8 = bufferSize - size1;
int ofs;
// copy multiples of 8 bytes first
for(ofs = 0; ofs < size8; ofs += 8)
Marshal.WriteInt64(dest, ofs, Marshal.ReadInt64(src, ofs));
// copy remaining bytes
for(int n = 0; n < size1; n++,ofs++)
Marshal.WriteByte(dest, ofs, Marshal.ReadByte(src, ofs));

Willy.
 
J

Jason Who

How about a simple loop?
while (count-- > 0) (p2++)* = (p1++)*;

Making n reads of m bytes is generally slower than making one read of m*n
bytes.
You will see that there are specifik opcodes on the cpu for repetitive reads
like stosb and the larger versions.
 
J

Jason Who

If you want a "pure" managed (but slower) solution, you can always use
Marshal.ReadInt64 and Marshal.WriteInt64 like this:

That is larger blocks then one byte, but stille it is a large number of
small reads and writes and not a single large copy.
Yes, I realize that the cpu can not in one operation copy a thousand
bytes.It does however have operations such as movsw which is optimized for
looping over a large number of copies and which is faster than the generic
read and write operations done a number of times.

In a way i do not "want" managed and slow. I was simply suprised that there
are no operations for the task built into .net.
 
W

Willy Denoyette [MVP]

Jason Who said:
That is larger blocks then one byte, but stille it is a large number of
small reads and writes and not a single large copy.
Yes, I realize that the cpu can not in one operation copy a thousand
bytes.It does however have operations such as movsw which is optimized for
looping over a large number of copies and which is faster than the generic
read and write operations done a number of times.

Yep, "rep movsd" is what is used by memcopy (RtlMoveMemory), now, what takes
time is storing and loading the data to/from main memory, whether you do it
with one single REP instruction or in a loop is a nonissue.
To give you an idea, the "RtlMoveMemory" version is less than twice as fast
as the "managed version" (400MB/s vs. 790MB/s on my box). If this is too
slow, well, then you will have to call "RtlMoveMemory".
In a way i do not "want" managed and slow. I was simply suprised that
there are no operations for the task built into .net.

Managed code primary deals with "managed" memory, unmanaged memory is only
dealt with in interop scenarios, that is moving data across the
unmanaged/managed memory boundary, moving from unmanaged to unmanaged memory
was not high on the priority list when FCL team designed the Marshal class.
After all, PInvoke is part of .NET., so you can always call into unmanaged
code if you need to.

Willy.
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

Jason said:
Making n reads of m bytes is generally slower than making one read of m*n
bytes.
You will see that there are specifik opcodes on the cpu for repetitive reads
like stosb and the larger versions.

The pointers doesn't have to be byte pointers. :)
 
J

Jason Who

To give you an idea, the "RtlMoveMemory" version is less than twice as
fast as the "managed version" (400MB/s vs. 790MB/s on my box). If this is
too slow, well, then you will have to call "RtlMoveMemory".

The point is that managed code is pointer to array or the reverse, while
what I need is pointer to pointer.
That means that I have to resort to a loop copying small blocks one at a
time and THAT is slow.
Managed code primary deals with "managed" memory, unmanaged memory is only
dealt with in interop scenarios, that is moving data across the
unmanaged/managed memory boundary, moving from unmanaged to unmanaged
memory was not high on the priority list when FCL team designed the
Marshal class. After all, PInvoke is part of .NET., so you can always call
into unmanaged code if you need to.

Yes, I can see the reason for it. Unmanaged to managed and managed to
unmanaged while unmanaged to unmanaged in a way is none of .net's business
 
J

Jason Who

The pointers doesn't have to be byte pointers. :)

No, but there are no built in datatypes which are more than 64 bit, i think,
so it doesnt make a lot of difference.
What will happen if defining a struct of a large number of bytes?
 
W

Willy Denoyette [MVP]

Jason Who said:
The point is that managed code is pointer to array or the reverse, while
what I need is pointer to pointer.
That means that I have to resort to a loop copying small blocks one at a
time and THAT is slow.

As I said before using "RtlMoveMemory" (or "rep movsd") is the fastest, but
using Marshal.ReadXXXX and WriteXXXX is only two times slower (worse case)
no matter the size of the blocks (assuming they are > 64 bytes). If you
call this TOO SLOW, then you know what you'll have to do, don't you?

Willy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top