Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何将cuda DevicePtr用作加速阵列_Haskell_Cuda_Gpu_Ffi_Accelerate Haskell - Fatal编程技术网

Haskell 如何将cuda DevicePtr用作加速阵列

Haskell 如何将cuda DevicePtr用作加速阵列,haskell,cuda,gpu,ffi,accelerate-haskell,Haskell,Cuda,Gpu,Ffi,Accelerate Haskell,我正在尝试使用从外部代码返回的(在CUDA land中称为a)作为with 我在下面编写的代码有些有效: import Data.Array.Accelerate (Acc, Array, DIM1, Z(Z), (:.)((:.)), use) import qualified Data.Array.Accelerate as Acc import Data.Array.Accelerate.Array.Data (GArrayData(AD_Float), uns

我正在尝试使用从外部代码返回的(在CUDA land中称为a)作为with

我在下面编写的代码有些有效:

import Data.Array.Accelerate
       (Acc, Array, DIM1, Z(Z), (:.)((:.)), use)
import qualified Data.Array.Accelerate as Acc
import Data.Array.Accelerate.Array.Data
       (GArrayData(AD_Float), unsafeIndexArrayData)
import Data.Array.Accelerate.Array.Sugar
       (Array(Array), fromElt, toElt)
import Data.Array.Accelerate.Array.Unique
       (UniqueArray, newUniqueArray)
import Data.Array.Accelerate.LLVM.PTX (run)
import Foreign.C.Types (CULLong(CULLong))
import Foreign.CUDA.Driver (DevicePtr(DevicePtr))
import Foreign.ForeignPtr (newForeignPtr_)
import Foreign.Ptr (intPtrToPtr)

-- A foreign function that uses cuMemAlloc() and cuMemCpyHtoD() to
-- create data on the GPU.  The CUdeviceptr (initialized by cuMemAlloc)
-- is returned from this function.  It is a CULLong in Haskell.
--
-- The data on the GPU is just a list of the 10 floats
-- [0.0, 1.0, 2.0, ..., 8.0, 9.0]
foreign import ccall "mytest.h mytestcuda"
  cmyTestCuda :: IO CULLong

-- | Convert a 'CULLong' to a 'DevicePtr'.
--
-- A 'CULLong' is the type of a CUDA @CUdeviceptr@.  This function
-- converts a raw 'CULLong' into a proper 'DevicePtr' that can be
-- used with the cuda Haskell package.
cullongToDevicePtr :: CULLong -> DevicePtr a
cullongToDevicePtr = DevicePtr . intPtrToPtr . fromIntegral

-- | This function calls 'cmyTestCuda' to get the 'DevicePtr', and
-- wraps that up in an accelerate 'Array'.  It then uses this 'Array'
-- in an accelerate computation.
accelerateWithDataFromC :: IO ()
accelerateWithDataFromC = do
  res <- cmyTestCuda
  let DevicePtr ptrToXs = cullongToDevicePtr res
  foreignPtrToXs <- newForeignPtr_ ptrToXs
  uniqueArrayXs <- newUniqueArray foreignPtrToXs :: IO (UniqueArray Float)
  let arrayDataXs = AD_Float uniqueArrayXs :: GArrayData UniqueArray Float
  let shape = Z :. 10 :: DIM1
      xs = Array (fromElt shape) arrayDataXs :: Array DIM1 Float
      ys = Acc.fromList shape [0,2..18] :: Array DIM1 Float
      usedXs = use xs :: Acc (Array DIM1 Float)
      usedYs = use ys :: Acc (Array DIM1 Float)
      computation = Acc.zipWith (+) usedXs usedYs
      zs = run computation
  putStrLn $ "zs: " <> show z
然而,从阅读accelerate和accelerate llvm ptx源代码来看,这似乎不应该起作用

在大多数情况下,它似乎像一个加速
数组
携带一个指向主机内存中数组数据的指针,以及一个唯一标识
数组
的值。在执行计算时,accelerate将根据需要将阵列数据从主机内存加载到GPU内存中,并使用
Unique
索引的
HashMap
对其进行跟踪

在上面的代码中,我使用指向GPU数据的指针直接创建了一个
数组。这似乎不应该起作用,但在上面的代码中似乎起作用

然而,有些事情不起作用。例如,试图打印出
xs
(我的
数组
,指针指向GPU数据)会因segfault而失败。这是有意义的,因为
Array
Show
实例只是尝试
peek
主机指针中的数据。此操作失败,因为它不是主机指针,而是GPU指针:

-- Trying to print xs causes a segfault.
putStrLn $ "xs: " <> show xs
--尝试打印xs会导致SEG故障。
putStrLn$“xs:“显示xs”


有没有合适的方法可以使用CUDA
DevicePtr
并将其直接用作加速
阵列

事实上,我很惊讶上面的方法已经起到了同样的作用;我无法复制

这里的问题之一是设备内存与执行上下文隐式关联;一个上下文中的指针在不同的上下文中无效,即使在同一GPU上也是如此(除非在这些上下文之间显式启用对等内存访问)

因此,这个问题实际上有两个组成部分:

  • 以其理解的方式将外来数据导入Accelerate;及
  • 确保后续的加速计算在可访问此内存的上下文中执行
  • 解决方案 下面是我们将用于在GPU上生成数据的C代码:

    #包括
    #包括
    #包括
    CUdeviceptr生成gpu数据()
    {
    CUresult状态=CUDA_成功;
    CUdeviceptr d_arr;
    常数int N=32;
    浮动h_arr[N];
    对于(int i=0;i
    以及使用它的Haskell/Accelerate代码:

    {-#语言外来函数接口#-}
    导入Data.Array.Accelerate作为
    将Data.Array.Accelerate.Array.Sugar导入为Sugar
    将Data.Array.Accelerate.Array.Data作为AD导入
    将Data.Array.Accelerate.Array.Remote.LRU导入为LRU
    将Data.Array.Accelerate.LLVM.PTX导入为PTX
    将Data.Array.Accelerate.LLVM.PTX.Foreign导入为PTX
    将Foreign.CUDA.Driver作为CUDA导入
    导入文本.Printf
    main::IO()
    main=do
    --初始化CUDA并创建执行上下文。由此我们也创造了
    --我们的加速程序将在其中运行。
    --
    CUDA.initialise[]
    发展
    
    -- Trying to print xs causes a segfault.
    putStrLn $ "xs: " <> show xs