Pages:
Author

Topic: New pure-python CPU miner, for fun and testing - page 3. (Read 25535 times)

hero member
Activity: 566
Merit: 500
Unselfish actions pay back better
The way I see it, these two lines have the effect of reversing the entire data string:

Code:
hash = bufreverse(hash)
hash = wordreverse(hash)

and could be replaced by

Code:
hash = hash[::-1]

If I am right, then the following small patch will triple the efficiency (from ~32 khash/sec to more than 100 khash/sec):

Code:
--- pyminer.py 2011-02-17 19:37:34.254845344 +0100
+++ pyminer-opt.py 2011-02-17 19:47:44.794843788 +0100
@@ -76,18 +76,10 @@
  def getwork(self, data=None):
  return self.rpc('getwork', data)
 
-def uint32(x):
- return x & 0xffffffffL
-
-def bytereverse(x):
- return uint32(( ((x) << 24) | (((x) << 8) & 0x00ff0000) |
- (((x) >> 8) & 0x0000ff00) | ((x) >> 24) ))
-
 def bufreverse(in_buf):
  out_words = []
  for i in range(0, len(in_buf), 4):
- word = struct.unpack('@I', in_buf[i:i+4])[0]
- out_words.append(struct.pack('@I', bytereverse(word)))
+ out_words.append(in_buf[i:i+4][::-1])
  return ''.join(out_words)
 
 def wordreverse(in_buf):
@@ -115,10 +107,7 @@
 
  hash_o = hashlib.sha256()
  hash_o.update(hash1)
- hash = hash_o.digest()
-
- hash = bufreverse(hash)
- hash = wordreverse(hash)
+ hash = hash_o.digest()[::-1]
 
  hash_str = hash.encode('hex')
  l = long(hash_str, 16)


A few other optimizations can be made within the loop to raise the efficiency to approx. 110 khash/sec on my machine, but this will make the code less legible and is probably not worth it.

Cheers,
legendary
Activity: 1596
Merit: 1091
It is computational expensive to repeatedly concatenate strings in Python.  I suggest using [].append() in the bufreverse() and wordreverse() methods:

Updated the source code with your suggestions.  Thanks -- this is my second python program, so I guarantee there are other improvements that expert Python programmers can discover.
hero member
Activity: 566
Merit: 500
Unselfish actions pay back better
required args?
not sure of the format for files in python
Pyminer takes as its single argument the name of the config file.

The config file consists of lines of the form

Code:
key = value

Keys can be host, port, rpcuser, rpcpass, threads, logdir and hashmeter.

Cheers,
newbie
Activity: 10
Merit: 0
required args?
not sure of the format for files in python


hero member
Activity: 566
Merit: 500
Unselfish actions pay back better
Furthermore, you could bytereverse a 4-byte buf using it's own builtin medthod:

Code:
>>> x = 'abcd'
>>> x[::-1]
'dcba'
>>>

No need to use the pack/unpack stuff…

Cheers,
hero member
Activity: 489
Merit: 504
Great stuff, finally I can wrap my head around how mining works without having to crawl through additional stuff Smiley
hero member
Activity: 566
Merit: 500
Unselfish actions pay back better
It is computational expensive to repeatedly concatenate strings in Python.  I suggest using [].append() in the bufreverse() and wordreverse() methods:

Code:
diff --git a/pyminer.py b/pyminer.py
index cfd79a2..f972a75 100644
--- a/pyminer.py
+++ b/pyminer.py
@@ -84,21 +84,18 @@ def bytereverse(x):
  (((x) >> 8) & 0x0000ff00) | ((x) >> 24) ))
 
 def bufreverse(in_buf):
- out_words = ""
+ out_words = []
  for i in range(0, len(in_buf), 4):
  word = struct.unpack('@I', in_buf[i:i+4])[0]
- out_words += struct.pack('@I', bytereverse(word))
- return out_words
+ out_words.append(struct.pack('@I', bytereverse(word)))
+ return ''.join(out_words)
 
 def wordreverse(in_buf):
  out_words = []
  for i in range(0, len(in_buf), 4):
  out_words.append(in_buf[i:i+4])
  out_words.reverse()
- out_buf = ""
- for word in out_words:
- out_buf += word
- return out_buf
+ return ''.join(out_words)
 
 class Miner:
  def __init__(self, id):


Cheers,
Kiv
full member
Activity: 162
Merit: 100
This is really cool Smiley It'll definitely help me understand better how the mining works.
hero member
Activity: 566
Merit: 500
Unselfish actions pay back better
I wonder if this will run faster under PyPy?
I just had to try…   Wink

Running pyminer on Python2.7 yields ~30 khash/sec, under PyPy less than 3 khash/sec.  Oh, well…

Cheers,

hero member
Activity: 566
Merit: 500
Unselfish actions pay back better
This is single-threaded, and pulls a whopping 43 Khash/sec on my box.
Cool!   Cool

I wonder if this will run faster under PyPy (pystone.main() is more than 10 times faster on PyPy on my machine)?

Cheers,
hero member
Activity: 726
Merit: 500
This is single-threaded, and pulls a whopping 43 Khash/sec on my box.

What type of system are you running?  Hamsters in a box with pencil and paper?  Grin
legendary
Activity: 1596
Merit: 1091
Here is a new high performance, highly optimized CPU miner:

     https://github.com/jgarzik/pyminer

This pulls a whopping 256 Khash/sec per thread on my box.

The main purpose is to demonstrate the mining algorithm, in a small amount of portable code.  And to have a bit of fun.
Pages:
Jump to: