Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.91/35: Рейтинг темы: голосов - 35, средняя оценка - 4.91
4 / 4 / 3
Регистрация: 05.08.2014
Сообщений: 54
.NET 4.x

Прошу консультации экспертов (ООП, многопоточность)

16.11.2016, 13:02. Показов 7078. Ответов 45

Студворк — интернет-сервис помощи студентам
Здравствуйте уважаемые форумчане! Давеча пытался устроиться на работу и прислали мне тестовое задание, далее привожу его текст:
Требуется написать консольную программу на C# для генерации сигнатуры указанного файла. Сигнатура генерируется следующим образом: исходный файл делится на блоки заданной длины (кроме последнего блока), для каждого блока вычисляется значение hash-функции SHA256, и вместе с его номером выводится в консоль.
Программа должна уметь обрабатывать файлы, размер которых превышает объем оперативной памяти, и при этом максимально эффективно использовать вычислительные мощности многопроцессорной системы. При работе с потоками допускается использовать только стандартные классы и библиотеки из .Net 3.5 (исключая ThreadPool, BackgroundWorker, TPL). Ожидается реализация с использованием Thread-ов. Путь до входного файла и размер блока задаются в командной строке. В случае возникновения ошибки во время выполнения программы ее текст и StackTrace необходимо вывести в консоль.
В общем посидел пару вечеров и наваял прогу на сколько позволяли знания и навыки. Поскольку ранее ничего подобного не делал, поначалу даже показалось, что задание несложное. Однако отправляя проект не оставляло ощущение, что сделал не так как надо.
Так в итоге и оказалось. Мне вежливо отказали дополнив комментариями касательно кода:
1. Вся программа в одном файле, двух классах и нескольких статических методах. ООП нет.
Классы не являются лишними, если у них есть понятная область отвественности.
В данном случае, если бы выделили класс для запуска потоков и отслеживания их завершения – то это не было бы лишним.

2.Алгоритм работы не эффективный. Файл сразу бьется на блоки и для каждого блока стартует новый поток. Все сразу. Никого thread pool нет.
Для подсчета хэша каждого блока запускается отдельный поток. Запуск потока трудоемкая операция, которая требует много ресурсов. Вариантов решения этой проблемы возможно несколько. Или реализовывать свою вариацию threadPool или использовать долгоживущие потоки.
Кроме того, сейчас никак не ограничивается число запущенных потоков. При их большом количестве, они будут бороться за процессорное время и значительная часть ресурсов будет тратиться на переключение контекстов между потоками.

3.Ожидание окончания всех потоков на Thread.Sleep
Ожидание завершения на Thread.Sleep является ресурсоемким. Поскольку основной поток, ждущий завершения, постоянно просыпается и занимает процессорное время, которое можно было потратить на обсчет следующего блока. Для решения этих проблем используют примитивы синхронизации.
Проверка окончания всех потоков происходит на статической перемерной threadCount. К ней осуществляется доступ из нескольких потоков, и доступ никак не синхронизирован.
Это стандартная проблема разделения ресурсов между и не исключена ситуация, что threadCount никогда не достигнет 0.
Собственно чтобы я хотел попросить: прокомментировать код, указать на проблемные места и предложить пример более удачной реализации. Хочу понять где слабые места и что надо подтянуть в плане знаний и навыков. Заранее всем благодарен!
Вложения
Тип файла: rar Program.rar (1.2 Кб, 72 просмотров)
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
16.11.2016, 13:02
Ответы с готовыми решениями:

Прошу мнения экспертов
Всем здрасте! 'Недавно начал изучать PHP' короче бла-бла-бла=) Прислали мне тест сгенерировать html табличку.Сделать функцию которая...

Прошу совета экспертов о смене провайдера интернет
Здравствуйте. Сейчас тормозящий оптоволоконный ДжиПон 70 Мбит (реально до 30), хочу сменить на 2Ком или Билайн, что посоветуете? Читал...

Прошу консультации!
Ребятки всем привет. Собственно чуть в краткрости раскажу.. Я всю жизнь имел ток ноуты ... Теперь все уже терпения нет ...хочется...

45
Неадекват
 Аватар для freeba
1501 / 1237 / 248
Регистрация: 02.04.2010
Сообщений: 2,807
16.11.2016, 18:50
Студворк — интернет-сервис помощи студентам
TopLayer, да, действительно. Значит я ошибся, в любом случае ошибка не критичная и никак не влияющая на выполнение задачи программой.
0
907 / 664 / 318
Регистрация: 23.10.2016
Сообщений: 1,543
16.11.2016, 18:54
Цитата Сообщение от insite2012 Посмотреть сообщение
На 32-х битной XP все отрабатывает как положено.
Что бы это значило?
0
Неадекват
 Аватар для freeba
1501 / 1237 / 248
Регистрация: 02.04.2010
Сообщений: 2,807
16.11.2016, 18:57
Цитата Сообщение от TopLayer Посмотреть сообщение
Что бы это значило?
то что x86 clr отличается от x64 версии, как минимум обработкой инкремента.
0
907 / 664 / 318
Регистрация: 23.10.2016
Сообщений: 1,543
16.11.2016, 19:24
Цитата Сообщение от freeba Посмотреть сообщение
то что x86 clr отличается от x64 версии, как минимум обработкой инкремента.
Как-то странно это. Не понимаю, как можно оптимально реализовать потокобезопасный инкремент. Или при каждом инкременте оверхэд?

Добавлено через 23 минуты
Exerion,
А вот я против таких строчек while (!exitFlag), где переменная используется несколькими потоками. Считаю, что если речь не идёт об убероптимизации, то нужно явно синхронизировать доступ, при помощи Interlocked или хотя бы объявлять поле волатильным. Потому что результат работы этой строки неявно зависит от наличия вызовов .WaitOne() и .Set(), что является неочевидным.
C#
1
2
3
4
5
6
7
8
9
10
                while (!exitFlag)
                {
                    ready.WaitOne();
 
                    string hash = BitConverter.ToString(sha.ComputeHash(data)).Replace("-", string.Empty);
                    //sha.Clear();
 
                    onCalculated?.Invoke(this, new CalcWorkerEventArgs(hash, number));
                    done.Set();
                }
0
[Bicycle Reinventor]
 Аватар для Exerion
332 / 270 / 109
Регистрация: 19.10.2011
Сообщений: 668
Записей в блоге: 2
16.11.2016, 19:32
Цитата Сообщение от freeba Посмотреть сообщение
Посмотрите код Exerion, он убивает старый поток прежде чем стартануть новый.
but...
Миниатюры
Прошу консультации экспертов (ООП, многопоточность)  
0
Неадекват
 Аватар для freeba
1501 / 1237 / 248
Регистрация: 02.04.2010
Сообщений: 2,807
16.11.2016, 19:40
Цитата Сообщение от Exerion Посмотреть сообщение
but...
Точно Явный вызов Dispose сбил с толку.
0
907 / 664 / 318
Регистрация: 23.10.2016
Сообщений: 1,543
16.11.2016, 19:45
Exerion, Вы заджоиниваете старый поток. А что если метод
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        private void Calculating()
        {
            using (SHA256 sha = SHA256.Create())
            {
                while (!exitFlag)
                {
                    ready.WaitOne();
 
                    string hash = BitConverter.ToString(sha.ComputeHash(data)).Replace("-", string.Empty);
                    //sha.Clear();
 
                    onCalculated?.Invoke(this, new CalcWorkerEventArgs(hash, number));
                    done.Set();
                }
            }
            Console.WriteLine("Worker exiting");
        }
Зависнет на строчке ready.WaitOne()? А потом вы его попытаетесь заджоинить?
1
[Bicycle Reinventor]
 Аватар для Exerion
332 / 270 / 109
Регистрация: 19.10.2011
Сообщений: 668
Записей в блоге: 2
16.11.2016, 19:55
Цитата Сообщение от TopLayer Посмотреть сообщение
Зависнет на строчке ready.WaitOne()? А потом вы его попытаетесь заджоинить?
Ну косяк, чё, торопился. Там помимо этого ещё кучка всего интересного есть.
Этот по крайней мере легко исправить, если заджоиниванию таймаут поставить.

