Skip to content

Commit 3cdf8e4

Browse files
committed
Merge branch 'develop' into feature/sycl
2 parents 5ac80a6 + d94e75a commit 3cdf8e4

133 files changed

Lines changed: 2778 additions & 3186 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎CMakeLists.txt‎

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -192,14 +192,6 @@ option(QUDA_BUILD_ALL_TESTS "build tests by default" ON)
192192
option(QUDA_INSTALL_ALL_TESTS "install tests by default" ON)
193193
option(QUDA_BUILD_SHAREDLIB "build quda as a shared lib" ON)
194194

195-
set(QUDA_ORDER_FP "8" CACHE STRING "which data order to use for Wilson, gauge (recon-8/9) and clover fixed-point fields (4, 8)")
196-
set(QUDA_ORDER_SP_MG "2" CACHE STRING "which data order to use for fp32 MG fields (2, 4)")
197-
set(QUDA_ORDER_FP_MG "2" CACHE STRING "which data order to use for fixed-point MG fields (2, 4, 8)")
198-
199-
set_property(CACHE QUDA_ORDER_FP PROPERTY STRINGS 4 8)
200-
set_property(CACHE QUDA_ORDER_SP_MG PROPERTY STRINGS 2 4)
201-
set_property(CACHE QUDA_ORDER_FP_MG PROPERTY STRINGS 2 4 8)
202-
203195
option(QUDA_BUILD_NATIVE_LAPACK "build the native blas/lapack library according to QUDA_TARGET" ON)
204196
option(QUDA_BUILD_NATIVE_FFT "build the native FFT library according to QUDA_TARGET" ON)
205197

@@ -235,6 +227,8 @@ set(QUDA_RECONSTRUCT
235227
"7"
236228
CACHE STRING "which reconstructs to instantiate in QUDA (3-bit number - 18, 13/12, 9/8)")
237229

230+
option(QUDA_FLUSH_DENORMALS "Whether to fliush denormals to zero" OFF)
231+
238232
option(QUDA_CLOVER_DYNAMIC "Dynamically invert the clover term" ON)
239233
option(QUDA_CLOVER_RECONSTRUCT "set to ON to enable compressed clover storage (requires QUDA_CLOVER_DYNAMIC)" ON)
240234
option(QUDA_CLOVER_CHOLESKY_PROMOTE "Whether to promote the internal precision when inverting the clover term" ON)
@@ -248,8 +242,6 @@ option(QUDA_CTEST_DISABLE_BENCHMARKS "Disable benchmark test" ON)
248242
option(QUDA_FAST_COMPILE_REDUCE "enable fast compilation in blas and reduction kernels (single warp per reduction)" OFF)
249243
option(QUDA_FAST_COMPILE_DSLASH "enable fast compilation in dslash kernels (~20% perf impact)" OFF)
250244

