I know if I want to copy an array of the same type, I have at least 3 Options, I can use a double for loop, use Array.copy or Buffer.BulkCopy. The two copy methods are much faster. See for instance here: https://stackoverflow.com/a/33030421 .
Both copy methods allow you to only copy parts of the 2d array but Array.copy needs rank of source and destination to be equal while bulk.copy does not.
I get data from a com interface and doubles or int come through as object. Lets say I want to include a cast on the copy. I can do this:
Stopwatch watch = new Stopwatch();
const int width = 2;
const int depth = 10 * 1000000;
Random r = new Random(100);
object[,] objdata = new object[width, depth];
for (int i = 0; i < width; i++)
{
for (int j = 0; j < depth; j++)
{
objdata[i, j] = r.Next();
}
}
int[,] arr2dint = new int[width, depth];
watch.Reset();
watch.Start();
Array.Copy(objdata, 0, arr2dint, 0, objdata.GetLength(0) * objdata.GetLength(1));
watch.Stop();
Console.WriteLine("ArrayCopy to 2 dimensional array including cast took {0}", watch.ElapsedMilliseconds);
watch.Reset();
var bufferloopcast = new int[width, depth];
watch.Start();
for (int i = 0; i < width; i++)
{
for (int j = 0; j < depth; j++)
{
bufferloopcast[i, j] = (int)objdata[i, j];
}
}
watch.Stop();
Console.WriteLine("Loop-copy to 2 dimensional array including cast took {0} ms", watch.ElapsedMilliseconds);
Now the copy method is slower. Also it comes with the limitation that source and destination rank have to be equal so I cannot use it to copy only part of an array (say only the first row).
I cannot make the Buffer.BulkCopy to work, error must be primitive type. I tried this, in wain:
int[,] buff2dint = new int[width, depth];
watch.Reset();
watch.Start();
int sizeo = Marshal.SizeOf(objdata[0, 0]);
Buffer.BlockCopy(objdata, 0, buff2dint, 0, objdata.GetLength(0) * objdata.GetLength(1)* sizeo);
watch.Stop();
Console.WriteLine("BufferCopy to 2 dimensional array including cast took {0}", watch.ElapsedMilliseconds);
SO, why did array.copy become so slow? And what is the best method to copy an 2d array, or parts of it, if you need to include a cast?
What about using an array of arrays instead of a 2d-array?
int [][] buff2dint = new int[width][];
for(int i = 0; i < width; ++i)
{
buff2dint[i] = new int[depth];
Buffer.BlockCopy(srcArray, 0, buff2dint[i], depth);
}
Related
Im trying to find the offset(difference between the array elements) of an array of double..The formula for my offset calculation is Offset= ((double[x+1]-double[x])*33)..
The problem I encounter is I cant seem to display the offsetX. What am I doing wrong here ?
Is there an easier way to do this ?
Here are my codes :
//double[] test is an infinite array containing double values that are passed from the Client to Server via UDP
//example : double[] test={1.11,2.344,3.45,4.54,....,......,....}
//Partial codes on the Server side to calculate and display offset
List<double> array = new List<double>();
//Im trying to store just the elements of postion 0,3,6..from the double []test into list array
//ignore array1[] and array2[]
for (int j = 0; j < test.Length;)
{
array.Add(test[j]); j++;
array1.Add(test[j]); j++;
array2.Add(test[j]); j++;
}
double[] gg = array.ToArray();
//Finding the offset
for (int i = 0, j = 1; i < gg.Length - 1; i++, j++)
{
offsetX.Add(gg[j] - gg[i]);
offsetX[i] = Math.Round(offsetX[i], 1);
offsetX[i] = (offsetX[i] * 33);
}
Console.Write( "OffsetX:" + string.Join(",", offsetX) +"/n");
The method below just iterates over the arrays adding the offsets during the initial iteration of the list
List<double> array = new List<double>() { 1.11,2.344,3.45,4.54 };
var offsets = new List<double>();
for (int i = 1; i < array.Count; i++)
offsets.Add(array[i] - array[i-1]);
This results in the offsets of:
Offsets: 1.234,1.106,1.09
I'm quite new to C# and I'm having difficult with our arrays, arrays of arrays, jagged arrays, matrixes and stuff. It's quite different from the C++ , since I can't get a reference (unless I use unsafe code) to a row of a matrix, using pointers and stuff.
Anyway, here's the problem: I have a struct/class called "Image" that cointains 1024 columns and 768 lines. For each line/column theres a 'pixel' struct/class that contains 3 bytes. I'd like to get/set pixels in random places of the matrix as fast as possible.
Let's pretend I have a matrix with 25 pixels. That is 5 rows and 5 columns, something like this:
A B C D E
F G H I J
K L M N O
P Q R S T
U V X W Y
And I need to compare M to H and R. Then M to L and N. Then I need to 'sum' G+H+I+L+M+N+Q+R+S.
How can I do that?
Possibilities:
1) Create something like pixel[5][5] (that's a jagged array, right?), which will be slow whenever I try to compare elements on different columns, right?
2) Create something like pixel[25] , which won't be as easy to code/ready because I'll need to do some (simple) math each and everything I want to access a element
3) Create something like pixe[5,5] (that's a multi-dimensional array, right?)... But I don't know how that will be translated to actual memory... If it's going to be a single block of memory, like the pixe[25], or what...
Since I intend to do this operations ('random' sums/comparison of elements that are in different rows/columns) tens of thousands of times per image. And I have 1000+ imagens. Code optimization is a must... Sadly I'm not sure which structure / classe I should use.
TL;DR: Whats the FASTEST and whats the EASIEST (coding wise) way of getting/setting elements in random positions of a (fixed size) matrix?
edit: I do not want to compare C++ to C#. I'm just saying I AM NEW TO C# and I'd like to find the best way to accomplish this, using C#. Please don't tell me to go back to C++.
I have worked on pixel based image processing in C#. I found that pattern #2 in your list is fastest. For speed, you must forget about accessing pixels via some kind of nice abstract interface. The pixel processing routines must explicitly deal with the width and height of the image. This makes for crappy code in general, but unless Microsoft improves the C# compiler, we are stuck with this approach.
If your for loops start at index 0 of an array, and end at array.Length - 1, the compiler will optimize out the array index bounds testing. This is nice, but typically you have to use more than one pixel at a time while processing.
I just finished testing, heres the result:
SD Array Test1: 00:00:00.9388379
SD Array Test2: 00:00:00.4117926
MD Array Test1: 00:00:01.4977765
MD Array Test2: 00:00:00.8950093
Jagged Array Test1: 00:00:03.6850013
Jagged Array Test2: 00:00:00.5036041
Conclusion: Single dimensional array is the way to go... Sadly we lose in readability.
And heres the code:
int[] myArray = new int[10000 * 10000];
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
myArray[(i*10000)+j] = i+j;
}
}
Stopwatch sw = new Stopwatch();
int sum = 0;
sw.Start();
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
sum += myArray[(j * 10000) + i];
}
}
sw.Stop();
Console.WriteLine("SD Array Test1: " + sw.Elapsed.ToString());
sum=0;
sw.Restart();
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
sum += myArray[(i * 10000) + j];
}
}
sw.Stop();
Console.WriteLine("SD Array Test2: " + sw.Elapsed.ToString());
myArray = null;
int[,] MDA = new int[10000, 10000];
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
MDA[i, j] = i + j;
}
}
sum = 0;
sw.Restart();
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
sum += MDA[j, i];
}
}
sw.Stop();
Console.WriteLine("MD Array Test1: " + sw.Elapsed.ToString());
sw.Restart();
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
sum += MDA[i, j];
}
}
sw.Stop();
Console.WriteLine("MD Array Test2: " + sw.Elapsed.ToString());
MDA = null;
int[][] JA = new int[10000][];
for (int i = 0; i < 10000; i++)
{
JA[i] = new int[10000];
}
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
JA[i][j] = i + j;
}
}
sum = 0;
sw.Restart();
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
sum += JA[j][i];
}
}
sw.Stop();
Console.WriteLine("Jagged Array Test1: " + sw.Elapsed.ToString());
sw.Restart();
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
sum += JA[i][j];
}
}
sw.Stop();
Console.WriteLine("Jagged Array Test2: " + sw.Elapsed.ToString());
MDA = null;
Console.ReadKey();
I am wanting to create multiple arrays of ints(in C#). However they all must have a unique number in the index, which no other array has that number in that index. So let me try show you what I mean:
int[] ints_array = new int[30];
for (int i = 0; i < ints_array.Count(); i++)
ints_array[i] = i;
//create a int array with 30 elems with each value increment by 1
List<int[]> arrayList = new List<int[]>();
for(int i = 0; i < ints_array.Count(); i++)
arrayList.Add(ints_array[i]. //somehow sort the array here randomly so it will be unique
So I am trying to get the arrayList have 30 int[] arrays and each is sorted so no array has the same int in the same index as another.
Example:
arrayList[0] = {5,2,3,4,1,6,7,8,20,21... etc }
arrayList[1] = {1,0,5,2,9,10,29,15,29... etc }
arrayList[2] = {0,28,4,7,29,23,22,17... etc }
So would this possible to sort the array in this unique kind of way? If you need anymore information just ask and ill fill you in :)
Wouldn't it be easier to create the arrays iteratively using an offset pattern?
What I mean is that if you created the first array using 1-30 where 1 is at index 0, the next array could repeat this using 2-30 where 2 is at index 0 and then wrap back to 1 and start counting forward again as soon as you go past 30. It would be an easy and repeatable way to make sure no array shared the same value/index pair.
You can do it like that:
List<int[]> arrayList = new List<int[]>();
Random rnd = new Random();
for (int i = 0; i < ints_array.Length; i++)
{
ints_array = ints_array.OrderBy(x => rnd.Next()).ToArray();
var isDuplicate = arrayList.Any(x => x.SequenceEqual(ints_array));
if (isDuplicate)
{
while (arrayList.Any(x => x.SequenceEqual(ints_array)))
{
ints_array = ints_array.OrderBy(x => rnd.Next()).ToArray();
}
}
arrayList.Add(ints_array);
}
I think, this wouldn't be so efficient for bigger numbers than 30.But in this case it shouldn't be a problem, in my machine it takes 7 milliseconds.
Jesse's idea would be best unless you needed a pure random pattern. In that case I would recommend generating a random number, checking all your previous arrays, and then placing it in an array if it did not match any other arrays current index. Otherwise, generate a new random number until you find a fresh one. Put that into a loop until all your arrays are filled.
Use a matrix (2D-array). It is easier to handle than a list of arrays. Create a random number generator. Make sure to initialize it only once, otherwise random number generator may create bad random numbers, if created in too short time intervals, since the slow PC-clock might not have ticked in between. (The actual time is used as seed value).
private static Random random = new Random();
Create two helper arrays with shuffeled indexes for rows and columns:
const int N = 30;
int[] col = CreateUniqueShuffledValues(N);
int[] row = CreateUniqueShuffledValues(N);
Then create and initialize the matrix by using the shuffeled row and column indexes:
// Create matrix
int[,] matrix = new int[N, N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
matrix[row[i], col[j]] = (i + j) % N;
}
}
The code uses these two helper methods:
private static int[] CreateUniqueShuffledValues(int n)
{
// Create and initialize array with indexes.
int[] array = new int[n];
for (int i = 0; i < n; i++) {
array[i] = i;
}
// Shuffel array using one variant of Fisher–Yates shuffle
// http://en.wikipedia.org/wiki/Fisher-Yates_shuffle#The_modern_algorithm
for (int i = 0; i < n; i++) {
int j = random.Next(i, n);
Swap(array, i, j);
}
return array;
}
private static void Swap(int[] array, int i, int j)
{
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
int size = 10;
// generate table (no duplicates in rows, no duplicates in columns)
// 0 1 2
// 1 2 0
// 2 0 1
int[,] table = new int[size, size];
for (int y = 0; y < size; y++)
for (int x = 0; x < size; x++)
table[y, x] = (y + x) % size;
// shuffle rows
Random rnd = new Random();
for (int i = 0; i < size; i++)
{
int y1 = rnd.Next(0, size);
int y2 = rnd.Next(0, size);
for (int x = 0; x < size; x++)
{
int tmp = table[y1, x];
table[y1, x] = table[y2, x];
table[y2, x] = tmp;
}
}
// shuffle columns
for (int i = 0; i < size; i++)
{
int x1 = rnd.Next(0, size);
int x2 = rnd.Next(0, size);
for (int y = 0; y < size; y++)
{
int tmp = table[y, x1];
table[y, x1] = table[y, x2];
table[y, x2] = tmp;
}
}
// sample output
for (int y = 0; y < size; y++)
{
for (int x = 0; x < size; x++)
Console.Write("{0} ", table[y, x]);
Console.WriteLine();
}
This code works fine:
var newArray = new Rectangle[newHeight, newWidth];
for (int x = 0; x < newWidth; x++)
for (int y = 0; y < newHeight; y++)
newArray[y, x] = (x >= width) || (y >= height) ? Rectangle.Empty : tiles[y, x];
But I am not having much luck replacing it with Array.Copy. Basically, if the resized array is larger it just adds blank rectangles to the edges. If it is smaller then it should just cut off the edges.
When doing this:
Array.Copy(tiles, newArray, newWidth * newHeight);
It messes up the array and all of its contents become disordered and do not retain their original index. Maybe I'm just having a brainfart or something?
Yes. However, it doesn't work the way you are thinking it works. Rather, it thinks of each mutlidimensional array as a single-dimensional array (which is actually what they are in memory, it's just a trick that lets us place some structure on top of them to think of them as multidimensional) and then copies the single-dimensional structures. So if you have
1 2 3
4 5 6
and want to copy it into
x x x x
x x x x
then it will think of the first array as
1 2 3 4 5 6
and the second as
x x x x x x x x
and the result will be
1 2 3 4 5 6 x x
which will appear to you as
1 2 3 4
5 6 x x
Got it?
I use this code:
public static void ResizeBidimArrayWithElements<T>(ref T[,] original, int rows, int cols)
{
T[,] newArray = new T[rows, cols];
int minX = Math.Min(original.GetLength(0), newArray.GetLength(0));
int minY = Math.Min(original.GetLength(1), newArray.GetLength(1));
for (int i = 0; i < minX; ++i)
Array.Copy(original, i * original.GetLength(1), newArray, i * newArray.GetLength(1), minY);
original = newArray;
}
calling like this for array of strings
ResizeBidimArrayWithElements<string>(ref arrayOrigin, vNumRows, vNumCols);
Simple use the "Clone()" function like the following:
This is your array list
object newArray = new object [row, column];
When you are creating another Array just use this code:
object[,] clonedArray = (object[,]) newArray.Clone();
Simple! Have fun!
I had a need to consume data from a buffer and copy off to a large holding array before the next interrupt hit. Copying in a loop wasn't an option; far too slow. I didn't need the multidimensional structure of the combined data until all of the copying was done, this meant I could Buffer.BlockCopy() to a single dimension array, then copy again onto a multidimensional array to obtain the required structure. Here's some code (run it in a console) that will demonstrate the technique as well as the performance.
static class Program
{
[STAThread]
static void Main()
{
Stopwatch watch = new Stopwatch();
const int width = 2;
const int depth = 10 * 1000000;
// Create a large array of data
Random r = new Random(100);
int[,] data = new int[width, depth];
for(int i = 0; i < width; i++)
{
for(int j = 0; j < depth; j++)
{
data[i, j] = r.Next();
}
}
// Block copy to a single dimension array
watch.Start();
int[] buffer = new int[width * depth];
Buffer.BlockCopy(data, 0, buffer, 0, data.Length * sizeof(int));
watch.Stop();
Console.WriteLine("BlockCopy to flat array took {0}", watch.ElapsedMilliseconds);
// Block copy to multidimensional array
int[,] data2 = new int[width, depth];
watch.Start();
Buffer.BlockCopy(buffer, 0, data2, 0,buffer.Length * sizeof(int));
watch.Stop();
Console.WriteLine("BlockCopy to 2 dimensional array took {0}", watch.ElapsedMilliseconds);
// Now try a loop based copy - eck!
data2 = new int[width, depth];
watch.Start();
for (int i = 0; i < width; i++)
{
for (int j = 0; j < depth; j++)
{
data2[i, j] = data[i, j];
}
}
watch.Stop();
Console.WriteLine("Loop-copy to 2 dimensional array took {0} ms", watch.ElapsedMilliseconds);
}
}
Output:
BlockCopy to flat array took 14 ms
BlockCopy to 2 dimensional array took 28 ms
Loop-copy to 2 dimensional array took 149 ms
Is it more performant to have a bidimensional array (type[,]) or an array of arrays (type[][]) in C#?
Particularly for initial allocation and item access
Of course, if all else fails... test it! Following gives (in "Release", at the console):
Size 1000, Repeat 1000
int[,] set: 3460
int[,] get: 4036 (chk=1304808064)
int[][] set: 2441
int[][] get: 1283 (chk=1304808064)
So a jagged array is quicker, at least in this test. Interesting! However, it is a relatively small factor, so I would still stick with whichever describes my requirement better. Except for some specific (high CPU/processing) scenarios, readability / maintainability should trump a small performance gain. Up to you, though.
Note that this test assumes you access the array much more often than you create it, so I have not included timings for creation, where I would expect rectangular to be slightly quicker unless memory is highly fragmented.
using System;
using System.Diagnostics;
static class Program
{
static void Main()
{
Console.WriteLine("First is just for JIT...");
Test(10,10);
Console.WriteLine("Real numbers...");
Test(1000,1000);
Console.ReadLine();
}
static void Test(int size, int repeat)
{
Console.WriteLine("Size {0}, Repeat {1}", size, repeat);
int[,] rect = new int[size, size];
int[][] jagged = new int[size][];
for (int i = 0; i < size; i++)
{ // don't count this in the metrics...
jagged[i] = new int[size];
}
Stopwatch watch = Stopwatch.StartNew();
for (int cycle = 0; cycle < repeat; cycle++)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
rect[i, j] = i * j;
}
}
}
watch.Stop();
Console.WriteLine("\tint[,] set: " + watch.ElapsedMilliseconds);
int sum = 0;
watch = Stopwatch.StartNew();
for (int cycle = 0; cycle < repeat; cycle++)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
sum += rect[i, j];
}
}
}
watch.Stop();
Console.WriteLine("\tint[,] get: {0} (chk={1})", watch.ElapsedMilliseconds, sum);
watch = Stopwatch.StartNew();
for (int cycle = 0; cycle < repeat; cycle++)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
jagged[i][j] = i * j;
}
}
}
watch.Stop();
Console.WriteLine("\tint[][] set: " + watch.ElapsedMilliseconds);
sum = 0;
watch = Stopwatch.StartNew();
for (int cycle = 0; cycle < repeat; cycle++)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
sum += jagged[i][j];
}
}
}
watch.Stop();
Console.WriteLine("\tint[][] get: {0} (chk={1})", watch.ElapsedMilliseconds, sum);
}
}
I believe that [,] can allocate one contiguous chunk of memory, while [][] is N+1 chunk allocations where N is the size of the first dimension. So I would guess that [,] is faster on initial allocation.
Access is probably about the same, except that [][] would involve one extra dereference. Unless you're in an exceptionally tight loop it's probably a wash. Now, if you're doing something like image processing where you are referencing between rows rather than traversing row by row, locality of reference will play a big factor and [,] will probably edge out [][] depending on your cache size.
As Marc Gravell mentioned, usage is key to evaluating the performance...
It really depends. The MSDN Magazine article, Harness the Features of C# to Power Your Scientific Computing Projects, says this:
Although rectangular arrays are generally superior to jagged arrays in terms of structure and performance, there might be some cases where jagged arrays provide an optimal solution. If your application does not require arrays to be sorted, rearranged, partitioned, sparse, or large, then you might find jagged arrays to perform quite well.
type[,] will work faster. Not only because of less offset calculations. Mainly because of less constraint checking, less memory allocation and greater localization in memory. type[][] is not a single object -- it's 1 + N objects that must be allocated and can be away from each other.