我正在研究我的十年级科学博览会项目,我有点碰壁了。我的项目正在测试并行性对强制md5密码哈希的效率的影响。我将使用1,4,1,3,3,6,12,128,512和1024个线程计算密码组合的数量/秒测试以查看其效率。我不确定我是否会做字典蛮力或纯粹的暴力。我认为字典更容易并行化;只需将列表拆分为每个线程的相等部分。我还没写很多代码;我只是在开始编码之前尝试计划它。
我的问题是:
计算密码组合测试/秒是根据线程数确定性能的最佳方法吗?
字典还是纯粹的暴力?如果是纯粹的暴力,你会如何将任务分成可变数量的线程?
还有其他建议吗?
答案 0 :(得分:6)
我并没有试图削弱你的热情,但这已经是一个很好理解的问题了。我将尝试解释下面会发生什么。但也许在另一个地区做你的项目会更好。如何“最大化MD5散列吞吐量”,那么您不会仅限于查看线程。
我认为,当您编写项目时,您需要提供某种分析,以确定何时适合并行处理,何时不适合。
每当您的CPU更改为另一个线程时,它必须持久保存当前线程上下文并加载新线程上下文。在单线程进程中不会发生此开销(除了像垃圾收集这样的托管服务)。所以其他条件相同,添加线程不会提高性能,因为它必须执行原始工作负载以及所有上下文切换。
但是,如果您有多个CPU(核心)可供使用,则为每个CPU创建一个线程意味着您可以并行化计算,而不会产生上下文切换成本。如果你有比CPU更多的线程,那么上下文切换将成为一个问题。
有两类计算:IO绑定和计算绑定。 IO绑定计算可能会花费大量CPU周期来等待来自某些硬件(如网卡或硬盘)的响应。由于这种开销,您可以将线程数增加到CPU再次被最大化的点,这可以抵消上下文切换的成本。但是线程数量有限制,超过这个数量,上下文切换将花费更多的时间,而不是线程花费阻塞IO。
计算限制计算只需要CPU时间进行数字运算。这是密码破解者使用的一种计算方法。计算绑定操作不会被阻止,因此添加比CPU更多的线程会降低整体吞吐量。
C#ThreadPool已经为您完成了所有这些 - 您只需添加任务,并将它们排队直到线程可用。新线程仅在线程被阻止时创建。这样,上下文切换最小化。
我有一台四核机器 - 将问题分解为4个线程,每个线程在自己的核心上运行,或多或少与我的机器强制密码一样快。
要认真并行化这个问题,你需要大量的CPU。我读过using the GPU of a graphics card来解决这个问题。
我对here的攻击向量进行了分析,如果对你有用的话。彩虹表和处理器/内存权衡将成为项目的另一个有趣的领域。
答案 1 :(得分:2)
回答你的问题: 1)没有什么比测试线程性能更好的方法了。不同的问题与线程的比例不同,具体取决于目标问题中每个操作的独立程度。所以你可以尝试字典的事情。但是,当您分析结果时,您获得的结果可能不适用于所有问题。然而,一个非常流行的例子是人们尝试共享计数器,其中计数器由每个线程增加固定次数。
2)蛮力将涵盖大量案件。事实上,通过蛮力,可以有无限多种可能性。因此,您可能必须通过某些限制来限制密码,例如密码的最大长度等。分配暴力的一种方法是为每个线程分配一个不同的密码起始字符。然后该线程测试该起始字符的所有可能密码。一旦线程完成其工作,它将获得另一个起始字符,直到您使用所有可能的起始符号。
3)我想给你的一个建议是测试少量的线程。你最多要1024个线程。这不是一个好的理想。计算机上的核心数通常为4到10.因此,尽量不要超过核心数量,而不是核心数量。因为,处理器不能同时运行多个线程。在任何给定时间每个处理器一个线程。相反,尝试测量不同方案的性能,以便将问题分配给不同的线程。
请告诉我这是否有帮助!
答案 2 :(得分:1)
一种适用于所有可能密码的字典和暴力的解决方案是使用基于将作业划分为工作单元的方法。有一个共享对象负责将问题空间划分为工作单元 - 理想情况下,每个工作单元的工作时间为100毫秒到5秒 - 并为您启动的每个线程提供此对象的引用。然后每个线程都在这样的循环中运行:
for work_block in work_block_generator.get():
for item in work_block:
# Do work
这样做的好处就是如果每个线程预先将整个工作区分成一个块,那么如果一个线程比其他线程工作得更快,它就不会耗尽工作而只是闲置 - 它会起作用更多的块。
理想情况下,您的工作项生成器将具有一个接口,该接口在被调用时返回一个迭代器,该迭代器本身返回要测试的单个密码。然后,基于字典的字典从字典中选择一个范围,而强制一个选择前缀来测试每个批次。当然,您需要使用同步原语来阻止尝试抓取工作单元的不同线程之间的竞争。
答案 3 :(得分:0)
在字典和暴力方法中,问题是Embarrassingly Parallel。 用n个线程来分解暴力问题,就是说,将前两个(或三个)字母(“前缀”)分成n个部分。然后,每个线程都有一组分配的前缀,例如“aa - fz”,它只负责测试其前缀后面的所有内容。
在实践中,词典通常在破解更多密码方面稍微好一些,但是暴力,因为它涵盖了所有内容,不会错过目标长度内的密码。