Например, нет обработки исключений в потоках. Если что отвалится - внешний try catch вряд ли это отловит.
Также момент с типом количества блоков. Пробовал работоспособность на файле в 7Гб - если размер блока будет достаточно маленьким, то количество блоков не влезет в int32 и оно станет отрицательным.

Ну и ещё наверняка куча всего, о чём я и не догадываюсь.
0
Эксперт .NET
 Аватар для Usaga
14747 / 9521 / 1364
Регистрация: 21.01.2016
Сообщений: 35,916
17.11.2016, 06:33
Цитата Сообщение от TopLayer Посмотреть сообщение
Не понимаю, как можно оптимально реализовать потокобезопасный инкремент.
Использовать Interlocked.Increment().

Добавлено через 9 минут
Только атомарный инкремент действительно работает немного по-разному на x86 и x64. Вот выдержка из статьи на википедии:

3. Если значение в памяти было равно значению в аккумуляторе, процессор записывает значение из второго операнда в область памяти, указанную первым операндом. (Особенность реализации x86: запись происходит всегда, но если сравнение на шаге 2 показало неравенство, в аккумулятор записывается то значение, что было прочтено из памяти на шаге 1.) По завершении записи, блокировка шины снимается.
0
907 / 664 / 318
Регистрация: 23.10.2016
Сообщений: 1,543
17.11.2016, 07:25
Цитата Сообщение от Usaga Посмотреть сообщение
Использовать Interlocked.Increment().
И ведь всё равно это снижает производительность. Не думаю, что особенность х86 полностью нивелирует издержки.

Не по теме:

Не ожидал такой подставы от арифметических операций :D

0
Эксперт .NET
 Аватар для Usaga
14747 / 9521 / 1364
Регистрация: 21.01.2016
Сообщений: 35,916
17.11.2016, 07:28
Цитата Сообщение от TopLayer Посмотреть сообщение
И ведь всё равно это снижает производительность.
Каким это боком оно снижает производительность? Метод Interlocked.Increment() - обёртка над процессорной командой cmpxchg. Ты можешь что-то быстрее изобрести?
0
907 / 664 / 318
Регистрация: 23.10.2016
Сообщений: 1,543
17.11.2016, 07:48
Usaga, я не могу изобрести более быстрый атомарный инкремент. Я лишь удивлён тем, что этот атомарный инкремент используется повсеместно на х86. Ведь это снижает производительность (я не спец, может я и неправ).

http://faydoc.tripod.com/cpu/cmpxchg.htm
This instruction can be used with a LOCK prefix to allow the instruction to be executed atomi-cally. To simplify the interface to the processor's bus, the destination operand receives a write cycle without regard to the result of the comparison.
http://www.agner.org/optimize/... tables.pdf
Instructions with a LOCK prefix have a long latency that depends on cache organization and possibly RAM speed. If there are multiple processors or cores or direct memory access (DMA) devices then all locked instructions will lock a cache line for exclusive access, which may involve RAM access. A LOCK prefix typically costs more than a hundred clock cycles, even on single-processor systems. This also applies to the XCHG instruction with a memory operand.
1
Неадекват
 Аватар для freeba
