Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.67/21: Рейтинг темы: голосов - 21, средняя оценка - 4.67
3 / 3 / 2
Регистрация: 21.10.2013
Сообщений: 225

Проблема производительности при работе с массивами большой размерности

03.09.2015, 09:57. Показов 4570. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
здравствуйте дорогие форумчанине!
Сбагрил программку обрабатывающую шум с прибора и фильтрующая его, после чего выдаёт это всё на zedgraph.
При прогоне 10тыс точек всё получалось достаточно быстро, но как только я вогнал туда 1млн точек...
Комп подвис и через минуту-две выдал-таки графики с шумами и без. Но это слишком долго. значения коэффициентов для фильтров мне нужно практически вручную определять и если на кажду проверку будет уходить по 1-2 мин. А если массив возьму пару часов(более 16 млн точек).
Для обработки пользуюсь простыми массивами.
т.е. создаю массив нужной размерности и пошло поехало.
private double[,] massiv = new double[,];
м.б. в случаях с большими массивами стоит пользоваться какими-нибудь другими способами???
Или же у меня где-нибудь в программе(VS) стоит какая-нибудь фича которая тормозит просчёт????
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
03.09.2015, 09:57
Ответы с готовыми решениями:

Снижение производительности при работе в потоке
Здравствуйте! нужно было реализовать поток который бы двигал географические объекты по PictureBox. При этом 2-х ядерный ноут очень жестко...

Ошибка SystemOutOfMemory при работе с большой разреженной матрицей
Здравствуйте уважаемые программисты, помогите пожалуйста. Проблема следующая: В моем проекте строится очень большая разреженная матрица...

Проблема при работе с большой БД
Проблема в следующем - есть скрипт, который выполняет запрос к БД, в которой много записей, при этом возникает загрузка сервера на 100%....

21
Заблокирован
03.09.2015, 10:00
ToLexx, не видя кода сказать что-либо конкретное сложно.
0
TheGreatCornholio
 Аватар для Woldemar89
1255 / 733 / 285
Регистрация: 30.07.2015
Сообщений: 2,408
03.09.2015, 12:19
Цитата Сообщение от ToLexx Посмотреть сообщение
м.б. в случаях с большими массивами стоит пользоваться какими-нибудь другими способами???
Следует пользоваться многопоточностью как минимум, а то и параллельными вычислениями иногда.

И да, код бы тебе привести, в слепую сложновато
0
3 / 3 / 2
Регистрация: 21.10.2013
Сообщений: 225
03.09.2015, 12:21  [ТС]
а вот и файлики)allan.rar
0
3 / 3 / 2
Регистрация: 21.10.2013
Сообщений: 225
03.09.2015, 12:41  [ТС]
я вот тут подумал, можете ли вы заодно вообще оценить такую программку, нормально сварганено или можно и даже нужно улучшить и где?
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
03.09.2015, 12:49
ToLexx, первое, что я заметил - повыноси объявления и инициализацию переменных и массивов и цикла
C#
1
for (int pT = 10; pT < maxPoints; pT++)
Да и вообще в каждой итерации цикла создавать переменные - дополнительная нагрузка на систему связанная в выделением памяти и отправкой предыдущего объекта сборщику ресурсов.
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18298 / 14222 / 5368
Регистрация: 17.03.2014
Сообщений: 28,900
Записей в блоге: 1
03.09.2015, 12:51
aquaMakc, не говори глупостей. Память под переменную pT будет выделена один раз в начале метода. На стеке.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
03.09.2015, 12:54
OwenGlendower, у него в этом цикле создаются переменные и массивы
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 for (int pT = 10; pT < maxPoints; pT++)
            {
                double[] sum = { 0, 0, 0, 0, 0, 0 };
                int numMeans = strLen / pT;
 
                for (int i = 0; i < strLen; i++)
                {
                    for (int j = 0; j < 3; j++)
                    {
                        if (i % pT == 0 && i > 9)
                        {
                            int numBusket = i / pT - 1;
                            means[numBusket, j] = sum[j] / pT;
                            sum[j] = 0;
                        }
                    }
                }
                for (int j = 0; j < 3; j++)
                {
                    double raznost;
                    double raznostSqr = 0;
                    for (int i = 0; i < numMeans - 1; i++)
                    {
                        raznost = means[i + 1, j] - means[i, j];
                        raznostSqr += Math.Pow(raznost, 2);
                        means[i, j] = 0;
                    }
                    sigma[pT - 10, j] = Math.Sqrt(raznostSqr) / (2 * numMeans - 2);
                }
            }
