R on 64 bit and 32 bit (U of Minnesota Statistics)

University of Minnesota, Twin Cities     School of Statistics     Charlie's Home Page

Who This Page is For

This web page provides information about use of R on the computers in the School of Statistics, University of Minnesota.

Machines

As readers may or may not know, all of our linux workstations run the same version of linux (SuSE 9.3) but we have two kinds of hardware. The machines bought this year having the Frontier Systems brand are AMD Opteron dual-processor systems. We call them 64 bit for short because they have 64 bit C pointers. The machines bought in previous years having the General Nanosystems brand are AMD Athlon dual-processor (black case) or single-processor (white case) systems. We call them 32 bit for short because they have 32 bit C pointers.

You can always tell what kind of a machine you have (under linux) by doing

cat /proc/cpuinfo

which will give information about the number and types of processors in the machine.

A simpler way to distinguish machines with with the arch command.

oak$ arch
i686

is what you see on a 32 bit machine, and

zephyr$ arch
x86_64

is what you see on a 64 bit machine.

Programs

When you run programs that come with the SuSE linux installed on the machine, they just work.

Problems arise when you try to run a program compiled for one architecture on a different architecture. Your home directory and the directory in which R is installed are visible on all machines and can therefore contain code compiled on either architecture.

The 64 bit machines have a hardware 32 bit emulation mode. So binaries and libraries compiled on 32 bit machines work on all machines.

This does not work the other way around. Stuff compiled on 64 bit machines does not run on 32 bit machines.

R

As of 3 January 2006 we have two R binaries

/APPS/32/bin/R
/APPS/64/bin/R

If you are on 32 bit, then you automatically get the first when you just say R. If you are on 64 bit, then you automatically get the second when you just say R.

On 64 bit you can run the first, if you so desire, but you must invoke it using the full path name /APPS/32/bin/R. It will work in emulation mode.

If you never load your own C code into R with dyn.load(sharedlibraryname) and never use libraries other than those that those installed by the system administrators and you load with library(packagename), then you should have no problems. Just say R with no additional fuss to invoke R, and it will work.

Otherwise, you will have to be aware of

Everything must match except that you can run /APPS/32/bin/R on a 64 bit machine and load a library compiled on 32 bit.

Also, when compiling, everything must be compiled on one architecture. Remove all object files .o and .so before compiling. Any stuff compiled with the other architecture won't work!

Examples

32 Bit Working O. K.

The machine named oak is 32 bit. The code foo.c is found on the web page explaining Calling C and Fortran from R.

oak$ /APPS/32/bin/R CMD SHLIB foo.c
gcc -I/APPS/32/lib/R/include  -I/usr/local/include   -fPIC  -g -O2 -c foo.c -o foo.o
gcc -shared -L/usr/local/lib -o foo.so foo.o
oak$ /APPS/32/bin/R --vanilla --quiet
> dyn.load("foo.so")
> .C("foo", n=as.integer(5), x=as.double(rnorm(5)))
$n
[1] 5

$x
[1] 0.23809671 5.92472146 0.48857718 0.35638561 0.04285859

Compiled 32 Bit, Failing to Load on 64 Bit

The machine named zephyr is 64 bit. The shared library foo.so was compiled on 32 bit (in the preceding section).

zephyr$ /APPS/64/bin/R --vanilla --quiet
> dyn.load("foo.so")
Error in dyn.load(x, as.logical(local), as.logical(now)) :
        unable to load shared library '/HOME/faculty/charlie/tmp/moof/foo.so':
  /HOME/faculty/charlie/tmp/moof/foo.so: cannot open shared object file: No such file or directory

The error message is cryptic, but what happened is clear. It doesn't work.

Compiled 32 Bit, Working on 64 bit when 32 bit R Binary is Used

zephyr$ /APPS/32/bin/R --vanilla --quiet
> dyn.load("foo.so")
> .C("foo", n=as.integer(5), x=as.double(rnorm(5)))
$n
[1] 5

$x
[1] 0.06865342 0.09680243 0.01240681 0.71240126 0.48262325

Compiled 64 Bit, Working on 64 bit

zephyr$ rm *.o *.so
zephyr$ /APPS/64/bin/R CMD SHLIB foo.c
gcc -I/APPS/64/lib64/R/include  -I/usr/local/include   -fPIC  -g -O2 -c foo.c -o foo.o
gcc -shared -L/usr/local/lib64 -o foo.so foo.o
zephyr$ /APPS/64/bin/R --vanilla --quiet
> dyn.load("foo.so")
> .C("foo", n=as.integer(5), x=as.double(rnorm(5)))
$n
[1] 5

$x
[1] 0.006842728 0.010809147 0.226847601 0.829887253 0.974997980

> q()

It just works. But note well the rm *.o *.so. It wouldn't have worked without that.

Compiled 64 Bit, Failing to Load on 32 Bit

The machine named oak is 32 bit. The shared library foo.so was compiled on 64 bit (in the preceding section).

oak$ cd tmp/moof
oak$ /APPS/32/bin/R --vanilla --quiet
> dyn.load("foo.so")
Error in dyn.load(x, as.logical(local), as.logical(now)) :
        unable to load shared library '/HOME/faculty/charlie/tmp/moof/foo.so':
  /HOME/faculty/charlie/tmp/moof/foo.so: cannot open shared object file: No such file or directory
> q()

Again the error is cryptic. The file command will always tell you what you are dealing with.

oak$ file foo.so
foo.so: ELF 64-bit LSB shared object, AMD x86-64, version 1 (SYSV), not stripped

If you know that AMD x86-64 doesn't work on this (32 bit) architecture, then you know what's going on.

Summary

Of the five examples, two don't work.

You must be aware of (1) where you compiled (2) where you are, and (3) which R binary you are running to understand what happens.

Building and Checking R Packages

There is no problem building or checking an R package (with R CMD check) so long as

If you don't, R will give very uninformative error messages when R CMD check fails. The most informative part of the error message is where it tells you

* checking if this is a source package ... WARNING
Subdirectory 'packagename/src' contains object files.

When you fail to clean the src subdirectory before compiling on the other architecture, bad things happen.

* checking replacement functions ... WARNING
Error: .First.lib failed for 'bernor'
Call sequence:
2: stop(gettextf(".First.lib failed for '%s'", libraryPkgName(package)),
       domain = NA)
1: library(package, lib.loc = lib.loc, character.only = TRUE, verbose = FALSE)
Execution halted
In R, the argument of a replacement function which corresponds to the right
hand side must be named 'value'.
* checking foreign function calls ... WARNING
Error: .First.lib failed for 'bernor'
Call sequence:
2: stop(gettextf(".First.lib failed for '%s'", libraryPkgName(package)),
       domain = NA)
1: library(package, lib.loc = lib.loc, character.only = TRUE, verbose = FALSE)
Execution halted
See section 'System and foreign language interfaces' of the 'Writing R
Extensions' manual.

But what does all that mean? The error messages are totally uninformative. You must think. What version of R am I using? The unix command type R will tell you what binary will run if you type R. And what kind of binaries do I have in the src directory? The unix command file *.o *.so will tell you what they are.

Loading R Libraries You Compiled Yourself

You will need a separate install of each architecture (if you use both), and you will need some kind if trickery in your .bashrc that I haven't bothered to figure out yet to chose which one gets loaded.

Alternatively, you will have to use /APPS/32/bin/R on both architectures and always build on 32 bit.