MCPcopy Create free account
hub / github.com/arrayfire/arrayfire / threadsMgt

Method threadsMgt

src/backend/opencl/threadsMgt.hpp:86–167  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

84// OUTPUT this.loop0, this.loop1, this.loop3 are ready to create the kernel
85template<typename T>
86threadsMgt<T>::threadsMgt(const T dims[4], const T ndims,
87 const unsigned nrInputs, const unsigned nrOutputs,
88 const size_t totalSize, const size_t sizeofT)
89 : loop0(false)
90 , loop1(false)
91 , loop3(false)
92 , d0(static_cast<unsigned>(dims[0]))
93 , d1(static_cast<unsigned>(dims[1]))
94 , d2(static_cast<unsigned>(dims[2]))
95 , d3(static_cast<unsigned>(dims[3]))
96 , ndims(ndims)
97 , totalSize(totalSize)
98 , dev(opencl::getDevice())
99 , maxParallelThreads(getMaxParallelThreads(dev))
100 , maxThreads(maxParallelThreads *
101 (sizeofT * nrInputs * nrInputs > 8 ? 1 : 2))
102 , largeVolDivider(1) {
103 const unsigned cacheLine{getMemoryBusWidth(dev)};
104 const size_t L2CacheSize{getL2CacheSize(dev)};
105 // The bottleneck of anykernel is dependent on the type of memory
106 // used.
107 // a) For very small arrays (elements < maxParallelThreads), each
108 // element receives it individual thread
109 // b) For arrays (in+out) smaller
110 // than 3/2 L2cache, memory access no longer is the bottleneck,
111 // because enough L2cache is available at any time. Threads are
112 // limited to reduce scheduling overhead.
113 // c) For very large arrays and type sizes
114 // (<long double), 1 thread will not generate enough data to keep
115 // the memory sync mechanism saturated, so we start loooping inside
116 // each thread.
117 //
118 if (ndims == 1) {
119 if (d0 > maxThreads) {
120 loop0 = true;
121 if (totalSize * 2 > L2CacheSize * 3) {
122 // General formula to calculate best #loops
123 // Dedicated GPUs:
124 // 32/sizeof(T)**2/#outBuffers*(3/4)**(#inBuffers-1)
125 // Integrated GPUs:
126 // 4/sizeof(T)/#outBuffers*(3/4)**(#inBuffers-1)
127 largeVolDivider = cacheLine == 64 ? sizeofT == 1 ? 4
128 : sizeofT == 2 ? 2
129 : 1
130 : (sizeofT == 1 ? 32
131 : sizeofT == 2 ? 8
132 : 1) /
133 nrOutputs;
134 for (unsigned i = 1; i < nrInputs; ++i)
135 largeVolDivider = largeVolDivider * 3 / 4;
136 loop0 = largeVolDivider > 1;
137 }
138 }
139 } else {
140 loop3 = d3 != 1;
141 if ((d1 > 1) & (d0 * d1 * d2 > maxThreads)) {
142 loop1 = true;
143 if ((d0 * sizeofT * 8 > cacheLine * getComputeUnits(dev)) &

Callers

nothing calls this directly

Calls 5

getDeviceFunction · 0.85
getMaxParallelThreadsFunction · 0.70
getMemoryBusWidthFunction · 0.70
getL2CacheSizeFunction · 0.70
getComputeUnitsFunction · 0.70

Tested by

no test coverage detected