Skip to main content

Sponsors

Programming

My Reversi is Memory Leak Free: Certified by Valgrind

When we write programs, we spend lots of time in managing memory. Improper memory management can lead to memory leak, therefore reserving memory that will never be used. Memory leak problems can be serious especially when an application needs to run for a long time. No matter how much memory you have, regular memory leaks can make you run out of memory eventually.

I run "valgrind" to check if my Reversi in C++ has memory leak problems.

$ time valgrind --tool=memcheck ./reversi
==4305== Memcheck, a memory error detector.
==4305== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al.
==4305== Using LibVEX rev 1658, a library for dynamic binary translation.
==4305== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.
==4305== Using valgrind-3.2.1, a dynamic binary instrumentation framework.
==4305== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.
==4305== For more details, rerun with: -v
==4305==

(0,0): 9999990
7 1 1 1 1 1 1 1 1
6 1 1 0 0 0 0 1 1
5 1 1 1 0 1 1 0 1
4 1 1 0 1 1 0 0 1
3 1 1 0 0 1 1 0 1
2 1 0 1 0 0 1 0 1
1 1 1 0 0 0 0 1 1
0 1 1 1 1 1 1 1 1
  0 1 2 3 4 5 6 7

White: 44 Black: 20
Recursive evaluate: 53671516
Recursive end eval: 135214583
Evaluation: 44228633

==4305==
==4305== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 1)
==4305== malloc/free: in use at exit: 0 bytes in 0 blocks.
==4305== malloc/free: 289,208,130 allocs, 289,208,130 frees, 6,940,995,120 bytes allocated.
==4305== For counts of detected errors, rerun with: -v
==4305== All heap blocks were freed -- no leaks are possible.

real    142m53.138s
user    139m9.606s
sys     0m37.606s

Hooray!!! But a 3min run becomes 2+hours run. Can it be faster?

FPGA Optimization

Posted in

C-level Optimization such as in Impulse C

  1. Limit the amount of hardware resources used by introducing loops.
  2. Split arrays for multiple storage accesses. Storage for each array can be constructed to stream directly into local computation unit, i.e. parallel local memory accesses. Note that register bank can be read by many sources in the same cycle. Thus, small & hot data should go into register.
  3. Improve communication performance by fully utilizing the CPU-FPGA bus width. Transfer more bits at a time matching the CPU-FPGA bus width. DMA is another feasible mechanism for communication. But it will hog the bus if you do it too frequently.
  4. Loop unrolling to realize higher parallelism using more gates in FPGA.
  5. Pipelining in main loop to close the communication gaps of different iterations due to data loading & flushing.

Reference: Optimizing Impulse C Code for Performance by Scott Thibault & David Pellerin.

Logic-level Optimization in Boolean Network model

  • Restructuring operations.
    • Reduce dependent inputs.
    • Factorize.
    • Substitute.
    • Eliminate.
  • Node minimization.
    • Minimize using dont-care inputs.
    • ...

Lex & Yacc

Posted in
lex-exp1.l:
%{
/* C code section */
#include <stdio.h>
#include "y.tab.h"    /* Include tokens generated by Yacc */
%}

num     [0-9]+

%%
{num}   { printf("Number: %s\t token: %d\n", yytext, NUMBER) ;
          return NUMBER ;
        }

[a-z]+  { printf("Text: ") ;
          ECHO ; /* Macro to print the current matching text. */
          printf("\n") ;
          return TEXT ;
        }
\n      return '\n' ;
.       ;
%%

/* A routine that will be called at end of file reading. */
int yywrap()
{       /* return 1: No more input files.
           return 0: More input files. */
        return 1 ;
}

Ruby

# A function.
=begin
Multi-line comment.
But =begin and =end must be at the beginning of the lines.
=end
def work(name = "yman")
        result = "name: " + name
        return result
end
puts work("xman")
print "hello world\n"
printf "hello world %d\n", 100
# Output:
name: xman
hello world
hello world 100

name = gets()
puts "hello world, #{name}"
puts "hello world, #{(1+2)*3}"
# Output:
hello world, xman
hello world, 9

# Iterators.
a = [1,2,5,6]
a.each do |i|
        puts i*2
end
# Output:
2
4
10
12

Programming

Posted in

All computer scientists and engineers study programming. I'm of no exception. This book page collects all my little programming experiments.

Running Dual-Core using Makefile

Posted in

Problem: Given a set of .mp3 files. I like to convert these files into .ogg files. In addition, I like the processing takes advantage of the dual-core processor, i.e. two simultaneous processing at a time.

Solution:

Make (Make is a Unix utility widely used to manage program compilations. It is used to compile only updated source files to create target files. Hence, the overall compilation time can be reduced significantly, especially during software development) provides some concurrency facility, that it allows multiple targets to be created simultaneously.

Makefile:

.SUFFIXES:
.SUFFIXES: .mp3 .ogg

all: $T

.mp3.ogg:
        echo "Encoding: $<"
        lame --decode $< ${<:.mp3=.wav}
        oggenc ${<:.mp3=.wav}

Now, with the .mp3 files in the current directory, assign the .ogg files to be created in environment variable T.

$ T=
$ for i in *.mp3; do T="$T ${i%.*}.ogg"; done

Then, run "make" with certain number of simultaneous creations say 2.

$ make -j 2 T=$T

In overall, for each .ogg found in T, "make" will try to create its .wav then the .ogg from a .mp3 file. COOL ;)

Using BASH to print/manipulate all files in a directory

Posted in

There are two files in my tmp directory.

xman@sai tmp $ ls
file1.txt file version 2.txt

You are probably familiar with simple for-loop in BASH script. But, see the following:

xman@sai tmp $ for i in `ls`
> do
> echo $i
> done
file1.txt
file
version
2.txt
xman@sai tmp $

Opssss, it doesnt print out each of the file names properly when there is space characters in the file names. The file names will be broken when there are spaces. Instead, you probably want to do the following:

xman@sai tmp $ export IFS=$'\n'
xman@sai tmp $ for i in `ls`
> do
> echo $i
> done
file1.txt
file version 2.txt
xman@sai tmp $

So now you can manipulate each of the files in a directory properly.

Python

If you can learn a language by example, this is a place for you to learn the core of python programming. However, some statements are mis-indented. But indentation should not be a problem to you if you are familiar with structured programming.

# Getting started.
>>> print "hello world"
hello world

xman@sai python $ cat hello.py
#!/usr/bin/python
# hello world comment
print "hello world"

>>> execfile("hello.py")
hello world

>>> import sys
>>> sys.exit()
xman@sai python $

>>> while x <= y:
... print x,y
... x=x+1
>>> x = 0 ; y = 1 ; z = 2
>>> print "%4d %0.2f" % (x,y)
100 5.00

# Conditional.
>>> if x < z =" x"> y:
... z = y
... elif x == y:
... pass
... else:
... raise RuntimeError, "Unknown"
...

# Keywords: and assert break class continue def del elif else except exec finally for from global
if import in is lambda not or pass print raise return try while
# Operators: + - * ** / % << >> < > <= >= == != <> & | ^ ~ not and or

# File.
>>> f = open("hello.py")
>>> line = f.readline()
>>> while line:
... print line
... line = f.readline()
...
>>> f.close()

# File methods
f.read([n])
f.readline()
f.readlines()
f.write(s) # Write string s.
f.writelines(l) # Write all strings in list l.
f.close()
f.tell()
f.seek(offset [,where])
f.isatty()
f.flush()
f.truncate([size])
f.fileno()
f.readinto(buffer, nbytes)

# String & Char
>>> a = "hello world"
>>> print a[4]
o
>>> a = 'hello world'
>>> b = "hello world"
>>> c = """hello world"""
>>> d = """hello
... world
... """

>>> print d
hello
world

# Slice
>>> x = a[0:5]
>>> y = a[1:]
>>> z = a[:4]

# String
>>> a = "hello" ; b = "world"
>>> c = a + b ; print c
helloworld

# List
>>> data = ["a", "b", "c"]
>>> data.append("d")
>>> data = data + ['e','f']

# Reference count
>>> a = [1,3,5]
>>> b = a
>>> a, b
([1, 3, 5], [1, 3, 5])
>>> b[1] = 100
>>> a, b
([1, 100, 5], [1, 100, 5])

# Nested list.
>>> data = ['a' , ['b','c' ]]
>>> print data[1][1]
c

# Map.
>>> import string
>>> import sys
>>> f = open("data.dat")
>>> svalues = f.readlines()
>>> f.close()
>>> fvalues = map(string.atof, svalues)
>>> print svalues
['0.1\n', '0.4\n', '0.2\n', '0.3\n', '0.24\n']
>>> print fvalues
[0.10000000000000001, 0.40000000000000002, 0.20000000000000001, 0.29999999999999999, 0.2399999999
9999999]
>>> print min(fvalues)
0.1
>>> print max(fvalues)
0.4

# Tuple (Create once, no modifications allowed)
>>> a = (1,3)
>>> b = (2,4)
>>> c = (4,)
>>> print a,b,c
(1, 3) (2, 4) (4,)
>>> print a[0], a[1]

# Range.
>>> print range(3)
[0, 1, 2]
>>> print range(1,10)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> print range(1,10,2)
[1, 3, 5, 7, 9]
>>> for i in range(1,10,2):
... print i
...
1
3
5
7
9
a = xrange(0,10000000) # Recompute to save memory.

# Dictionary (associative array).
>>> a = {
... "a" : "va" ,
... "b" : "vb"
... }
>>> print a["a"], a["b"]
>>> a.keys()
>>> a.has_key("a")
>>> del a["a"]

# Function. Local scope by default.
>>> def swap(a,b,c=0):
... "SWAP: Documentation string"
... global msg
... if c != 0 : print msg
... return (b,a)
...
>>> a,b=swap(a,b)
>>> a,b=swap(a,b,1)

# Variable-length argument, keyword argument.
# args: Additional variables in a tuple.
# kw: Additional keyword arguments in a table.
>>> def func(x, *args, **kw):

# Class.
# def: Define a method.
# First argument of a method: the object.
>>> class stack:
... "Stack data structure"
... name = "Stack"
... def __init__(self):
... self.stack = []
... def push(self,object):
... "Append object to the end"
... self.stack.append(object)
... def pop(self):
... "Remove an object from the end and return it"
... return self.stack.pop()
... def length(self):
... "Number of objects in stack"
... return len(self.stack)
>>> s = stack()
>>> s.push("data1")
>>> s.push("data2")
>>> x = s.pop()

# Inheritance.
>>> class C(A,B):
# Encapsulation.
>>> class C:
... __x = 500

# Class relationship
>>> isinstance(c,C)
>>> issubclass(C,A)

# Exception.
>>> try:
... f = open("data.txt")
... except IOError, e:
... print "My error:" , e
...
My error: [Errno 2] No such file or directory: 'data.txt'

# Module.
# Import the module hello.py.
>>> import hello
>>> import string
>>> dir(string) # List contents of module string.

# Syntax.
# Multi-line.
>>> c = a + \
... b

# Consistent indentation.
# Codes in the same block must uses the same indentation.

# Documentation strings.
>>> def func(n):
... "Documentation string"
... return n

# Type & ID
>>> type(a)

>>> id(a)
5280552
>>> a is b
>>> a is not b
>>> type(a) == type(b)

# Copy.
>>> import copy
>>> b = [1,2,3]
>>> a = copy.deepcopy(b)

# List:
list(s)
s.append(x)
s.extend(x)
s.count(x)
s.index(x)
s.insert(i,x)
s.pop([i])
s.remove(x)
s.reverse()
s.sort([cmpfunc])

# Mapping types:
len(m)
m[k]
del m[k]
m.clear()
m.copy()
m.has_key(k)
m.items()
m.keys()
m.update(b)
m.values()
m.get(k,[,f]) # Return m[k] if found; otherwise return f.

# Unbound method object, bound method object.
# C is a class, c is an instance of class C.
>>> c.work()
hello world
>>> C.work(c)
hello world

# Functional programming
>>> a = lambda x,y : x+y
>>> print a(2,5)

# map(), reduce(), filter().
# Apply func to elements in s.
>>> t = map(func,s)
# Reduce a using sum function.
>>> b = reduce(sum, a)
# Filter objects which satisfy the conditions.
>>> b = filter(lambda x: x < style="font-weight: bold;"># Execution.
# eval(str, [,globals [,locals]])
>>> c = eval('a+b')
>>> exec "print 4+3"
# execfile(filename [,globals [,locals]])
>>> execfile("hello.py")
# compile(str,filename,kind)
>>> c = compile(str, '', 'single')
>>> c = compile(str, '', 'exec')
>>> c = compile(str, '', 'eval')

# Input, Output
>>> s = raw_input("type something")
>>> c = sys.stdin.read(1)
>>> sys.stdout = open("output.txt", "w")

# Serialize
>>> f = open("save.dat", "w")
>>> pickle.dump(a,f)
>>> pickle.dump(b,f)
>>> f.close()
>>> f = open("save.dat", "r")
>>> obj = pickle.load(f)
>>> obj
2

# Built-in Functions
abs(x)
apply(func [,args [,keywords]])
buffer(object [,offset [,size]])
callable(obj)
chr(i)
cmp(x,y)
coerce(x,y)
compile(string, filename, kind)
complex(real [,img])
delattr(obj, attr)
dir([obj])
divmod(a,b)
eval(expr [, globals [,locals]])
execfile(filename [,globals [,locals]])
filter(function, list)
float(x)
getattr(obj,name)
globals()
hasattr(obj,name)
hash(obj)
hex(x)
id(obj)
input([prompt])
intern(string)
isinstance(obj,class)
issubclass(subclass,class)
len(s)
list(s)
locals()
long(x)
map(function, list, ...)
max(s [,args, ...])
min(s [,args, ...])
oct(x)
open(fname [, mode [, bufsize]])
ord(c)
power(x, y, [,z])
range([start,] stop [,step])
raw_input([prompt])
reduce(func, seq [,initializer])
reload(module)
repr(obj)
round(x [,n])
setattr(obj, name, value)
slice([start,] stop [,step])
str(obj)
tuple(s)
type(obj)
vars([obj])
xrange([start,] stop [, step])

# Built-in Exceptions
Exception
StandardError
ArithmeticError
LookupError
EnvironmentError
AssertionError
AttributeError
EOFError
FloatingPointError
IOError
ImportError
IndexError
KeyError
KeyboardInterrupt
MemoryError
NameError
NotImplementedError
OSError
OverflowError
RuntimeError
SyntaxError
SystemError
SystemExit
TypeError
ValueError
ZeroDivisionError

# Internal.
>>> a = [1,4,6]
>>> a.__doc__
"list() -> new list\nlist(sequence) -> new list initialized from sequence's items"
>>> class C:
... a = 0
... def work(self):
... print("hello world")
...
>>> c = C()
>>> c.__dict__
{}
>>> C.__dict__
{'a': 0, '__module__': '__main__', 'work': , '__doc__': None}
# There are many other built-in attributes for classes, instances, modules ...

Reference: Python Essential Reference by David M. Beazley

Make

Inside Makefile:

TARGET: DEPENDENCY LINE OR RULES LINE
COMMAND
COMMAND
...

A command line (with TAB in front) is running in a subshell by itself.

Awk

By default, a record is a line. A line is made up of fields with default delimiter. Main programs are mainly based on C program syntax.

Syndicate content