В настоящее время я пытаюсь улучшить проект C#, над которым я работаю. В частности, моя цель - распараллелить некоторые операции, чтобы сократить время обработки. Я начинаю с небольших фрагментов, чтобы получить его. Следующий код (не параллельно) работает правильно (как и ожидалось)Parallel.for вызывает разные результаты
for (int i = 0; i < M; i++)
{
double d;
try
{
d = Double.Parse(lData[i]);
}
catch (Exception)
{
throw new Exception("Wrong formatting on data number " + (i + 1) + " on line " + (lCount + 1));
}
sg[lCount % N][i] = d;
}
Используя следующее (параллельный) код, который я бы ожидать, чтобы получить те же результаты, но это не так.
Parallel.For(0, M, i =>
{
double d;
try
{
d = Double.Parse(lData[i]);
}
catch (Exception)
{
throw new Exception("Wrong formatting on data number " + (i + 1) + " on line " + (lCount + 1));
}
sg[lCount % N][i] = d;
});
Часть программы, от которой эти фрагменты считываются из файла, по одной строке за раз. Каждая строка представляет собой последовательность чисел двойной точности, разделенных запятыми, которые я вставляю в вектор lData [], используя String.Split(). Каждые M строк последовательность данных начинается с нового кадра данных (следовательно, % M
в индексе элемента, когда я присваиваю значения).
Это мое понимание (явно неправильное), что, поместив код из (последовательного) цикла в третий параметр Parallel.For
, я распараллеливаю его выполнение. Это не должно изменить результаты. Проблема в том, что все потоки доступны для lCount и M? Должен ли я делать потоковые локальные копии?
Спасибо.
(так как я новый, я не позволил создать Parallel.For
тег)
EDIT: я провел еще несколько тестов. В основном я смотрел на результат ранее в коде, чем то, что я делал раньше. Похоже, что параллельная версия моего кода не заполняет массив sg[][]
полностью. Скорее, некоторые значения оставлены по умолчанию (0, в моем случае).
EDIT 2 (ответить на некоторые из комментариев): lData[]
является string[]
, полученный с помощью string.Split()
. Исходная строка, которую я разделяю, считывается из моих файлов данных. Я написал код, который их генерирует, поэтому они обычно хорошо отформатированы (я по-прежнему использовал конструкцию try-catch
по привычке). Как раз перед циклом for (петля параллельна или последовательна) я проверяю, что lData[]
имеет правильное количество значений (M). Если это не так, я выдаю исключение, которое мешает программе достичь заданного цикла. sg[][]
представляет собой массив N по M типа double
(в отпечатках была опечатка, теперь исправлена; в моем исходном коде эта ошибка отсутствовала). После того, как я прочитал N строк из файла, массив sg[][]
содержит целый набор данных. После цикла for (loop) (параллельного или последовательного) есть часть прихода, которая выглядит так: lCount ++; // считая строки, я уже читал если ((LCOUNT% N) == 0) { // делать вещи с Sg [] [] // сброс к.с. [] [] } Итак, я специально переписывая все строки sg[][]
. Общая цель for-loop - обновить значения в sg[][]
.
Кроме того, вы можете увеличить производительность с помощью 'Double.TryParse' вместо обработки исключений. – James
Спасибо @ Джеймс, я этого не знал. – Bovaz
Для отсутствующих значений вы получили исключение? Также, если ваша обработка зависит от порядка, Parallel.For не выполняется в определенном порядке. – seshuk