packages feed

hhlo-0.11.0.0: test/Test/Runtime/MultiGPU.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}

module Test.Runtime.MultiGPU (tests) where

import qualified Data.Vector.Storable as V
import Data.Int (Int64)
import Test.Tasty
import Test.Tasty.HUnit

import HHLO.Core.Types
import HHLO.EDSL.Ops
import HHLO.IR.AST (FuncArg(..), TensorType(..))
import HHLO.IR.Builder
import HHLO.IR.Pretty
import HHLO.Runtime.PJRT.Types
import HHLO.Runtime.Device
import HHLO.Runtime.Compile
import HHLO.Runtime.Execute
import HHLO.Runtime.Buffer
import Test.Runtime.GPUResource (GPUResource(..))

tests :: IO GPUResource -> TestTree
tests getGPU = testGroup "Runtime.MultiGPU"
    [ testCase "execute replicas on all GPUs" $ do
        GPUResource api client _dev <- getGPU
        devs <- addressableDevices api client
        case devs of
            [] -> assertFailure "No GPU devices found"
            _  -> do
                let numDevs = length devs
                let modu = moduleFromBuilder @'[2, 2] @'F32 "main"
                        [ FuncArg "arg0" (TensorType [Just 2, Just 2] F32)
                        , FuncArg "arg1" (TensorType [Just 2, Just 2] F32)
                        ]
                        $ do
                            x <- arg @'[2, 2] @'F32
                            y <- arg @'[2, 2] @'F32
                            z <- add x y
                            return z

                exec <- compileWithOptions api client (render modu)
                            (defaultCompileOptions { optNumReplicas = numDevs })

                let inputA = V.fromList [1, 2, 3, 4] :: V.Vector Float
                    inputB = V.fromList [10, 20, 30, 40] :: V.Vector Float
                    dims = [2, 2] :: [Int64]

                deviceArgs <- mapM (\dev -> do
                    bufA <- toDeviceOn api client dev inputA dims bufferTypeF32
                    bufB <- toDeviceOn api client dev inputB dims bufferTypeF32
                    return (dev, [bufA, bufB])
                  ) devs

                results <- executeReplicas api exec deviceArgs

                mapM_ (\(idx, outs) -> do
                    let [bufOut] = outs
                    result <- fromDeviceF32 api bufOut 4
                    assertEqual ("GPU " ++ show idx ++ " result") result (V.fromList [11, 22, 33, 44] :: V.Vector Float)
                  ) (zip [0..] results)
    ]