Mark Clements
2018-09-09 20:15:26 UTC
I am enjoying using polyml's Foreign structure.
However, in using the GNU Scientific Library (GSL), I have run into a
problem with linkage. The GSL library (libgsl.so) calls standard cBLAS
matrix functions with unknown symbols to allow the user to link with
different cBLAS implementations (NB: GSL provides an unoptimised cBLAS
implementation named libgslcblas.so). When I call a GSL function that
depends on the cBLAS functions, I get a symbol not defined error.
I have tried unsuccessfully (a) loading the libgslcblas library either
before or after loading libgsl, (b) changing the loadLibrary
implementation to use dlopen with RTLD_LAZY | RTLD_GLOBAL, and (c)
compiling the SML code to an object file and then linking against the
libraries.
How could this be made to work?
Sincerely, Mark.
PS test code for (a) is:
open Foreign;
val gsl = loadLibrary "/usr/lib/x86_64-linux-gnu/libgsl.so";
val gslcblas = loadLibrary "/usr/lib/x86_64-linux-gnu/libgslcblas.so";
type gsl_matrix_t = Memory.voidStar; (* for demonstration only *)
local
val call1 = buildCall2((getSymbol gsl "gsl_matrix_calloc"),
(cInt,cInt), cPointer)
val call2 = buildCall4((getSymbol gsl "gsl_matrix_set"),
(cPointer,cInt,cInt,cDouble), cVoid)
val call3 = buildCall3((getSymbol gsl
"gsl_linalg_exponential_ss"), (cPointer, cPointer, cDouble), cVoid)
in
fun gsl_matrix_alloc (size1,size2) = call1(size1,size2)
fun gsl_matrix_set (ptr : gsl_matrix_t, i, j, x) = call2(ptr, i, j, x)
fun gsl_matrix (arr : real Array2.array) =
let
val size1 = Array2.nRows arr
val size2 = Array2.nCols arr
val ptr = gsl_matrix_alloc(size1, size2)
val _ = Array2.tabulate Array2.RowMajor (size1, size2, fn (i,j) =>
gsl_matrix_set(ptr, i, j, Array2.sub(arr, i, j)))
in
ptr
end
fun gsl_mexp (arr : real Array2.array) =
let
val size1 = Array2.nRows arr
val size2 = Array2.nCols arr
val ptr = gsl_matrix arr
val ptr2 = gsl_matrix_alloc(size1, size2)
val _ = call3(ptr, ptr2, 0.01)
in
ptr2
end
end;
fun main() =
let
val a = Array2.fromList [[1.0,2.0],[3.0,4.0]];
val ptr = gsl_matrix(a);
val m = gsl_mexp(a) (* fails *)
in
()
end;
(* symbol lookup error: /usr/lib/x86_64-linux-gnu/libgsl.so: undefined
symbol: cblas_dgemm *)
For (c):
polyc -c test.sml
g++ test.o -L/usr/lib/x86_64-linux-gnu -lgsl -lgslcblas `pkg-config
--libs polyml`
./a.out
# same error
However, in using the GNU Scientific Library (GSL), I have run into a
problem with linkage. The GSL library (libgsl.so) calls standard cBLAS
matrix functions with unknown symbols to allow the user to link with
different cBLAS implementations (NB: GSL provides an unoptimised cBLAS
implementation named libgslcblas.so). When I call a GSL function that
depends on the cBLAS functions, I get a symbol not defined error.
I have tried unsuccessfully (a) loading the libgslcblas library either
before or after loading libgsl, (b) changing the loadLibrary
implementation to use dlopen with RTLD_LAZY | RTLD_GLOBAL, and (c)
compiling the SML code to an object file and then linking against the
libraries.
How could this be made to work?
Sincerely, Mark.
PS test code for (a) is:
open Foreign;
val gsl = loadLibrary "/usr/lib/x86_64-linux-gnu/libgsl.so";
val gslcblas = loadLibrary "/usr/lib/x86_64-linux-gnu/libgslcblas.so";
type gsl_matrix_t = Memory.voidStar; (* for demonstration only *)
local
val call1 = buildCall2((getSymbol gsl "gsl_matrix_calloc"),
(cInt,cInt), cPointer)
val call2 = buildCall4((getSymbol gsl "gsl_matrix_set"),
(cPointer,cInt,cInt,cDouble), cVoid)
val call3 = buildCall3((getSymbol gsl
"gsl_linalg_exponential_ss"), (cPointer, cPointer, cDouble), cVoid)
in
fun gsl_matrix_alloc (size1,size2) = call1(size1,size2)
fun gsl_matrix_set (ptr : gsl_matrix_t, i, j, x) = call2(ptr, i, j, x)
fun gsl_matrix (arr : real Array2.array) =
let
val size1 = Array2.nRows arr
val size2 = Array2.nCols arr
val ptr = gsl_matrix_alloc(size1, size2)
val _ = Array2.tabulate Array2.RowMajor (size1, size2, fn (i,j) =>
gsl_matrix_set(ptr, i, j, Array2.sub(arr, i, j)))
in
ptr
end
fun gsl_mexp (arr : real Array2.array) =
let
val size1 = Array2.nRows arr
val size2 = Array2.nCols arr
val ptr = gsl_matrix arr
val ptr2 = gsl_matrix_alloc(size1, size2)
val _ = call3(ptr, ptr2, 0.01)
in
ptr2
end
end;
fun main() =
let
val a = Array2.fromList [[1.0,2.0],[3.0,4.0]];
val ptr = gsl_matrix(a);
val m = gsl_mexp(a) (* fails *)
in
()
end;
(* symbol lookup error: /usr/lib/x86_64-linux-gnu/libgsl.so: undefined
symbol: cblas_dgemm *)
For (c):
polyc -c test.sml
g++ test.o -L/usr/lib/x86_64-linux-gnu -lgsl -lgslcblas `pkg-config
--libs polyml`
./a.out
# same error