2013-12-18 3 views
5

Я использую чужой .NET 4 с открытым исходным кодом сглаживаемый код гидродинамики частиц, и я пытаюсь преобразовать его в проект Unity, на который вы можете рассчитывать только на .NET. 2. К сожалению, в коде используется класс Parallels (что здорово!), Но он использовал одну из более неясных перегрузок. Может ли кто-нибудь увидеть хороший способ добиться того же в .NET 2 без огромного успеха?Преобразование .NET 4 Threading в .NET 2

Parallel.For(
     0, 
     _numActiveParticles, 
     () => new Vector2[MAX_PARTICLES], 
     (i, state, accumulatedDelta) => calculateForce(_activeParticles[i], accumulatedDelta), 
     (accumulatedDelta) => 
     { 
      lock (_calculateForcesLock) 
      { 
       for (int i = _numActiveParticles - 1; i >= 0; i--) 
       { 
        int index = _activeParticles[i]; 
        _delta[index] += accumulatedDelta[index]/MULTIPLIER; 
       } 
      } 
     } 
    ); 

Я думаю это то, что делает код (Non Резьбовые):

for (int i = 0; i < _numActiveParticles; i++) 
    { 
     Vector2[] temp = new Vector2[MAX_PARTICLES]; 
     temp = calculateForce(_activeParticles[i], temp); 


     for (int k = _numActiveParticles - 1; k >= 0; k--) 
     { 
      int index = _activeParticles[k]; 
      _delta[index] += temp[index]/MULTIPLIER; 
     } 
    } 
+2

Вы могли бы найти это полезным http://stackoverflow.com/q/12386686/809009 –

+0

@OndrejJanacek Спасибо, что это но я также не уверен на 100%, что делает версия Parallels, поэтому я хочу, чтобы я правильно ее переводил. – PorcupineRending

+0

Я не думаю, что ваше понимание правильное. Вы даже не используете переменную temp. Прочтите это: http://msdn.microsoft.com/en-us/library/ff963547.aspx –

ответ

1

Ваш второй код не является правильным. Я думаю, что правильный код выглядит так:

var accumulatedDelta= new Vector2[MAX_PARTICLES]; 

for(int i = 0; i < _numActiveParticles; ++i) 
{ 
    accumulatedDelta = calculateForce(_activeParticles[i], accumulatedDelta); 
} 

for (int i = _numActiveParticles - 1; i >= 0; i--) 
{ 
    int index = _activeParticles[i]; 
    _delta[index] += accumulatedDelta[index]/MULTIPLIER; 
} 

Я не знаю, что .net2 есть, а что нет. Но вы можете имитировать Parallel.For.

объяснение этой перегрузки Parallel.For заключается в следующем:

Первый параметр: начальный индекс цикла

Второй параметр: конечный индекс цикла

Третий параметр: делегат, который будет создавать задачи локальные данные , для каждого каждого потока, который используется Parallel.For (задача), этот делегат будет вызываться и возвращать данные localInit.

Четвертый параметр: делегат, действующий как орган for. При первом выполнении делегата body этот делегат будет извлекать данные, созданные делегатом previuse (localInit). в каждом последующем цикле делегат тела может изменить localInit, а затем вернуть это к следующему выполнению тела. При последнем выполнении делегата тела данные localInit будут переданы последнему делегату.

Последний параметр: еще один делегат, который будет вызываться по каждой задаче, когда задача завершит работу. localInit будет передан этому делегату. Поскольку этот делегат можно назвать параллелизмом несколькими задачами, вы должны защитить свои общие данные.

Edit:

Версия ParallelFor может быть, как это:

public static void ParallerFor<TLocal>(int startIndex, int endIndex, Func<TLocal> initData, Func<int, TLocal, TLocal> body, Action<TLocal> finalizer) 
    { 
     int numThreads = Environment.ProcessorCount; 
     int chunkOffset = ((endIndex - startIndex)/numThreads) + 1; 

     Task[] tasks = new Task[numThreads]; 

     Enumerable.Range(0, numThreads).ToList().ForEach(x => 
      { 
       int start = x * chunkOffset; 
       int end = ((x + 1) * chunkOffset); 
       end = end > endIndex ? endIndex : end; 

       tasks[x] = Task.Factory.StartNew(() => 
       { 
        TLocal init = initData(); 

        for(int i = start; i < end; ++i) 
        { 
         init = body(i, init); 
        } 

        finalizer(init); 
       }); 
      }); 

     Task.WhenAll(tasks).Wait(); 
    } 
+0

Использование класса Task для переопределения Parallel.For - это своеобразное настроение. Если он у вас есть, у вас также есть другой (оба - .net 4 и выше). –

+0

@ Christian.K Спасибо за ваше упоминание. Я не знаю, что такое параллельные помощники '.net 2', но замена' task' на ручной запуск 'thread' - это простая работа. – MRB

+0

Вы можете проверить msdn. Это скажет вам. Обратите внимание, что задача не такая же, как поток (по крайней мере, используйте пул потоков, а не простой поток). Как правило, переопределение функций TPL является нетривиальным, чтобы получить правильное и эффективное. Много материала об этом в Интернете. –

Смежные вопросы