1501 / 1237 / 248
Регистрация: 02.04.2010
Сообщений: 2,807
17.11.2016, 13:13
Цитата Сообщение от TopLayer Посмотреть сообщение
Я лишь удивлён тем, что этот атомарный инкремент используется повсеместно на х86. Ведь это снижает производительность (я не спец, может я и неправ).
На всех процессорах поддерживающих windows существует аппаратный примитив CAS (Compare and Swap), собственно он и скрывается за перегрузками Interlocked, так что на производительность это не сильно влияет. Интереснее почему от его принудительного использования отказались в x64 - возможно в угоду кроссплатформенности, а может просто по желанию левой пятки.
1
4 / 4 / 3
Регистрация: 05.08.2014
Сообщений: 54
17.11.2016, 23:40  [ТС]
Спасибо, что откликнулись! Из всего прочитанного сделал вывод, что однозначно лучшего подхода нет, надо исходить из поставленной задачи и подбирать вариант реализации. Думаю надо параллельно (!) изучать теорию и опробовать на практике с замером производительности.
Кстати, есть ли вариант многопоточной загрузки файла в ОЗУ. Для примера, есть метод считывающий данные из файла Excel (или базу SQLite) и формирующий на его основе DataTable, как реализовать в данном случае?
Вложения
Тип файла: rar Database.rar (1.6 Кб, 4 просмотров)
0
0 / 0 / 0
Регистрация: 02.11.2015
Сообщений: 4
20.11.2016, 22:02
Здравствуйте!
Начал изучать многопоточность (по Рихтеру), выполняю упражнения и заодно смотрю коды опытных программеров.
Запустил Ваш код, и обратил внимание, что блоки выводятся на консоль непоследовательно.
Это нормально для потоков или допущена ошибка?
З.Ы. еще не совсем понял, почему Вы создаете отдельный класс FileStreamer, какой у него смысл?
Миниатюры
Прошу консультации экспертов (ООП, многопоточность)  
0
0 / 0 / 0
Регистрация: 02.11.2015
Сообщений: 4
20.11.2016, 22:05
Здравствуйте!
Недавно начал изучать потоки (по Рихтеру) и заодно просматриваю коды опытных программеров.
При запуске Вашего кода обнаружил, что некоторые блоки выводятся непоследовательно (см. скриншот)
Это нормально для потоков или допущена какая-то ошибка?
0
4 / 4 / 3
Регистрация: 05.08.2014
Сообщений: 54
20.11.2016, 22:30  [ТС]
AlexPtr, здравствуйте, блоки могут обрабатываться непоследовательно поскольку каждый поток работает со своим блоком файла и позже запущенный может закончить раньше чем его предшественник.
1
0 / 0 / 0
Регистрация: 02.11.2015
Сообщений: 4
20.11.2016, 22:40
Спасибо. Понял. Пожалуй, потоки одна из самых сложных (но интересных) тем в курсе C#.
Еще такой вопрос - можете посоветовать хорошую литературу на тему многопоточности? В книге Рихтера все подробно рассмотрено, но примеров маловато.
0
[Bicycle Reinventor]
 Аватар для Exerion
332 / 270 / 109
Регистрация: 19.10.2011
Сообщений: 668
Записей в блоге: 2
21.11.2016, 08:55
Joseph Albahari о многопоточности в C# в пяти частях: тык.
На RSDN есть переводы некоторых частей: первая, вторая. Остальные, скорее всего, придётся искать в кеше гугла, потому что их выпилили. Помнится у кого-то из старичков форума были сохранены эти переводы.
0
Неадекват
 Аватар для freeba
1501 / 1237 / 248
Регистрация: 02.04.2010
Сообщений: 2,807
21.11.2016, 09:59
Цитата Сообщение от AlexPtr Посмотреть сообщение
З.Ы. еще не совсем понял, почему Вы создаете отдельный класс FileStreamer, какой у него смысл?
Смысл в том, что дисковая подсистема не любит когда файлы читаются в несколько потоков. В моем примере используются т.н. "тяжелые" потоки - их просто нужно запустить, а далее они сами разберутся, что нужно сделать - для взаимодействия с файловой системой им и нужен FileStreamer, который обеспечивает последовательное, поблочное чтение.

PS: Данное решение с точки зрения ООП является не очень правильным - пример уважаемого Exerion более точно соответствует парадигме, хотя и является чуть более медленным. Для обучения лучше использовать именно его.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
21.11.2016, 09:59

Прошу консультации по iptables
Доброго всем времени суток! Установлена у меня ubuntu 10.04. Поставлен apache2 в качестве веб сервера и ещё иное серверное ПО. Вот...

Прошу консультации в выборе!
Добрый день уважаемые форумчане! Нужна ваша квалифицированная помощь в выборе ноутбука. Сразу опишу принцип будущего использования, время...

Прошу Вашей профессиональной консультации
Всем здравствуйте уважаемые. Помогите разобраться в логах. Не могу "вкурить" что хочет от меня android studio. Добавил в свой проект код...

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

Учусь водить, прошу консультации :)
В общем недавно начал обучаться вождению, на автомобиле Skoda Fabia 2010г. Никак не могу заставить себя нормально работать ногами с...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek ВВЕДЕНИЕ Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru