2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2, 3  След.
 
 Сравнение массивов больших размеров
Сообщение08.10.2009, 21:57 


30/09/06
68
Одесса
Имеются два массива строк; 1-й на 26 тысяч, 2-й на 16 тысяч. Нужно сравнить имеются ли во втором массиве строки из первого. Подскажите рациональный алгоритм или литературку на эту тему.

 Профиль  
                  
 
 Re: Сравнение массивов больших размеров
Сообщение08.10.2009, 22:00 
Заслуженный участник


09/08/09
3438
С.Петербург
Второй отсортировать, затем искать в нем строки из первого двоичным поиском.

 Профиль  
                  
 
 Re: Сравнение массивов больших размеров
Сообщение08.10.2009, 22:07 


30/09/06
68
Одесса
Спасибо, про сортировку одного думала.

 Профиль  
                  
 
 Re: Сравнение массивов больших размеров
Сообщение08.10.2009, 22:22 
Аватара пользователя


31/10/08
1244
Для массивов строк считаем хэши потом сортируем хэши и сравниваем массивы. Вначале по хэшам потом по символьно строки.
В STD вроде это уже реализовано если не ошибаюсь. Советую поискать в интернете вопрос частый.

 Профиль  
                  
 
 Re: Сравнение массивов больших размеров
Сообщение09.10.2009, 00:42 


21/03/06
1545
Москва
Маленькое дополнение: конечно, предложение Pavia - одно из самых эффективных (на ум другое не приходит), да и предложение Maslov тоже содержит значительную оптимизацию процесса, но, как и в любой задаче, можно для начала прикинуть PROFIT:
1. Пускай каждая строка содержит по 256 символов
2. Пускай расхождение находится (если находится) всегда на последнем символе строки (уж невезет, так невезет :) ).
3. Размер первого массива: 6,4 Мб; Размер второго массива: 4 Мб. Легко помещаются в ОЗУ, а на современных процессорах еще и большая их часть поместится в L2 - кеше процессора. Таким образом, временем доступа пренебрегаем.
4. Считаем кол-во операций сравнения: $26000*256*16000 = 1,07*10^{11}$.
5. Берем относительно современный (но и не топовый) одноядерный процессор Intel Pentium IV@3.2 GHz и смотрим, что у него около 10 MIPS, т.е. около 10 миллионов целочисленных операций в сек. Предполагаем, что операция сравнения не займет более 1-й целочисленной операции, имеем время работы: $1,07*10^{11} / 1*10^7 = 10 700$ сек $ = 3$ часа. Заметим, что топовые процы (четырехядерные атлоны и core 2) имеют более 40 MIPS, т.е. сравнение займет меньше часа, там правда надо морочиться с распараллеливанием на несколько ядер, но задача параллелится оч. легко - достаточно разбить первый массив на четыре части, записать их в отдельные файлы, запустить 4 эксземпляра программы каждый со своим файлом и с помощью программы типа process explorer закрепить каждый процесс (set affinity) за своим ядром. Т.е. на код это не влияет вообще :).
6. Учитываем, что на практике сравнение завершится гораздо быстрее, т.к. несовпадения будут находиться, конечно, ранее чем на самом последнем символе.

Вывод: если нужна однократная сортировка, то подход "лоб" даст эффект быстрее, чем писать и отлаживать всякие хэши :).

 Профиль  
                  
 
 Re: Сравнение массивов больших размеров
Сообщение09.10.2009, 01:07 
Заслуженный участник


04/05/09
4587
Да вы что!
Если бы я учил программированию, и мне кто-нибудь из учеников принёс программу, которая вместо предполагаемых секунд работает час из-за неэффективного алгоритма, я бы в лучшем случае поставил тройку за то, что хоть какой-то результат есть.
Делайте как Maslov посоветовал. С использованием STL собственно алгоритм, вез ввода/вывода, займёт меньше десятка операторов. Можно ещё не сортировать массив, а сразу использовать std::set.

-- Чт окт 08, 2009 18:10:49 --

e2e4, я подозреваю, что вы так пошутили, но, боюсь, Lotos шутки не оценит.

 Профиль  
                  
 
 Re: Сравнение массивов больших размеров
