Optimized Basic Linear Algebra Subprograms (BLAS) providing level-1, level-2, and level-3 operations with automatic native acceleration. The BLAS object itself is internal (private[spark] object BLAS), but its operations are accessible through public Vector and Matrix APIs.
Note: While the BLAS object is not directly accessible to users, its functionality is exposed through:
vector1.dot(vector2) uses BLAS.dot(vector1, vector2)matrix.multiply(vector) uses BLAS.gemvmatrix.multiply(matrix) uses BLAS.gemmThe methods documented here show the underlying BLAS API signatures for reference.
Operations between vectors with O(n) complexity.
object BLAS {
/**
* Vector addition: y += a * x
* @param a Scalar multiplier
* @param x Source vector
* @param y Target vector (modified in-place, must be dense)
*/
def axpy(a: Double, x: Vector, y: Vector): Unit
/**
* Dot product: x^T * y
* @param x First vector
* @param y Second vector (must have same size as x)
* @return Dot product result
*/
def dot(x: Vector, y: Vector): Double
/**
* Vector copy: y = x
* @param x Source vector
* @param y Target vector (modified in-place, must be dense)
*/
def copy(x: Vector, y: Vector): Unit
/**
* Vector scaling: x *= a
* @param a Scalar multiplier
* @param x Vector to scale (modified in-place)
*/
def scal(a: Double, x: Vector): Unit
/**
* Matrix addition: Y += a * X (for dense matrices)
* @param a Scalar multiplier
* @param X Source matrix
* @param Y Target matrix (modified in-place)
*/
private[spark] def axpy(a: Double, X: DenseMatrix, Y: DenseMatrix): Unit
}Usage Examples:
import org.apache.spark.ml.linalg._
val x = Vectors.dense(1.0, 2.0, 3.0)
val y = Vectors.dense(4.0, 5.0, 6.0)
val target = Vectors.dense(0.0, 0.0, 0.0)
// Dot product
val dotProduct = BLAS.dot(x, y) // 32.0
// Vector addition: target += 2.0 * x
BLAS.axpy(2.0, x, target) // target becomes [2.0, 4.0, 6.0]
// Vector copy
BLAS.copy(y, target) // target becomes [4.0, 5.0, 6.0]
// Vector scaling
BLAS.scal(0.5, target) // target becomes [2.0, 2.5, 3.0]Operations between matrices and vectors with O(n²) complexity.
object BLAS {
/**
* General matrix-vector multiplication: y := alpha * A * x + beta * y
* @param alpha Scalar multiplier for A * x
* @param A Matrix operand
* @param x Vector operand (size must match A.numCols)
* @param beta Scalar multiplier for y
* @param y Result vector (modified in-place, size must match A.numRows)
*/
def gemv(
alpha: Double,
A: Matrix,
x: Vector,
beta: Double,
y: DenseVector
): Unit
/**
* General matrix-vector multiplication with array storage: y[0:A.numRows] := alpha * A * x[0:A.numCols] + beta * y[0:A.numRows]
* @param alpha Scalar multiplier for A * x
* @param A Matrix operand
* @param x Vector values as array (size must be >= A.numCols)
* @param beta Scalar multiplier for y
* @param y Result array (modified in-place, size must be >= A.numRows)
*/
def gemv(
alpha: Double,
A: Matrix,
x: Array[Double],
beta: Double,
y: Array[Double]
): Unit
/**
* Symmetric matrix-vector multiplication: y := alpha*A*x + beta*y
* where A is symmetric and stored in packed format
* @param n Order of matrix A
* @param alpha Scalar multiplier for A * x
* @param A Symmetric matrix in packed format (upper triangular)
* @param x Vector operand
* @param beta Scalar multiplier for y
* @param y Result vector (modified in-place)
*/
def dspmv(
n: Int,
alpha: Double,
A: DenseVector,
x: DenseVector,
beta: Double,
y: DenseVector
): Unit
/**
* Symmetric rank-1 update: A := alpha * x * x^T + A
* @param alpha Scalar multiplier
* @param x Vector operand
* @param A Symmetric matrix (modified in-place)
*/
def syr(alpha: Double, x: Vector, A: DenseMatrix): Unit
/**
* Symmetric packed rank-1 update: U += alpha * v * v^T
* where U is upper triangular part stored in packed format
* @param alpha Scalar multiplier
* @param v Vector operand
* @param U Upper triangular matrix in packed format (modified in-place)
*/
def spr(alpha: Double, v: Vector, U: DenseVector): Unit
}Usage Examples:
import org.apache.spark.ml.linalg._
val A = Matrices.dense(3, 3, Array(
1.0, 0.0, 0.0, // column 1
0.0, 2.0, 0.0, // column 2
0.0, 0.0, 3.0 // column 3
))
val x = Vectors.dense(1.0, 2.0, 3.0)
val y = Vectors.dense(0.0, 0.0, 0.0).asInstanceOf[DenseVector]
// Matrix-vector multiplication: y = 1.0 * A * x + 0.0 * y
BLAS.gemv(1.0, A, x, 0.0, y) // y becomes [1.0, 4.0, 9.0]
// Symmetric rank-1 update
val symmetric = DenseMatrix.eye(3)
BLAS.syr(1.0, x, symmetric) // Updates symmetric matrixOperations between matrices with O(n³) complexity.
object BLAS {
/**
* General matrix-matrix multiplication: C := alpha * A * B + beta * C
* @param alpha Scalar multiplier for A * B
* @param A Left matrix operand
* @param B Right matrix operand (must be DenseMatrix, A.numCols must equal B.numRows)
* @param beta Scalar multiplier for C
* @param C Result matrix (modified in-place, must be DenseMatrix)
*/
def gemm(
alpha: Double,
A: Matrix,
B: DenseMatrix,
beta: Double,
C: DenseMatrix
): Unit
/**
* General matrix-matrix multiplication with array storage: CValues[0: A.numRows * B.numCols] := alpha * A * B + beta * CValues[0: A.numRows * B.numCols]
* @param alpha Scalar multiplier for A * B
* @param A Left matrix operand
* @param B Right matrix operand (must be DenseMatrix, A.numCols must equal B.numRows)
* @param beta Scalar multiplier for CValues
* @param CValues Result array (modified in-place, must have length >= A.numRows * B.numCols)
*/
def gemm(
alpha: Double,
A: Matrix,
B: DenseMatrix,
beta: Double,
CValues: Array[Double]
): Unit
}Usage Examples:
import org.apache.spark.ml.linalg._
val A = Matrices.dense(2, 3, Array(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
val B = DenseMatrix.ones(3, 2)
val C = DenseMatrix.zeros(2, 2)
// Matrix multiplication: C = 1.0 * A * B + 0.0 * C
BLAS.gemm(1.0, A, B, 0.0, C)
// Result: C contains the product A * BAdditional BLAS operations for specific use cases.
object BLAS {
/**
* Symmetric packed rank-1 update with array storage
* @param alpha Scalar multiplier
* @param v Vector operand
* @param U Upper triangular matrix in packed array format (modified in-place)
*/
def spr(alpha: Double, v: Vector, U: Array[Double]): Unit
}The BLAS implementation automatically uses the best available backend:
object BLAS {
/**
* Get Java-based BLAS implementation
* @return NetlibBLAS instance using pure Java
*/
private[spark] def javaBLAS: dev.ludovic.netlib.blas.BLAS
/**
* Get native BLAS implementation with fallback
* @return NetlibBLAS instance using native libraries or Java fallback
*/
private[spark] def nativeBLAS: dev.ludovic.netlib.blas.BLAS
/**
* Choose optimal BLAS implementation based on vector size
* @param vectorSize Size of vectors in operation
* @return Appropriate BLAS implementation
*/
private[spark] def getBLAS(vectorSize: Int): dev.ludovic.netlib.blas.BLAS
}dspmv operation regardless of size// Supported combinations for different operations:
// axpy: x can be Dense/Sparse, y must be Dense
BLAS.axpy(1.0, denseX, denseY) // ✓
BLAS.axpy(1.0, sparseX, denseY) // ✓
BLAS.axpy(1.0, denseX, sparseY) // ✗ (throws exception)
// dot: both x and y can be Dense/Sparse
BLAS.dot(denseX, denseY) // ✓
BLAS.dot(sparseX, denseY) // ✓
BLAS.dot(denseX, sparseY) // ✓
BLAS.dot(sparseX, sparseY) // ✓
// gemv: A can be Dense/Sparse, x can be Dense/Sparse, y must be Dense
BLAS.gemv(1.0, denseA, denseX, 0.0, denseY) // ✓
BLAS.gemv(1.0, sparseA, sparseX, 0.0, denseY) // ✓
// gemm: A can be Dense/Sparse, B and C must be Dense
BLAS.gemm(1.0, sparseA, denseB, 0.0, denseC) // ✓
BLAS.gemm(1.0, denseA, sparseB, 0.0, denseC) // ✗ (throws exception)BLAS operations validate inputs and throw exceptions for invalid parameters:
IllegalArgumentException: Dimension mismatches or invalid parameter valuesUnsupportedOperationException: Unsupported vector/matrix type combinationsExample Error Cases:
// Dimension mismatch
val x = Vectors.dense(1.0, 2.0)
val y = Vectors.dense(1.0, 2.0, 3.0)
BLAS.dot(x, y) // throws IllegalArgumentException
// Unsupported type combination
val sparse = Vectors.sparse(3, Array(0, 2), Array(1.0, 3.0))
BLAS.axpy(1.0, sparse, sparse) // throws IllegalArgumentException (y must be dense)BLAS operations are used internally by:
vector.dot(other) calls BLAS.dot(vector, other)matrix.multiply(vector) uses BLAS.gemvmatrix.multiply(matrix) uses BLAS.gemm