|
| 1 | +# mergesort using mmap |
| 2 | + |
| 3 | +import shutil |
| 4 | +import tempfile |
| 5 | +import mmap |
| 6 | +import os |
| 7 | +import random |
| 8 | +from time import time |
| 9 | + |
| 10 | +def mergesort (A): |
| 11 | + """public method for using mergesort on array""" |
| 12 | + copy = list(A) |
| 13 | + mergesort_array (copy, A, 0, len(A)) |
| 14 | + |
| 15 | +def mergesort_array(A, result, start, end): |
| 16 | + """mergesort array in memory""" |
| 17 | + if end - start < 2: |
| 18 | + return |
| 19 | + if end - start == 2: |
| 20 | + if result[start] > result[start+1]: |
| 21 | + result[start],result[start+1] = result[start+1],result[start] |
| 22 | + return |
| 23 | + |
| 24 | + mid = (end + start)/2 |
| 25 | + mergesort_array(result, A, start, mid) |
| 26 | + mergesort_array(result, A, mid, end) |
| 27 | + |
| 28 | + # merge A left-and right |
| 29 | + i = start |
| 30 | + j = mid |
| 31 | + idx = start |
| 32 | + while idx < end: |
| 33 | + if j >= end or (i < mid and A[i] < A[j]): |
| 34 | + result[idx] = A[i] |
| 35 | + i += 1 |
| 36 | + else: |
| 37 | + result[idx] = A[j] |
| 38 | + j += 1 |
| 39 | + |
| 40 | + idx += 1 |
| 41 | + |
| 42 | + |
| 43 | +def compareSortTimes(): |
| 44 | + """compare sorting algorithms""" |
| 45 | + |
| 46 | + n = 128 |
| 47 | + while n <= 262144: |
| 48 | + timeN = timeM = 0 |
| 49 | + for t in range(10): |
| 50 | + a1 = [random.randint(1,n) for x in range(n)] |
| 51 | + a2 = list(a1) |
| 52 | + |
| 53 | + now = time() |
| 54 | + a1.sort() |
| 55 | + timeN += (time() - now) |
| 56 | + |
| 57 | + now = time() |
| 58 | + mergesort(a2) |
| 59 | + timeM += (time() - now) |
| 60 | + |
| 61 | + assert a1 == a2 |
| 62 | + |
| 63 | + print n, '\t', timeN/10, '\t', timeM/10 |
| 64 | + n *= 2 |
| 65 | + |
| 66 | +def output (src): |
| 67 | + """print numbers in file""" |
| 68 | + srcFile = open(src, "a+b") |
| 69 | + srcMap = mmap.mmap(srcFile.fileno(), 0) |
| 70 | + length = os.stat(src).st_size |
| 71 | + |
| 72 | + while length > 0: |
| 73 | + print readInt(srcMap) |
| 74 | + length -= 4 |
| 75 | + srcMap.close() |
| 76 | + srcFile.close() |
| 77 | + |
| 78 | +def mergeSortFile (src): |
| 79 | + """external mergesort using mmap""" |
| 80 | + |
| 81 | + length = os.stat(src).st_size |
| 82 | + |
| 83 | + dest = tempfile.NamedTemporaryFile(delete=False) |
| 84 | + dest.close() |
| 85 | + shutil.copy(src, dest.name) |
| 86 | + |
| 87 | + srcFile = open(src, "a+b") |
| 88 | + srcMap = mmap.mmap(srcFile.fileno(), 0) |
| 89 | + destFile = open(dest.name, "a+b") |
| 90 | + destMap = mmap.mmap(destFile.fileno(), 0) |
| 91 | + |
| 92 | + mergeSortMMap (destMap, srcMap, 0, length) |
| 93 | + srcMap.close() |
| 94 | + destMap.close() |
| 95 | + srcFile.close() |
| 96 | + destFile.close() |
| 97 | + |
| 98 | +def readInt(m): |
| 99 | + """read four bytes as int""" |
| 100 | + b1 = ord(m.read_byte()) |
| 101 | + b2 = ord(m.read_byte()) |
| 102 | + b3 = ord(m.read_byte()) |
| 103 | + b4 = ord(m.read_byte()) |
| 104 | + |
| 105 | + ival= (b1 << 24) + (b2 << 16) + (b3 << 8) + (b4 << 0) |
| 106 | + return ival |
| 107 | + |
| 108 | +def writeInt(m, n): |
| 109 | + """write int as four bytes""" |
| 110 | + b1 = (n >> 24) & 255 |
| 111 | + b2 = (n >> 16) & 255 |
| 112 | + b3 = (n >> 8) & 255 |
| 113 | + b4 = n & 255 |
| 114 | + |
| 115 | + m.write_byte(chr(b1)) |
| 116 | + m.write_byte(chr(b2)) |
| 117 | + m.write_byte(chr(b3)) |
| 118 | + m.write_byte(chr(b4)) |
| 119 | + |
| 120 | +def mergeSortMMap(A, result, start, end): |
| 121 | + """recursively mergesort A[start:end] into result""" |
| 122 | + |
| 123 | + if end - start < 8: |
| 124 | + return |
| 125 | + |
| 126 | + if end - start == 8: |
| 127 | + result.seek(start) |
| 128 | + left = readInt(result) |
| 129 | + right = readInt(result) |
| 130 | + |
| 131 | + if left > right: |
| 132 | + result.seek(start) |
| 133 | + writeInt(result, right) |
| 134 | + writeInt(result, left) |
| 135 | + return |
| 136 | + |
| 137 | + mid = (end + start)/8*4; |
| 138 | + mergeSortMMap(result, A, start, mid); |
| 139 | + mergeSortMMap(result, A, mid, end); |
| 140 | + |
| 141 | + result.seek(start) |
| 142 | + |
| 143 | + i = start |
| 144 | + j = mid |
| 145 | + idx = start |
| 146 | + while idx < end: |
| 147 | + |
| 148 | + A.seek(i) |
| 149 | + Ai = readInt(A) |
| 150 | + Aj = 0; |
| 151 | + if j < end: |
| 152 | + A.seek(j) |
| 153 | + Aj = readInt(A) |
| 154 | + |
| 155 | + if j >= end or (i < mid and Ai < Aj): |
| 156 | + writeInt(result, Ai) |
| 157 | + i += 4 |
| 158 | + else: |
| 159 | + writeInt(result, Aj) |
| 160 | + j += 4 |
| 161 | + |
| 162 | + idx += 4 |
| 163 | + |
| 164 | +def createRandom(n, name, high=1000): |
| 165 | + """Create file containing n random integers with maximum value""" |
| 166 | + |
| 167 | + out = open(name, "wb") |
| 168 | + for i in range(n): |
| 169 | + val = random.randint(1,high) |
| 170 | + |
| 171 | + out.write(chr((val >> 24) & 255)) |
| 172 | + out.write(chr((val >> 16) & 255)) |
| 173 | + out.write(chr((val >> 8) & 255)) |
| 174 | + out.write(chr(val & 255)) |
| 175 | + |
| 176 | + out.close() |
| 177 | + |
| 178 | +""" |
| 179 | +Change Log |
| 180 | +---------- |
| 181 | +2014.05.23 createRandom |
| 182 | + defect: out = open(name, "w") |
| 183 | + fix: out = open(name, "wb") |
| 184 | +""" |
0 commit comments