Добавлено через 2 минуты
Можно подсчитать сколько раз выделяется память под эти переменные при 1 миллионе maxPoints. Меня цифра слегка пугает.
0
3 / 3 / 2
Регистрация: 21.10.2013
Сообщений: 225
03.09.2015, 12:56  [ТС]
вполне может быть, но у меня проблемы уже на этапе фильтрации получаются когда выбираю фильтрацию и идёт обращение к ф-иям transform и CalcMat в файле calc.cs. Выбираю для обработки массив 1мдн точек и он просто зависает.
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18298 / 14222 / 5368
Регистрация: 17.03.2014
Сообщений: 28,900
Записей в блоге: 1
03.09.2015, 13:06
aquaMakc, на каждой итерации память выделяется только на массив sum. Остальные переменные являются локальными переменными value-типа и значит память для них резервируется один раз в начале метода на стеке.

Добавлено через 7 минут
ToLexx, у тебя наверное ошибка в алгоритме. Массив sum всегда содержит только нули. Поэтому цикл обновляющий массив means будет заполнять его всегда нулями.
1
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
03.09.2015, 13:13
Цитата Сообщение от OwenGlendower Посмотреть сообщение
Остальные переменные являются локальными переменными value-типа и значит память для них резервируется один раз в начале метода на стеке
Если честно с выделением памяти под базовые типы я не разбирался, но я всё-таки сомневаюсь, что мы в каждой итерации цикла будем иметь дело с одними и теми-же экземплярами структур Int32 и Double. В конце-концов на MSDN написано
Члены, которые должны менять состояние экземпляра, в действительности возвращают новый экземпляр, инициализированный новым значением.
Хотя я могу ошибаться.
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18298 / 14222 / 5368
Регистрация: 17.03.2014
Сообщений: 28,900
Записей в блоге: 1
03.09.2015, 13:30
aquaMakc, ты глубоко ошибаешься. Память под все локальные переменные резервируется в начале метода. Цитата из MSDN всего лишь описывает фундаментальное свойство value-типов - передачу по значению.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
03.09.2015, 14:00
OwenGlendower, ) спасибо, буду иметь в виду

Добавлено через 28 минут
ToLexx, подвисает потому-что выполняется в основном потоке, если вынести в отдельный поток врядли будет работать быстрее, но форма зависать не будет ).
Могу посоветовать вынести тяжёлые математические функции в отдельную библиотеку на том-же c++ и вызывать их из твоей программы. Читал, что это нормальное решение, если нужна производительность, а уходить с шарпа не хочется, но сам пока так не заморачивался.
0
3 / 3 / 2
Регистрация: 21.10.2013
Сообщений: 225
03.09.2015, 14:59  [ТС]
ооо о как.
то бишь всё -таки рассчитывается именно массив долго?! Не zedgrapр отображает и ни что иное?!
Ща посоветовали каждую итерация pt кидать в txt файл вместе с системным временем.Если получится равномерное занесение, то типа всё дело ток в кол-ве точек.

Добавлено через 20 минут
сейчас прочитал статью http://http://ferrum-box.blogspot.ru/2013/09/linq.html. стоит смотреть в эту сторону или как? Реально уменьшить??
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
03.09.2015, 15:21
Цитата Сообщение от ToLexx Посмотреть сообщение
Ща посоветовали каждую итерация pt кидать в txt файл вместе с системным временем
Нагляднее использовать StopWatch

LINQ, конечно, хорошая штука, в "лабораторных" опытах с ним в некоторых случаях время выполнения сокращалось на порядки, но ты для начала найди где именно у тебя затык.
0
3 / 3 / 2
Регистрация: 21.10.2013
Сообщений: 225
03.09.2015, 15:40  [ТС]
Ага кроме того сейчас обрезал обрабатываемые массивы. ведь вывожу то 1 столбец, а обрабатываю 3. код сразу какой- то маленький стал без всех этих итераций j.
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
03.09.2015, 16:52
Лучший ответ Сообщение было отмечено ToLexx как решение

Решение

