Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In code converted from C++ to C#, what should I use instead of memcpy?

Tags:

c++

c#

The line in question is here:

memcpy(v[0], b_y1[0], 160U * sizeof(double));

where v and b_y1 area double arrays (double[]).

What exactly is this line doing? It was generated by converting MatLab to C++ to C#. I can provide the full function below if needed.

like image 600
Mini Avatar asked Aug 01 '18 01:08

Mini


People also ask

How do you convert in C?

Implicit Type Conversion In Cint number = value; Here, the C compiler automatically converts the double value 4150.12 to integer value 4150. Since the conversion is happening automatically, this type of conversion is called implicit type conversion.

Can C++ code be converted to C?

It is possible to implement all of the features of ISO Standard C++ by translation to C, and except for exception handling, it typically results in object code with efficiency comparable to that of the code generated by a conventional C++ compiler.

Can you convert C# to C?

If you mean "Is it possible to convert C# to readable and maintainable C-code?", then sorry, the answer is no — C# features don't directly map to C.


2 Answers

There are oodles of way you can do this. Import the DLL if you so choose and use memcpy.

However you can also use:

  • Buffer.BlockCopy

Copies a specified number of bytes from a source array starting at a particular offset to a destination array starting at a particular offset.

  • Array.Copy

Copies a range of elements in one Array to another Array and performs type casting and boxing as required.

  • Manually copy item by item as has been suggested

  • Or even faster is to use, fixed and unsafe and pointers

However if you really want speed, Array.Copy and Buffer.BlockCopy is probably your fastest and closest match.

Benchmarks

Just because I had the benchmarker open. Race your horses!

----------------------------------------------------------------------------
Operating System : Microsoft Windows 10 Pro
Version          : 10.0.17134
----------------------------------------------------------------------------
CPU Name         : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
Description      : Intel64 Family 6 Model 58 Stepping 9
Cores (Threads)  : 4 (8)      : Architecture  : x64
Clock Speed      : 3901 MHz   : Bus Speed     : 100 MHz
L2Cache          : 1 MB       : L3Cache       : 8 MB
----------------------------------------------------------------------------

Total Benchmarks : Inputs (1) * Scales (7) * Benchmarks (4) * Runs (500) = 14,000

Results 1

----------------------------------------------------------------------------
Mode             : Release (64Bit)
Test Framework   : .NET Framework 4.7.1 (CLR 4.0.30319.42000)
----------------------------------------------------------------------------

Total Benchmarks : Inputs (1) * Scales (7) * Benchmarks (4) * Runs (500) = 14,000

NET Framework 4.7.1

