You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[ArrayFire](http://arrayfire.com) is a library for GPU and accelerated computing. ArrayFire.jl wraps the ArrayFire library for Julia, and provides a Julian interface.
6
+
[ArrayFire](http://ArrayFire.com) is a library for GPU and accelerated computing. ArrayFire.jl wraps the ArrayFire library for [Julia](https://JuliaLang.org), and provides a Julia interface.
7
7
8
8
## Installation
9
9
10
10
### OSX
11
11
12
-
If you are on OSX, the easiest way to install arrayfire is by doing
12
+
If you are on OSX, the easiest way to install arrayfire is by using [brew](https://brew.sh/):
13
13
```
14
14
brew install arrayfire
15
15
```
@@ -30,14 +30,17 @@ Now, start Julia, and do:
30
30
```julia
31
31
Pkg.add("ArrayFire")
32
32
```
33
+
33
34
You can also get the latest nightly version of `ArrayFire.jl` by doing:
34
35
```julia
35
36
Pkg.checkout("ArrayFire")
36
37
```
38
+
37
39
Check if `ArrayFire.jl` works by running the tests:
38
40
```julia
39
41
Pkg.test("ArrayFire")
40
42
```
43
+
41
44
If you have any issues getting `ArrayFire.jl` to work, please check the Troubleshooting section below. If it still doesn't work, please file an issue.
42
45
43
46
### Windows
@@ -50,72 +53,77 @@ Pkg.test("ArrayFire")
50
53
```
51
54
52
55
Arrayfire requires vcomp120.dll. If you do not have Visual Studio installed, install the [Visual C++ redistributable](https://www.microsoft.com/en-us/download/details.aspx?id=40784).
56
+
53
57
## Simple Usage
54
58
Congratulations, you've now installed `ArrayFire.jl`! Now what can you do?
55
59
56
60
Let's say you have a simple Julia array on the CPU:
57
61
```julia
58
62
a =rand(10, 10)
59
63
```
64
+
60
65
You can transfer this array to the device by calling the `AFArray` constructor on it.
61
66
```julia
62
-
using ArrayFire # Don't forget to load the library
67
+
using ArrayFire # Don't forget to load the library
63
68
ad =AFArray(a)
64
69
```
70
+
65
71
Now let us perform some simple arithmetic on it:
66
72
```julia
67
73
bd = (ad +1) /5
68
74
```
75
+
69
76
Of course, you can do much more than just add and divide numbers. Check the supported functions section for more information.
70
77
71
78
Now that you're done with all your device computation, you can bring your array back to the CPU (or host):
72
79
```julia
73
80
b =Array(bd)
74
81
```
82
+
75
83
Here are other examples of simple usage:
76
84
77
85
```julia
78
86
using ArrayFire
79
87
80
-
#Random number generation
88
+
#Random number generation
81
89
a =rand(AFArray{Float64}, 100, 100)
82
90
b =randn(AFArray{Float64}, 100, 100)
83
91
84
-
#Transfer to device from the CPU
92
+
#Transfer to device from the CPU
85
93
host_to_device =AFArray(rand(100,100))
86
94
87
-
#Transfer back to CPU
95
+
#Transfer back to CPU
88
96
device_to_host =Array(host_to_device)
89
97
90
-
#Basic arithmetic operations
98
+
#Basic arithmetic operations
91
99
c =sin(a) +0.5
92
100
d = a *5
93
101
94
-
#Logical operations
102
+
#Logical operations
95
103
c = a .> b
96
104
any_trues =any(c)
97
105
98
-
#Reduction operations
106
+
#Reduction operations
99
107
total_max =maximum(a)
100
108
colwise_min =min(a,2)
101
109
102
-
#Matrix operations
110
+
#Matrix operations
103
111
determinant =det(a)
104
112
b_positive =abs(b)
105
113
product = a * b
106
114
dot_product = a .* b
107
115
transposer = a'
108
116
109
-
#Linear Algebra
117
+
#Linear Algebra
110
118
lu_fact =lu(a)
111
-
cholesky_fact =chol(a*a') #Multiplied to create a positive definite matrix
119
+
cholesky_fact =chol(a*a') #Multiplied to create a positive definite matrix
112
120
qr_fact =qr(a)
113
121
svd_fact =svd(a)
114
122
115
-
#FFT
123
+
#FFT
116
124
fast_fourier =fft(a)
117
-
118
125
```
126
+
119
127
## The Execution Model
120
128
`ArrayFire.jl` introduces an `AFArray` type that is a subtype of `AbstractArray`. Operations on `AFArrays` create other `AFArrays`, so data always remains on the device unless it is specifically transferred back. This wrapper provides a simple Julian interface that aims to mimic Base Julia's versatility and ease of use.
121
129
@@ -125,17 +133,13 @@ fast_fourier = fft(a)
125
133
126
134
The library also performs some kernel fusions on elementary arithmetic operations (see the arithmetic section of the Supported Functions). `arrayfire` has an intelligent runtime JIT compliation engine which converts array expressions into the smallest number of OpenCL/CUDA kernels. Kernel fusion not only decreases the number of kernel calls, but also avoids extraneous global memory operations. This asynchronous behaviour ends only when a non-JIT operation is called or an explicit synchronization barrier `sync(array)` is called.
127
135
128
-
**Garbage collection and memory management**: `arrayfire` is using its own memory management that relies on Julia
129
-
garbage collector releasing refences to unused arrays. Sometimes it could be a bottleneck as Julia garbage collector
130
-
can be slow and not even notice the pressure in GPU memory usage. The best way to avoid it is to use `@afgc` macro
131
-
that would free all unused `AFArray` references when leaving the scope of a function or a block. The alternative is to
132
-
call afgc() periodically.
136
+
**Garbage collection and memory management**: `arrayfire` is using its own memory management that relies on Julia garbage collector releasing refences to unused arrays. Sometimes it could be a bottleneck as Julia garbage collector can be slow and not even notice the pressure in GPU memory usage. The best way to avoid it is to use `@afgc` macro that would free all unused `AFArray` references when leaving the scope of a function or a block. The alternative is to call `afgc()` periodically.
133
137
134
-
**A note on benchmarking**: In Julia, one would use the `@time` macro to time execution times of functions. However, in this particular case, `@time` would simply time the function call, and the library would execute asynchronously in the background. This would often lead to misleading timings. Therefore, the right way to time individual operations is to run them multiple times, place an explicit synchronization barrier at the end, and take the average of multiple runs.
138
+
**A note on benchmarking**: In Julia, one would use the `@time` macro to time execution times of functions. However, in this particular case, `@time` would simply time the function call, and the library would execute asynchronously in the background. This would often lead to misleading timings. Therefore, the right way to time individual operations is to run them multiple times, place an explicit synchronization barrier at the end, and take the average of multiple runs.
135
139
136
-
Also, note that this doesn't affect how the user writes code. Users can simply write normal Julia code using `ArrayFire.jl` and this asynchronous behaviour is abstracted out. Whenever the data is needed back onto the CPU, an implicit barrier ensures that the computatation is complete, and the values are transferred back.
140
+
Also, note that this does not affect how the user writes code. Users can simply write normal Julia code using `ArrayFire.jl` and this asynchronous behaviour is abstracted out. Whenever the data is needed back onto the CPU, an implicit barrier ensures that the computatation is complete, and the values are transferred back.
137
141
138
-
**operations between CPU and device arrays**: Consider the following code. It will return an error:
142
+
**Operations between CPU and device arrays**: Consider the following code. It will return an error:
139
143
```julia
140
144
a =rand(Float32, 10, 10)
141
145
b =AFArray(a)
@@ -149,7 +153,7 @@ AFArray(a) - b # This works too!
149
153
150
154
**A note on correctness**: Sometimes, `ArrayFire.jl` and Base Julia might return marginally different values from their computation. This is because Julia and `ArrayFire.jl` sometimes use different lower level libraries for BLAS, FFT, etc. For example, Julia uses OpenBLAS for BLAS operations, but `ArrayFire.jl` would use clBLAS for the OpenCL backend and CuBLAS for the CUDA backend, and these libraries might not always the exact same values as OpenBLAS after a certain decimal point. In light of this, users are encouraged to keep testing their codes for correctness.
151
155
152
-
**A note on performance**: Some operations can be slow due to Base's generic implementations. This is intentional, to enable a "make it work, then make it fast" workflow. When you're ready you can disable slow fallback methods:
156
+
**A note on performance**: Some operations can be slow due to `Base`'s generic implementations. This is intentional, to enable a "make it work, then make it fast" workflow. When you're ready you can disable slow fallback methods:
ArrayFire was benchmarked on commonly used operations.
@@ -244,10 +248,10 @@ backend. `ArrayFire.jl` starts up with the unified backend.
244
248
245
249
If the backend selected by ArrayFire by default (depends on the available drivers) is not the desired one (depending on the available hardware), you can override the default by setting the environment variable `$JULIA_ARRAYFIRE_BACKEND` before starting Julia (more specifically, before loading the `ArrayFire` module). Possible values for `$JULIA_ARRAYFIRE_BACKEND` are `cpu`, `cuda` and `opencl`.
246
250
247
-
You may also change the backend at runtime via, e.g., `set_backend(AF_BACKEND_CPU)` (resp. `AF_BACKEND_CUDA` or
248
-
`AF_BACKEND_OPENCL`). The unified backend isn't a computational backend by itself but represents an interface to switch
251
+
You may also change the backend at runtime via, e.g., `set_backend(AF_BACKEND_CPU)` (resp. `AF_BACKEND_CUDA` or`AF_BACKEND_OPENCL`).
252
+
The unified backend isn't a computational backend by itself but represents an interface to switch
249
253
between different backends at runtime. `ArrayFire.jl` starts up with the unified backend, but `get_active_backend()`
250
-
will return either a particular default backend, depending on how you've installed the library. For example, if you've
254
+
will return either a particular default backend, depending on how you have installed the library. For example, if you have
251
255
built `ArrayFire.jl` with the CUDA backend, `get_active_backend()` will return `AF_BACKEND_CUDA` backend.
252
256
253
257
@@ -264,7 +268,7 @@ If you're using the CUDA backend, try checking if `libcudart` and `libnvvm` are
264
268
265
269
If you want to use the CUDA backend, check if you have installed CUDA for your platform. If you've installed CUDA, simply downloaded a binary and it still doens't work, try adding `libnvvm`, `libcudart` to your path.
266
270
267
-
> `ArrayFire.jl`doesn't work with Atom.
271
+
> `ArrayFire.jl`does not work with Atom.
268
272
269
273
Create a file in your home directory called `.juliarc.jl` and write `ENV["LD_LIBRARY_PATH"] = "/usr/local/lib/"` (or the path to `libaf`) in it. Atom should now be able to load it.
0 commit comments