example: call cuda toolkit curand API from common lisp

2 篇文章 0 订阅

continue example: call cuda toolkit API from python, curand

This time I tried to use SWIG to generate the wrapper for common lisp.

1.create an interface file "curand.i"

%module curand

#define size_t unsigned long long
#define __host__ 
#define cudaError_t int
#define CUDARTAPI 
#define __cudart_builtin__

enum cudaMemcpyKind {
   cudaMemcpyHostToHost = 0,
   cudaMemcpyHostToDevice = 1,
   cudaMemcpyDeviceToHost = 2,
   cudaMemcpyDeviceToDevice = 3,
   cudaMemcpyDefault = 4
 };

%include "/usr/local/cuda/include/curand.h"
%include "/usr/local/cuda/include/cuda_runtime_api.h"
Here we use some macro define, for these macro can be recognized by nvcc only, not SWIG.

2. use swig to generate the wrapper.

swig -cffi curand.i
Then there is a file named curand.lisp, it contains the lisp definitions for the C API in curand & cuda runtime.

3. Use common lisp to call curand, and generate some random numbers. file: cffi-curand.lisp

(require :asdf)
(require :cffi)
(defpackage :curand (:use :common-lisp :cffi))
(in-package :curand)
(define-foreign-library libcurand
  (:unix (:or "/usr/local/cuda/lib64/libcurand.so"))
  (t (:default "libcurand")))
(use-foreign-library libcurand)
(define-foreign-library libcudart
  (:unix (:or "/usr/local/cuda/lib64/libcudart.so"))
  (t (:default "libcudart")))
(use-foreign-library libcudart)
(load "curand.lisp")

(defmacro with-curand-generator (gen curand-rng-type &rest body)
  (let ((pg (gensym)) (ret (gensym)))
    `(with-foreign-object (,pg :unsigned-long-long)
       (let ((,ret (curandcreategenerator ,pg ,curand-rng-type)))
	 (if (equal :CURAND_STATUS_SUCCESS ,ret)
	     (let ((,gen (make-pointer (mem-ref ,pg :unsigned-long-long))))
	       (unwind-protect (progn ,@body)
		 (curanddestroygenerator ,gen)))
	     (format t "curandcreategenerator failed: ~A" ,ret)
	     )))))

(defmacro with-cuda-buf (dev-buf host-buf bytes &rest body)
  (let ((ptr (gensym)) (ret (gensym)))
    `(with-foreign-objects ((,ptr :unsigned-long-long) (,host-buf :char ,bytes))
       (let ((,ret (cudamalloc ,ptr ,bytes) ))
	 (if (equal ,ret 0)
	     (let ((,dev-buf (make-pointer (mem-ref ,ptr :unsigned-long-long))))
	       (unwind-protect (progn ,@body)
		 (cudafree dev-buf)))
	     (format t "cudamalloc failed: ~A" ,ret))))))

(with-foreign-object (version :int)
  (format t "RET: ~A~%Ver: ~D~%" (curandgetversion version) (mem-ref version :int)))

(let* ((size 500) (bytes (* 4 size)))
  (with-cuda-buf dev-buf host-buf bytes
		 (with-curand-generator gen :curand_rng_pseudo_default
					(if (equal :CURAND_STATUS_SUCCESS (curandgenerateuniform gen dev-buf size))
					    (progn
					      (cudamemcpy host-buf dev-buf bytes :cudamemcpydevicetohost)
					      (format t "~{~A~^, ~}~%"
						      (loop for i from 0 below size
							 collect (mem-aref host-buf :float i)))
					      t)
					    (format t "generate failed")))))

4. Run it. (use sbcl)

sbcl --script cffi-curand.lisp 
Then you can see some float number has been printed.


I have created a project on Github:

lisp-cudalib

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值