«Правильный» способ сделать это - иметь пул рабочих (равный количеству ядер ЦП, либо не считая ядер гиперпотока, либо считая их все как «одно») и незаблокированную очередь FIFO, в которую вы отправляете группы из ста тысяч или около того задач. Это дает приемлемый баланс между накладными расходами на синхронизацию и балансировкой нагрузки.
Хитрость заключается в том, чтобы разделить работу на относительно небольшие группы, чтобы время, когда только один поток выполняет последнюю группу, было не слишком долгим (никакого параллелизма!), но в то же время не делайте группы слишком маленькими, чтобы вы были связаны синхронизацией/конкуренцией за шину. MD5 довольно быстр, поэтому от нескольких десятков до сотен тысяч рабочих элементов должно хватить.
Однако, учитывая конкретную проблему, это на самом деле излишество. Слишком сложно.
5-буквенных паролей в 26 раз больше, чем 4-буквенных, 6-буквенных паролей в 26 раз больше, чем 5-буквенных, и так далее. Другими словами, самый длинный пароль имеет значительно наибольшую долю в общем количестве комбинаций. Все 4,5,6-значные комбинации вместе составляют только около 3,9% комбинаций всех 7-значных комбинаций. Другими словами, они совершенно ничтожны. 96% всего времени выполнения находится в пределах 7-значных комбинаций, независимо от того, что вы делаете с остальными. Это еще более экстремально, если вы рассматриваете буквы и цифры или заглавные буквы.
Таким образом, вы можете просто запустить столько потоков, сколько у вас ядер процессора, и запускать все 4-значные комбинации в одном потоке, все 5-значные комбинации в другом и так далее. Это не очень хорошо, но этого достаточно, поскольку никто все равно не заметит разницы.
Затем просто разбейте возможные 7-значные комбинации на num_thread
диапазонов одинакового размера, и пусть каждый поток, закончивший свой начальный диапазон, продолжит работу с этим. один.
Работа не всегда будет идеально сбалансирована, но так будет в течение 96% времени выполнения. И он работает с абсолютным минимумом управления задачами (нет) и синхронизации (нужно просто установить глобальный флаг для выхода при обнаружении совпадения).
Поскольку вы не можете ожидать идеальной балансировки нагрузки, даже если вы выполняете идеальное и правильное планирование задач (поскольку планирование потоков находится в руках операционной системы, а не ваших), это должно быть очень близко к «идеальному» подходу.
В качестве альтернативы вы можете рассмотреть возможность запуска одного дополнительного потока, который выполняет весь диапазон комбинаций, кроме самого длинного («незначительные 3%), и разделяет остальные поровну. Это вызовет несколько дополнительных переключений контекста во время запуска, но, с другой стороны, сделает логику программы еще проще.
person
Damon
schedule
20.08.2014