Ch14 Speed
Ch14 Speed
Machine Language:
05 01 255 255
10 01 13
20 127 255
122 63 255
Devices are also just memory
A computer can interact with external devices (like
displays, microphones, and speakers) in lots of ways.
Easiest way to understand it (and is often the actual
way it’s implemented) is to think about external
devices as corresponding to a memory location.
Store a 255 into location 65,542, and suddenly the red component of the
pixel at 101,345 on your screen is set to maximum intensity.
Everytime the computer reads location 897,784, it’s a new sample just read
from the microphone.
So the simple loads and stores handle multimedia,
too.
Machine language is executed very quickly
Imagine a relatively slow computer today (not latest
generation) having a clock rate of 1.5 Gigahertz.
What that means exactly is hard to explain,
but let’s interpret it as processing 1.5 billion bytes per
second.
Those 12 bytes would execute inside the computer,
then, in 12/1,500,000,000th of a second!
Applications are typically compiled
Applications like Adobe Photoshop and Microsoft
Word are compiled.
This means that they execute in the computer as pure
machine language.
They execute at that level speed.
However, Python, Java, Scheme, and many other
languages are (in many cases) interpreted.
They execute at a slower speed.
Why? It’s the difference between translating
instructions and directly executing instructions.
An example
Consider this problem from the book:
Write a function doGraphics that will take a list as input. The function
doGraphics will start by creating a canvas from the 640x480.jpg file in the
mediasources folder. You will draw on the canvas according to the commands
in the input list.
Each element of the list will be a string. There will be two kinds of strings in
the list:
"b 200 120" means to draw a black dot at x position 200 y position 120. The
numbers, of course, will change, but the command will always be a "b". You
can assume that the input numbers will always have three digits.
"l 000 010 100 200" means to draw a line from position (0,10) to position
(100,200)
So an input list might look like: ["b 100 200","b 101 200","b 102 200","l 102 200
102 300"] (but have any number of elements).
A sample solution This program processes each
def doGraphics(mylist):
canvas = makePicture(getMediaPath("640x480.jpg"))
string in the command list.
for i in mylist: If the first character is “b”,
if i[0] == "b":
x = int(i[2:5])
then the x and y are pulled
y = int(i[6:9]) out, and a pixel is set to black.
print "Drawing pixel at ",x,":",y
setColor(getPixel(canvas, x,y),black)
If the first character is “l”, then
if i[0] =="l": the two coordinates are pulled
x1 = int(i[2:5]) out, and the line is drawn.
y1 = int(i[6:9])
x2 = int(i[10:13])
y2 = int(i[14:17])
print "Drawing line at",x1,y1,x2,y2
addLine(canvas, x1, y1, x2, y2)
return canvas
Running doGraphics()
>>> canvas=doGraphics(["b 100
200","b 101 200","b 102 200","l
102 200 102 300","l 102 300
200 300"])
Drawing pixel at 100 : 200
Drawing pixel at 101 : 200
Drawing pixel at 102 : 200
Drawing line at 102 200 102 300
Drawing line at 102 300 200 300
>>> show(canvas)
We’ve invented a new
language
["b 100 200","b 101 200","b 102 200","l 102 200 102
300","l 102 300 200 300"] is a program in a new
graphics programming language.
Postscript, PDF, Flash, and AutoCAD are not too
dissimilar from this.
There’s a language that, when interpreted, “draws” the
page, or the Flash animation, or the CAD drawing.
But it’s a slow language!
Would this run faster?
def doGraphics():
canvas = makePicture(getMediaPath("640x480.jpg"))
setColor(getPixel(canvas, 100,200),black)
setColor(getPixel(canvas, 101,200),black)
setColor(getPixel(canvas, 102,200),black)
addLine(canvas, 102,200,102,300)
addLine(canvas, 102,300,200,300)
show(canvas)
return canvas
Does the exact same thing
>>> doGraphics()
Which do you think will run faster?
def doGraphics(mylist): def doGraphics():
canvas = canvas = makePicture(getMediaPath("640x480.jpg"))
makePicture(getMediaPath("640x480.jpg") setColor(getPixel(canvas, 100,200),black)
) setColor(getPixel(canvas, 101,200),black)
for i in mylist: setColor(getPixel(canvas, 102,200),black)
if i[0] == "b": addLine(canvas, 102,200,102,300)
x = int(i[2:5]) addLine(canvas, 102,300,200,300)
y = int(i[6:9]) show(canvas)
print "Drawing pixel at ",x,":",y return canvas
setColor(getPixel(canvas, x,y),black)
if i[0] =="l":
x1 = int(i[2:5]) One just draws the picture.
y1 = int(i[6:9])
x2 = int(i[10:13]) The other one figures out (interprets)
y2 = int(i[14:17]) the picture, then draws it.
print "Drawing line at",x1,y1,x2,y2
addLine(canvas, x1, y1, x2, y2)
return canvas
Could we generate that second program?
What if we could write a function that:
Takes as input ["b 100 200","b 101 200","b 102 200","l 102
200 102 300","l 102 300 200 300"]
Writes a file that is the Python version of that program.
def doGraphics():
canvas = makePicture(getMediaPath("640x480.jpg"))
setColor(getPixel(canvas, 100,200),black)
setColor(getPixel(canvas, 101,200),black)
setColor(getPixel(canvas, 102,200),black)
addLine(canvas, 102,200,102,300)
addLine(canvas, 102,300,200,300)
show(canvas)
return canvas
Introducing a
def makeGraphics(mylist):
file = open("graphics.py","wt")
file.write('def doGraphics():\n')
compiler
file.write(' canvas = makePicture(getMediaPath("640x480.jpg"))\n');
for i in mylist:
if i[0] == "b":
x = int(i[2:5])
y = int(i[6:9])
print "Drawing pixel at ",x,":",y
file.write(' setColor(getPixel(canvas, '+str(x)+','+str(y)+'),black)\n')
if i[0] =="l":
x1 = int(i[2:5])
y1 = int(i[6:9])
x2 = int(i[10:13])
y2 = int(i[14:17])
print "Drawing line at",x1,y1,x2,y2
file.write(' addLine(canvas, '+str(x1)+','+str(y1)+','+ str(x2)+','+str(y2)+')\n')
file.write(' show(canvas)\n')
file.write(' return canvas\n')
file.close()
Why do we write programs?
One reason we write programs is to be able to do the
same thing over-and-over again, without having to
rehash the same steps in Photoshop each time.
Which one leads to shorter time overall?
Interpreted version:
10 times
doGraphics(["b 100 200","b 101 200","b 102 200","l 102 200 102
300","l 102 300 200 300"]) involving interpretation and drawing
each time.
Compiled version
1 time makeGraphics(["b 100 200","b 101 200","b 102 200","l 102 200 102
300","l 102 300 200 300"])
Takes as much time (or more) as intepreting.
But only once
10 times running the very small graphics program.
Applications are compiled
Applications like Photoshop and Word are written in
languages like C or C++
These languages are then compiled down to machine
language.
That stuff that executes at a rate of 1.5 billion bytes per
second.
Jython programs are interpreted.
Actually, they’re interpreted twice!
Java programs typically don’t compile to machine
language.
Recall that every processor has its own machine
language.
How, then, can you create a program that runs on any
computer?
The people who invented Java also invented a make-
believe processor—a virtual machine.
It doesn’t exist anywhere.
Java compiles to run on the virtual machine
The Java Virtual Machine (JVM)
What good is it to run only on a computer that
doesn’t exist?!?
Machine language is a very simple language.
A program that interprets the machine language of
some computer is not hard to write.
def VMinterpret(program):
for instruction in program:
if instruction == 1: #It's a load
...
if instruction == 2: #It's an add
...
Java runs on everything…
Everything that has a JVM on it!
Each computer that can execute Java has an
interpreter for the Java machine language.
That interpreter is usually compiled to machine
language, so it’s very fast.
Interpreting Java machine is pretty easy
Takes only a small program
Devices as small as wristwatches can run Java VM
interpreters.
What happens when you execute a Python
statement in JES
Your statement (like “show(canvas)”) is first compiled
to Java!
Really! You’re actually running Java, even though you wrote Python!
The code to increase the red will execute it’s body (the
length)*(the height) times.
That means that the body is executed O(l*h) times
That explains why smaller pictures take less time to process than
larger ones.
You’re processing fewer pixels in a smaller picture.
But how do we compare the two programs?
We would still call this O(n) because we address each pixel only once.
How about movie code?
def slowsunset(directory): def makeSunset(picture):
canvas = for x in range(1,getWidth(picture)):
makePicture(getMediaPath("beach- for y in range(1,getLength(picture)):
smaller.jpg")) #outside the loop!
p = getPixel(picture,x,y)
for frame in range(0,100): #99 frames
value=getBlue(p)
printNow("Frame number: "+str(frame))
setBlue(p,value*0.99) #Just 1% decrease!
makeSunset(canvas)
value=getGreen(p)
# Now, write out the frame
setGreen(p,value*0.99)
writeFrame(frame,directory,canvas)
More efficient:
Best case: It’s there first place you look.
Average and worst case: log n steps
Implementing a binary search
def findInSortedList(something , alist ):
start = 0
While there’s anymore
end = len(alist) - 1 pages to search…
while start <= end: #While there are more to search
checkpoint = int(( start+end )/2.0)
if alist[checkpoint ]== something:
return "Found it!"
if alist[checkpoint]<something:
start=checkpoint +1
if alist[checkpoint]>something:
end=checkpoint -1
return "Not found"
printNow("Checking at: "+str(checkpoint )+"
Start:"+str(start )+" End:"+str(end))
Running the
>>> findInSortedList("giraffe" ,["apple","bear","cat",
"dog"])
Checking at: 1 Start :0 End:3
Checking at: 2 Start :2 End:3
Checking at: 3 Start :3 End:3 binary search
’Not found ’
>>> findInSortedList("apple" ,["apple","bear","cat",
"dog"])
Checking at: 1 Start :0 End:3
Checking at: 0 Start :0 End:0
’Found it!’
>>> findInSortedList("dog" ,["apple","bear","cat",
"dog"])
Checking at: 1 Start :0 End:3
Checking at: 2 Start :2 End:3
Checking at: 3 Start :3 End:3
’Found it!’
>>> findInSortedList("bear" ,["apple","bear","cat",
"dog"])
Checking at: 1 Start :0 End:3
’Found it!’
Thought Experiment:
Optimize your song
You’re writing a song that will be entirely generated
by computer by assembling portions of other sounds.
Splicing one onto the end of the other.