================================================================================================
| 665 | |
| 666 | // ================================================================================================ |
| 667 | void Kernel::FindLocalWorkSize(size_t workDim, const amd::NDRange& gblWorkSize, |
| 668 | amd::NDRange& lclWorkSize) const { |
| 669 | // Initialize the default workgoup info |
| 670 | // Check if the kernel has the compiled sizes |
| 671 | if (workGroupInfo()->compileSize_[0] == 0) { |
| 672 | // Find the default local workgroup size, if it wasn't specified |
| 673 | if (lclWorkSize[0] == 0) { |
| 674 | // Find threads per group |
| 675 | size_t thrPerGrp = workGroupInfo()->size_; |
| 676 | |
| 677 | // Check if kernel uses images |
| 678 | if (flags_.imageEna_ && |
| 679 | // and thread group is a multiple value of wavefronts |
| 680 | ((thrPerGrp % workGroupInfo()->wavefrontSize_) == 0) && |
| 681 | // and it's 2 or 3-dimensional workload |
| 682 | (workDim > 1) && (((gblWorkSize[0] % 16) == 0) && ((gblWorkSize[1] % 16) == 0))) { |
| 683 | // Use 8x8 workgroup size if kernel has image writes |
| 684 | if (flags_.imageWriteEna_ || (thrPerGrp != device().info().preferredWorkGroupSize_)) { |
| 685 | lclWorkSize[0] = 8; |
| 686 | lclWorkSize[1] = 8; |
| 687 | } else { |
| 688 | lclWorkSize[0] = 16; |
| 689 | lclWorkSize[1] = 16; |
| 690 | } |
| 691 | if (workDim == 3) { |
| 692 | lclWorkSize[2] = 1; |
| 693 | } |
| 694 | } else { |
| 695 | size_t tmp = thrPerGrp; |
| 696 | // Split the local workgroup into the most efficient way |
| 697 | for (uint d = 0; d < workDim; ++d) { |
| 698 | size_t div = tmp; |
| 699 | for (; (gblWorkSize[d] % div) != 0; div--); |
| 700 | lclWorkSize[d] = div; |
| 701 | tmp /= div; |
| 702 | } |
| 703 | |
| 704 | if (!workGroupInfo()->uniformWorkGroupSize_) { |
| 705 | // Assuming DWORD access |
| 706 | const uint cacheLineMatch = device().info().globalMemCacheLineSize_ >> 2; |
| 707 | |
| 708 | // Check if we couldn't find optimal workload |
| 709 | if (((lclWorkSize.product() % workGroupInfo()->wavefrontSize_) != 0) || |
| 710 | // or size is too small for the cache line |
| 711 | (lclWorkSize[0] < cacheLineMatch)) { |
| 712 | size_t maxSize = 0; |
| 713 | size_t maxDim = 0; |
| 714 | for (uint d = 0; d < workDim; ++d) { |
| 715 | if (maxSize < gblWorkSize[d]) { |
| 716 | maxSize = gblWorkSize[d]; |
| 717 | maxDim = d; |
| 718 | } |
| 719 | } |
| 720 | // Use X dimension as high priority. Runtime will assume that |
| 721 | // X dimension is more important for the address calculation |
| 722 | if ((maxDim != 0) && (gblWorkSize[0] >= (cacheLineMatch / 2))) { |
| 723 | lclWorkSize[0] = cacheLineMatch; |
| 724 | thrPerGrp /= cacheLineMatch; |
no test coverage detected