--- Standard input --------------------------------------------------------------------
| Value           |   Average |   Fastest |    Cycles |    Garbage | Test |      Gain |
--- Scale 10 ----------------------------------------------------------- Time 0.994 ---
| ArrayCopy       |  0.005 ms |  0.004 ms |  23.016 K |   7.927 KB | N/A  |   14.98 % |
| ElemCopy        |  0.006 ms |  0.004 ms |  23.591 K |   8.000 KB | N/A  |   12.08 % |
| ElemCopy Unsafe |  0.006 ms |  0.004 ms |  26.426 K |   7.915 KB | N/A  |    0.77 % |
| BlockCopy       |  0.006 ms |  0.004 ms |  26.295 K |   7.836 KB | Base |    0.00 % |
--- Scale 100 ---------------------------------------------------------- Time 1.124 ---
| ArrayCopy       |  0.005 ms |  0.004 ms |  20.581 K |   7.937 KB | N/A  |    1.60 % |
| BlockCopy       |  0.005 ms |  0.004 ms |  20.915 K |   8.000 KB | Base |    0.00 % |
| ElemCopy        |  0.005 ms |  0.004 ms |  21.836 K |   8.000 KB | N/A  |   -4.15 % |
| ElemCopy Unsafe |  0.005 ms |  0.004 ms |  22.357 K |   7.970 KB | N/A  |  -10.85 % |
--- Scale 1,000 -------------------------------------------------------- Time 1.322 ---
| ArrayCopy       |  0.005 ms |  0.005 ms |  23.106 K |   8.000 KB | N/A  |    6.31 % |
| ElemCopy Unsafe |  0.006 ms |  0.005 ms |  24.075 K |   8.000 KB | N/A  |    1.41 % |
| ElemCopy        |  0.006 ms |  0.005 ms |  24.392 K |   8.000 KB | N/A  |    0.46 % |
| BlockCopy       |  0.006 ms |  0.004 ms |  24.766 K |   8.015 KB | Base |    0.00 % |
--- Scale 10,000 ------------------------------------------------------- Time 1.727 ---
| BlockCopy       |  0.013 ms |  0.009 ms |  51.749 K |  86.172 KB | Base |    0.00 % |
| ArrayCopy       |  0.016 ms |  0.014 ms |  61.467 K |  86.172 KB | N/A  |  -23.61 % |
| ElemCopy Unsafe |  0.017 ms |  0.015 ms |  63.659 K |  86.172 KB | N/A  |  -28.22 % |
| ElemCopy        |  0.019 ms |  0.016 ms |  70.479 K |  86.172 KB | N/A  |  -41.93 % |
--- Scale 100,000 ------------------------------------------------------ Time 1.825 ---
| BlockCopy       |  0.050 ms |  0.045 ms | 178.829 K | 789.273 KB | Base |    0.00 % |
| ArrayCopy       |  0.101 ms |  0.089 ms | 357.518 K | 789.273 KB | N/A  | -102.24 % |
| ElemCopy Unsafe |  0.121 ms |  0.108 ms | 428.179 K | 789.273 KB | N/A  | -143.35 % |
| ElemCopy        |  0.133 ms |  0.118 ms | 469.168 K | 789.273 KB | N/A  | -166.41 % |
--- Scale 1,000,000 ---------------------------------------------------- Time 4.946 ---
| BlockCopy       |  0.494 ms |  0.409 ms |   1.730 M |   7.637 MB | Base |    0.00 % |
| ElemCopy Unsafe |  1.336 ms |  1.164 ms |   4.674 M |   7.637 MB | N/A  | -170.59 % |
| ArrayCopy       |  1.478 ms |  1.298 ms |   5.169 M |   7.637 MB | N/A  | -199.40 % |
| ElemCopy        |  1.910 ms |  1.607 ms |   6.675 M |   7.637 MB | N/A  | -286.95 % |
--- Scale 10,000,000 -------------------------------------------------- Time 31.376 ---
| BlockCopy       |  5.408 ms |  4.589 ms |  18.896 M |  76.302 MB | Base |    0.00 % |
| ElemCopy Unsafe | 43.981 ms | 35.344 ms | 153.137 M |  76.302 MB | N/A  | -713.21 % |
| ElemCopy        | 46.318 ms | 37.623 ms | 161.225 M |  76.302 MB | N/A  | -756.43 % |
| ArrayCopy       | 48.171 ms | 38.471 ms | 167.548 M |  76.302 MB | N/A  | -790.69 % |
---------------------------------------------------------------------------------------

Results 2

----------------------------------------------------------------------------
Mode             : Release (64Bit)
Test Framework   : .Net Core 2.0 (CLR 4.0.30319.42000)
----------------------------------------------------------------------------

Total Benchmarks : Inputs (1) * Scales (7) * Benchmarks (4) * Runs (500) = 14,000

.Net Core 2.0

Test 1

