eigen-hhlo-0.1.0.0: src/EigenHHLO/Runtime/Session.hs
{-# LANGUAGE OverloadedStrings #-}
-- | Session lifecycle management for eigen-hhlo backends.
module EigenHHLO.Runtime.Session
( withEigenCPU
, withEigenGPU
) where
import Data.Char (toLower, toUpper)
import System.Directory (doesFileExist)
import System.Environment (lookupEnv)
import HHLO.Runtime.CustomCall (loadCustomCallLibrary, registerGpuCustomCall)
import HHLO.Session (Session(..), withCPU, withGPU)
import EigenHHLO.Core.Types (BackendType(..), EigenSession(..))
-- | Resolve the path to a custom-call shared library.
--
-- Priority:
-- 1. @EIGENHHLO_<BACKEND>_LIB@ environment variable
-- 2. @lib/libeigenhhlo_<backend>.so@ relative to CWD
-- 3. Runtime error with instructions
getCustomCallLibPath :: String -> FilePath -> IO FilePath
getCustomCallLibPath backend defaultName = do
mEnv <- lookupEnv ("EIGENHHLO_" ++ map toUpper backend ++ "_LIB")
case mEnv of
Just p -> return p
Nothing -> do
let defaultPath = "lib/" ++ defaultName
exists <- doesFileExist defaultPath
if exists
then return defaultPath
else error $ unlines
[ "eigen-hhlo " ++ backend ++ " custom-call library not found at: " ++ defaultPath
, ""
, "To fix this, either:"
, " 1. Build the library:"
, " cd cbits/" ++ map toLower backend ++ " && bash build.sh"
, " 2. Set the environment variable:"
, " export EIGENHHLO_" ++ map toUpper backend ++ "_LIB=/path/to/" ++ defaultName
]
-- | Create an eigen-hhlo session on the CPU backend.
-- Loads the CPU custom-call library via RTLD_GLOBAL.
--
-- The library path is resolved via 'getCustomCallLibPath'.
withEigenCPU :: (EigenSession -> IO a) -> IO a
withEigenCPU action = withCPU $ \sess -> do
libPath <- getCustomCallLibPath "CPU" "libeigenhhlo_cpu.so"
loadCustomCallLibrary libPath
action (EigenSession sess CPU)
-- | Create an eigen-hhlo session on the GPU backend.
-- Registers all decomposition symbols with the PJRT CUDA plugin.
--
-- The library path is resolved via 'getCustomCallLibPath'.
withEigenGPU :: (EigenSession -> IO a) -> IO a
withEigenGPU action = withGPU $ \sess -> do
libPath <- getCustomCallLibPath "GPU" "libeigenhhlo_gpu.so"
-- Register all symbols with the PJRT GPU plugin
registerGpuCustomCall (sessionApi sess) libPath "eigenhhlo_dgesvd"
registerGpuCustomCall (sessionApi sess) libPath "eigenhhlo_dgeqrf"
registerGpuCustomCall (sessionApi sess) libPath "eigenhhlo_dorgqr"
registerGpuCustomCall (sessionApi sess) libPath "eigenhhlo_dsyevd"
registerGpuCustomCall (sessionApi sess) libPath "eigenhhlo_dpotrf"
registerGpuCustomCall (sessionApi sess) libPath "eigenhhlo_dgetrf"
action (EigenSession sess GPU)