| 27 | |
| 28 | template<typename T, typename To> |
| 29 | void allDistances(Param dist, Param query, Param train, const dim_t dist_dim, |
| 30 | af_match_type dist_type) { |
| 31 | constexpr unsigned THREADS = 256; |
| 32 | |
| 33 | const unsigned feat_len = static_cast<uint>(query.info.dims[dist_dim]); |
| 34 | const unsigned max_kern_feat_len = |
| 35 | min(THREADS, static_cast<unsigned>(feat_len)); |
| 36 | const To max_dist = maxval<To>(); |
| 37 | |
| 38 | // Determine maximum feat_len capable of using shared memory (faster) |
| 39 | cl_ulong avail_lmem = getDevice().getInfo<CL_DEVICE_LOCAL_MEM_SIZE>(); |
| 40 | size_t lmem_predef = |
| 41 | 2 * THREADS * sizeof(unsigned) + max_kern_feat_len * sizeof(T); |
| 42 | size_t ltrain_sz = THREADS * max_kern_feat_len * sizeof(T); |
| 43 | bool use_lmem = (avail_lmem >= (lmem_predef + ltrain_sz)) ? true : false; |
| 44 | size_t lmem_sz = (use_lmem) ? lmem_predef + ltrain_sz : lmem_predef; |
| 45 | |
| 46 | unsigned unroll_len = nextpow2(feat_len); |
| 47 | if (unroll_len != feat_len) unroll_len = 0; |
| 48 | |
| 49 | std::array<TemplateArg, 4> targs = { |
| 50 | TemplateTypename<T>(), |
| 51 | TemplateArg(dist_type), |
| 52 | TemplateArg(use_lmem), |
| 53 | TemplateArg(unroll_len), |
| 54 | }; |
| 55 | |
| 56 | std::vector<std::string> options = { |
| 57 | DefineKeyValue(T, dtype_traits<T>::getName()), |
| 58 | DefineKeyValue(To, dtype_traits<To>::getName()), |
| 59 | DefineValue(THREADS), |
| 60 | DefineKeyValue(FEAT_LEN, unroll_len), |
| 61 | }; |
| 62 | options.emplace_back(getTypeBuildDefinition<T>()); |
| 63 | if (use_lmem) { options.emplace_back(DefineKey(USE_LOCAL_MEM)); } |
| 64 | if (dist_type == AF_SAD) { |
| 65 | options.emplace_back(DefineKeyValue(DISTOP, "_sad_")); |
| 66 | } |
| 67 | if (dist_type == AF_SSD) { |
| 68 | options.emplace_back(DefineKeyValue(DISTOP, "_ssd_")); |
| 69 | } |
| 70 | if (dist_type == AF_SHD) { |
| 71 | options.emplace_back(DefineKeyValue(DISTOP, "_shd_")); |
| 72 | options.emplace_back(DefineKey(__SHD__)); |
| 73 | } |
| 74 | auto hmOp = common::getKernel("knnAllDistances", |
| 75 | {{nearest_neighbour_cl_src}}, targs, options); |
| 76 | |
| 77 | const dim_t sample_dim = (dist_dim == 0) ? 1 : 0; |
| 78 | |
| 79 | const unsigned ntrain = train.info.dims[sample_dim]; |
| 80 | |
| 81 | unsigned nblk = divup(ntrain, THREADS); |
| 82 | const cl::NDRange local(THREADS, 1); |
| 83 | const cl::NDRange global(nblk * THREADS, 1); |
| 84 | |
| 85 | // For each query vector, find training vector with smallest Hamming |
| 86 | // distance per CUDA block |
nothing calls this directly
no test coverage detected