/// <summary> /// Calculate the kernel values. /// </summary> /// /// <param name="kernel">The kernel to calculate for.</param> /// <param name="training">The training params to use.</param> public void CalculateKernelParams(EncogKernel kernel, IEngineIndexableSet training) { bool globalValuesAssigned = false; int workPerIteration; // there are two special cases // first, if the ratio is 1.0 if (Math.Abs(this.segmentationRatio - 1.0d) < EncogEngine.DEFAULT_ZERO_TOLERANCE) { // if the segmentation ratio is 1, then we want NO SEGMENTATION // we will have to find a workgroup size that is even int trialLocalSize = (int)Math.Min(kernel.MaxWorkGroupSize, training.Count); trialLocalSize++;// falsely add one so the loop can decrease it with // no effect. // loop and try to find a local size small enough to be even. do { trialLocalSize--; this.kernelLocalWorkgroup = (int)(trialLocalSize * this.localRatio); this.kernelGlobalWorkgroup = (int)(this.kernelLocalWorkgroup * this.globalRatio); this.kernelWorkPerCall = (int)((training.Count / this.kernelGlobalWorkgroup) * this.segmentationRatio); workPerIteration = this.kernelGlobalWorkgroup * this.kernelWorkPerCall; } while ((workPerIteration != training.Count) && trialLocalSize > 1); if (trialLocalSize > 0) globalValuesAssigned = true; } // if we either wanted to segment, or the attempt to find an even group // size above failed if (!globalValuesAssigned) { // otherwise divide into segments int maxLocalSize = (int)Math.Min(kernel.MaxWorkGroupSize, training.Count); this.kernelLocalWorkgroup = (int)(maxLocalSize * this.localRatio); this.kernelGlobalWorkgroup = (int)(this.kernelLocalWorkgroup * this.globalRatio); // second special case, if the segmentation ratio is zero, then just // do one item per OpenCL call if (this.segmentationRatio < EncogEngine.DEFAULT_ZERO_TOLERANCE) { this.kernelWorkPerCall = 1; } else { this.kernelWorkPerCall = (int)((training.Count / this.kernelGlobalWorkgroup) * this.segmentationRatio); if (this.kernelWorkPerCall == 0) { this.kernelWorkPerCall = 1; } } } workPerIteration = this.kernelGlobalWorkgroup * this.kernelWorkPerCall; this.kernelNumberOfCalls = (int)(training.Count / workPerIteration); this.kernelRemainder = (int)(training.Count % workPerIteration); this.kernelRemainderGlobal = this.kernelGlobalWorkgroup; // if there is no "final training set", because it lined up evenly, // still create one. // the final training set is where learning happens. if (this.kernelRemainder == 0) { this.kernelRemainder = this.kernelGlobalWorkgroup; this.kernelRemainderPer = this.kernelWorkPerCall; this.kernelNumberOfCalls--; } else this.kernelRemainderPer = this.kernelRemainder / this.kernelGlobalWorkgroup; // does the remainder not have enough to fill the global tasks global? if (this.kernelRemainderPer == 0) { this.kernelRemainderPer = 1; this.kernelRemainderGlobal = this.kernelRemainder; } }
/// <summary> /// Execute the specified kernel. /// </summary> /// /// <param name="kernel">The kernel to execute.</param> public void Execute(EncogKernel kernel) { long[] globalWorkSize = new long[] { kernel.GlobalWork }; long[] localWorkSize = new long[] { kernel.LocalWork }; // Execute the kernel this.commands.Execute(kernel.Kernel, null, globalWorkSize, localWorkSize, null); }