251-
option(QUDA_ALTERNATIVE_I_TO_F "enable using alternative integer-to-float conversion" OFF)
252-
253245
option(QUDA_OPENMP "enable OpenMP" OFF)
254246
set(QUDA_CXX_STANDARD
255247
17
@@ -277,19 +269,15 @@ option(QUDA_GENERATE_DOXYGEN "generate doxygen documentation")
277269
mark_as_advanced(QUDA_BUILD_ALL_TESTS)
278270
mark_as_advanced(QUDA_INSTALL_ALL_TESTS)
279271

280-
mark_as_advanced(QUDA_ORDER_FP)
281-
mark_as_advanced(QUDA_ORDER_SP_MG)
282-
mark_as_advanced(QUDA_ORDER_FP_MG)
283272
mark_as_advanced(QUDA_FAST_COMPILE_REDUCE)
284273
mark_as_advanced(QUDA_FAST_COMPILE_DSLASH)
285274

286-
mark_as_advanced(QUDA_ALTERNATIVE_I_TO_F)
287-
288275
mark_as_advanced(QUDA_MAX_MULTI_BLAS_N)
289276
mark_as_advanced(QUDA_MAX_MULTI_RHS)
290277
mark_as_advanced(QUDA_MAX_MULTI_RHS_TILE)
291278
mark_as_advanced(QUDA_MAX_KERNEL_ARG_SIZE)
292279
mark_as_advanced(QUDA_PRECISION)
280+
mark_as_advanced(QUDA_FLUSH_DENORMALS)
293281
mark_as_advanced(QUDA_RECONSTRUCT)
294282
mark_as_advanced(QUDA_CLOVER_CHOLESKY_PROMOTE)
295283
mark_as_advanced(QUDA_MULTIGRID_DSLASH_PROMOTE)

‎include/blas_helper.cuh‎

Lines changed: 104 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ namespace quda
5050

5151
#ifdef QUAD_SUM
5252
__host__ __device__ inline double set(doubledouble &a) { return a.head(); }
53-
__host__ __device__ inline double2 set(doubledouble2 &a) { return make_double2(a.x.head(), a.y.head()); }
54-
__host__ __device__ inline double3 set(doubledouble3 &a) { return make_double3(a.x.head(), a.y.head(), a.z.head()); }
53+
__host__ __device__ inline double2 set(doubledouble2 &a) { return {a.x.head(), a.y.head()}; }
54+
__host__ __device__ inline double3 set(doubledouble3 &a) { return {a.x.head(), a.y.head(), a.z.head()}; }
5555
__host__ __device__ inline void sum(double &a, doubledouble &b) { a += b.head(); }
5656
__host__ __device__ inline void sum(double2 &a, doubledouble2 &b)
5757
{
@@ -99,20 +99,14 @@ namespace quda
9999
Helper struct that contains the meta data required for
100100
read and writing to a spinor field in the BLAS kernels.
101101
@tparam store_t Type used to store field in memory
102-
@tparam N Length of vector
103102
*/
104-
template <typename store_t, int N, bool is_fixed> struct data_t {
105-
store_t *spinor;
106-
int stride;
107-
unsigned int cb_offset;
108-
data_t() :
109-
spinor(nullptr),
110-
stride(0),
111-
cb_offset(0)
112-
{}
113-
103+
template <typename store_t, bool is_fixed> struct data_t {
104+
store_t *spinor = nullptr;
105+
int stride = 0;
106+
unsigned int cb_offset = 0;
107+
data_t() = default;
114108
data_t(const ColorSpinorField &x) :
115-
spinor(x.data<store_t *>()), stride(x.VolumeCB()), cb_offset(x.Bytes() / (2 * sizeof(store_t) * N))
109+
spinor(x.data<store_t *>()), stride(x.VolumeCB()), cb_offset(x.Bytes() / (2 * sizeof(store_t)))
116110
{}
117111
};
118112

@@ -122,28 +116,20 @@ namespace quda
122116
specialized variant for fixed-point fields where need to store
123117
the meta data for the norm field.
124118
@tparam store_t Type used to store field in memory
125-
@tparam N Length of vector
126119
*/
127-
template <typename store_t, int N> struct data_t<store_t, N, true> {
120+
template <typename store_t> struct data_t<store_t, true> {
128121
using norm_t = float;
129-
store_t *spinor;
130-
norm_t *norm;
131-
int stride;
132-
unsigned int cb_offset;
133-
unsigned int cb_norm_offset;
134-
data_t() :
135-
spinor(nullptr),
136-
norm(nullptr),
137-
stride(0),
138-
cb_offset(0),
139-
cb_norm_offset(0)
140-
{}
141-
122+
store_t *spinor = nullptr;
123+
norm_t *norm = nullptr;
124+
int stride = 0;
125+
unsigned int cb_offset = 0;
126+
unsigned int cb_norm_offset = 0;
127+
data_t() = default;
142128
data_t(const ColorSpinorField &x) :
143129
spinor(x.data<store_t *>()),
144130
norm(static_cast<norm_t *>(x.Norm())),
145131
stride(x.VolumeCB()),
146-
cb_offset(x.Bytes() / (2 * sizeof(store_t) * N)),
132+
cb_offset(x.Bytes() / (2 * sizeof(store_t))),
147133
cb_norm_offset(x.Bytes() / (2 * sizeof(norm_t)))
148134
{}
149135
};
@@ -156,10 +142,9 @@ namespace quda
156142
template <typename store_t, int N> struct Spinor {
157143
using Vector = typename VectorType<store_t, N>::type;
158144
using norm_t = float;
159-
data_t<store_t, N, isFixed<store_t>::value> data;
160-
161-
Spinor() {}
145+
data_t<store_t, isFixed<store_t>::value> data;
162146

147+
Spinor() = default;
163148
Spinor(const ColorSpinorField &x) : data(x) {}
164149

165150
/**
@@ -234,37 +219,37 @@ namespace quda
234219
array<real, len> v_;
235220

236221
constexpr int M = len / N;
222+
constexpr int Nrem = len - M * N;
237223
#pragma unroll
238224
for (int i = 0; i < M; i++) {
239225
// first load from memory
240-
Vector vecTmp = vector_load<Vector>(data.spinor, parity * data.cb_offset + x + data.stride * i);
226+
auto vecTmp = vector_load<store_t, N>(data.spinor + parity * data.cb_offset, data.stride * i + x);
241227
// now copy into output and scale
242-
#pragma unroll
243-
// for (int j = 0; j < N; j++) copy_and_scale(v_[i * N + j], reinterpret_cast<store_t *>(&vecTmp)[j], nrm);
244-
for (int j = 0; j < N; j++) copy_and_scale(v_[i * N + j], elem(vecTmp, j), nrm);
228+
copy_and_scale(&v_[i * N], vecTmp, nrm);
229+
}
230+
if constexpr (Nrem > 0) {
231+
// first load from memory
232+
auto vecTmp = vector_load<store_t, Nrem>(data.spinor + parity * data.cb_offset + data.stride * M * N, x);
233+
// now copy into output and scale
234+
copy_and_scale(&v_[M * N], vecTmp, nrm);
245235
}
246236

237+
#pragma unroll
247238
for (int i = 0; i < n; i++) { v[i] = complex<real>(v_[2 * i + 0], v_[2 * i + 1]); }
248239
} else {
249240
// specialized path for half precision staggered
250-
using Vector = int4;
251241
auto cb_offset = data.cb_norm_offset / 4;
252242
norm_t nrm;
253243
array<real, len> v_;
254244

255245
// first load from memory
256-
Vector vecTmp = vector_load<Vector>(data.spinor, parity * cb_offset + x);
246+
auto vecTmp = vector_load<store_t, 8>(data.spinor, parity * cb_offset + x);
257247

258248
// extract norm
259-
memcpy(&nrm, &vecTmp.w, sizeof(norm_t));
260-
array<short, 6> vecTmpShort;
261-
memcpy(&vecTmpShort, &vecTmp, sizeof(vecTmpShort));
249+
memcpy(&nrm, &vecTmp[6], sizeof(norm_t));
262250

263251
// now copy into output and scale
264-
#pragma unroll
265-
// for (int i = 0; i < len; i++) copy_and_scale(v_[i], reinterpret_cast<store_t *>(&vecTmp)[i], nrm);
266-
// for (int i = 0; i < len; i++) copy_and_scale(v_[i], elem(vecTmp, i), nrm);
267-
for (int i = 0; i < len; i++) copy_and_scale(v_[i], vecTmpShort[i], nrm);
252+
copy_and_scale(&v_[0], vecTmp, nrm);
268253

269254
#pragma unroll
270255
for (int i = 0; i < n; i++) { v[i] = complex<real>(v_[2 * i + 0], v_[2 * i + 1]); }
@@ -284,56 +269,47 @@ namespace quda
284269
{
285270
constexpr int len = 2 * n; // real-valued length
286271

287-
if constexpr (!(n == 3 && isHalf<store_t>::value)) {
288-
array<real, len> v_;
289-
290-
if constexpr (isFixed<store_t>::value) {
291-
real scale_inv = store_norm<isFixed<store_t>::value, real, n>(v, data.norm[x + parity * data.cb_norm_offset]);
292-
#pragma unroll
293-
for (int i = 0; i < n; i++) {
294-
v_[2 * i + 0] = scale_inv * v[i].real();
295-
v_[2 * i + 1] = scale_inv * v[i].imag();
296-
}
297-
} else {
272+
array<real, len> v_;
298273
#pragma unroll
299-
for (int i = 0; i < n; i++) {
300-
v_[2 * i + 0] = v[i].real();
301-
v_[2 * i + 1] = v[i].imag();
302-
}
303-
}
274+
for (int i = 0; i < n; i++) {
275+
v_[2 * i + 0] = v[i].real();
276+
v_[2 * i + 1] = v[i].imag();
277+
}
278+
279+
if constexpr (!(n == 3 && isHalf<store_t>::value)) {
280+
real scale_inv = 0.0;
281+
if constexpr (isFixed<store_t>::value)
282+
scale_inv = store_norm<isFixed<store_t>::value, real, n>(v, data.norm[x + parity * data.cb_norm_offset]);
304283

305284
constexpr int M = len / N;
285+
constexpr int Nrem = len - M * N;
306286
#pragma unroll
307287
for (int i = 0; i < M; i++) {
308-
Vector vecTmp;
288+
array<store_t, N> vecTmp;
309289
// first do scalar copy converting into storage type
310-
#pragma unroll
311-
// for (int j = 0; j < N; j++) copy_scaled(reinterpret_cast<store_t *>(&vecTmp)[j], v_[i * N + j]);
312-
for (int j = 0; j < N; j++) copy_scaled(elem(vecTmp, j), v_[i * N + j]);
290+
copy_and_scale<store_t, real, N>(vecTmp, &v_[i * N], scale_inv);
291+
// second do vectorized copy into memory
292+
vector_store(data.spinor + parity * data.cb_offset, data.stride * i + x, vecTmp);
293+
}
294+
295+
if constexpr (Nrem > 0) {
296+
array<store_t, Nrem> vecTmp;
297+
// first do copy converting into storage type
298+
copy_and_scale<store_t, real, Nrem>(vecTmp, &v_[M * N], scale_inv);
313299
// second do vectorized copy into memory
314-
vector_store(data.spinor, parity * data.cb_offset + x + data.stride * i, vecTmp);
300+
vector_store(data.spinor + parity * data.cb_offset + data.stride * M * N, x, vecTmp);
315301
}
316302
} else {
317303
// specialized path for half precision staggered
318-
using Vector = int4;
319304
auto cb_offset = data.cb_norm_offset / 4;
320305
norm_t norm;
321306
norm_t scale_inv = store_norm<isFixed<store_t>::value, real, n>(v, norm);
322-
array<real, len> v_;
323-
#pragma unroll
324-
for (int i = 0; i < n; i++) {
325-
v_[2 * i + 0] = scale_inv * v[i].real();
326-
v_[2 * i + 1] = scale_inv * v[i].imag();
327-
}
328307

329-
Vector vecTmp;
330-
memcpy(&vecTmp.w, &norm, sizeof(norm_t)); // pack the norm
331-
array<short, 6> vecTmpShort;
332-
#pragma unroll
333-
// for (int i = 0; i < len; i++) copy_scaled(reinterpret_cast<store_t *>(&vecTmp)[i], v_[i]);
334-
// for (int i = 0; i < len; i++) copy_scaled(elem(vecTmp, i), v_[i]);
335-
for (int i = 0; i < len; i++) copy_scaled(vecTmpShort[i], v_[i]);
336-
memcpy(&vecTmp, &vecTmpShort, sizeof(vecTmpShort));
308+
array<store_t, 8> vecTmp;
309+
memcpy(&vecTmp[6], &norm, sizeof(norm_t)); // pack the norm
310+
array<store_t, 6> vecTmp2;
311+
copy_and_scale<store_t, real, 6>(vecTmp2, &v_[0], scale_inv);
312+
std::memcpy(&vecTmp, &vecTmp2, sizeof(vecTmp2));
337313
// second do vectorized copy into memory
338314
vector_store(data.spinor, parity * cb_offset + x, vecTmp);
339315
}
@@ -349,42 +325,59 @@ namespace quda
349325
@tparam site_unroll Whether we enforce all site components must
350326
be unrolled onto the same thread (required for fixed-point precision)
351327
*/
352-
template <typename store_t, bool GPU, int nSpin, bool site_unroll> constexpr int n_vector() { return 0; }
328+
template <typename store_t, bool GPU> constexpr int n_vector(int, int) { return 0; }
353329

354330
// native ordering
355-
template <> constexpr int n_vector<double, true, 4, false>() { return 2; }
356-
template <> constexpr int n_vector<double, true, 1, false>() { return 2; }
357-
358-
template <> constexpr int n_vector<double, true, 4, true>() { return 2; }
359-
template <> constexpr int n_vector<double, true, 1, true>() { return 2; }
360-
361-
template <> constexpr int n_vector<float, true, 4, false>() { return 4; }
362-
template <> constexpr int n_vector<float, true, 1, false>() { return 4; }
331+
template <> constexpr int n_vector<double, true>(int nSpin, int site_unroll)
332+
{
333+
if (site_unroll)
334+
return nSpin == 4 ? colorspinor::get_vector_order<double>(24) : colorspinor::get_vector_order<double>(6);
335+
else
336+
return colorspinor::get_vector_order<double>(4);
337+
}
363338

364-
template <> constexpr int n_vector<float, true, 4, true>() { return 4; }
365-
template <> constexpr int n_vector<float, true, 1, true>() { return 2; }
339+
template <> constexpr int n_vector<float, true>(int nSpin, int site_unroll)
340+
{
341+
if (site_unroll)
342+
return nSpin == 4 ? colorspinor::get_vector_order<float>(24) : colorspinor::get_vector_order<float>(6);
343+
else
344+
return colorspinor::get_vector_order<float>(8);
345+
}
366346

367-
template <> constexpr int n_vector<short, true, 4, true>() { return QUDA_ORDER_FP; }
368-
template <> constexpr int n_vector<short, true, 1, true>() { return 2; }
347+
template <> constexpr int n_vector<short, true>(int nSpin, int site_unroll)
348+
{
349+
if (site_unroll)
350+
return nSpin == 4 ? colorspinor::get_vector_order<short>(24) : colorspinor::get_vector_order<short>(6);
351+
else
352+
return colorspinor::get_vector_order<short>(16);
353+
}
369354

370-
template <> constexpr int n_vector<int8_t, true, 4, true>() { return QUDA_ORDER_FP; }
371-
template <> constexpr int n_vector<int8_t, true, 1, true>() { return 2; }
355+
template <> constexpr int n_vector<int8_t, true>(int nSpin, int site_unroll)
356+
{
357+
if (site_unroll)
358+
return nSpin == 4 ? colorspinor::get_vector_order<int8_t>(24) : colorspinor::get_vector_order<int8_t>(6);
359+
else
360+
return colorspinor::get_vector_order<int8_t>(16);
361+
}
372362

373363
// Just use float-2/float-4 ordering on CPU when not site unrolling
374-
template <> constexpr int n_vector<double, false, 4, false>() { return 2; }
375-
template <> constexpr int n_vector<double, false, 1, false>() { return 2; }
376-
template <> constexpr int n_vector<float, false, 4, false>() { return 4; }
377-
template <> constexpr int n_vector<float, false, 1, false>() { return 4; }
378-
379-
// AoS ordering is used on CPU uses when we are site unrolling
380-
template <> constexpr int n_vector<double, false, 4, true>() { return 24; }
381-
template <> constexpr int n_vector<double, false, 1, true>() { return 6; }
382-
template <> constexpr int n_vector<float, false, 4, true>() { return 24; }
383-
template <> constexpr int n_vector<float, false, 1, true>() { return 6; }
384-
template <> constexpr int n_vector<short, false, 4, true>() { return 24; }
385-
template <> constexpr int n_vector<short, false, 1, true>() { return 6; }
386-
template <> constexpr int n_vector<int8_t, false, 4, true>() { return 24; }
387-
template <> constexpr int n_vector<int8_t, false, 1, true>() { return 6; }
364+
template <> constexpr int n_vector<double, false>(int nSpin, int site_unroll)
365+
{
366+
if (site_unroll) {
367+
return nSpin * 6;
368+
} else {
369+
return 2;
370+
}
371+
}
372+
373+
template <> constexpr int n_vector<float, false>(int nSpin, int site_unroll)
374+
{
375+
if (site_unroll) {
376+
return nSpin * 6;
377+
} else {
378+
return 4;
379+
}
380+
}
388381

389382
template <template <typename...> class Functor,
390383
template <template <typename...> class, typename store_t, typename y_store_t, int, typename> class Blas,

0 commit comments

Comments
 (0)