1

I have this python code to generate prime numbers. I added a little piece of code (between # Start progress code and # End progress code) to display the progress of the operation but it slowed down the operation.

#!/usr/bin/python

a = input("Enter a number: ")
f = open('data.log', 'w')

for x in range (2, a):
  p = 1
  # Start progress code
  s = (float(x)/float(a))*100
  print '\rProcessing     ' + str(s) + '%',
  # End progress code
  for i in range(2, x-1):
    c = x % i
    if c == 0:
      p = 0
      break
  if p != 0:
    f.write(str(x) + ", ")

print '\rData written to \'data.log\'. Press Enter to exit...'

raw_input()

My question is how to show the progress of the operation without slowing down the actual code/loop. Thanks in advance ;-)

2
  • How much did it slow you down? I think that if you want to be technical about it, you cannot add operations without slowing something down, and printing to the screen tends to be costly. Commented Jun 13, 2014 at 21:16
  • github.com/rasbt/pyprind Commented Jun 14, 2014 at 0:17

3 Answers 3

1

To answer your question I/O is very expensive, and so printing out your progress will have a huge impact on performance. I would avoid printing if possible.

If you are concerned about speed, there is a very nice optimization you can use to greatly speed up your code.

For you inner for loop, instead of

  for i in range(2, x-1):
    c = x % i
    if c == 0:
      p = 0
      break

use

  for i in range(2, x-1**(1.0/2)):
    c = x % i
    if c == 0:
      p = 0
      break

You only need to iterate from the range of 2 to the square root of the number you are primality testing.

You can use this optimization to offset any performance loss from printing your progress.

Sign up to request clarification or add additional context in comments.

Comments

1

Your inner loop is O(n) time. If you're experiencing lag toward huge numbers then it's pretty normal. Also you're converting x and a into float while performing division; as they get bigger, it could slow down your process.

Comments

0

First, I hope this is a toy problem, because (on quick glance) it looks like the whole operation is O(n^2).

You probably want to put this at the top:

from __future__ import division # Make floating point division the default and enable the "//" integer division operator.

Typically for huge loops where each iteration is inexpensive, progress isn't output every iteration because it would take too long (as you say you are experiencing). Try outputting progress either a fixed number of times or with a fixed duration between outputs:

N_OUTPUTS = 100
OUTPUT_EVERY = (a-2) // 5
...
    # Start progress code
    if a % OUTPUT_EVERY == 0:
        print '\rProcessing     {}%'.format(x/a),
    # End progress code

Or if you want to go by time instead:

UPDATE_DT = 0.5
import time
t = time.time()
...
    # Start progress code
    if time.time() - t > UPDATE_DT:
        print '\rProcessing     {}%'.format(x/a),
        t = time.time()
    # End progress code

That's going to be a little more expensive, but will guarantee that even as the inner loop slows down, you won't be left in the dark for more than one iteration or 0.5 seconds, whichever takes longer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.