How do i deal with threading.Lock being super slow? - python
I wrote a singlethreaded prime-finding algorithm a while ago, and decided to try to optimise it using threading. Unfortunately, the multithreaded version is at best running 3/4 the speed of the singlethreaded one. After some research it seems that the 'threading.Lock' function is what slows it down so much. How can I improve the code?
The single-threaded code:
from math import sqrt, ceil
import time
import pickle
os.system("mode con: lines=8")
os.system("title Prime finder in Python")
primes = []
#Load primes from logprimes.data
with open("logprimes.data", "rb") as f:
primes = pickle.load(f)
if len(primes) < 4:
primes = [2, 3, 5, 7]
#Function to save results to logprimes.data
def SaveRes():
with open("logprimes.data", "wb") as f:
pickle.dump(primes, f)
return("Saved " + str(len(primes)) + " primes.")
#Function to find out if a number is a prime
def is_prime(n):
i = 0
while primes[i] < ceil(sqrt(n)):
if n % primes[i] == 0:
return False
i = i + 1
return True
starttime = time.time()
currentcheck = int(primes[len(primes) - 1])
lastsaved = time.time()
lastshowed = time.time()
#Main loop
os.system("cls")
while True:
try:
currentcheck = currentcheck + 1
if is_prime(currentcheck) == True:
primes.append(currentcheck)
if time.time() - lastshowed > 4:
print("\n\n\nTotal time: " + str(time.time() - starttime))
print("Currently checking: " + str(currentcheck))
print("Total number of primes: " + str(len(primes)))
print("Primes per sec: " + str(len(primes) / float(time.time() - starttime)))
print("Checks per sec: " + str(currentcheck / float(time.time() - starttime)))
print("Prime rarity: " + str(len(primes) / currentcheck) + "%")
lastshowed = time.time()
if time.time() - lastsaved > 300:
os.system("cls")
print(SaveRes())
lastshowed = time.time() + 2
lastsaved = time.time()
except (KeyboardInterrupt, SystemExit):
os.system("cls")
print(SaveRes())
lastsaved = time.time()
lastshowed = time.time() + 2
The multi-threaded code:
from math import sqrt, ceil
import time
import pickle
import threading
#os.system("mode con: lines=8")
os.system("title Prime finder in Python")
running = True
primes = []
threads = []
#Load primes from logprimes.data
with open("logprimes.data", "rb") as f:
primes = pickle.load(f)
if len(primes) < 4:
primes = [2, 3, 5, 7]
#Function to save results to logprimes.data
def SaveRes():
with open("logprimes.data", "wb") as f:
pickle.dump(primes, f)
return("Saved " + str(len(primes)) + " primes.")
#Function to find out if a number is a prime
def is_prime(n):
while primes[-1] < ceil(sqrt(n)): #Wait until we have enough primes to correctly deem wether or not 'n' is a prime. I know, not the most optimal solution, but it works.
pass
i = 0
while primes[i] < ceil(sqrt(n)):
if n % primes[i] == 0:
return False
i = i + 1
return True
def threadfunction(threadid, startnum = primes[-1] + 1):
global primes, running
currentcheck = startnum
with lock:
print(threadid)
while running:
if not currentcheck in primes:
if is_prime(currentcheck * (threadid + 1)):
with lock:
primes.append(currentcheck)
currentcheck += 1
exit()
startsize = len(primes)
starttime = time.time()
starthighestprime = primes[-1]
#currentcheck = int(primes[len(primes) - 1])
lastsaved = time.time()
lastshowed = time.time()
#Create threads
lock = threading.Lock()
for i in range(os.cpu_count()):
threads.append(
threading.Thread(
target=threadfunction,
args=(i,)
)
)
threads[-1].start()
#Main loop
os.system("cls")
while running and __name__ == "__main__":
try:
time.sleep(1)
if time.time() - lastshowed > 4:
print("\n\n\nTotal time: " + str(time.time() - starttime))
print("Last found prime: " + str(primes[-1]))
print("Total number of primes: " + str(len(primes)))
print("Primes per sec: " + str((len(primes) - startsize) / float(time.time() - starttime)))
print("Checks per sec: " + str((primes[-1] - starthighestprime) / float(time.time() - starttime)))
print("Prime rarity: " + str((len(primes) / primes[-1]) * 100) + "%")
lastshowed = time.time()
if time.time() - lastsaved > 300:
os.system("cls")
print(SaveRes())
lastshowed = time.time() + 2
lastsaved = time.time()
except (KeyboardInterrupt, SystemExit):
os.system("cls")
print(SaveRes())
lastsaved = time.time()
lastshowed = time.time() + 2
exit()```
Related
Socket Programming Python Server and C client
this is what i make in python server code (receiving data length from C client and then receiving image file(.jpg)) but problem is when i receiving data length error occurs "invaild base64-encoded string" here is my servercode (Removed unnecessary functions) and when trying to run the stringData part the error occurs import os import socket import cv2 import numpy import base64 import glob import sys import time import threading from datetime import datetime class ServerSocket: def receiveImages(self): cnt_str = '' cnt = 0 try: while True: if (cnt < 10): cnt_str = '000' + str(cnt) elif (cnt < 100): cnt_str = '00' + str(cnt) elif (cnt < 1000): cnt_str = '0' + str(cnt) else: cnt_str = str(cnt) if cnt == 0: startTime = time.localtime() cnt += 1 length = self.conn.recv(64) print(length) length1 = length.decode('utf-8') print(length1) stringData = self.recvall(self.conn, int(length1)) ## stringData = self.conn.recv(100000) ##print(stringData) msg = "ready" self.conn.sendall(msg.encode()) stime = self.recvall(self.conn, 64) print('send time: ' + stime.decode('utf-8')) now = time.localtime() print('receive time: ' + datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')) data = numpy.frombuffer(base64.b64decode(stringData), numpy.uint8) decimg = cv2.imdecode(data, 1) cv2.imshow("image", decimg) cv2.imwrite('./' + str(self.TCP_PORT) + '_images' + str(self.folder_num) + '/img' + cnt_str + '.jpg', decimg) cv2.waitKey(1) if (cnt == 60 * 10): cnt = 0 convertThread = threading.Thread(target=self.convertImage(str(self.folder_num), 600, startTime)) convertThread.start() self.folder_num = (self.folder_num + 1) % 2 except Exception as e: print(e) #self.convertImage(str(self.folder_num), cnt, startTime) self.socketClose() cv2.destroyAllWindows() self.socketOpen() self.receiveThread = threading.Thread(target=self.receiveImages) self.receiveThread.start() def recvall(self, sock, count): buf = b'' while count: newbuf = sock.recv(count) if not newbuf: return None buf += newbuf count -= len(newbuf) return buf def convertImage(self, fnum, count, now): img_array = [] cnt = 0 for filename in glob.glob('./' + str(self.TCP_PORT) + '_images' + fnum + '/*.jpg'): if (cnt == count): break cnt = cnt + 1 img = cv2.imread(filename) height, width, layers = img.shape size = (width, height) img_array.append(img) file_date = self.getDate(now) file_time = self.getTime(now) name = 'video(' + file_date + ' ' + file_time + ').mp4' file_path = './videos/' + name out = cv2.VideoWriter(file_path, cv2.VideqqoWriter_fourcc(*'.mp4'), 20, size) for i in range(len(img_array)): out.write(img_array[i]) out.release() print(u'complete') def main(): server = ServerSocket('ServerIP', PORT) if __name__ == "__main__": main() what could it be the problems? in my expectation when decode the string data it can be the problem that C client encode causes problem
Python multiprocessing shared memory without copy
I'm currently working on a project for fun, involving calculating way too many numbers of the Fibonacci sequence. Thing is, I want it to go fast and I also don't want to loose too much progress if I have to do an update or have a computer issues.... So I over-engineered that, and I am currently looking to implement it with multiprocessing, but everywhere I look the only way to share memory in that case is to make a duplicate of it and that takes about an hour for (Yeah I have very big numbers) Is there any way to share a dictionary with multiprocessing without making a copy of it? Here is the code, currently with my last implementation using threading instead of using multiprocessing. (ignore the bad timekeeping of this, i'll fix it later) import threading import time def printProgressBar(iteration, total, prefix="", suffix="", decimals=1, length=100, fill="█", printEnd="\r"): """ Call in a loop to create terminal progress bar #params: iteration - Required : current iteration (Int) total - Required : total iterations (Int) prefix - Optional : prefix string (Str) suffix - Optional : suffix string (Str) decimals - Optional : positive number of decimals in percent complete (Int) length - Optional : character length of bar (Int) fill - Optional : bar fill character (Str) printEnd - Optional : end character (e.g. "\r", "\r\n") (Str) """ percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total))) filledLength = int(length * iteration // total) bar = fill * filledLength + "-" * (length - filledLength) print( f"\r{prefix} |{bar}| {percent}% {suffix} {time.strftime('%dd %H:%M:%S', time.gmtime(time.time() - start_time - 86400)).replace('31d', '0d')}", end=printEnd, ) # Print New Line on Complete if iteration == total: print() dict47 = {0: 0, 1: 1, 2: 1} dict47[0] = 2 def fibSequence(n): if n not in dict47: dict47[n] = fibSequence(n - 1) + fibSequence(n - 2) if n > dict47[0]: dict47[0] = n if n > 5 and not ((n - 3) % (iterations // 100) == 0) and not ((n - 2) % (iterations // 100) == 0): dict47.pop(n - 3, None) return dict47[n] def makeBackup(start, num, total): x = threading.Thread(target=writeBackup, args=(num,), daemon=False) y = threading.Thread(target=writeBackup, args=(num - 1,), daemon=False) x.start() y.start() x.join() y.join() time.sleep(1) print( f'{num/10000000}% done after {time.strftime("%dd %H:%M:%S", time.gmtime(time.time() - start - 86400)).replace("31d", "0d")}' ) timings = open("times.txt", "a") timings.write(str(int(time.time() - start)) + "\n") timings.close() def writeBackup(num): file = open(f".temp/fib{num}.txt", "a") file.write(str(num) + " : " + str(dict47[num])) file.close() dict47.pop(num, None) def loadDict(): from pathlib import Path maximum = 0 for n in range(1, 100): if Path(f".temp/fib{n*10000000}.txt").is_file(): maximum = n * 10000000 print("Maximum number found:", maximum) if maximum != 0: file = open(f".temp/fib{maximum}.txt", "r") temp = "".join(file.readlines()) dict47[maximum] = int(temp.lstrip(str(maximum) + " : ")) file.close() file = open(f".temp/fib{maximum - 1}.txt", "r") temp = "".join(file.readlines()) dict47[maximum - 1] = int(temp.lstrip(str(maximum - 1) + " : ")) file.close() dict47[0] = maximum print("Dictionary loaded at ", maximum) else: print("No dictionary found, starting from scratch") if __name__ == "__main__": try: timings = open("times.txt", "r") lastTime = int(timings.readlines()[-1]) start_time = time.time() - lastTime timings.close() except: start_time = time.time() + 86400 print("Start duration:", time.strftime("%dd %H:%M:%S", time.gmtime(time.time() - start_time)).replace("31d", "0d")) try: iterations = int(input("Enter the number of iterations: ")) except: iterations = 1000000000 print(iterations, "iterations will be performed") loadDict() num = dict47[0] while num < iterations: if num == 2: num += 248 else: num += 250 fibSequence(num) if num % 1000 == 0: printProgressBar(num, iterations, prefix="Progress:", suffix="Complete", length=100) if num % (iterations // 100) == 0: save = threading.Thread( target=makeBackup, args=(start_time, num, iterations), daemon=False, ) save.start() file = open("fib.txt", "a") file.write(str(iterations) + " : " + str(fibSequence(iterations)) + "\n") file.close() try: save.join() except: print("No save thread running, exiting...")
How to print the time of execution PYTHON
I have this code, but I want to print the time that a specific part of it takes. The block of code that I want to know the time is between: def TSP(lista2d): import copy origen = input("Ciudad de origen: ") resultado = [int(origen)] iteracion, indicador = int(origen) - 1, 0 distancia, copia = [], copy.deepcopy(lista2d) for j in range(1, len(lista2d)): for x in range(len(lista2d)): lista2d[x][iteracion] = 999 distancia.append(min(lista2d[iteracion])) for i in range(len(lista2d)): if min(lista2d[iteracion]) == lista2d[iteracion][i]: indicador = i lista2d[indicador][iteracion] = 999 resultado.append(indicador + 1) iteracion = indicador resultado.append(int(origen)) a = copia[resultado[-2] - 1][int(origen) - 1] distancia.append(a) print("El camino mas corto: " + str(resultado) + "\nCosto total: " + str(sum(distancia))) TSP([[999,100,150,140,130,120,78,150,90,200,180,190,160,135,144,300,60,77,87,90], [100,999,200,180,190,160,135,144,90,150,140,130,120,78,300,160,88,99,87,95], [150,200,999,167,156,169,123,134,156,177,155,188,176,143,192,146,170,152,176,122], [140,180,167,999,190,198,213,321,252,123,234,111,112,114,167,189,203,205,234,300], [130,190,156,190,999,333,300,178,167,143,200,111,156,267,299,152,100,90,97,99], [120,160,169,198,333,999,480,389,412,500,253,222,333,378,287,273,266,255,199,201], [78,135,123,213,300,480,999,140,150,143,177,194,166,200,181,154,177,133,122,109], [150,144,134,321,178,389,140,999,149,129,129,136,156,177,141,186,175,153,133,122], [90,90,156,252,167,412,150,149,999,89,82,83,60,124,59,78,89,99,100,123], [200,150,177,123,143,500,143,129,89,999,99,200,254,233,211,197,183,154,167,169], [180,140,155,234,200,253,177,129,82,99,999,77,88,89,289,222,311,471,122,109], [190,130,188,111,111,222,194,136,83,200,77,999,91,90,93,106,132,100,98,35], [160,120,176,112,156,333,166,156,60,254,88,91,999,102,103,107,111,113,200,101], [135,78,143,114,267,378,200,177,124,233,89,90,102,999,77,79,201,166,173,102], [144,300,192,167,299,287,181,141,59,211,289,93,103,77,999,55,103,105,101,201], [300,160,146,189,152,273,154,186,78,197,222,106,107,79,55,999,76,78,84,92], [60,88,170,203,100,266,177,175,89,183,311,132,111,201,103,76,999,93,102,29], [77,99,152,205,90,255,133,153,99,154,471,100,113,166,105,78,93,999,88,65], [87,87,176,234,97,199,122,133,100,167,122,98,200,173,101,84,102,88,999,333], [90,95,122,300,99,201,109,122,123,169,109,35,101,102,201,92,29,65,333,999]])
You can use 'time.time()' for example Start_time = time.time() End_time = time.time() Diff_time = End_time()-Start_time()
Calculating the amount of time left until completion
I am wondering how to calculate the amount of time it would take to example: Complete a brute force word list. I know how to use the time function and measure in time, but the problem is i need to find out how long it would take in the program itself... Here is the code i made this yesterday import itertools, math import os Alphabet = ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") # Add or remove whatevs you think will be in the password you're cracking (example, [symbols]) counter = 1 CharLength = 1 range_num = int(raw_input("Enter range: ")) stopper = range_num + 1 filename = "bruteforce_%r.txt" % (range_num) f = open(filename, 'a') #n_1 = len(Alphabet) #n_2 = n_1 - 1 # <-- total useless peice of garbage that could of been great in vurtual life #n_3 = '0' * n_2 #n = '1' + n_3 x = range_num y = len(Alphabet) amount = math.pow(y, x) total_items = math.pow(y, x) for CharLength in range(range_num, stopper): passwords = (itertools.product(Alphabet, repeat = CharLength)) for i in passwords: counter += 1 percentage = (counter / total_items) * 100 amount -= 1 i = str(i) i = i.replace("[", "") i = i.replace("]", "") i = i.replace("'", "") i = i.replace(" ", "") i = i.replace(",", "") i = i.replace("(", "") i = i.replace(")", "") f.write(i) f.write('\n') print "Password: %r\tPercentage: %r/100\tAmount left: %r" % (i, int(percentage), amount) if i == '0'* range_num: print "*Done" f.close() exit(0) else: pass This is my timer function i managed to make #import winsound # Comment this out if your using linux import os import time from sys import exit print "This is the timer\nHit CTRL-C to stop the timer\nOtherwise just let it rip untill the time's up" hours = int(raw_input('Enter the hours.\n>>> ')) os.system('clear') # Linux #os.system('cls') # Windows minutes = int(raw_input('Enter the minutes.\n>>> ')) os.system('clear') # linux #os.system('cls') # Windows seconds = int(raw_input('Enter the seconds.\n>>> ')) os.system('clear') # Linux #os.system('cls') # Windows stop_time = '%r:%r:%r' % (hours, minutes, seconds) t_hours = 00 t_minutes = 00 t_seconds = 00 while t_seconds <= 60: try: os.system('clear') # Linux #os.system('cls') # Windows current_time = '%r:%r:%r' % (t_hours, t_minutes, t_seconds) print current_time time.sleep(1) t_seconds+=1 if current_time == stop_time: print "// Done" #winsound.Beep(500,1000) #winsound.Beep(400,1000) break elif t_seconds == 60: t_minutes+=1 t_seconds=0 elif t_minutes == 60: t_hours+=1 t_minutes = 00 except KeyboardInterrupt: print "Stopped at: %r:%r:%r" % (t_hours, t_minutes, t_seconds) raw_input("Hit enter to continue\nHit CTRL-C to end") try: pass except KeyboardInterrupt: exit(0) Now i just cant figure out how to make this again but to calculate how long it will take rather than how long it is taking...
You cannot predict the time a script is going to take. Firstly because two machines wouldn't run the script in the same time, and secondly, because the execution time on one machine can vary from on take to another. What you can do, however, is compute the percentage of execution. You need to figure out, for example, how many iterations your main loop will do, and calculate at each iteration the ratio current iteration count / total number of iterations. Here is a minimalist example of what you can do: n = 10000 for i in range(n): print("Processing file {} ({}%)".format(i, 100*i//n)) process_file(i) You can take it further and add the time as an additional info: n = 10000 t0 = time.time() for i in range(n): t1 = time.time() print("Processing file {} ({}%)".format(i, 100*i//n), end="") process_file(i) t2 = time.time() print(" {}s (total: {}s)".format(t2-t1, t2-t0)) The output will look like this: ... Processing file 2597 (25%) 0.2s (total: 519.4s) Processing file 2598 (25%) 0.3s (total: 519.7s) Processing file 2599 (25%) 0.1s (total: 519.8s) Processing file 2600 (25%)
This is my implementation, which returns time elapsed, time left, and finish time in H:M:S format. def calcProcessTime(starttime, cur_iter, max_iter): telapsed = time.time() - starttime testimated = (telapsed/cur_iter)*(max_iter) finishtime = starttime + testimated finishtime = dt.datetime.fromtimestamp(finishtime).strftime("%H:%M:%S") # in time lefttime = testimated-telapsed # in seconds return (int(telapsed), int(lefttime), finishtime) Example: import time import datetime as dt start = time.time() cur_iter = 0 max_iter = 10 for i in range(max_iter): time.sleep(5) cur_iter += 1 prstime = calcProcessTime(start,cur_iter ,max_iter) print("time elapsed: %s(s), time left: %s(s), estimated finish time: %s"%prstime) Output: time elapsed: 5(s), time left: 45(s), estimated finish time: 14:28:18 time elapsed: 10(s), time left: 40(s), estimated finish time: 14:28:18 time elapsed: 15(s), time left: 35(s), estimated finish time: 14:28:18 ....
You will never ever be able to know exactly how long it is going to take to finish. The best you can do is calculate was percentage of the work you have finished and how long that has taken you and then project that out. For example if you are doing some work on the range of numbers from 1 to 100 you could do something such as start_time = get the current time for i in range(1, 101): # Do some work current_time = get the current time elapsed_time = current_time - start_time time_left = 100 * elapsed_time / i - elapsed_time print(time_left) Please understand that the above is largely pseudo-code
The following function will calculate the remaining time: last_times = [] def get_remaining_time(i, total, time): last_times.append(time) len_last_t = len(last_times) if len_last_t > 5: last_times.pop(0) mean_t = sum(last_times) // len_last_t remain_s_tot = mean_t * (total - i + 1) remain_m = remain_s_tot // 60 remain_s = remain_s_tot % 60 return f"{remain_m}m{remain_s}s" The parameters are: i : The current iteration total : the total number of iterations time : the duration of the last iteration It uses the average time taken by the last 5 iterations to calculate the remaining time. You can the use it in your code as follows: last_t = 0 iterations = range(1,1000) for i in iterations: t = time.time() # Do your task here last_t = time.time() - t get_remaining_time(i, len(iterations), last_t)
Python For loop repeating endlessly
I'm currently writing a program to check speeds of cars and their license plates, and I want to repeat the function that does this x number of times, the problem I'm having though is that the function is repeating endlessly and is not adhering to the number of times I want it to loop. Here is what I have so far: if correctMatch: pass else: with open('Camera Output.txt', 'a') as f: print("DATA RECORDED TO: Camera Output.txt") exactTime2 = datetime.now() f.write("{} has a non-standard license plate and has been recorded at {}.".format(licensePlate, exactTime2) + "\n") f.write("---------------------------------------------------------\n") if speedCarMph > 60: with open('Camera Output.txt', 'a') as f: print("DATA RECORDED TO: Camera Output.txt") exactTime= datetime.now() f.write("{} was travelling at {}MPH, recorded at {} and has broken the law.".format(licensePlate, speedCarMph, exactTime) + "\n") f.write("----------------------------------------------------------\n") licensePlateCheck() for x in range(N): repeatNum = 0 while repeatNum < 10: repeatNum += 1 licensePlateCheck() if repeatNum == 10: print("Completed generation") I also attempted to use a thread but that didn't work. If you need any more of the code, just ask. The full code is here (excluding an unrelated function and the function choice): import re import threading from queue import Queue def licensePlateCheck(): camInput1 = datetime.now() print(camInput1) print("Car is travelling...") time.sleep(0.1) print("Car has passed cam2") camInput2 = timedelta(seconds = random.uniform(5, 10)) distance = 200 duration = camInput2.total_seconds() print("Time Delta is equal to: {0}".format(duration)) speedCarMs = distance/duration print("Car is travelling in m/s at: {0}".format(speedCarMs)) speedCarMph = 2.237*speedCarMs print("Car is travelling in MPH at: {0}".format(speedCarMph)) licenseCharNum = randint(2,9) licensePlate = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(licenseCharNum)) licensePlateLayout = re.compile('[A-Z][A-Z]\d\d[A-Z][A-Z][A-Z]') correctMatch = licensePlateLayout.match(licensePlate) if correctMatch: pass else: with open('Camera Output.txt', 'a') as f: print("DATA RECORDED TO: Camera Output.txt") exactTime2 = datetime.now() f.write("{} has a non-standard license plate and has been recorded at {}.".format(licensePlate, exactTime2) + "\n") f.write("----------------------------------------------------------\n") if speedCarMph > 60: with open('Camera Output.txt', 'a') as f: print("DATA RECORDED TO: Camera Output.txt") exactTime= datetime.now() f.write("{} was travelling at {}MPH, recorded at {} and has broken the law.".format(licensePlate, speedCarMph, exactTime) + "\n") f.write("----------------------------------------------------------\n") licensePlateCheck() for x in range(N): repeatNum = 0 while repeatNum < 10: repeatNum += 1 licensePlateCheck() if repeatNum == 10: print("Completed generation")
In that case you have unnecessary used while loop:) for x in range(N): // will iterate x times licensePlateCheck() print("Completed generation") With nested while loop, your method would execute: x * 10 times: x - for loop 10 - while loop Both For and While are correct, the choice is up to you.