2014-02-14 3 views
2

Я работаю над анимацией целевой морфы.Использование параллельной обработки для Point3D

Я пытаюсь найти способы ускорить некоторые вычисления точек сетки в 3D WPF.

Итак, у меня есть две сетки - «текущая» сетка, которая содержит состояние игры и сетку «морфинга», которые мне нужно рассчитать различия между ними.

Я пытаюсь использовать параллельный цикл, но он продолжает бросать ошибку:

Первый шанс исключение типа «System.InvalidOperationException» произошло в WindowsBase.dll Первый шанс исключение type 'System.InvalidOperationException' произошел в mscorlib.dll В начале случайное исключение типа 'System.AggregateException' произошло в mscorlib.dll Дополнительная информация: Произошла одна или несколько ошибок.

Программа '[7444] HelixTrial.vshost.exe' вышла с кодом -1 (0xffffffff).

Мой код довольно простой. Он делает список, подсчитывает позиции в текущей сетке (которая равна целевой сетке морщин). Затем он пересекает сетки, обнаруживая разницу в позициях через Vector3D. Затем он должен добавить вектор в список.

List<Vector3D> listVectors = new List<Vector3D>(); 
int i = currentMesh.Positions.Count; 

Parallel.For(0, i, thisloop => 
{ 
    Point3D mor = morphMesh.Positions[thisloop]; 
    Point3D cur = currentMesh.Positions[thisloop]; 
    Vector3D foo = mor - cur; 
    listVectors.Add(foo); 
}); 

Это выглядит хорошо для меня, но не работает. Возможно ли, что Point3D нельзя использовать в параллельном цикле?

Большое спасибо.

EDIT

Это должно показать, как делается «morphMesh» и откуда приходит.

morphMesh берется из группы в мишени для моей модели человека (импортированный формат .OBJ). Я всего лишь анимация частей сетки. Поэтому я получаю группу меша, которую меня интересует, захватывая ребенка целевой модели морфинга.

var lipsmorph = morph.Children[21]; 
morphgeometry = (GeometryModel3D)lipsmorph; 
morphMesh = (MeshGeometry3D)morphgeometry.Geometry; 

Так что это делает, получая губы группу целевой модели оборотня, это идентифицируется как группа в индексе ребенка 21. Тогда получается, что в сетке, так что я могу использовать его вычислить координировать различия и манипулировать соответствующей сеткой в ​​живой «текущей» модели. Я также использую весовые коэффициенты, но я попытался свести код примера к минимуму, чтобы сначала получить его работу с различиями в сетке. Веса - это простые математики, поэтому не следует представлять такую ​​большую проблему, как то, что я прошу здесь.

EDIT TWO

Использование кода Скотта и замораживании модели первых - это будет работать. Но для меня это не стоит делать, так как выполнение этого кода происходит в то же время, что и непараллельное решение для всех моих вычислений, таких как веса. Скотт ссылался на это в одном из своих комментариев. Я просто не занимаюсь математикой, чтобы изменить ситуацию.

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

i = currentMesh.Positions.Count; 
List<Vector3D> listVectors = new List<Vector3D>(); 
morphMesh.Freeze(); 
currentMesh.Freeze(); 

try 
{ 
    Parallel.For(0, i, 
    () => new List<Vector3D>(), //Create a thread local list per thread 
    (thisloop, loopstate, localList) => //"localList" is the variable we created above or was the list that was returned from a previous loop iteration. 
    { 
     Point3D mor = morphMesh.Positions[thisloop]; 
     Point3D cur = currentMesh.Positions[thisloop]; 
     Vector3D foo = mor - cur; 
     localList.Add(foo); 
     return localList; //This hands the list off to be the input "localList" variable for the next thread that uses it. 
    }, 
    localList => //Combine the thread local lists in to the master list in a thread safe way. 
    { 
     lock (listVectors) 
      listVectors.AddRange(localList); 
    }); 
} 
catch (AggregateException b) 
{ 
    data.Text = b.InnerException.ToString(); 
} 
+0

Ещё не ответ на ваш вопрос, но я рекомендую вам забрать бесплатную книгу от Microsoft [«Шаблоны для параллельного программирования»] (http://www.microsoft.com/en-us/download/details.aspx?id=19222) многие примеры кода в ней вращаются вокруг 3D и он даст вам хорошие рекомендации о том, какую работу вы должны выполнять в своем цикле 'Parallel.For'. –

ответ

2

listVectors не поточно, так что вы не можете получать доступ к ним из нескольких потоков. При работе со списком вы должны либо использовать потоковые локальные объекты, либо поточно-безопасную коллекцию.

Вот эта локальная версия с использованием this overload из Parallel.For.

int i = currentMesh.Positions.Count; 
List<Vector3D> listVectors = new List<Vector3D>(); 

Parallel.For(0, i, 
    () => new List<Vector3D>(), //Create a thread local list per thread 
    (thisloop, loopstate, localList) => //"localList" is the variable we created above or was the list that was returned from a previous loop iteration. 
    { 
     Point3D mor = morphMesh.Positions[thisloop]; 
     Point3D cur = currentMesh.Positions[thisloop]; 
     Vector3D foo = mor - cur; 
     localList.Add(foo); 
     return localList; //This hands the list off to be the input "localList" variable for the next thread that uses it. 
    }, 
    localList => //Combine the thread local lists in to the master list in a thread safe way. 
    { 
     lock(listVectors) 
      listVectors.AddRange(localList); 
    }); 

Однако, как я имел в виду в комментарии я сделал в вашем вопросе, я думаю, вы не можете делать достаточно работы внутри цикла и некоторые из накладных расходов может быть больно потенциальную производительность. Посмотрите at the book я рекомендовал и конкретно смотреть на «ТОО мелкозернистого, ТОО крупнозернистый» пример анти-паттерн на странице 28.

+0

Спасибо, я попробую это. – Rog

+0

На самом деле нужно немного поработать, нужно также вычислить весы, но это не намного больше. Я уже приурочил не параллельный код, который у меня есть, поэтому я смогу сравнить два метода скорости. И спасибо, я обязательно прочитаю ваши рекомендации. – Rog

+0

Этот код вызывает ошибки: в WindowsBase.dll произошел первый случай исключения типа «System.InvalidOperationException» Первое исключение исключения типа «Исключение System.InvalidOperationException» произошло в mscorlib.dll Первое исключение случайного типа «Система. AggregateException 'произошел в mscorlib.dll – Rog

1

AsParallel использовать Linq в:

listVectors.AddRange(Enumerable.Range(0, currentMesh.Positions.Count) 
    .AsParallel() 
    .Select(thisloop => morphMesh.Positions[thisloop] - currentMesh.Positions[thisloop])); 
+0

Спасибо, я попробую. – Rog

+0

Я не знаю, будет ли это делать это параллельно или нет. В самом списке я думаю, что '.Select()' должен появиться после '.AsParallel()' для получения каких-либо преимуществ. –

+0

K, вам не нужен '.ToList()', поскольку он уже является 'IEnumerable'. –

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