/build/arrayfire/src/arrayfire-full-3.6.1/docs/pages/unified_backend.md
Go to the documentation of this file.
1 Unified Backend {#unifiedbackend}
2 ==========
3 
4 [TOC]
5 
6 # Introduction
7 
8 The Unified backend was introduced in ArrayFire with version 3.2.
9 While this is not an independent backend, it allows the user to switch between
10 the different ArrayFire backends (CPU, CUDA and OpenCL) at runtime.
11 
12 # Compiling with Unified
13 
14 The steps to compile with the unified backend are the same as compiling with
15 any of the other backends.
16 The only change being that the executable needs to be linked with the __af__
17 library (`libaf.so` (Linux), `libaf.dylib` (OSX), `af.lib` (Windows)).
18 
19 Check the Using with [Linux](\ref using_on_linux), [OSX](\ref using_on_osx),
20 [Windows](\ref using_on_windows) for more details.
21 
22 To use with CMake, use the __ArrayFire_Unified_LIBRARIES__ variable.
23 
24 # Using the Unified Backend
25 
26 The Unified backend will try to dynamically load the backend libraries. The
27 priority of backends is __CUDA -> OpenCL -> CPU__
28 
29 The most important aspect to note here is that all the libraries the ArrayFire
30 libs depend on need to be in the environment paths
31 
32 * `LD_LIBRARY_PATH` -> Linux, Unix, OSX
33 * `DYLD_LIBRARY_PATH` -> OSX
34 * `PATH` -> Windows
35 
36 If any of the libs are missing, then the library will fail to load and the
37 backend will be marked as unavailable.
38 
39 Optionally, The ArrayFire libs may be present in `AF_PATH` or `AF_BUILD_PATH`
40 environment variables if the path is not in the system paths. These are
41 treated as fallback paths in case the files are not found in the system paths.
42 However, all the other upstream libraries for ArrayFire libs must be present
43 in the system path variables shown above.
44 
45 # Switching Backends
46 
47 The af_backend enum stores the possible backends.
48 To select a backend, call the af::setBackend function as shown below.
49 
50 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
51 af::setBackend(AF_BACKEND_CUDA); // Sets CUDA as current backend
52 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53 
54 To get the count of the number of backends available (the number of `libaf*`
55 backend libraries loaded successfully), call the af::getBackendCount function.
56 
57 # Example
58 
59 This example is shortened form of [basic.cpp](\ref unified/basic.cpp).
60 
61 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
62 #include <arrayfire.h>
63 
64 void testBackend()
65 {
66  af::info();
67  af_print(af::randu(5, 4));
68 }
69 
70 int main()
71 {
72  try {
73  printf("Trying CPU Backend\n");
74  af::setBackend(AF_BACKEND_CPU);
75  testBackend();
76  } catch (af::exception& e) {
77  printf("Caught exception when trying CPU backend\n");
78  fprintf(stderr, "%s\n", e.what());
79  }
80 
81  try {
82  printf("Trying CUDA Backend\n");
83  af::setBackend(AF_BACKEND_CUDA);
84  testBackend();
85  } catch (af::exception& e) {
86  printf("Caught exception when trying CUDA backend\n");
87  fprintf(stderr, "%s\n", e.what());
88  }
89 
90  try {
91  printf("Trying OpenCL Backend\n");
92  af::setBackend(AF_BACKEND_OPENCL);
93  testBackend();
94  } catch (af::exception& e) {
95  printf("Caught exception when trying OpenCL backend\n");
96  fprintf(stderr, "%s\n", e.what());
97  }
98 
99  return 0;
100 }
101 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
102 
103 This output would be:
104 
105  Trying CPU Backend
106  ArrayFire v3.2.0 (CPU, 64-bit Linux, build fc7630f)
107  [0] Intel: Intel(R) Core(TM) i7-4770K CPU @ 3.50GHz Max threads(8)
108  af::randu(5, 4)
109  [5 4 1 1]
110  0.0000 0.2190 0.3835 0.5297
111  0.1315 0.0470 0.5194 0.6711
112  0.7556 0.6789 0.8310 0.0077
113  0.4587 0.6793 0.0346 0.3834
114  0.5328 0.9347 0.0535 0.0668
115 
116  Trying CUDA Backend
117  ArrayFire v3.2.0 (CUDA, 64-bit Linux, build fc7630f)
118  Platform: CUDA Toolkit 7.5, Driver: 355.11
119  [0] Quadro K5000, 4093 MB, CUDA Compute 3.0
120  af::randu(5, 4)
121  [5 4 1 1]
122  0.7402 0.4464 0.7762 0.2920
123  0.9210 0.6673 0.2948 0.3194
124  0.0390 0.1099 0.7140 0.8109
125  0.9690 0.4702 0.3585 0.1541
126  0.9251 0.5132 0.6814 0.4452
127 
128  Trying OpenCL Backend
129  ArrayFire v3.2.0 (OpenCL, 64-bit Linux, build fc7630f)
130  [0] NVIDIA : Quadro K5000
131  -1- INTEL : Intel(R) Core(TM) i7-4770K CPU @ 3.50GHz
132  af::randu(5, 4)
133  [5 4 1 1]
134  0.4107 0.0081 0.6600 0.1046
135  0.8224 0.3775 0.0764 0.8827
136  0.9518 0.3027 0.0901 0.1647
137  0.1794 0.6456 0.5933 0.8060
138  0.4198 0.5591 0.1098 0.5938
139 
140 # Dos and Don'ts
141 
142 It is very easy to run into exceptions if you are not careful with the
143 switching of backends.
144 
145 ### Don't: Do not use arrays between different backends
146 
147 ArrayFire checks the input arrays to functions for mismatches with the active
148 backend. If an array created on one backend, but used when another backend is
149 set to active, an exception with code 503 (`AF_ERR_ARR_BKND_MISMATCH`) is
150 thrown.
151 
152 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
153 #include <arrayfire.h>
154 
155 int main()
156 {
157  try {
158  af::setBackend(AF_BACKEND_CUDA);
159  af::array A = af::randu(5, 5);
160 
161  af::setBackend(AF_BACKEND_OPENCL);
162  af::array B = af::constant(10, 5, 5);
163  af::array C = af::matmul(A, B); // This will throw an exception
164 
165  } catch (af::exception& e) {
166  fprintf(stderr, "%s\n", e.what());
167  }
168 
169  return 0;
170 }
171 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
172 
173 ### Do: Use a naming scheme to track arrays and backends
174 
175 We recommend that you use a technique to track the arrays on the backends. One
176 suggested technique would be to use a suffix of `_cpu`, `_cuda`, `_opencl`
177 with the array names. So an array created on the CUDA backend would be named
178 `myarray_cuda`.
179 
180 If you have not used the af::setBackend function anywhere in your code, then
181 you do not have to worry about this as all the arrays will be created on the
182 same default backend.
183 
184 ### Don't: Do not use custom kernels (CUDA/OpenCL) with the Unified backend
185 
186 This is another area that is a no go when using the Unified backend. It not
187 recommended that you use custom kernels with unified backend. This is mainly
188 becuase the Unified backend is meant to be ultra portable and should use only
189 ArrayFire and native CPU code.