ToLexx, Попробовал я ваш исходник. Не знаю как у вас, а у меня больше всего времени тратится не на расчеты, а на парсинг текстового файла. Поэтому:
1) Не нужно вызывать парсинг несколько раз (он вызывается сначала в CalcMat, а затем вызывается еще раз при отображении графика). Нужно один раз пропарсить, а потом передавать в методы сформированный double[,]
2) Парсинг CSV файла - не оптимален, используйте вот этот парсер Передача данных из файла *CSV в таблицу dataGridView он будет значительно быстрее.
3) Ваш код у меня сразу вылетел в исключение, из-за того что вы все числа преобразуете в формат с запятой, а у меня стоит разделитель - точка.
4) Вы тратите очень много времени на Replace('.', ','). Это неправильно и не оптимально.
5) Math.Pow(raznost, 2); => raznost * raznost;
6) Рассчет выражений типа (beta / (beta + 1)) и (1 / (beta + 1)) нужно вынести за пределы циклов, поскольку они константны.

Касаемо пунктов 3 и 4: заменять точки на запятые - неправильно в принципе. Во-первых, метод double.Parse() парсит с текущими настройками пользователя. Поскольку вы точки заменяете на запятые, то ваш код считает нормально, только если у пользователя стоит разделитель запятая.
Во-вторых, я пользуюсь таким правилом: если парсится число, вводимое пользователем в интерфейсе программы, то нужно пользоваться просто double.Parse(), который парсит с текущими настройками разделителя. Запятые на точки заменять не нужно. Если же текстовый файл приходит извне (ваш случай) - тогда я считаю, что он в InvariantCulture, и имеет разделитель точку.
Итого, в методе transform вам не нужно заменять точку на запятую или наоборот, вам просто нужно парсить в инвариантной культуре:
C#
1
var val = double.Parse(str, CultureInfo.InvariantCulture);
2
3 / 3 / 2
Регистрация: 21.10.2013
Сообщений: 225
04.09.2015, 08:31  [ТС]
Сейчас посмотрю, завтра закончу, отпишусь и файлик покажу как сделаю.

Добавлено через 9 минут
сейчас попробовал double.Parse(tbBetta1.Text) выдало exception:
"Необработанное исключение типа "System.FormatException" в mscorlib.dll
Дополнительные сведения: Входная строка имела неверный формат."

Добавлено через 11 минут
Попробоваля ещё такой вариант:
beta1 = double.Parse(tbBetta1.Text,NumberStyles. AllowDecimalPoint);
Тоже исключение. Всё утро вечера мудрёнее. Пойду спать. всё равно спс.

Добавлено через 8 часов 5 минут
Storm23
beta1 = double.Parse(tbBetta1.Text,CultureInfo.I nvariantCulture);
Всё заработало, вот только вы предлагали данный parse для чтения из файла, нормально ли его использовать с текстбоксами?
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
04.09.2015, 10:11
ToLexx, Ок. Теперь посмотрим на метод вычисления дисперсии Аллана (allanFunc).
Тут конечно прекрасно все: и алгоритм, и реализация, и оптимизация
Во-первых, у вас там ошибка, собственно сумма элементов массива не вычисляется (вам уже писали об этом в посте #10).
Но это не главное. Главное то, что в вычислительной математике нельзя вот просто так взять и применить математические формулы в лоб. Сложность вашего алгоритма O(n * k). Где n - число исходных точек (1000000) а k - число интервалов для тау (у вас 50000). Понятно, что число итераций огромно. Поэтому и считается это долго.
Оптимизируется это дело следующим образом: для вычисления всевозможных сумм в массивах используется т.н. интегральное представление. Смысл в том, что вы считаете первообразную (накопительную сумму) по всему массиву значений. А далее вы можете быстро посчитать сумму на любом отрезке этого массива, пользуясь свойством интеграла:
https://www.cyberforum.ru/cgi-bin/latex.cgi?\int_{a}^{b} f(x) = F(b) - F(a)
(где F - первообразная)

Таким образом для вычисления суммы на любом отрезке массива вам нужно просто посчитать разность двух чисел.
Т.о. сложность алгоритма для вычисления Аллана становится O(k), вместо прежних O(n * k). Прирост производительности можете посчитать сами

Исправленный исходник allan.zip.
Ошибки и иcправления я отметил стрелкой <<------

Еще пару моментов:
1) Вы в интерфейсе пишете что считается дисперсия Аллана, а на самом деле пытались считать ср.кв. отклонение (то есть корень из дисперсии). Я сейчас считаю дисперсию, если нужно отклонение - возьмите корень.
2) У вас вывод по осям сделан неоптимально. Вам нужно один раз посчитать результат (он сичтается по всем осям), а при переключении радиобаттона осей, нужно просто перестраивать график для соотв оси. Вы же сейчас для каждой оси начинаете пересчет заново.
3) Алгоритм хорошо паралелится, но мне было лень. Вы можете распаралелить сами, если не будет хватать производительности.



