So I came across a pointless/impossible problem someone had about md5 hashing. The goal is to find an MD5 hash that hashes to itself: MD5( X ) = X<br><br>My goal in coming up with a solution "finder" was just as an exercise in distributed Erlang, not necessarily to achieve the near impossible and brute force the problem.<br>
<br>I wrote up a quick and dirty distributed app, but the performance seems really bad (around 10,000 keys/sec on a 3700+ Athlon) It scales nicely, but 10,000 keys/sec/machine is terrible when other languages can get 1M+/sec (some CUDA GP/GPU implementations get 300M+/sec)<br>
<br>So, now my interest lies in what's so slow about my code....maybe it's Erlang's md5 implementation, or more probably how I'm generating the random string? <br><br>What does everyone think?<br><br><br>-module(md5id).<br>
<br>-export([start/0]).<br>-export([recv/1]).<br>-export([start_slave/1]).<br>-export([spawner/2]).<br>-export([checkMD5/2]).<br>-export([randomHexString/0]).<br>-export([randomHex/0]).<br><br>start()-><br>
<br> register(receiverProc, self()),<br><br> SpawnerPid = spawn(?MODULE, spawner, [0, receiverProc]),<br><br> recv(0),<br><br> io:fwrite("Exiting~n"),<br> exit(SpawnerPid, done)<br>.<br><br>recv(T)-><br>
receive<br> {found, String} -><br> io:fwrite("Found the Identity String: ~p~n", [String])<br> ;<br> {checked, Count} -><br> T1 = T + Count,<br> io:fwrite("Checked ~p hashes so far~n", [T1]),<br>
recv(T1)<br> ;<br> {connected, Node}-><br> io:fwrite("Node ~p connected to help out~n", [Node]),<br> recv(T)<br> end<br>.<br><br><br>start_slave(MasterNodeName)-><br>
pong = net_adm:ping(MasterNodeName),<br> {receiverProc, MasterNodeName} ! {connected, node()},<br> spawn(?MODULE, spawner, [0, {receiverProc, MasterNodeName}])<br>.<br><br>%% send an update message after every 10,000 keys<br>
spawner(10000, ReceiverPid)-><br>
ReceiverPid ! {checked, 10000},<br> spawner(0, ReceiverPid)<br>;<br>spawner(N, ReceiverPid)-><br> spawn(?MODULE, checkMD5, [randomHexString(), ReceiverPid]),<br> spawner(N+1, ReceiverPid)<br>.<br><br><br>
checkMD5(String, ReceiverPid)-><br><br>
Hashed = lists:flatten([io_lib:format("~.16b",[N]) || N <- binary_to_list(erlang:md5(String))]),<br><div id=":87" class="ii gt"> case Hashed == String of<br> true -><br> ReceiverPid ! {found, String}<br>
;<br>
false -><br> ok<br> end<br>.<br><br><br>randomHexString()-><br> lists:flatten( lists:foldl( fun(_X, Accumulator) -> [randomHex() | Accumulator] end, [], lists:seq(1,32) ) )<br>.<br><br>randomHex()-><br>
N = random:uniform(16)-1,<br> Hex = io_lib:format("~.16b",[N]),<br> lists:flatten(Hex)<br>.</div><br>