--- Standard input ----------------------------------------------------------------------
| Value           |   Average |   Fastest |    Cycles |    Garbage | Test |        Gain |
--- Scale 10 ------------------------------------------------------------- Time 1.221 ---
| ElemCopy Unsafe |  0.006 ms |  0.003 ms |  23.940 K |   8.000 KB | N/A  |     13.53 % |
| BlockCopy       |  0.007 ms |  0.004 ms |  27.573 K |   7.923 KB | Base |      0.00 % |
| ArrayCopy       |  0.007 ms |  0.004 ms |  28.341 K |   7.914 KB | N/A  |     -5.98 % |
| ElemCopy        |  0.007 ms |  0.003 ms |  28.939 K |   7.914 KB | N/A  |     -6.12 % |
--- Scale 100 ------------------------------------------------------------ Time 1.333 ---
| BlockCopy       |  0.005 ms |  0.004 ms |  19.855 K |   7.970 KB | Base |      0.00 % |
| ElemCopy        |  0.005 ms |  0.004 ms |  22.061 K |   7.950 KB | N/A  |    -11.44 % |
| ArrayCopy       |  0.005 ms |  0.004 ms |  22.793 K |   8.000 KB | N/A  |    -15.94 % |
| ElemCopy Unsafe |  0.006 ms |  0.004 ms |  23.715 K |   7.999 KB | N/A  |    -21.65 % |
--- Scale 1,000 ---------------------------------------------------------- Time 1.464 ---
| BlockCopy       |  0.005 ms |  0.004 ms |  21.045 K |   8.001 KB | Base |      0.00 % |
| ElemCopy Unsafe |  0.005 ms |  0.004 ms |  21.731 K |   8.016 KB | N/A  |     -5.53 % |
| ElemCopy        |  0.006 ms |  0.004 ms |  24.120 K |   8.000 KB | N/A  |    -17.49 % |
| ArrayCopy       |  0.006 ms |  0.004 ms |  27.113 K |   8.013 KB | N/A  |    -31.62 % |
--- Scale 10,000 --------------------------------------------------------- Time 1.846 ---
| BlockCopy       |  0.010 ms |  0.008 ms |  37.962 K |  86.172 KB | Base |      0.00 % |
| ArrayCopy       |  0.018 ms |  0.014 ms |  67.134 K |  86.172 KB | N/A  |    -83.72 % |
| ElemCopy Unsafe |  0.019 ms |  0.014 ms |  72.097 K |  86.172 KB | N/A  |    -99.35 % |
| ElemCopy        |  0.021 ms |  0.016 ms |  77.657 K |  86.172 KB | N/A  |   -113.22 % |
--- Scale 100,000 -------------------------------------------------------- Time 2.880 ---
| BlockCopy       |  0.027 ms |  0.020 ms | 100.355 K | 789.305 KB | Base |      0.00 % |
| ArrayCopy       |  0.385 ms |  0.289 ms |   1.346 M | 789.305 KB | N/A  | -1,305.09 % |
| ElemCopy Unsafe |  0.404 ms |  0.280 ms |   1.414 M | 789.305 KB | N/A  | -1,374.97 % |
| ElemCopy        |  0.408 ms |  0.322 ms |   1.424 M | 789.305 KB | N/A  | -1,389.61 % |
--- Scale 1,000,000 ----------------------------------------------------- Time 11.892 ---
| BlockCopy       |  0.632 ms |  0.415 ms |   2.198 M |   7.637 MB | Base |      0.00 % |
| ElemCopy        |  4.645 ms |  3.347 ms |  16.159 M |   7.637 MB | N/A  |   -635.36 % |
| ArrayCopy       |  4.706 ms |  3.684 ms |  16.376 M |   7.637 MB | N/A  |   -645.01 % |
| ElemCopy Unsafe |  4.774 ms |  3.467 ms |  16.568 M |   7.637 MB | N/A  |   -655.66 % |
--- Scale 10,000,000 ---------------------------------------------------- Time 35.806 ---
| BlockCopy       |  6.116 ms |  4.635 ms |  21.294 M |  76.302 MB | Base |      0.00 % |
| ElemCopy Unsafe | 44.132 ms | 35.039 ms | 153.807 M |  76.302 MB | N/A  |   -621.63 % |
| ArrayCopy       | 49.990 ms | 40.360 ms | 173.860 M |  76.302 MB | N/A  |   -717.41 % |
| ElemCopy        | 50.552 ms | 38.044 ms | 175.432 M |  76.302 MB | N/A  |   -726.60 % |
-----------------------------------------------------------------------------------------

Input

public static double[] ArrayOfDouble(int scale)
{
   return Enumerable.Range(1, scale)
                    .Select(x =>_rand.NextDouble())
                    .ToArray();
}

Code

[Test("BlockCopy", "", true)]
public double[] Test1(double[] input, int scale)
{
   var result = new double[scale];
   Buffer.BlockCopy(input, 0, result, 0, input.Length);
   return result;
}

[Test("ArrayCopy", "", false)]
public  double[] Test2(double[] input, int scale)
{
   var result = new double[scale];
   Array.Copy(input, 0, result, 0, input.Length);
   return result;
}

[Test("ElemCopy", "", false)]
public  double[] Test3(double[] input, int scale)
{
   var result = new double[scale];
   for (var i=0; i <input.Length; i++)
      result[i] = input[i];
   return result;
}

[Test("ElemCopy Unsafe", "", false)]
unsafe public  double[] Test4(double[] input, int scale)
{
   var result = new double[scale];
   fixed(double* pInput = input, pResult = result)
   for (var i=0; i <input.Length; i++)
      *(pResult+i) = *(pResult+i);
   return result;
}

Summary

This should be taken with a grain of salt, and any real tests should be done on your own system. However it is a good estimate of what I'm getting when scaled.

In this case with doubles BlockCopy performs really well, ArrayCopy falls off at high scales, I'm not sure why, Unsafe always has performance benefits in these kind of things, but can't match the dedicated BCL Methods.

like image 185
TheGeneral Avatar answered Oct 18 '22 03:10

TheGeneral


It's just copying the data from b_y1 to v (160 doubles).

The most obvious substitute would be something like this:

for (int i=0; i<160; i++)
    v[i] = b_y1[i];
like image 41
Jerry Coffin Avatar answered Oct 18 '22 03:10

Jerry Coffin