簡體   English   中英

C#快速元素查找矩陣作為Matlab

[英]C# Fast Element Find Matrix as Matlab

我有一個1000x1000的矩陣,並且使用Emgu CV。 我嘗試在此矩陣中找到元素索引

所以首先我在Matlab中嘗試

test_matrix=rand(1000,1000);
tic
[row,col]=find(test_matrix==test_matrix(1,1));
toc;

它在9.7毫秒內完成。

然后我在C#中使用經典的for循環。

for (int i = 0; i < element_matrix.Height; i++)
 for (int j = 0; j < element_matrix.Width; j++)
    if (element_matrix[i, j] == finding_element)
       {
         Find_Row_List.Add(i);
         Find_Col_List.Add(j);         
       }

它在460毫秒內完成。

然后,我將矩陣划分為10個小矩陣,並計算不同線程中的每個部分。

             t1= new Thread(() => {
                for(int i = 0; i < 100; i++)
                {
                    for(int j=0;j<element_matrix.Width;j++)
                    {
                        if(element_matrix[i,j]==finding_element)
                        {
                            Find_Row_List.Add(i);
                            Find_Col_List.Add(j);
                        }
                    }
                }
            });
            ...
            t1.Start();
            t2.Start();
            ...
            t10.Start();

            t1.Join();
            t2.Join();
            ...
            t10.Join();

它在310毫秒內完成。

我對20個小的矩陣和線程重復此過程。

它在380毫秒內完成。

然后我使用Parallel.For

  Parallel.For(0, element_matrix.Height, i =>
    {
        for(int j = 0; j < element_matrix.Width; j++)
        {
            if(element_matrix[i,j]==finding_element)
            {
                Find_Row_List.Add(i);
                Find_Col_List.Add(j);
            }
        }
    });

它在224毫秒內完成。

我使用兩個線程和Parallel.For

      t1 = new Thread(() => {
            Parallel.For(0, 500, i =>
            {
                for (int j = 0; j < element_matrix.Width; j++)
                {
                    if (element_matrix[i, j] == finding_element)
                    {
                        Find_Row_List.Add(i);
                        Find_Col_List.Add(j);
                    }
                }
            });
        });

        t2 = new Thread(() => {
            Parallel.For(500, 1000, i =>
            {
                for (int j = 0; j < element_matrix.Width; j++)
                {
                    if (element_matrix[i, j] == finding_element)
                    {
                        Find_Row_List.Add(i);
                        Find_Col_List.Add(j);
                    }
                }
            });
        });

        t1.Start();
        t2.Start();

        t1.Join();
        t2.Join();

它在240毫秒內完成。

摘要

**Method                       Duration (ms)**
------------------------       ------------
Matlab                         9.7
For Loop (Classic)             460
For Loop (10 threads)          310
For Loop (20 threads)          380
Parallel.For                   224
Parallel.For(2 threads)        250

所有持續時間均為10次計算的平均值。

我嘗試了與Matlab一樣快的不同方法來進行計算。 最快的解決方案是Parallel.For(224 ms)。 但是它比Matlab慢25倍。 我怎樣才能改善這個持續時間?

您的並行對象不是線程安全的,

同樣,最快的方法是使用非托管代碼,指針和(可能)線程

但是,這應該比您擁有的更快

var width = Input.GetLength(0);
var height = Input.GetLength(1);
var array = new Point[width * height];
var count = 0;

fixed (Point* r = array)
fixed (double* pInput = Input)
{
   var len = array.Length;

   for (var i = 0; i < len; i++)
      if (*(pInput + i) == someValue)
      {
         var temp = r + count++;
         (*(temp)).X = i;
         (*(temp)).Y = i / width;
      }

   var result = new Point[count];
   Array.Copy(array, 0, result, 0, count);
   return result;
}

基准測試

----------------------------------------------------------------------------
Mode             : Release (64Bit)
Test Framework   : .NET Framework 4.7.1 (CLR 4.0.30319.42000)
----------------------------------------------------------------------------
Operating System : Microsoft Windows 10 Pro
Version          : 10.0.17134
----------------------------------------------------------------------------
CPU Name         : Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
Description      : Intel64 Family 6 Model 42 Stepping 7
Cores (Threads)  : 4 (8)      : Architecture  : x64
Clock Speed      : 3401 MHz   : Bus Speed     : 100 MHz
L2Cache          : 1 MB       : L3Cache       : 8 MB
----------------------------------------------------------------------------

結果

--- Standard input ---------------------------------------------------------
| Value   |    Average |    Fastest |    Cycles | Garbage | Test |    Gain |
--- Scale 100 ----------------------------------------------- Time 0.163 ---
| Unsafe2 |  23.472 µs |  21.013 µs |  81.444 K | 0.000 B | N/A  | 80.92 % |
| Index   | 123.034 µs | 114.073 µs | 420.831 K | 0.000 B | Base |  0.00 % |
--- Scale 1,000 -------------------------------------------- Time 16.477 ---
| Unsafe2 |   2.940 ms |   2.324 ms |   9.761 M | 0.000 B | N/A  | 76.77 % |
| Index   |  12.657 ms |  12.021 ms |  43.033 M | 0.000 B | Base |  0.00 % |
----------------------------------------------------------------------------

您可以並行進行,盡管我不確定使用TPL會獲得這么多的性能提升,盡管您會得到一些,但是這將需要更多工作

您是否在“ Math.Net”庫中進行了多維操作?

        var sw = new Stopwatch();
        sw.Start();
        var test_matrix = Matrix<double>.Build.Dense(1000, 1000, 0);

        double finding_Element = 1;
        test_matrix[999, 999] = finding_Element;
        test_matrix[998, 999] = finding_Element;

        var result = new List<ValueTuple<int, int>>();

        for (int row = 0; row < 1000; row++)
        {
            for (int column = 0; column < 1000; column++)
            {
                if (test_matrix[row, column] == finding_Element)
                {
                    result.Add(new ValueTuple<int, int>(row, column));
                }
            }
        }

        sw.Stop();
        Console.WriteLine("Find List of Result: " + sw.ElapsedMilliseconds + "ms");

        var sw1 = new Stopwatch();
        sw1.Start();
        var result2 = test_matrix.Find(x => x.Equals(finding_Element)); // First Value
        sw1.Stop();
        Console.WriteLine("Find First Occurence: " + sw.ElapsedMilliseconds + "ms");

        Console.ReadLine();

我在這里的結果大約是34毫秒以獲取出現或首次出現的列表

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM