| 66 | } |
| 67 | |
| 68 | void CPUConv::submitKernels(const Ref<CancellationToken>& ct) |
| 69 | { |
| 70 | if (!src || !dst || !weight || !bias) |
| 71 | throw std::logic_error("convolution argument not set"); |
| 72 | |
| 73 | ispc::CPUConvKernel kernel; |
| 74 | kernel.src = *src; |
| 75 | kernel.weight = *weight; |
| 76 | kernel.bias = *bias; |
| 77 | kernel.dst = *dst; |
| 78 | kernel.relu = activation == Activation::ReLU; |
| 79 | |
| 80 | engine->submitFunc([=] |
| 81 | { |
| 82 | const int OH = kernel.dst.H; // output height |
| 83 | const int OW = kernel.dst.W; // output width |
| 84 | const size_t N = size_t(OCBB) * OH * OWC; // total number of work items |
| 85 | |
| 86 | parallel_for(N, [&](size_t i) |
| 87 | { |
| 88 | const size_t j = i / OCBB; |
| 89 | const int ocbb = int(i % OCBB); // output channel block block index |
| 90 | const int oh = int(j % OH); // output height index |
| 91 | const int owc = int(j / OH); // output width chunk index |
| 92 | |
| 93 | constexpr int PW = 1; // KW = 3 |
| 94 | const int owr = OWC * (blockOW - PW - 1); |
| 95 | const int owBegin = owc > 0 ? (owc * OW + owr) / (OWC*blockOW) * blockOW + PW : 0; |
| 96 | const int owEnd = owc+1 < OWC ? ((owc+1) * OW + owr) / (OWC*blockOW) * blockOW + PW : OW; |
| 97 | |
| 98 | ispc::CPUConvKernel_run_f32(&kernel, blockOCB, ocbb * blockOCB, oh, owBegin, owEnd); |
| 99 | }); |
| 100 | }, ct); |
| 101 | } |
| 102 | |
| 103 | OIDN_NAMESPACE_END |
nothing calls this directly
no test coverage detected