1
- # EXCLUDE FROM TESTING
1
+ # TODO tag CUDArt#103 and use that
2
2
import CUDArt
3
+ export CompileError
3
4
4
5
# Generate a temporary file with specific suffix
5
6
# NOTE: mkstemps is glibc 2.19+, so emulate its behavior
6
7
function mkstemps (suffix:: AbstractString )
7
8
base = tempname ()
8
9
filename = base * suffix
10
+
9
11
# make sure the filename is unique
10
12
i = 0
11
13
while isfile (filename)
12
14
i += 1
13
15
filename = base * " .$i " * suffix
14
16
end
17
+
15
18
return (filename, Base. open (filename, " w" ))
16
19
end
17
20
21
+ macro compile (dev, kernel, code)
22
+ kernel_name = string (kernel)
23
+ containing_file = @__FILE__
24
+
25
+ return Expr (:toplevel ,
26
+ Expr (:export ,esc (kernel)),
27
+ :($ (esc (kernel)) = _compile ($ (esc (dev)), $ kernel_name, $ code, $ containing_file)))
28
+ end
18
29
19
- type CompileError <: Base.WrappedException
30
+ immutable CompileError <: Exception
20
31
message:: String
21
- error
22
32
end
23
33
24
34
const builddir = joinpath (@__DIR__ , " .cache" )
@@ -31,7 +41,7 @@ function _compile(dev, kernel, code, containing_file)
31
41
mkpath (builddir)
32
42
end
33
43
34
- # Check if we need to compile
44
+ # check if we need to compile
35
45
codehash = hex (hash (code))
36
46
output = " $builddir /$(kernel) _$(codehash) -$(arch) .ptx"
37
47
if isfile (output)
@@ -40,47 +50,44 @@ function _compile(dev, kernel, code, containing_file)
40
50
need_compile = true
41
51
end
42
52
43
- # Compile the source, if necessary
53
+ # compile the source, if necessary
44
54
if need_compile
45
- # Write the source into a compilable file
55
+ # write the source to a compilable file
46
56
(source, io) = mkstemps (" .cu" )
47
57
write (io, """
48
58
extern "C"
49
59
{
50
60
$code
51
61
}
52
62
""" )
53
- close (io)
63
+ Base . close (io)
54
64
55
65
compile_flags = vcat (CUDArt. toolchain_flags, [" --gpu-architecture" , arch])
56
- try
57
- # TODO : capture STDERR
58
- run (pipeline (` $(CUDArt. toolchain_nvcc) $(compile_flags) -ptx -o $output $source ` , stderr = DevNull))
59
- catch ex
60
- isa (ex, ErrorException) || rethrow (ex)
61
- rethrow (CompileError (" compilation of kernel $kernel failed (typo in C++ source?)" , ex))
62
- finally
63
- rm (source)
66
+ err = Pipe ()
67
+ cmd = ` $(CUDArt. toolchain_nvcc) $(compile_flags) -ptx -o $output $source `
68
+ result = success (pipeline (cmd; stdout = DevNull, stderr = err))
69
+ Base. close (err. in)
70
+ rm (source)
71
+
72
+ errors = readstring (err)
73
+ if ! result
74
+ throw (CompileError (" compilation of kernel $kernel failed\n $errors " ))
75
+ elseif ! isempty (errors)
76
+ warn (" during compilation of kernel $kernel :\n $errors " )
64
77
end
65
78
66
79
if ! isfile (output)
67
80
error (" compilation of kernel $kernel failed (no output generated)" )
68
81
end
69
82
end
70
83
71
- # Pass the module to the CUDA driver
72
- mod = try
73
- CUDAdrv. CuModuleFile (output)
74
- catch ex
75
- rethrow (CompileError (" loading of kernel $kernel failed (invalid CUDA code?)" , ex))
76
- end
84
+ mod = CUDAdrv. CuModuleFile (output)
85
+ return CUDAdrv. CuFunction (mod, kernel)
86
+ end
77
87
78
- # Load the function pointer
79
- func = try
80
- CUDAdrv. CuFunction (mod, kernel)
81
- catch ex
82
- rethrow (CompileError (" could not find kernel $kernel in the compiled binary (wrong function name?)" , ex))
88
+ function clean_cache ()
89
+ if ispath (builddir)
90
+ @assert isdir (builddir)
91
+ rm (builddir; recursive= true )
83
92
end
84
-
85
- return func
86
93
end
0 commit comments