Сообщение09.10.2009, 01:33 
Заслуженный участник


09/08/09
3438
С.Петербург
e2e4 в сообщении #250260 писал(а):
Предполагаем, что операция сравнения не займет более 1-й целочисленной операции, имеем время работы: $1,07*10^{11} / 1*10^7 = 10 700$ сек $ = 3$ часа.
Какие страшные ужасы Вы рассказываете :)
2 массива по 50000 строк по 260 символов с общим префиксом 256 байт сравниваются "в лоб" все-со-всеми около 20 сек (на одном процессоре Core2Duo 2.4 GHz). При этом все работает под .Net, так что все строки юникодные (2 байта на символ). C++ будет работать быстрее.
Но дело не в этом. Какое-то немного неэстетичное решение Вы предлагаете :)
А вообще было бы интересно сравнить по времени работы и затратам на программирование/отладку все три способа - без сортировки, с сортировкой только второго, и с сортировкой хэшей и последующим их сравнением за один параллельный проход по двум массивам.
Правда на таких незначительных объемах данных разница может просто не прозвучать.

 Профиль  
                  
 
 Re: Сравнение массивов больших размеров
Сообщение09.10.2009, 01:33 


21/03/06
1545
Москва
venco писал(а):
e2e4, я подозреваю, что вы так пошутили, но, боюсь, Lotos шутки не оценит.

Да нет, вроде не шутил. Я попытался показать некоторый "инженерный" подход к делу - может быть, конкретно здесь и не очень удачный, т.к. алгоритмы сортировки уже написаны дядей Васей (и даже с большой долей верятности не содержат ошибок :) ).
Если задача не учебная, а реальная - всегда ее нужно оценивать с разных сторон, и быстрота написания кода/простота (а, следоватлеьно, надежность) отладки - выливаются в конце концов в экономику. Когда я вижу такую постановку задачи, как в первом сообщении - есть какие-то определенные цифры, четко очерчены рамки - всегдя тянет прикинуть несколько вариантов, и, если самый простой возможен - принимается как правило, именно он.

-- Пт окт 09, 2009 02:39:04 --

Maslov писал(а):
Какое-то немного неэстетичное решение Вы предлагаете

Полностью с Вами согласен :). Я не предлагаю, я только предлагаю его обсудить, а потом - отклонить :).

Maslov писал(а):
А вообще было бы интересно сравнить по времени работы и затратам на программирование/отладку все три способа - без сортировки, с сортировкой только второго, и с сортировкой хэшей и последующим их сравнением за один параллельный проход по двум массивам.

Еще один способ - хэши посчитать, но их не сортирвать. В качестве хэша можно взять простую контрольную сумму по модулю $2^{16}$, к примеру. Уже будет существенное ускорение без необходимости писать сортировку, что сложнее.

Maslov писал(а):
2 массива по 50000 строк по 260 символов с общим префиксом 256 байт сравниваются "в лоб" все-со-всеми около 20 сек (на одном процессоре Core2Duo 2.4 GHz). При этом все работает под .Net, так что все строки юникодные (2 байта на символ). C++ будет работать быстрее.

Хммм... я ошибся в $10 700/20$ = 535 раз? Странно. Вряд ли дело в оптимизации на уровне процессора. Где же ошибка? Завтра сам напишу подобную программу и потестирую на рабочем Pentium M @1,86 GHz.

 Профиль  
                  
 
 Re: Сравнение массивов больших размеров
Сообщение09.10.2009, 01:44 
Заслуженный участник


09/08/09
3438
С.Петербург
e2e4 в сообщении #250276 писал(а):
Если задача не учебная, а реальная - всегда ее нужно оценивать с разных сторон, и быстрота написания кода/простота (а, следоватлеьно, надежность) отладки - выливаются в конце концов в экономику.

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

 Профиль  
                  
 
 Re: Сравнение массивов больших размеров
Сообщение09.10.2009, 02:00 


21/03/06
1545
Москва
e2e4 писал(а):
Хммм... я ошибся в = 535 раз? Странно. Вряд ли дело в оптимизации на уровне процессора. Где же ошибка?

