Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Fast 2D array copy 1

Status
Not open for further replies.

Disruptive

Programmer
Mar 8, 2005
40
GB
Hi

I am repeatedly copying the array elements from old array to new array, performing operations on the new array (changing) in the process and then determining whether or not use the new array values or the old ones. To speed things up what I do is create a new array and using pointers reassign the pointer such that the updated pointer points at the right place to which ever array is the desired one.

Now the question I have relates to speed. How can I speed up the process of copying this array. Currently the code I am using is listed below:

for(i=0;i<BeadTotal;i++)
{
// Take a copy of all original positions...
ptrBeadArrayOld[0]=(*ptrBeadArray)[0];
ptrBeadArrayOld[1]=(*ptrBeadArray)[1];
ptrBeadArrayOld[2]=(*ptrBeadArray)[2];
}

memcpy(ptrBeadArrayOld,ptrBeadArray,3*BeadTotal*sizeof(double));

I have tried using memcpy but I keep getting a segmentation fault. Can you please advise of the fastest way of performing this operation.

Thanks
 
That would depend entirely on how you declared and initialised your arrays.

Please use [code][/code] tags when posting code.

--
 
I have explicitly listed how the arrays have been defined below.

the source array is passed to the function handling the opy with the following form:

void cop_fun (double ***ptrBeadArray)

ptrBeadArrayOld = (double **)malloc(BeadTotal * sizeof(double *));
for (i = 0; i< BeadTotal; i++)
ptrBeadArrayOld = (double *)malloc(3 * sizeof(double));
 
I can only guess at what you're trying to achieve here.

> memcpy(ptrBeadArrayOld,ptrBeadArray,3*BeadTotal*sizeof(double));
> void cop_fun (double ***ptrBeadArray)

How did you call cop_fun()
Code:
double **p; /* some malloc calls */ cop_fun(&p);
If it wasn't like that, then it's probably gone wrong already.

Also, is ptrBeadArray where you want to copy FROM or where you want to copy TO?

Assuming that all you want to copy are the pointers, then something like this might do what you want.
Code:
memcpy ( *ptrBeadArray, 
          ptrBeadArrayOld, 
          BeadTotal * sizeof *ptrBeadArrayOld );
Use a for loop to do the really obvious thing (and type-checked thing) before throwing all caution to the wind and going with memcpy. If you can't make the for loop approach work, then memcpy() isn't going anywhere.

--
 
I have the for loop working just fine and hence the copying function works fine. However the memcpy function causes a segmentation fault and I just cannot see from where it would occur, the sizes should be ok.
 
And I'm telling you that your for loop and memcpy() are not equivalent.

memcpy() copies ONE contiguous block of memory from one place to another. You do not have one contiguous block of memory.

> ptrBeadArrayOld = (double *)malloc(3 * sizeof(double));
ptrBeadArrayOld[0][0] to ptrBeadArrayOld[0][2] are contiguous.

ptrBeadArrayOld[1][0] on the other hand is a whole separate malloc call, which means it could be anywhere else in memory, and certainly won't be contiguous with the end of row 0 of your array.



--
 
Aha yes, I forgot about that, so is there a way of using memcpy or something faster that will perform the copying?
 
You can keep your for loop, but replace these 3 operations with one memcpy()
Code:
ptrBeadArrayOld[i][0]=(*ptrBeadArray)[i][0];
ptrBeadArrayOld[i][1]=(*ptrBeadArray)[i][1];
ptrBeadArrayOld[i][2]=(*ptrBeadArray)[i][2];
 
Basically what Salem has already said/written - in the original post the bug was that you did not put indirection on the destination.
Code:
memcpy(*ptrBeadArray,ptrBeadArrayOld,3*BeadTotal*sizeof(double));
Note that you have the parameters in the wrong order in your original post. It is destination, source, size.

Note that if you are copying from Berkley Unix, they use equivalents of memcpy which switch the positions of source and destination.

If you are doing this on your own hardware, you could always use the DMA controller. That is blindlingly fast for shifting stuff around.
 
> I am repeatedly copying the array elements from old array to new array,
> performing operations on the new array (changing) in the process and then
> determining whether or not use the new array values or the old ones.

Consider this
Code:
#include <stdio.h>
#define ROWS    10
#define COLS    20

typedef int (*twod_ptr)[COLS];

void clear ( twod_ptr arr ) {
    int r,c;
    for ( r = 0 ; r < ROWS; r++ ) {
        for ( c = 0 ; c < COLS; c++ ) {
            arr[r][c] = 0;
        }
    }
}

int calc ( twod_ptr old_a, twod_ptr new_a ) {
    printf( "old_a=%p new_a=%p\n", (void*)old_a, (void*)new_a );
    new_a[0][0] = old_a[0][0] + 1;
    return new_a[0][0];
}

void swap_arrays ( twod_ptr *p1, twod_ptr *p2 ) {
    twod_ptr    temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}

int main ( ) {
    int array1[ROWS][COLS], array2[ROWS][COLS];
    twod_ptr old_a = array1;
    twod_ptr new_a = array2;
    int result, i;

    printf( "Array1 at %p, array2 at %p\n", (void*)array1, (void*)array2 );
    printf( "old_a  at %p, new_a  at %p\n", (void*)old_a, (void*)new_a );

    clear( old_a );
    clear( new_a );

    for ( i = 0 ; i < 10 ; i++ ) {
        old_a[0][0] = i;
        result = calc( old_a, new_a );
        if ( result % 2 == 0 ) {
            printf("Result - swapping\n" );
            swap_arrays( &old_a, &new_a );
        }
    }

    return 0;
}
Not a malloc() or a memcpy() to be seen.

The arrays themselves don't move, all that changes are the two pointers to the start of each 2D array. The whole thing is exchanged with 3 simple pointer assignments.

My results
[tt]$ ./a.exe
Array1 at 0x22c9c0, array2 at 0x22c6a0
old_a at 0x22c9c0, new_a at 0x22c6a0
old_a=0x22c9c0 new_a=0x22c6a0
old_a=0x22c9c0 new_a=0x22c6a0
Result - swapping
old_a=0x22c6a0 new_a=0x22c9c0
old_a=0x22c6a0 new_a=0x22c9c0
Result - swapping
old_a=0x22c9c0 new_a=0x22c6a0
old_a=0x22c9c0 new_a=0x22c6a0
Result - swapping
old_a=0x22c6a0 new_a=0x22c9c0
old_a=0x22c6a0 new_a=0x22c9c0
Result - swapping
old_a=0x22c9c0 new_a=0x22c6a0
old_a=0x22c9c0 new_a=0x22c6a0
Result - swapping[/tt]

--
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top