2017-01-01 8 views
1
int n = varRatio.Count * varRatio[0].Count; 
     double[] y_0 = new double[var_ratio_ne.Count]; 
     double[] y_n = new double[y_0.Length]; 
     double[] var_map = new double[y_0.Length]; 
     double[] var_fa_map = new double[y_0.Length]; 
     for (int j = 0; j < var_width.Count; j++) 
     { 
      List<double> tempRow = new List<double>(); 
      for (int index = 0; index < var_ratio_ne.Count; index++) 
      { 
       y_0[index] = ((var_ratio_ne[index] - var_thr[0])/var_width[j]); 
      } 
      double inc = delta/var_width[j]; 
      for (int i = 0; i < var_thr.Count; i++) 
      { 
       if (var_thr[i] >= curr_max) 
       { 
        break; 
       } 
       Parallel.For(0, y_0.Length, k => 
       { 
        y_n[k] = y_0[k] - i*inc; 
        var_map[k] = Math.Min(Math.Max(y_n[k], 0), 1); 
        var_fa_map[k] = (not_edge_map[k]*var_map[k]); 
       }); 
       tempRow.Add(var_fa_map.Sum()/n); 
      } 
      var_measure.Add(tempRow); 
     } 

Вот это MATLAB код я преобразования:Matlab код намного быстрее, чем C# код не ожидается

curr_max = max(var_ratio(:)); 
N = numel(var_ratio); 
for j = 1:numel(var_width) 
    y_0 = (var_ratio_ne - var_thr(1))/var_width(j); 
    inc = delta/var_width(j); 
    z = not_edge_map; 
    for i = 1:numel(var_thr) 
     if var_thr(i)>=curr_max 
      break; 
     end 
     y_n = y_0 - (i-1)*inc; 
     var_map = min(max(y_n,0),1); 
     var_fa_map = z.*var_map; 
     var_measure(i,j) = sum(var_fa_map(:))/N; 
     % optimization for matlab: pixels that didn't contribute to the false alarm in this 
     % iteration will not contribute in the next one as well becouse the treshold increses so we can throw them out 
     ii = y_n>0; 
     y_0 = y_0(ii); 
     z = z(ii); 
    end 
end 

Размеры массивов:

  • N = 673326
  • var_ratio_ne = 586417
  • var_thr = 131072
  • var_width = [15 30 45]
  • not_edge_map = 586417
  • var_ratio = 666x1011 двойная матрица

UPDATE: мой код работает намного быстрее после этого изменения

//N = numel(var_ratio); 
    int n = varRatio.Count * varRatio[0].Count; 
    double[] y_0 = new double[var_ratio_ne.Count]; 
    for (int j = 0; j < var_width.Count; j++) 
    { 
     for (int index = 0; index < var_ratio_ne.Count; index++) 
     { 
      y_0[index] = ((var_ratio_ne[index] - var_thr[0])/var_width[j]); 
     } 
     double inc = delta/var_width[j]; 
     int indexOF = var_thr.FindIndex(x => x >= curr_max); 
     double[] tempRow = new double[indexOF]; 
     Parallel.For(0, indexOF ,i => 
     { 
      var total = 0d; 
      for (int k = 0; k < y_0.Length; k++) 
      { 
       total += (not_edge_map[k] * Math.Min(Math.Max(y_0[k] - i * inc, 0), 1)); 
      } 
      tempRow[i] = total/n; 
     }); 

     List<double> tempRowList = new List<double>(); 
     //copy the results of Parallel compute 
     for (int i = 0; i < indexOF; i++) 
     { 
      tempRowList.Add(tempRow[i]); 
     } 
     //fill the rest with zeros 
     for (int i = indexOF; i < var_thr.Count; i++) 
     { 
      tempRowList.Add(0); 
     } 
     var_measure.Add(tempRowList); 
    } 

Я думаю, что я m над вычислением чего-то здесь. Хотя я работаю в режиме отладки, производительность C# (в минутах) ужасна по сравнению с matlab (~ 20 секунд).
Не могли бы вы помочь мне с оптимизацией времени выполнения? Мне трудно понять, почему Matlab работает лучше, чем код C#.

+0

C# будет быстрее, чем язык общего назначения, но MATLAB предназначен для вычисления математических выражений. Поэтому, когда вся ваша программа делает хруст кучей чисел, MATLAB победит каждый раз. – Abion47

+0

Если вы включите весь код, то мы сможем оптимизировать определенные части, но в его текущей форме недостаточно информации, чтобы ее можно было компилировать, не допуская огромного количества. – Stuart

+0

@ Abion47 мой пост об этом конкретном фрагменте кода, есть много примеров, где у Matlab есть верхняя часть, и много примеров для C#, имеющих верх. Мне нужна помощь в этом конкретном фрагменте кода, и почему это так медленно по сравнению с кодом matlab. – Gilad

ответ

1

Я хотел бы предложить сокращение больших ассигнований, так это:

List<double> y_n = new List<double>(); 
List<double> var_map = new List<double>(); 
List<double> var_fa_map = new List<double>(); 
for (int k = 0; k < y_0.Count; k++) 
{ 
    y_n.Add(y_0[k] - i * inc); 
    var_map.Add(Math.Min(Math.Max(y_n[k], 0), 1)); 
    var_fa_map.Add(not_edge_map[k] * var_map[k]); 
} 
tempRow.Add(var_fa_map.Sum()/n); 

становится:

var total = 0d; 
for (int k = 0; k < y_0.Count; k++) 
{ 
    total += (not_edge_map[k] * Math.Min(Math.Max(y_0[k] - i * inc, 0), 1)); 
}  
tempRow.Add(total/n); 

В моих тестах это половины времени, но ваш пробег может варьироваться. Есть еще одна оптимизация, которая должна быть сделана так же, как сокращение распределений и объединение некоторых вычислительных задач, но мне нужны более качественные репрезентативные входы, чтобы иметь возможность эффективно ее профилировать, например, я не уверен, сделаю ли эту параллель и переключился на одновременные коллекции будут иметь положительный эффект.

+0

спасибо, что я сделал это, это не очень сильно влияет на производительность. – Gilad

+0

обновил мой ответ, лучше? – Stuart

+0

немного быстрее, я буду профилировать завтра, чтобы увидеть точную разницу.но что-то здесь очень странно для меня, количество времени, затрачиваемого на итерацию над матрицами, слишком велико. спасибо, в любом случае я дал +1 – Gilad