Saturday, June 20, 2009

Error "identifier "__builtin_va_arg_pack" is undefined" when compiling CUDA

For some installations of CUDA on Ubuntu 8.10 and earlier one will get the error:
/usr/include/bits/stdio2.h(35): error: identifier "__builtin_va_arg_pack" is undefined

/usr/include/bits/stdio2.h(66): error: identifier "__builtin_va_arg_pack" is undefined

/usr/include/bits/stdio2.h(99): error: identifier "__builtin_va_arg_pack" is undefined

/usr/include/bits/stdio2.h(105): error: identifier "__builtin_va_arg_pack" is undefined

/usr/include/bits/stdio2.h(159): error: identifier "__builtin_va_arg_pack" is undefined

/usr/include/bits/stdio2.h(167): error: identifier "__builtin_va_arg_pack" is undefined

/usr/include/bits/stdio2.h(174): error: identifier "__builtin_va_arg_pack" is undefined

/usr/include/bits/stdio2.h(182): error: identifier "__builtin_va_arg_pack" is undefined

This apparently a problem with GCC 4.3. There seems to be several ways to fix this:

Upgrade to Ubuntu 9.04 Jaunty or newer. This should fix the problem.

add the following after line 28 of /usr/include/bits/stdio2.h:
int __builtin_va_arg_pack();

This should remove the above errors, but a new one might appear:
could not find -lXmu

To fix this, install libxmu-dev package:
sudo apt-get install libxmu-dev

Remove the -O3 flag from the COMMONFLAGS section of NVIDA_CUDA_SDK/common/ file and do not use the flag when compiling other code either.

However, this will disable optimization which can make CPU code much slower.

Downgrade to GCC 4.2 or 4.1:
sudo apt-get install gcc-4.2
sudo apt-get install g++-4.2

After installation:
sudo rm -d /usr/bin/gcc
sudo ln -s /usr/bin/gcc-4.2 /usr/bin/gcc

This way your system will keep the gcc-4.3 but use by default gcc-4.2.

If you need to go back to 4.3 :
sudo rm -d /usr/bin/gcc
sudo ln -s /usr/bin/gcc-4.3 /usr/bin/gcc

Solution source:

Thursday, June 11, 2009

Mounting remote folder using SSH in Ubuntu 9.04 Jaunty

To mount a directory, for example your home directoyr, from a different linux computer is easily done using SSHFS, SSH Filesystem.

First you need to make sure you can connect to the remote computer using ssh, the remote computer needs to be running sshd. Try connecting to it using the command below, if you are able to connect, you are running sshd:
ssh <your username on the remove computer>@<remote computer name or ip>

Next we need to install sshfs, ssh file system, on the local computer:
sudo apt-get install sshfs

Note: Make sure you use sudo since this will give you root/administrator rights, if you are not allowed to do this you need to be added to the admin group. Someone already a member must then write:
sudo adduser <your username> admin
Alternatively log in with a user that is a member of this group.

Fuse, Filesystem in Userspace, makes it possible for non-root users to handle filesystems, in this case let sshfs mount a remote directory. You need to make sure the fuse is loaded:
sudo modprobe fuse

Then you need to become part of the fuse group, the group of non-root users who are allowed to handle filesystems:
sudo adduser <your username> fuse

The following commands will set up permissions to access the fuse utilities:
sudo chown root:fuse /dev/fuse
sudo chmod +x /dev/fuse

Since you added yourself to a new group, you need to log out of Ubuntu for this to take effect. Do so now.

Now you can finally mount the remote folder. You will need a folder to mount the remote folder into:
mkdir <foldername>

Then all you need to do is tell sshfs to mount the remote folder:
sshfs <remote computer username>@<remote computer name or ip>:<path to folder on the remote computer> <folder on local computer>

That's it!

Now, to unmount the folder type the follwing:
fusermount -u <path to local folder>

Below is an example of what this could look like. Here the local user is "tom", the remote user is "fred" and the remote computer is "fredsComputer":

sudo apt-get install sshfs
sudo modprobe fuse
sudo adduser tom fuse
sudo chown root:fuse /dev/fuse
sudo chmod +x /dev/fuse
mkdir fredsHomeDirectory
sshfs fred@fredsComputer:/home/fred fredsHomeDirectory

To unmount:
fusermount -u fredsHomeDirectory

Solution found at:

Wednesday, June 10, 2009

You are not smart enough to debug this!

"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it."

--Brian Kernighan

Monday, June 8, 2009

CUDA errors propagate

Sometimes if a kernel or a cudaMemcpy fails it will take CUDA some time to recover, this often causes kernels or memcpys that follow the failing one to also fail, or at least not execute.

It is therefore important to always include error checking after of all CUDA calls (as mentioned before here: alternatively use CUDA Utility Library. Also if you get several failures in a row, fix the first error first, since the others might just be because of the first call failing.

To use cutil you need to include the cutil_inline.h file located in /NVIDIA_CUDA_SDK/common/inc in your home directory. After doing so, you can enclose all your communication with the CUDA device with different inline functions that will catch errors. The functions are:
cutilExit(argc, argv)

To use, simply do the following for a kernel:
kernelCall<<>>(d_Data, dataSize);
cutilCheckMsg("kernelCall failed");

Or for a memcpy:
cutilSafeCall( cudaMemcpy(h_Data, d_Data, dataSize, cudaMemcpyDeviceToHost) );

Note: The CUDA Utility Library is a "wrapper" that makes it easier to utilize functions such as __cudaSafeCall()