- 1
- 2
- 3
- 4
- 5
foreach(string s in File.ReadAllText(input_text).Replace('ё', 'е').ToLower().Split(new char[] { ',', ' ', '.', '\t', '\r', '\n', '-', '?', '!', '\\', '/', ':', ';', '<', '>', '\'', '\"', '(', ')' }, StringSplitOptions.RemoveEmptyEntries).
AsParallel().Where<string>(s => (s.Length == 4)).GroupBy(x => x).Select(g => new { Value = g.Key, Count = g.Count() }). OrderByDescending(x => x.Count).Select(f => (f.Value + ' ' + f.Count.ToString())).ToArray())
{
Console.WriteLine(s);
}
abatishchev 22.01.2012 12:48 # 0
Говногость 22.01.2012 15:56 # +4
Но сарказм автора оценил:
martin 22.01.2012 17:14 # 0
Говногость 22.01.2012 17:35 # +5
martin 22.01.2012 17:47 # +3
существуют соглашения по оформлению кода, в которых подобное является обзательным, потому говорить "не нужны" в корне не правильно.
iwill 23.01.2012 11:28 # 0
koodeer 23.01.2012 15:29 # 0
Имеешь в виду ParallelQuery.ForAll()? Аналогично ;). Но тут есть способы выхода из положения.
Самое простое, наверное, использовать Array.ForEach или List.ForEach. Но это напрочь убивает ленивость.
iwill 24.01.2012 19:31 # 0
wvxvw 22.01.2012 19:20 # +5
TarasB 22.01.2012 21:20 # 0
kasthack 22.01.2012 21:54 # 0
koodeer 22.01.2012 22:10 # +15
Выведется что-то вроде:
мама 10
папа 5
вася 1
akaDElpher 23.01.2012 06:32 # 0
abatishchev 23.01.2012 11:32 # 0
т.к. в виде запроса можно записать только where, group by и select
а остальное - всё равно в виде методов
так что лучше оставить как есть, просто добавить добавить перенос строки перед каждым новым чейном (точкой)
koodeer 23.01.2012 15:31 # +9
Как уже замечено выше, получается почти нечитаемый уродец.
3.14159265 23.01.2012 19:30 # +4
Люди незамутненные сиквелом.
roman-kashitsyn 23.01.2012 19:38 # 0
TarasB 23.01.2012 09:25 # +2
Или она возвращает новый хитрожопый контейнер, у которого все методы сделаны как параллельнные?
roman-kashitsyn 23.01.2012 10:02 # 0
abatishchev 23.01.2012 11:30 # 0
koodeer 23.01.2012 15:35 # +4
Хорошо бы ещё Replace и ToLower перенести в параллельную часть.
3.14159265 23.01.2012 18:50 # +1
abatishchev 23.01.2012 18:56 # 0
3.14159265 23.01.2012 19:06 # +5
3.14159265 24.01.2012 17:38 # 0
Дейскать "напейшу AsParallel() и оно само в 2-4 раза ускорится"
Я поясню мысль. При нормальный трейдинге один тред потихоньку читает содержимое файла. Второй же парсит и обновляет статистику.
То есть время выполнения T будет следующим
T=t_считывания+t'
Где t' - время, которое нужно чтобы закончить работу второму треду. Оно ничтожно.
Т.к. второй тред работает быстрее жесткого диска и большую часть времени он будет простаивать в ожидании новой порции данных с HDD.
LINQ будет работать иначе:
Сначала он прочитает файл ReadAllText(input_text) в память.
Далее создаст список на 100000 элементов
Потом сделает распаралеленый проход for i=1 to 100000 Replace('ё', 'е')
Потом еще один распаралеленый цикл for i=1 to 100000 ToLower()
итд.
Возможно я неправ и LINQ будет обрабатывать конвейерно, не создавая промежуточных списков, но в конце-концов все-равно имеем:
T=t_считывания+t_обработки_всех_100000_э лементов
Ну о побочном эффекте - загрузке всего файла в память я умолчу.
Но проблема даже не в том, что паралелится не то что нужно.
abatishchev 24.01.2012 18:10 # +3
и только это
всё остальное происходит по-очереди
3.14159265 24.01.2012 18:59 # +1
Отлично!
Тут мы имеем вот что:
(С вашего позволения я перенесу стадии Replace('ё', 'е') и ToLower() после стадий Split и Where. Для простоты и оптимальности)
- Чтение из памяти слова
- Выполнение на нём простейших операций - проверка Where, Replace('ё', 'е'), ToLower()
- Нахождение в списке статистики (память, хотя очень вероятно кеш) этого слова
- Опциональное создание новой статистической записи
- Инкремент статистики (количество таких слов)
ЦПУ очень быстро осуществит Where, Replace('ё', 'е'), ToLower(), и оставшееся время будет ждать пока оно запишется в память/кеш.
и новой порции данных из памяти. Ибо латентность памяти очень высока.
Зачем это распаралеливать? Чтобы два ядра простаивали в ожидании данных?
Мало того затраты на распаралеливание в данном случае могут запросто получится дороже, чем сама задача.
guest 24.01.2012 19:36 # 0
koodeer 25.01.2012 18:21 # 0
Воистину, если тебе так не нравится C#, .NET и прочее, то не морочь голову ни себе, ни людям.
Возможности параллельного программирования в дотнете воистину шикарны. Ты увидел лишь одну команду, и начал исходить желчью. Ты пробовал, например, OpenMP? Я пробовал, и немало. Там тоже влёгкую добиваешься распараллеливания. И так же как в дотнете, во многих случаях не получается никакого выигрыша. Естественно! Потому что алгоритм под параллельность нужно менять.
Я тут упоминал, что ToLower и Replace нужно перенести в параллельную часть. Но, естественно, ты прицепился к неэффективному алгоритму, написанному студентотой, и громогласно заявляешь, что linq сосёт.
Да, ты прав: в хорошей многопоточке вычисления нужно проводить параллельно с поступлением данных. Но опять же, - здесь мы видим неэффективный элементарный код, написанный на коленке. В дотнете есть ленивое чтение из файла. В данном случае можно применять его, только и всего.
3.14159265 25.01.2012 19:04 # +2
Не спорю, более того все мои рассуждения основывались именно на этом предположении:
>перенесу стадии Replace('ё', 'е') и ToLower() после стадий Split и Where. Для простоты и оптимальности)
Я не говорю, что LINQ - совсем плохая технология. То есть, если б я делал ту лабу - я написал точно также (кроме оговоренных нюансов).
Она плоха лишь отчасти. Одна из причин - она отучает думать головой и заставляет думать, что всё за тебя ускорится само.
>если тебе так не нравится C#, .NET и прочее
Вы на говнокоде, сер.
>что linq сосёт.
Факт замедления кода в 20 раз просто не позволяет мне сказать, что оно рулит.
3.14159265 24.01.2012 17:39 # +1
Как бы парадоксально это не звучало.
abatishchev 24.01.2012 18:09 # −3
а может не изменит время
up to CLR
3.14159265 24.01.2012 19:02 # +2
Дабы мои слова не казались беспочвенными наездами на чудесную технлогоию linq - предлагаю провести кому-нибудь, имеющему шарп и не менее 2-х физ. ядер простой эксперимент.
Создать список с 1000000 рандомных чисел.
И замерить скорость вычислений на нем (суммирования, например)
1. цикл for
2. linq
3. parallel linq
Запостить результаты в тред.
guest 24.01.2012 19:27 # 0
поиска (не)четных чисел в отсортированном мастак - да
сделаю завтра если никто раньше меня
guest 24.01.2012 19:27 # 0
bugmenot 24.01.2012 19:50 # 0
коммутативность, ассоциативность, первый класс церковно-приходской
3.14159265 24.01.2012 21:06 # +5
Просто жуть, что шарп с мозгами делает.
Всё еще хуже, чем я предполагал.
abatishchev 24.01.2012 21:17 # 0
abatishchev 24.01.2012 21:17 # −4
bugmenot 24.01.2012 22:30 # +5
3.14159265 24.01.2012 21:13 # 0
А randomы генерируй в [0,10000);
Хотя я зашел в тред и хотел предложить более честный и приближенный к практике вариант - умножение чисел по некоему модулю n.
Подобные дискретные умножения/возведения в степень используются не одним криптоалгоритмом.
Em1ss1oN 25.01.2012 09:21 # +5
Простое суммирование. LINQ в среднем вдвое медленнее for(4000 тиков против 2000), PLINQ вообще хренью занимается в 10 раз больше обычного(~80000 тиков).
А вообще - не стоит ковырять инты, нужно придумывать более сложные задачи с более сложными типами. Никто на дотНете высокопроизводительный вычислительный софт не пишет.
roman-kashitsyn 25.01.2012 10:41 # +3
http://www.microsoft.com/en-us/sqlazurelabs/labs/numerics.aspx
Em1ss1oN 25.01.2012 11:04 # +1
3.14159265 25.01.2012 13:41 # +2
Просто шикарно! Я думал оно процентов так на 20-30 замедлится.
Но это вообще замечательно - чудесная параллельная технология замедляющая вычисления в 10 раз.
Em1ss1oN 25.01.2012 13:43 # 0
3.14159265 25.01.2012 13:50 # +3
И тут я подробно описал почему: http://govnokod.ru/9194#comment127899
Ну ладно, пусть чудо-LINQ замедляет код в 2 раза. Но тут торможение еще в 20 (двадцать)! раз от уже тормознутого LINQ.
PS. Благодарю за тесты.
roman-kashitsyn 25.01.2012 13:44 # 0
abatishchev 25.01.2012 13:47 # −2
+ аппаратную начинку тестовой станции в студию
вы совсем измерять производительность не умеете, да?
abatishchev 25.01.2012 14:00 # +2
for: 306
linq: 2645
plinq: 1743 (в 1,5 раза быстрее)
abatishchev 25.01.2012 14:27 # 0
3.14159265 05.07.2020 01:52 # +1
bugmenot 24.01.2012 19:35 # +3
вот и получается быстрее.
3.14159265 24.01.2012 21:05 # −1
Абсолютно в говно правильно!
Зогчем мне голова? Пусть за меня думает Майкрософт.
abatishchev 24.01.2012 21:17 # +3
bugmenot 25.01.2012 10:29 # +4
3.14159265 25.01.2012 13:44 # +2
>а может не изменит время
Как я и говорил чудес не бывает и этот ваш PLINQ соснул. Причем с причмоком.
abatishchev 25.01.2012 13:45 # −1
нашел выше
abatishchev 25.01.2012 14:03 # 0
roman-kashitsyn 25.01.2012 16:24 # +2
3.14159265 25.01.2012 19:11 # 0
Хотя ваши результаты тоже довольно интересны:
>for: 306
>linq: 2645
Замедление в 8 раз, против обычного цикла.
kasthack 23.01.2012 22:34 # +1
TarasB 23.01.2012 22:47 # +1
Мне знакомый гоп рассказывал, как они по приколу написали программу и обработали "Мастера и Маргариту", заменив
"," на ", бля, "
"?" на ", нахуй?"
В итоге получилось что-то типа "я, бля, пойду, нахуй?".
TheHamstertamer 24.01.2012 17:30 # +1
koodeer 23.01.2012 15:34 # 0
Ты прав, - вместо IEnumerable становится ParallelQuery, с тем же набором методов. Но параллельных.
abatishchev 23.01.2012 15:38 # +2
guest 24.01.2012 22:21 # −1
там еще есть аргумент -- на сколько именно.
например: asParralel(32) делает код оптимальным для 32х ядерных машин.
abatishchev 23.01.2012 11:32 # −1
roman-kashitsyn 23.01.2012 12:15 # +4
abatishchev 23.01.2012 12:19 # 0
eth0 23.01.2012 12:29 # +4
.Print(DEFAULT_PRINTER) // Печатаем
.MakeCoffee("Black") // Делаем кофе
И вся программа из одной строки.
Не технология - мечта.
absolut 23.01.2012 07:35 # −3
bugmenot 24.01.2012 05:21 # 0
absolut 24.01.2012 17:58 # 0
absolut 25.01.2012 12:53 # +1