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>