|
Message-ID: <20100703204759.GA27964@openwall.com> Date: Sun, 4 Jul 2010 00:47:59 +0400 From: Solar Designer <solar@...nwall.com> To: john-users@...ts.openwall.com Subject: Re: bitslice DES parallelization with OpenMP Hi, How do you like 356M c/s at LM hashes on a single system (no GPU, seriously), and 15M c/s at traditional DES-based crypt(3) with just a single hash being attacked (the slower case)? And that's with no hand-crafted assembly code at all. Please read on. ;-) This time, I came up with and implemented a new bitslice DES key setup algorithm (currently with SSE2 intrinsics only - a proof of concept). Although the new algorithm was meant to allow for vectorization and parallelization - and it does - it's also a lot faster even in a single process, single thread build (no OpenMP involved), albeit with SSE2 vectorization where appropriate. Here are the new single process, single thread benchmarks on Core i7 920 2.67 GHz: Benchmarking: Traditional DES [128/128 BS SSE2-16]... DONE Many salts: 2573K c/s real, 2573K c/s virtual Only one salt: 2484K c/s real, 2484K c/s virtual At first glance, this one is not exciting, but notice how the gap between multi-salt and single salt speed became much narrower. This will be important for subsequent parallelization (see below). Benchmarking: LM DES [128/128 BS SSE2-16]... DONE Raw: 38781K c/s real, 38781K c/s virtual And this one is exciting: it is more than twice faster than what a clean 1.7.6 achieves on this machine (around 17.5M c/s at LM). That's because LM hash computation is mostly about key setup (or at least it was prior to this change). Another exiting result: with 8 separate processes running on the Core i7 at once, I am getting a combined c/s rate of 173M c/s at LM hashes. For dual Xeon X5460 3.16 GHz, the numbers are 45M c/s (non-OpenMP build, single process, single thread) and as much as 356M c/s combined for 8 simultaneous processes (still no OpenMP). This is with john-1.7.6-fast-des-key-setup-3.diff.gz, which I uploaded to the wiki: http://openwall.info/wiki/john/patches I am also uploading these patches to: http://download.openwall.net/pub/projects/john/contrib/ so they get propagated to the mirrors. Now let's get back to OpenMP. 1.7.6-omp-des-7, also uploaded to the wiki, integrates the DES key setup code above and parallelizes it. For DES-based crypt(3), things are quite good. On the Core i7: $ GOMP_SPINCOUNT=10000 ../run/john -te -fo=des Benchmarking: Traditional DES [128/128 BS SSE2-16]... DONE Many salts: 9584K c/s real, 1202K c/s virtual Only one salt: 8565K c/s real, 1165K c/s virtual During the first part of the benchmark (multi-salt), system load stays at over 99%. During the second part, it drops to 92% (leaving 8% idle), which is quite normal given that some code that runs per-key hasn't been parallelized (doing so wouldn't fit well in the OpenMP model). With 8 separate non-OpenMP-enabled processes, the same system does around 10800K c/s combined for the single salt case, so the efficiency of the OpenMP-enabled build at this test is around 80%. Unfortunately, the speed for multi-salt has dropped from around 10200K for -omp-des-4 to around 9600K. I previously traced this to the move of the "expand key" step from DES_bs.c into "crypt bodies" in DES_bs_b.c, but why this causes a slowdown is a mystery to me. I haven't investigated this further yet - if anyone does, please let me know. Meanwhile, I am keeping the older -omp-des-4 patch on the wiki as well. I had to make this "expand key move" in this newer patch in order to move key setup inside the parallel region, which was required to achieve decent performance for single-salt. Let's see if it's achieved in practice: $ GOMP_SPINCOUNT=10000 ./john -i=alpha pw Loaded 1 password hash (Traditional DES [128/128 BS SSE2-16]) guesses: 0 time: 0:00:00:01 c/s: 2850K trying: lkuku - botink guesses: 0 time: 0:00:00:05 c/s: 6596K trying: droopapr - stpgehed guesses: 0 time: 0:00:00:14 c/s: 7464K trying: fedsuyog - fesidanc guesses: 0 time: 0:00:00:28 c/s: 7788K trying: vwhwca - vwcvfr guesses: 0 time: 0:00:00:53 c/s: 7965K trying: dcerkncs - alecismc guesses: 0 time: 0:00:01:09 c/s: 8002K trying: sejaxn - siqtui guesses: 0 time: 0:00:01:45 c/s: 8071K trying: eicomdm - eicvdic guesses: 0 time: 0:00:02:21 c/s: 8103K trying: huaugost - huluigra apmahoop (user) guesses: 1 time: 0:00:02:41 c/s: 8110K trying: apffjkbt - acchucrm Yes, it is. (It is normal for "incremental" mode, when not locked to a specific length, to take a while to get up to full speed. This is because length switches involve overhead, but those become very infrequent when running for a while. The speed would continue to increase even further if the above session were running for longer.) Now to LM hash parallelization. In short, there's some speedup from parallelization, but things are not great - and my recommendation is to run separate processes. Here's what I am getting on the Core i7 with 1.7.6-omp-des-7 running 8 threads: $ GOMP_SPINCOUNT=10000 ../run/john -te=1 -fo=lm Benchmarking: LM DES [128/128 BS SSE2-16]... DONE Raw: 65126K c/s real, 16120K c/s virtual That's about the best I can achieve with the current code. It leaves about 50% of CPU time idle (although due to SMT this corresponds to less than 50% of actual CPU resources staying idle). By running two 4-thread processes simultaneously, I achieve a combined c/s rate of 90M c/s: Raw: 45386K c/s real, 17443K c/s virtual Raw: 45386K c/s real, 17429K c/s virtual [1]- Done GOMP_SPINCOUNT=10000 OMP_NUM_THREADS=4 ./john -te -fo=lm [2]+ Done GOMP_SPINCOUNT=10000 OMP_NUM_THREADS=4 ./john -te -fo=lm That's better, but it's still very far from the combined c/s rate for 8 separate non-OpenMP-enabled processes, which is as high as 173M c/s. Now let's see how this behaves in actual usage. I'll use just one hash for this test for clarity, although multi-hash benchmarks are also very interesting and are of more practical relevance. Those show similar results ("trust me" - or better try on your own and post in here). First, just the new key setup (1.7.6-nsk-3), no OpenMP yet, back on the Core i7 machine: $ ./john -i -u=u3047 ~/john/pw-fake-nt Loaded 1 password hash (LM DES [128/128 BS SSE2-16]) guesses: 0 time: 0:00:00:02 c/s: 19644K trying: 09ACEBU - 09ACOS3 guesses: 0 time: 0:00:00:08 c/s: 26005K trying: BBOSNCR - BBOTPHA guesses: 0 time: 0:00:00:16 c/s: 28044K trying: PW0DSK - PW0D72 guesses: 0 time: 0:00:00:20 c/s: 28688K trying: COHJF9 - COVDFT guesses: 0 time: 0:00:00:27 c/s: 29225K trying: 34JYDW - 34JY31 guesses: 0 time: 0:00:00:43 c/s: 30049K trying: KS54WG - KS58TL guesses: 0 time: 0:00:01:06 c/s: 30444K trying: 408I1$O - 407929T NE1410S (u3047) guesses: 1 time: 0:00:01:11 c/s: 30387K trying: NECQ9SU - NE1411B This achieved over 30M c/s out of the "theoretical maximum" of 39M c/s. With a longer session (or with a length lock), the speed would be slightly higher. Note that only one CPU core was in use by John in the above run. Now 1.7.6-omp-des-7 running 8 threads, same machine: $ GOMP_SPINCOUNT=10000 ./john -i -u=u3047 ~/john/pw-fake-nt Loaded 1 password hash (LM DES [128/128 BS SSE2-16]) guesses: 0 time: 0:00:00:00 c/s: 6156K trying: PY2TY - M02TS guesses: 0 time: 0:00:00:04 c/s: 31746K trying: MW2C90 - MWIZDK guesses: 0 time: 0:00:00:11 c/s: 39202K trying: N1BAKK - NGCHCY guesses: 0 time: 0:00:00:17 c/s: 41378K trying: 0BAYBBS - 0BLMSD1 guesses: 0 time: 0:00:00:25 c/s: 43049K trying: 20RPPAD - 20MMNTS guesses: 0 time: 0:00:00:36 c/s: 44219K trying: ALY2AS8 - AR62899 NE1410S (u3047) guesses: 1 time: 0:00:00:48 c/s: 44756K trying: NECDRD3 - NE10TWO Yes, it's 47% faster, which is consistent with "--test" benchmarks. Those reported more like a 68% speedup, but we know that performance with OpenMP is less stable (it's very sensitive to system load) and that there's cracking-mode-specific overhead (not parallelized), which is not included in the "--test" benchmarks. So it is not surprising to see a difference like this for this very fast hash type. For slower hash types, "--test" benchmarks match actual runs much closer. BTW, the specific password "NE1410S" would normally be cracked instantly (given its LM hash) because it is found on JtR's bundled common passwords list, but I intentionally forced JtR to use the "incremental" mode to have this session take a little while. I did not even give JtR any hint on the character set used. Finally, some quick benchmarks for dual Xeon X5460 3.16 GHz (briefly mentioned above), under some unrelated load: Just the new key setup (no OpenMP), only one CPU core in use by John: Benchmarking: Traditional DES [128/128 BS SSE2-16]... DONE Many salts: 2982K c/s real, 2982K c/s virtual Only one salt: 2880K c/s real, 2880K c/s virtual Benchmarking: LM DES [128/128 BS SSE2-16]... DONE Raw: 45243K c/s real, 45243K c/s virtual 1.7.6-omp-des-7: Benchmarking: Traditional DES [128/128 BS SSE2-16]... DONE Many salts: 20054K c/s real, 2506K c/s virtual Only one salt: 15532K c/s real, 1941K c/s virtual That's over 15M c/s for the single-salt case. Quite good. Benchmarking: LM DES [128/128 BS SSE2-16]... DONE Raw: 63799K c/s real, 7974K c/s virtual Good speed, but nothing exciting now that we've already seen Core i7 perform a bit better. I think it's the system load (in combination with this very fast hash) that prevented the Xeon from showing a better result. This is as little as 18% of what this same system achieves with 8 separate non-OpenMP-enabled processes (64M out of 356M). It should be possible to achieve a better result on an idle dual-Xeon system - 100M c/s anyone? As usual, feedback is welcome. I'd like this stuff to become a bit more mature before I approach integrating it. Alexander
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.