Ежкин кот, брал MIPS'ы вот отсюда, на автомате подумал, что для Pentium 4 Extreme Edition 9,726 MIPS - это 9 целых, 726 сотых (что-то как-то сразу не смутила такая низкая производительность :( ). А они запятой просто тысячи отделяют. В общем ошибка прикидки в 1000 раз. Итого имеем 11 сек для исходной задачи (прикидочно), и 24 сек для Вашей задачи (2 массива по 50 000 строк, 260 байт на строку, core 2 duo), что довольно точно, я доволен - иду спать :). Насчет того, что у Вас unicode - т.е. 16 бит на символ, так это процессору все-равно, он как минимум 16-битными операндами и оперирует.

P. S.

e2e4 писал(а):
Завтра сам напишу подобную программу и потестирую на рабочем Pentium M @1,86 GHz.

Естественно, отменяется :).

 Профиль  
                  
 
 Re: Сравнение массивов больших размеров
Сообщение09.10.2009, 02:41 
Заслуженный участник


09/08/09
3438
С.Петербург
e2e4 в сообщении #250279 писал(а):
Насчет того, что у Вас unicode - т.е. 16 бит на символ, так это процессору все-равно, он как минимум 16-битными операндами и оперирует.
Ну это Вы бросьте :)
Может оперировать с байтами - CMP AL,1
может со словами (16 бит) - CMP AX,1
может с двойными словами (32 бита) - CMP EAX,1

 Профиль  
                  
 
 Re: Сравнение массивов больших размеров
Сообщение09.10.2009, 08:47 
Супермодератор
Аватара пользователя


29/07/05
8248
Москва
venco в сообщении #250267 писал(а):
Если бы я учил программированию, и мне кто-нибудь из учеников принёс программу, которая вместо предполагаемых секунд работает час из-за неэффективного алгоритма, я бы в лучшем случае поставил тройку за то, что хоть какой-то результат есть.


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

 Профиль  
                  
 
 Re: Сравнение массивов больших размеров
Сообщение09.10.2009, 09:08 
Заслуженный участник


09/08/09
3438
С.Петербург
Maslov в сообщении #250275 писал(а):
2 массива по 50000 строк по 260 символов с общим префиксом 256 байт сравниваются "в лоб" все-со-всеми около 20 сек (на одном процессоре Core2Duo 2.4 GHz). При этом все работает под .Net, так что все строки юникодные (2 байта на символ). C++ будет работать быстрее.
Опровержение!
Это я ночью куда-то не туда смотрел. :oops:
Там существенно медленнее все получается. Минимум на порядок. Так что есть куда оптимизировать.

 Профиль  
                  
 
 Re: Сравнение массивов больших размеров
Сообщение09.10.2009, 09:22 
Супермодератор
Аватара пользователя


29/07/05
8248
Москва
Думаю, что достаточно добавить какое-нибудь готовое хеширование и все будет работать вполне себе скоро.

 Профиль  
                  
 
 Re: Сравнение массивов больших размеров
Сообщение09.10.2009, 11:30 
Заслуженный участник


09/08/09
3438
С.Петербург
Некоторые соображения по поводу средней вычислительной сложности в разных случаях:

Вне зависимости от того, работаем мы с хэшами или с исходными строками, можно рассмотреть следующие варианты (m - длина первого массива, n - длина второго массива):

1. Ни один массив не отсортирован; линейный поиск элементов первого во втором.
Сложность поиска - $O(m\cdot n)$

2. Отсортирован только второй; двоичный поиск элементов первого во втором.
Сложность сортировки - $O(n \cdot log(n))$, сложность поиска - $O(m \cdot log(n))$, общая - $O((m+n) \cdot log(n))$

3. Отсортированы оба; параллельный поиск в двух массивах за один проход.
Сложность сортировки - $O(m \cdot log(m)) + O(n \cdot log(n))$, сложность поиска $O(m+n)$

4. Вариант, когда отсортирован только первый массив не анализируем ввиду его полной бессмысленности :)

В связи с тем, что в нашем случае m > n, второй вариант, скорее всего, будет работать немного быстрее третьего.

В наихудшем случае сложность сортировки $O(N^2)$, и разницу между тремя вариантами надо определять экспериментально.

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

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 36 ]  На страницу 1, 2, 3  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group