or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

blas.mddistributions.mdindex.mdmatrices.mdutils.mdvectors.md
tile.json

blas.mddocs/

Linear Algebra Operations

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:

  • Vector operations: vector1.dot(vector2) uses BLAS.dot(vector1, vector2)
  • Matrix operations: matrix.multiply(vector) uses BLAS.gemv
  • Matrix multiplication: matrix.multiply(matrix) uses BLAS.gemm

The methods documented here show the underlying BLAS API signatures for reference.

Capabilities

Level-1 BLAS (Vector-Vector Operations)

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]

Level-2 BLAS (Matrix-Vector Operations)

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 matrix

Level-3 BLAS (Matrix-Matrix Operations)

Operations 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 * B

Specialized Operations

Additional 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
}

Implementation Details

Native Acceleration

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
}

Backend Selection

  1. Native BLAS: Uses Intel MKL, OpenBLAS, or other optimized libraries when available
  2. Java BLAS: Pure JVM implementation as fallback
  3. Automatic selection: Chooses Java BLAS for small operations (< 256 elements) for better performance
  4. Level-1 optimization: Uses Java BLAS for dspmv operation regardless of size

Performance Characteristics

  • Level-1 operations: O(n) complexity, optimized for small to medium vectors
  • Level-2 operations: O(n²) complexity, benefits significantly from native acceleration
  • Level-3 operations: O(n³) complexity, requires native BLAS for good performance
  • Sparse operations: Custom implementations optimized for sparse data structures
  • Memory access: Column-major ordering for compatibility with Fortran BLAS

Supported Vector/Matrix Combinations

// 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)

Error Handling

BLAS operations validate inputs and throw exceptions for invalid parameters:

  • IllegalArgumentException: Dimension mismatches or invalid parameter values
  • UnsupportedOperationException: Unsupported vector/matrix type combinations

Example 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)

Integration with Other Components

BLAS operations are used internally by:

  • Vector dot product: vector.dot(other) calls BLAS.dot(vector, other)
  • Matrix multiplication: matrix.multiply(vector) uses BLAS.gemv
  • Matrix multiplication: matrix.multiply(matrix) uses BLAS.gemm
  • Statistical computations in MultivariateGaussian
  • Optimization algorithms throughout Spark MLlib