2

I have an existing R script that performs various operations, and I'm looking to create a C sub function to optimize a specific part of it. My goal is to integrate this C sub function within R Desktop for improved performance and efficiency.

For example, let's assume that I want to sum the elements obtained by multiplying the vector x and y. In R, I can achieve this with the following code:

R code

x <- c(1, 2, 3)
y <- c(4, 5, 6)
z <- sum(x * y)  

The same operation using oneMKL can be performed like this:

#include <stdio.h>
#include <mkl.h>
int main() {
    double x[] = {1.0, 2.0, 3.0};
    double y[] = {4.0, 5.0, 6.0};
    double z;
    // Perform vector multiplication and summation using Intel MKL
    z = cblas_ddot(3, x, 1, y, 1);
    printf("Result: %lf\n", z);
    return 0;
}

After compiling the .c function using CMD, I get:

C:\Program Files (x86)\Intel\oneAPI>cd C:/Users/Administrator/Desktop
C:\Users\Administrator\Desktop>icx -o example example.c /Qmkl /MD
Intel(R) oneAPI DPC++/C++ Compiler for applications running on Intel(R) 64, Version 2023.1.0 Build 20230320
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.

C:\Users\Administrator\Desktop>example.exe
Result: 32.000000 

What I want to do is replace the 4th line of the Rscript code with a .c function. I'm facing two problems:

1. Convert the C Function for General Inputs:

I don't know if I have defined the function correctly.

#include <stdio.h>
#include <mkl.h>

void multiplyAndSum(double *x, double *y, int length, double *result) {
    *result = cblas_ddot(length, x, 1, y, 1);
}

2. Calling the C Function in R:

I don't know how to call the .c function in step 1 within R. Is there a way to compile the function and run it explicitly within R Desktop, without using the command prompt (cmd)

Please, I understand that my question may be quite basic, but my knowledge is limited. I would greatly appreciate a step-by-step answer, ideally. I have installed Intel oneAPI Base Toolkit on windows platform.

Best regards, Anastasia

PS: My environment variables are displayed in the image below. Perhaps this information could be helpful for you to assist me. enter image description here

4
  • Yes you could compile the code using system function in R. Unfortunately I do not have the mkl.h header, Commented Sep 26, 2023 at 8:33
  • 2
    Are you sure that this is the performance limiting part of your code? Maybe the dot products in Armadillo or Eigen would offer sufficient performance? Those are easily integrated in R via RcppArmadillo or RcppEigen. Linking R against MKL BLAS might already be sufficient to improve performance further. Commented Sep 26, 2023 at 9:30
  • Thank you for your assistance. I appreciate your suggestion regarding using Armadillo or Eigen for dot products, as well as the mention of RcppArmadillo and RcppEigen for integration with R. I understand that my initial C function might be simplistic, and the actual code I'm looking to optimize is more complex. I have found about linking Intel MKL BLAS to R on Linux, but I'm currently working on Windows and am unsure about the specific steps for doing this on my platform. If you have any resources or guidance related to linking MKL BLAS to R on Windows, I would greatly appreciate it. Commented Sep 26, 2023 at 10:40
  • When using the .C interface, you must pass pointers the arguments. It's int *length, not int length. Commented Sep 26, 2023 at 14:18

1 Answer 1

2

Here is a working example with the C function in the question.

C code, file so_77177870.c

// file: so_77177870.c
#include <R.h>
#include <mkl.h>

void multiplyAndSum(double *x, double *y, int *length, double *result) {
  *result = cblas_ddot(*length, x, 1, y, 1);
}

Compile the code above with

R CMD SHLIB so_77177870.c

This will produce a shared library, extension .dll in Windows. Then, in R, load the library and write a wrapper function, dotprod. The C code's return value is its last argument.

See Writing R Extensions, section 5.2.

dynLoad <- function(dynlib){
  dynlib <- paste0(dynlib, .Platform$dynlib.ext)
  dyn.load(dynlib)
}
dynUnload <- function(dynlib){
  dynlib <- paste0(dynlib, .Platform$dynlib.ext)
  dyn.unload(dynlib)
}

dotprod <- function(x, y) {
  .C("multiplyAndSum", 
     as.double(x), as.double(y), 
     as.integer(length(x)),
     result = double(1)
  )$result
}

# load the shared library, in this case so_77177870.dll
dll <- "so_77177870"
dynLoad(dll)

x <- c(1, 2, 3)
y <- c(4, 5, 6)

sum(x * y)  
#> [1] 32
dotprod(x, y)
#> [1] 32

# unload the shared library when done
dynUnload(dll)

Created on 2023-09-26 with reprex v2.0.2

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much for your response!!! I slightly modified the C function so that it doesn't require the MKL and it worked perfectly! However, with the MKL, I'm encountering the following message. "fatal error:mkl.h: No such file or directory 3 | #include <mkl.h>." I suspect I haven't linked R with Intel, but I don't know how to do it. I've added the environment variables to my initial question. Perhaps they could be useful for you to help me.
@Anastasia There are several ways of solving that problem. It depends on your system, and there are questions on that here on SO. The main problem is to find the MKL shared libs and header files. Try a web search and see if you can find a solution that works for your case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.