Tuesday, January 24, 2012

CUDA ray tracing part 1


RTObject.h includes three basic classesRTObject, HitStructure, BBox. I combined Triangle and Sphere into one class--RTObject, based on the following considerations:
a. Sphere class has two basic properties (sphere center and radius), whereas, Triangle class has three points(points are float3 type, radius is float type)
b. In CUDA, it's not like C++ has complete class hierarchy, which means you can’t have a super class which does not contain anything and its two subclasses containing their own data. CUDA cannot figure out what the super class points to in running time. This is my supposition
c. In my RTObject there are four basic properties (three float3 data (points) and a float data(radius)). If a RTObject is a triangle, I ignore the radius, and if it's a sphere I ignore two points and let the left point be the sphere center. It may waste a lot of memory space for a scene full of many spheres, However I believe that a normal scene contains only a few spheres which may waste a little memory space three basic classes , whereas, triangles are the basic elements of meshes or complicated scenes, for the meshes, only radius data are useless(4 bytes), which is a kind of trade off between complexity design and a little overusing memory.

In Ray.h, I normalize every type of ray whenever created except the shadow ray. Each ray maintains its own tmin and tmax for the intersection test. tmax will be changed only if the intersection condition is satisfied, which is the criterion of intersection test.

In Mesh.h, technically it is supposed to have a pointer to a triangle list and a pointer to its BVH list. However on normal Nvidia devices, CUDA does not support deep copy (when you copy the data of Mesh class, it does not copy the data its data members(pointers) point to). Instead I use index tokens to mark the triangle list and BVH list. When you copy mesh lists, as well as the triangle lists and the BVH lists their tokens point to .

In BVH.h, building BVH is only based on the information of AABB (axis aligned bounding box) of all objects in the scene. I put the whole built BVH into BVH array .
a. Find the mid point of the current part of the BBoxes Array
b. Use spatial median cut
c. Store the start, median, and end position of the BBoxes Array,
let the start position be the start position of subarray1 (which still is inside of BBoxes Array), just as if it’s independent)
let the median position be the end position of subarray1
let the median position be thestart position of subarray2
let the end position be the end position of subarray2
d. goto a;

Tuesday, October 18, 2011

Boinc Server Ubuntu Install: How To

First off this was done on an install of Ubuntu 11.10

1) Create a user called boincadm and give it sudo access.

2) Install all the servers components
sudo apt-get install subversion build-essential apache2 php5 mysql-server php5-gd php5-cli php5-mysql python-mysqldb libtool automake autoconf pkg-config libmysql++-dev libssl-dev

3) Get the boinc server code and build it
svn co http://boinc.berkeley.edu/svn/branches/server_stable boinc
cd boinc; ./_autosetup; ./configure --disable-client; make


4) You should be in the boinc folder at this step, time to setup a project
cd tools
./make_project --url_base "DomainNameOfServer" --db_name "NameOfTheDatabaseYouWant" --db_user "root" --db_passwd "rootpassword" --drop_db_first NameOfProject NameOfProject@Home


5) The last step will ask you two questions answer y and press enter.

6) At the end of the project setup it will display something like
Done creating project. Please view
/var/tmp/boinc/boinctest/boinctest.readme
for important additional instructions.

Open up these instructions and follow them to the T. It will have you setup a cron job, and set the apache server config up. At the end it shows you how to stop, start and restart the server.

7) You now should be able to start actually creating and running a project. This is the step I am at and hopefully everything in the last few steps works out. I'll continue to edit and add to these pages so there is some sort of documentation.

Sources
http://www.spy-hill.net/~myers/help/boinc/Create_Project.html
http://w3.linux-magazine.com/issue/71/Distributed_Applications_With_BOINC.pdf
http://boinc.berkeley.edu/trac/wiki/ServerIntro
http://wiki.debian.org/BOINC/ServerGuide #Note sudo apt-get install boinc-server-maker does not work

Boost Timer

Boost Timer

If you have the boost library installed correctly on linux systems it should be sufficient to just add #include <boost/timer.hpp> or #include <boost/progress.hpp> depending on what you are looking for. There is a little more to it in a windows system, a quick google search on how to link library should point you in the right direction though.

So far I have just used the progress_timer. It is very nice in that as long as you create an instance of it upon your program completing it will print the execution time. You can also tell it to print the amount of time every so often and restart it, which is very useful in checking how long a certain function is taking to execute.

Here is a quick example of how I was using it.

progress_timer t;

start = t.elapsed();
correct = 0;
for(unsigned int i = 0; i < count; i++) { if (results[i] == data[i] * data[i]) { correct++; } } cout << "Second for loop took " << t.elapsed() - start << " seconds \n" << endl; cout << "Computed " << correct << "/" << count << " correct values" << endl; cout << "Computed " << 100.f * (float)correct/(float)count << "% correct values" << endl;


I imagine you can do something similar with the timer class.

Pretty Profiling Graphs in Linux


Profiling an application can be pretty useful. Visualizing it in a meaningful way can be even more helpful. Following the information in this post should get you on the right track to creating useful visualizations of your application like this:
So what does this actually give you?
  • A visual representation of how your application is executing
  • The percent of execution time spent in each function/method
  • Color coding for percentage of execution time
  • A function/method call count for each function/method in your application
Great, so what do you need?
  • gprof (or another compatible profiler) - This will generate the profile information about your application. Basically, this creates a record of everything your program does during an execution. Check if this is installed by running 'gprof' from a terminal.
  • You'll need some supported profiler output. Any of the gcc compilers should support this. For other compilers, check out this link to see if there is some compatibility. Read on to learn how to generate this output with a gcc compiler.
  • gprof2Dot.py script - This reads in the profile data created by gprof and a number of other profilers and creates a graph compatible with graphViz. This can be downloaded here.
  • GraphViz - GraphViz is a suite of tools for generating graphs. In particular, we need 'dot', which will take the output generated from gprof2Dot and create an image file. Check if this is installed by running 'dot' from a terminal.
Ok, so how do you use it?

There are 3 main steps to getting this to work:
  • Build your application with profiling support
  • Run your application
  • Run gprof, gprof2Dot, and dot on the profile output of your application
Building applications with profiling support is pretty strait-forward. For the gcc compilers, all that's needed is the compiler flag '-pg'. Lets say we have a file testApp.cpp which we want to compile with profiler support. Normally, we'd compile it like this:
  • g++ testApp.cpp -o testApp
To get profiling support, we just add the '-pg' flag like so:
  • g++ -pg testApp.cpp -o testApp
Assuming it compiles without errors, testApp should now support profiling. Note that for CMake and Makefiles, the '-pg' flag may need to be added to the linker commands as well.

Now that we've added profiling support to the application, we need to run it. Note that the profile output will reflect how the application was run, so if the application is interactive in some way, you'll likely want to run through a use-case that you find interesting.

In the case of our testApp, simply running ./testApp is all we need to do. You'll notice at this point that aside from any other output the application produces, it will also produce a file called gmon.out. This is the profiler information for the run of the application.

gmon.out is a mostly illegible file. We need gprof to interpret it. At this point, you could just use gprof and get some useful information. To do so, you would run the following command:
  • gprof [application name]
Where [application name] is the name of the executable you're running. In the case of testApp, we'd run the following command:
  • gprof testApp
This produces a large amount of information about the execution of your application. Everything you need to know is there, but it may be a bit complicated to interpret. That's where visualizing the information comes in.

To visualize the information like the graph above, we need to do some additional work with gprof2Dot and dot. Assuming gprof2Dot.py is in the directory of your application and graphViz is installed, you should be able to run something similar to the following command:
  • gprof testApp | ./gprof2dot.py -n 2.5 -e 2.5 -s | dot -Tpng -o output.png
This works by piping the output from gprof into gprof2Top. The output from that is then piped into dot. The end product (in this case) is a png file displaying the call structure of the application. Note that there are several settings here which can be configured:

  • -n 2.5 - this sets the minimum execution percentage for a graph node to show up in the graph. In this case, it means that any function that is not using 2.5% or more of the execution time is not displayed.
  • -e 2.5 - this is the same as the above, except for edges in the graph.
  • -s - this produces simple function names. Without it, the return type and parameter types will be displayed in the resulting graph. This makes for very verbose graph structures, so I've turned it off in the above case.
  • -Tpng - This specifies the output file format. dot supports a huge number of formats, so if PNG is not what you're looking for, there are many other options. Make sure to name your output file accordingly.
  • -o output.png - this is the output file that dot produces.

Hopefully that's enough to get you started!