Цитата Сообщение от ToLexx Посмотреть сообщение
Всё заработало, вот только вы предлагали данный parse для чтения из файла, нормально ли его использовать с текстбоксами?
Для текстбоксов используйте просто double.Parse(). Этот метод использует текущие настройки пользователя. И соотвественно ваша программа тоже ожидает ввод в том формате, который указан в настройках системы.
0
3 / 3 / 2
Регистрация: 21.10.2013
Сообщений: 225
04.09.2015, 11:51  [ТС]
Цитата Сообщение от Storm23 Посмотреть сообщение
Для текстбоксов используйте просто double.Parse(). Этот метод использует текущие настройки пользователя.
Я попробовал, в предыдущем посте отписался вылетает исключение.
Прикольно, понял с суммами. хотя вот этот момент:
C#
1
2
3
4
5
6
                var sum = 0d;
                for(var i=0; i<count; i++)
                {
                    sum += matrix[i, iAxis];
                    integral[i] = sum;
                }
почему не просто
C#
1
2
3
4
5
           
                for(var i=0; i<count; i++)
                {
                    integral[i] += matrix[i, iAxis];
                }
+ вопрос по самому Аллану: там разве не должна быть подобная кривая:
Название: images.jpg
Просмотров: 100

Размер: 5.4 Кб

или на Вашей кривой 1-ый нырок это и есть искомая кривая.
Вообще простите по сути ведь благодаря этой кривой мы можем определить оптимальное количество отсчётов для осреднения(для определения значения сигала на данном отрезке времени).
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
04.09.2015, 11:51
Помогаю со студенческими работами здесь

проблема при работе с китайским J-LINK 8 или же проблема с с
Всем привет. Решил Сам собрать себе дисковери кит на базе at91sam7s64-ek. Подарили мне китайский J-Link 8 c прошивкой 3.20. Недолго...

Ошибки при работе с массивами
В результате некоих вычислений получаю два массива чисел, используя которые хочу построить график. Программа выдаёт ошибку ...

Ошибка при работе с массивами
Здравствуйте. Хочу сделать программу, которая сортирует цифры. Вот код: #include &lt;iostream&gt; using namespace std; int...

Использование Random при работе с массивами
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication27 { ...

Использование указателей при работе с массивами
Здесь двумерный массив, теперь надо написать его с использованием указателей. У меня не получается. Помогите пожалуйста!!! ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
10 пpимет, которые всегда сбываются
Maks 31.03.2026
1. Чтобы, наконец, пришла маршрутка, надо закурить. Если сигарета последняя, маршрутка придет еще до второй затяжки даже вопреки расписанию. 2. Нaдоели зима и снег? Не надо переезжать. Достаточно. . .
Перемещение выделенных строк ТЧ из одного документа в другой
Maks 31.03.2026
Реализация из решения ниже выполнена на примере нетипового документа "ВыдачаОборудованияНаСпецтехнику" с единственной табличной частью "ОборудованиеИКомплектующие" разработанного в конфигурации КА2. . . .
Functional First Web Framework Suave
DevAlt 30.03.2026
Sauve. IO Апнулись до NET10. Из зависимостей один пакет, работает одинаково хорошо как в режиме проекта так и в интерактивном режиме. из сложностей - чисто функциональный подход. Решил. . .
Автоматическое создание документа при проведении другого документа
Maks 29.03.2026
Реализация из решения ниже выполнена на нетиповых документах, разработанных в конфигурации КА2. Есть нетиповой документ "ЗаявкаНаРемонтСпецтехники" и нетиповой документ "ПланированиеСпецтехники". В. . .
Настройка движения справочника по регистру сведений
Maks 29.03.2026
Решение ниже реализовано на примере нетипового справочника "ТарифыМобильнойСвязи" разработанного в конфигурации КА2, с целью учета корпоративной мобильной связи в коммерческом предприятии. . . .
Автозаполнение реквизита при выборе элемента справочника
Maks 27.03.2026
Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. При выборе "Спецтехники" (Тип Справочник. Спецтехника), заполняется. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru