The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.

13 - Compiler Optimizations

1 Motivation

R uses default GCC/Clang compiler optimizations, which can limit the performance of C++ code.

2 User-wide Makevars

You can use the following Makevars example, which should be placed in ~/.R/Makevars, to set the optimization level to -O3 for all C++ code compiled by R and use additional flags to enable more aggressive optimizations that can be set at setup level but not package level (or CRAN will reject the package):

# Override R's optimization level
CXXFLAGS = -g -O3 -march=native
CXX11FLAGS = -g -O3 -march=native
CXX14FLAGS = -g -O3 -march=native
CXX17FLAGS = -g -O3 -march=native

# Additional optimizations
CXXFLAGS += -funroll-loops -ftree-vectorize -fprefetch-loop-arrays
CXXFLAGS += -fomit-frame-pointer -fstrict-aliasing

# Link-time optimization
CXXFLAGS += -flto=auto
LDFLAGS += -flto=auto

3 Anticonf scripts

The idea of an “anticonf” configure script is to provide a tailored Makevars file with the understanding that a package will be run on different systems. The anticonf name comes from the fact that it is not a standard configure script created with tools such as GNU Autoconf, but rather a templated script that generates a Makevars by detecting the system and compiler settings (e.g., number of cores, optimization flags, etc.).

The capybara package has the following Makevars.in file:

CXX_STD ?= CXX11 CXX14 CXX17
PKG_CXXFLAGS = -DARMA_NO_DEBUG -DARMA_USE_BLAS -DARMA_USE_LAPACK -DCAPYBARA_NCORES=@ncores@ $(SHLIB_OPENMP_CXXFLAGS) @SAFE_OPTFLAGS@
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)

This file serves as a template for the Makevars file. The configure script, which runs when the package is installed, replaces the @ncores@ and @SAFE_OPTFLAGS@ placeholders.

The Capybara package uses the following configure script:

# Anticonf script by Pacha (2025)

PKG_CONFIG_NAME="capybara"

# Get R configuration
CXX=$(${R_HOME}/bin/R CMD config CXX)
CXXFLAGS=$(${R_HOME}/bin/R CMD config CXXFLAGS)

# Function to test compiler flag
test_flag() {
  echo 'int main(){return 0;}' > conftest.cpp
  if $CXX $CXXFLAGS $1 conftest.cpp -o conftest >/dev/null 2>&1; then
    rm -f conftest conftest.cpp
    return 0
  else
    rm -f conftest conftest.cpp
    return 1
  fi
}

# For CRAN, we cannot override -O2, but we can add other safe optimizations
SAFE_OPTFLAGS=""

# Test portable optimization flags that do not change the -O level
PORTABLE_OPTS="-funroll-loops -ftree-vectorize"
for opt in $PORTABLE_OPTS; do
  if test_flag "$opt"; then
    SAFE_OPTFLAGS="$SAFE_OPTFLAGS $opt"
  fi
done

if [ -n "$SAFE_OPTFLAGS" ]; then
  echo "Additional optimizations:$SAFE_OPTFLAGS"
fi

# Detect number of cores
if [ -n "$CAPYBARA_NCORES" ]; then
  num_cores="$CAPYBARA_NCORES"
else
  if [ -f /proc/cpuinfo ]; then
    num_cores=$(grep -c "^processor" /proc/cpuinfo 2>/dev/null || echo 1)
  elif [ "$(uname)" = "Darwin" ]; then
    num_cores=$(sysctl -n hw.ncpu 2>/dev/null || echo 1)
  else
    num_cores=1
  fi
  
  if [ "$num_cores" -gt 2 ]; then
    num_cores=$((num_cores - 1))
  fi
fi

echo "Default thread count: $num_cores"

# Create Makevars from template
echo "Creating src/Makevars"
sed -e "s|@ncores@|${num_cores}|g" \
    -e "s|@SAFE_OPTFLAGS@|${SAFE_OPTFLAGS}|g" \
    src/Makevars.in > src/Makevars

echo "Configuration complete"
echo ""
echo "NOTE: This build will use the default -O2 optimization level for CRAN compliance."
echo "For maximum performance, see inst/Makevars.user.example"

exit 0

This script detects the number of cores available on the system and sets the CAPYBARA_NCORES variable accordingly. It also tests for safe optimization flags that can be added to the Makevars file without changing the default -O2 optimization level used by R. It also serves the goal of testing that a simple file can be compiled.

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.