CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 18
  1. #1
    Join Date
    May 2012
    Posts
    8

    Quick Array Copy

    Hi,

    What would be a quick way to transfer the contents from an array of int[,] to UInt16[]?

    I am loading up the UInt16[] array for use in a BitmapSource object. The BitmapSource object is then associated with a WPF control image.Source to render it.

    Ideas appreciated. It is currently taking an extremely long time.

    Thanks,

    Alan

  2. #2
    VictorN's Avatar
    VictorN is online now Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,395

    Re: Quick Array Copy

    Define "extremely long": 1 month, 1 week, 1 hour, 1 minute, ...?
    What is the size of array?
    How did you implement this copying?
    Victor Nijegorodov

  3. #3
    Join Date
    Jan 2009
    Posts
    596

    Re: Quick Array Copy

    Before we can give suggestions to speed it up, we need to know how you are currently doing it

    But do you even need to do a copy in the first place? Could you just use a UInt16 array instead of the original int array?

    And does this need to be fully portable, or is machine-specific code (including assembler) allowed?

  4. #4
    Join Date
    Mar 2001
    Posts
    2,529

    Re: Quick Array Copy

    Also looks like a .net array of some type, or maybe C#???

    Code:
    int[,]
    What compiler / tools are you using? Also what programming language (/ extensions etc)?
    ahoodin
    To keep the plot moving, that's why.

  5. #5
    Join Date
    May 2012
    Posts
    8

    Re: Quick Array Copy

    Thanks for the replies. This is in C# so slightly preferred in that language/.NET, but open to anything that works. The copy is doing it pixel value by pixel value for a camera and is taking over 90 seconds. It would be great to get the copy/convert down to 2 seconds or less if possible (or somehow use the original array in the created bitmap). The total size is 8 megapixels. I am getting the source/original int[,] array data from the camera driver. The UInt16 is needed (or so I think) to create the bitmap used for display in the image control. It would be great if I could find a way to use the int[,] array directly without having to convert/copy it to the UInt16 array. The prototype code looks like:

    //Source
    int[,] imgArray = (int[,])C.ImageArray;
    //Destination
    UInt16[] img2Array = new UInt16[DestinationArraySize];

    //Loop that transfers "int" camera data in 2d array (from camera) to "UInt16" array. UInt16 array is needed for the bitmap used by the image control for display.
    //Loop (most details of loop not shown)
    ...
    //Core line in loop that copies/converts 1 camera value from the int[,] array to the UInt16[] array.
    img2Array[i] = (UInt16)(imgArray[iYPosition, iXPosition]
    ...

    //Destination array is put into the bitmap
    BitmapSource bitmap = BitmapSource.Create(width, height,
    96, 96, pf, null,
    img2Array, rawStride);

    //Newly created bitmap with destination array is associated with the image control for display
    image1.Source = bitmap;

    Thanks Again!

    Alan

  6. #6
    Join Date
    Jan 2009
    Posts
    596

    Re: Quick Array Copy

    I suspect that the problem lies here:
    Code:
    //Loop (most details of loop not shown)
    ...
    The 'copy' part of the code shouldn't be taking anything close to 90 seconds for an 8 megapixel image. So what happens in the rest of the loop?

  7. #7
    Join Date
    May 2012
    Location
    Bonn, Germany
    Posts
    43

    Re: Quick Array Copy

    Maybe you could implement only this part in a C DLL. It will probably be faster than anything you can achieve with .NET. You could also make use of SSE.
    By the way, I'm wondering why do you have to convert from int to Uint16?

  8. #8
    Join Date
    May 2012
    Posts
    8

    Re: Quick Array Copy

    UInt16 is used since I know it works in the Bitmapsource derived object for display within an image control (WPF). The very prototype code is as follows. This is very rough just wanted to get something that would convert the data from one source array to the destination. The 90+ seconds is in debug mode.
    int i = 0;
    int ImageSize= CameraXSize * CameraYSize;
    while (i < ImageSize)
    {
    iXPosition = 0;
    //Go across row doing copy/conversion
    while (iXPosition < CameraXSize)
    {
    img2Array[i] = (UInt16)(imgArray[iYPosition, iXPosition]);//Note: x and y position appear reversed for preloaded array from driver
    i++;
    iXPosition++;
    }
    //Increment row
    iYPosition++;
    }


    Thanks!!!

    Alan

  9. #9
    Join Date
    Jan 2009
    Posts
    596

    Re: Quick Array Copy

    You say it takes 90 seconds in debug mode - but code performance in debug mode is not important. How long does it take in release mode?

  10. #10
    Join Date
    May 2012
    Posts
    8

    Re: Quick Array Copy

    It turns out much greater than 90 seconds. 4 minutes, 7 seconds in release non-debug mode. The array size is 2016x3040. Thanks! - Alan

  11. #11
    Join Date
    Mar 2001
    Posts
    2,529

    Re: Quick Array Copy

    Wow this sounds like real slow performance times. You may want to look at using some multi-threaded approaches. Computers take advantage of multiple cores and a multi-threaded approach is key here. In any case, sometimes at the very least decreasing image resolution may not degrade user experience significantly in every case.
    ahoodin
    To keep the plot moving, that's why.

  12. #12
    Join Date
    May 2012
    Posts
    8

    Re: Quick Array Copy

    Thanks for the feedback. Ultimately, transfer and display of the image needs to be a couple seconds (or less). At least that is the goal. I will keep working on it. Thanks again.

  13. #13
    Join Date
    Jan 2009
    Posts
    596

    Re: Quick Array Copy

    I suspect that the problem is caused by all the bounds-checking which is being performed on your array accesses - though this wouldn't explain why Release is slower than Debug, that's just weird

    To speed this code up you could try to get the compiler to realise that you will never try to access an out-of-bounds element. Here is a simple example. Firstly, this code will perform bounds-checking:
    Code:
    int sum = 0;
    int[] numbers = new int[10];
    
    // Fill array with numbers - omitted
    
    for (int i = 0; i<10; i++) {
    	sum += numbers[i]; // Performs bounds-checking
    }
    but this code
    Code:
    for (int i = 0; i < numbers.Length; i++) {
    	sum += numbers[i]; // No bounds-checking performed
    }
    shouldn't, as the compiler will be able to see that the values of i will never be out of bounds so it can optimize out the bounds-checking (NB: this is of course subject to change with future compiler improvements).

    If you can rewrite your code so the compiler can perform this optimization it should improve performance. But given that you have 2 arrays, one of which is 1D and one which is 2D, I can't see how you could use this approach here.

    If all else fails your best chance might be to use pointers. When you access an array through a pointer there will be no bounds-checking. However, you have to be very careful when doing this. Also, you can only use pointers in 'unsafe' sections of code, and the entire application must be marked as 'unsafe'.

    This is how you would use pointers in the example given above:
    Code:
    unsafe fixed (int* numbersPtr = numbers)
    {
    	for (int i = 0; i<10; i++ ) {
    		sum += numbersPtr[i]; // No bounds-checking performed
    	}
    }
    A direct translation of your code but using pointers would be:
    Code:
    unsafe {
    	fixed(int* imageArrayPtr = imgArray) {
    		fixed(UInt16* img2ArrayPtr = img2Array) {
    			int i = 0;
    			int ImageSize = CameraXSize * CameraYSize;
    
    			int iYPosition = 0;
    			while (i < ImageSize) {
    				int iXPosition = 0;
    				while (iXPosition < CameraXSize) {
    					img2ArrayPtr[i] = (UInt16)(imgArrayPtr[iYPosition * CameraXSize + iXPosition]);
    					i++;
    					iXPosition++;
    				}
    				iYPosition++;
    			}
    		}
    	}
    }
    We can improve upon this though by using 'i' to index the original array (imgArray) also. This treats the 2d array as if it is 1d:
    Code:
    unsafe {
    	fixed(int* imageArrayPtr = imgArray) {
    		fixed(UInt16* img2ArrayPtr = img2Array) {
    			int i = 0;
    			int ImageSize = CameraXSize * CameraYSize;
    
    			while (i < ImageSize) {
    				img2ArrayPtr[i] = (UInt16)(imgArrayPtr[i]);
    				i++;
    			}
    		}
    	}
    }
    This will be as fast as you can make this loop (barring minor optimizations). If this still isn't fast enough then the original problem wasn't in this code after all - and in this case I would recommend going back to the 'safe' version.
    Last edited by Peter_B; May 22nd, 2012 at 09:28 AM.

  14. #14
    Join Date
    May 2012
    Posts
    8

    Re: Quick Array Copy

    Peter,

    Perfect solution. It executes in 0.02 seconds in release mode (without debugging) on an i5 processor. I am very excited about your solution not only for this but in other areas.

    Thank you!!!! I realize that took some effort.

    Best,

    Alan

  15. #15
    Join Date
    Jan 2009
    Posts
    596

    Re: Quick Array Copy

    Not bad - about 10,000 times faster! I'm really surprised how much of a difference this makes though - I wouldn't have thought the bounds-checking was so slow

Page 1 of 2 12 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured