Tuesday, March 17, 2009

perly pie

Thats right, perl "-p -i -e"!

This command is your friend for replacing strings in a batch of documents at once. As I am not a frequent perl user I tend to forget the order syntax for specifying search/replace, but know the rough format contains a "/s" a "/" and a "/g". I tend to try out a quick command line version trial with stdin before going to the full replace. Today I did the test with

perl -p -i -e 's/goodbye/hello/g'

As it worked first try, I then accidentally used the above command in my "find" expression to do my desired replace (e.g., "find ./ perl -p -i -e 's/hello/goodbye/g' {} \;" ). I totally wasn't thinking, as I really wanted to replace occurences of an old host name in the ".svn/entries" files with a new one. Unfortunately, there were actually occurrences of hello in some binary files (I guess I had blender files with objects called hello). Blender then opened these screwed up files without error but containing no objects (the change in length must have 'effed the offsets in the binary). Luckily these were the only files affected and it was easy enough to change. In the future I'll have to make sure to replace the above command with the appropriate search/replace string and a "-name" to find.

OOps.

wxWidgets documentation

Last week I was porting a wxWidget application to the Mac, which shouldn't be all that painful, but I was having trouble with the application opening command line arguments.

Being one of the first GUI programs that used the command line for loading files, I didn't realize that the command arguments (e.g, "open -a myapp.app anargument", don't get passed in through argv/argc). After doing some digging, I turned up a reference for MacOpenFile in the wxPython port. I looked at the current versions documentation (wx 2.8.x) to see if this was something available in the c++ libraries as well. Didn't appear to be on their page (and doesn't come up if you search the site for MacOpenFile). WTF wxDocs?

Anyway, MacOpenFile does exist but just doesn't appear to be documented (in the common docs that is). It is really too bad because I suspect that most people would check wxApp first for alternatives methods to access command line arguments. Instead, you end up wasting time scouring the web for others with similar problems.

I meant to post this right after I had found the solution so I could tag the blog with all the things I had searched for. Unfortunately, I waited more than a week and no longer remember what I had searched.

Friday, March 6, 2009

float cast underflow slow

Today I noticed that some of code that just blended some images was being really slow dependent on some of the coefficients used in the blending. After checking the coefficients for strange values (nans/infs), for which there were none, it was still slow. The problem was only appearing in one function used for blending (some integer code that used floating coefficients that were casted from doubles). The problem didn't appear when strictly using floating point arithmetic. Turns out it is due to slow casting from double to float when there is underflow.

Some timing results for casting from double to double (d), double to float (f), double to integer (i), for test program, included below:

Without optimization
time for d (init=1e-30) 0.013476
time for f (init=1e-30) 0.012164
time for i (init=1e-30) 0.016217
time for d (init=1e-50) 0.019088
time for f (init=1e-50) 0.229608
time for i (init=1e-50) 0.019010

Without optimization (-O3)
time for d (init=1e-30) 0.005358
time for f (init=1e-30) 0.004038
time for i (init=1e-30) 0.003713
time for d (init=1e-50) 0.004566
time for f (init=1e-50) 0.135538
time for i (init=1e-50) 0.003527

You can see the floating point cast is something like 30x slower for the value of 1e-50 (where there is underflow) as opposed to the case of 1e-30 where there is no underflow.

Try the code for yourself.


#!/bin/sh

cat <<EOF > _f_.cc
#include
#include
#include
#include
#include

template
void test(int m, double init){
double * v = new double[m];
T * f = new T[m];
struct timeval tv;
gettimeofday(&tv, 0);

for(int its=0; its< 20; its++){
v[0] = init;
double * vptr = v;
for(int i=0; i< m; i++){
*(vptr++) = v[0];
f[i] = ((T)v[i]);
}
}
struct timeval tva, el;
gettimeofday(&tva, 0);
timersub(&tva, &tv, &el);
printf("time for %s (init=%g) %lf\n", typeid(T).name(), init, double(el.tv_sec) + double(el.tv_usec)/1e6);
delete [] f;
delete [] v;
}

int main(int ac, char * av[]){
int m = 100000;

test(m, 1e-30);
test(m, 1e-30);
test(m, 1e-30);

test(m, 1e-50);
test(m, 1e-50);
test(m, 1e-50);
return 0;
}
EOF

echo "Without optimization"
g++ _f_.cc -lm -o _f_
./_f_

echo "Without optimization (-O)"
g++ _f_.cc -lm -o _f_ -O
./_f_

echo "Without optimization (-O3)"
g++ _f_.cc -lm -o _f_ -O3
./_f_

echo "Without optimization (-O3)"
g++ _f_.cc -lm -o _f_ -O3 -mmmx -msse
./_f_

rm _f_.cc _f_