LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 12-30-2016, 04:07 PM   #1
CincinnatiKid
Member
 
Registered: Jul 2010
Posts: 454

Rep: Reputation: 47
Python Threading Deadlock Issue


Below is a program that I wrote that uses the Lucas Lehmer algorithm to figure out if a number is a mersenne prime (2^prime number-1). In my program it is trying to determine if 2^NUM_TO_CHECK-1 is a prime. Using the code below it only runs the "t_run" thread and not the "t_progress" thread until t_run has finished. Is my code not thread safe or something? Any incite would be greatly appreciated.

Code:
import gmpy2
import threading
import time

NUM_TO_CHECK = 86243

class Primes:
	def __init__(self, n):
		self.num = n
		self.i = gmpy2.mpz(1)
		self.testnum = gmpy2.mpz(4)
		self.answer = gmpy2.mpz(0)
		
		self.progress = {'running': 1, 'isprime': 0, 'i': 1}

	def lucaslehmer(self):
		while (self.i <= NUM_TO_CHECK-2):
			self.answer = gmpy2.f_mod(((self.testnum*self.testnum)-2), self.num)
			self.testnum = self.answer
			self.i += 1
		
		if (self.answer == 0):
			self.progress['isprime'] = 2
		else:
			self.progress['isprime'] = 1
		self.progress['running'] = 0

	def getprogress(self, cont, delay):
		if cont:
			while self.progress['running']:
				self.progress['i'] = self.i
				print(self.progress)
				time.sleep(delay)
		print(self.progress)

if __name__ == "__main__":
	primecandidate = gmpy2.mpz(pow(2, NUM_TO_CHECK)-1)
	wwprime = Primes(primecandidate)
	t_progress = threading.Thread(target=wwprime.getprogress, args=(1,1))
	t_progress.start()
	t_run = threading.Thread(target=wwprime.lucaslehmer)
	t_run.start()
 
Old 12-30-2016, 04:20 PM   #2
CincinnatiKid
Member
 
Registered: Jul 2010
Posts: 454

Original Poster
Rep: Reputation: 47
I found out if I put a delay/time.sleep in this loop, the threads work fine together. The problem is, I will be doing millions of calculations and can't sleep here or my calculations will never complete. Any way to make this work as intended?
Code:
while (self.i <= NUM_TO_CHECK-2):
			self.answer = gmpy2.f_mod(((self.testnum*self.testnum)-2), self.num)
			self.testnum = self.answer
			self.i += 1
			time.sleep(1) #IF I DO THIS, BOTH THREADS WORK FINE.
 
Old 12-30-2016, 05:01 PM   #3
CincinnatiKid
Member
 
Registered: Jul 2010
Posts: 454

Original Poster
Rep: Reputation: 47
I read all about locking, I think that is my issue. Below is using RLock in both of my threads. For small numbers that I am checking it appears that using the RLock works as desired. When I calculate big numbers, t_progress only runs once every 10 seconds at most, even though I only sleep 1 second between each loop. I have tried threading.Lock(), threading.RLock(), threading.Semaphore(), and so far RLock() seems the closest, it just still isn't giving the desired result though.

Code:
import gmpy2
import threading
import time

NUM_TO_CHECK = 86243

class Primes:
	def __init__(self, n):
		self.num = n
		self.i = gmpy2.mpz(1)
		self.testnum = gmpy2.mpz(4)
		self.answer = gmpy2.mpz(0)
		
		self.progress = {'running': 1, 'isprime': 0, 'i': 1}
		self.lock = threading.RLock()

	def lucaslehmer(self):
		while (self.i <= NUM_TO_CHECK-2):
			self.lock.acquire()
			self.answer = gmpy2.f_mod(((self.testnum*self.testnum)-2), self.num)
			self.testnum = self.answer
			self.i += 1
			self.lock.release()
		
		if (self.answer == 0):
			self.progress['isprime'] = 2
		else:
			self.progress['isprime'] = 1
		self.progress['running'] = 0

	def getprogress(self, cont, delay):
		if cont:
			while self.progress['running']:
				self.lock.acquire()
				self.progress['i'] = self.i
				print(self.progress)
				self.lock.release()
				time.sleep(delay)
		print(self.progress)

if __name__ == "__main__":
	primecandidate = gmpy2.mpz(pow(2, NUM_TO_CHECK)-1)
	wwprime = Primes(primecandidate)
	t_progress = threading.Thread(target=wwprime.getprogress, args=(1,1))
	t_progress.start()
	t_run = threading.Thread(target=wwprime.lucaslehmer)
	t_run.start()
 
Old 12-30-2016, 11:18 PM   #4
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
You should minimize the amount time spent holding the lock. In this case, the only shared resource are the variables self.progress and self.i, so only hold the lock while reading and writing them.

Currently your lucaslehmer thread is hold the lock almost all of the time, including while it's doing the main f_mod calculation, which is why your other thread has a hard time obtaining the lock.
 
1 members found this post helpful.
Old 12-31-2016, 10:55 AM   #5
CincinnatiKid
Member
 
Registered: Jul 2010
Posts: 454

Original Poster
Rep: Reputation: 47
Quote:
Originally Posted by ntubski View Post
You should minimize the amount time spent holding the lock. In this case, the only shared resource are the variables self.progress and self.i, so only hold the lock while reading and writing them.

Currently your lucaslehmer thread is hold the lock almost all of the time, including while it's doing the main f_mod calculation, which is why your other thread has a hard time obtaining the lock.
It is running a lot better locking when only using the shared resources. It is still a little glitchy as far as not necessarily running t_progress every second, but it is close enough that I am not worried about it. Thanks for your help!
 
Old 01-02-2017, 09:04 AM   #6
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,659
Blog Entries: 4

Rep: Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940Reputation: 3940
In any language, every piece of code that is accessing a shared resource must "obtain a 'covering lock'" that will serialize access to that resource, before manipulating that resource. Then, it must release that lock as soon as possible thereafter.

Since the process of acquiring and releasing locks is expensive, even if no blocking occurs, you should be prudent in arranging your scheme so that the number of lock/unlock cycles is, within reason, minimized.

"Progress displays" are also very expensive. It is usually a good idea to maintain simple counters in the "worker" threads which can be periodically examined by a separate, timed thread which generates the progress displays. (And, generally, that thread can just retrieve the current counter-values without bothering with a lock on those values: any value obtained will be "close enough.")

Finally: threading will not speed up a CPU-bound activity, except to the extent that it might leverage "multiple cores" and then only if the implementation actually does so.

Last edited by sundialsvcs; 01-02-2017 at 09:06 AM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
python program,random crashes,threading jabfinger Programming 4 01-27-2010 01:15 PM
No preformance gain with Threading in Python gothicbob Programming 4 04-14-2009 02:54 PM
python threading - IM app vargadanis Programming 9 03-02-2007 09:11 AM
Python threading? Kedelfor Programming 2 10-25-2005 02:35 PM
Deadlock, cdrecord/cdrdao, SCSI emu issue? clip Linux - General 1 10-17-2003 08:17 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:17 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration