예제 #1
0
        public async Task CouldFindMaximumWithSpinWait()
        {
            var par0 = new Parameter("par0", 0, 10, 1);
            var par1 = new Parameter("par1", 0, 10, 1);
            var par2 = new Parameter("par2", 0, 10, 1);

            var pars = new Parameters(new[] { par0, par1, par2 });

            var total = pars.TotalInterations;

            Console.WriteLine($"Total iterations: {total}");

            Func <Parameters, ValueTask <double> > targetFunc = (args) =>
            {
                var task = Task.Run(() =>
                {
                    var sum = 0L;
                    for (var i = 0; i < 10000000; i++)
                    {
                        sum = sum + i;
                    }
                    // avoid any release optimization
                    if (sum == int.MaxValue)
                    {
                        throw new ApplicationException();
                    }

                    var result = -(Math.Pow(2 - args[0].Current, 2) + Math.Pow(1 - args[1].Current, 2) + Math.Pow(7 - args[2].Current, 2));
                    return(result);
                });
                return(new ValueTask <double>(task));
            };

            // true for memoize, second run is almost instant
            var maximizer = new GridOptimizer <double>(pars, targetFunc, true);

            EvalFolderFunc <double, EvalAddress> folder = FolderFunc;

            for (int i = 0; i < 2; i++)
            {
                var sw          = new Stopwatch();
                var startMemory = GC.GetTotalMemory(true);
                sw.Restart();

                var optimum = await maximizer.FoldGrid(EvalAddress.Worst, folder);

                var optParams = pars.SetPositionsFromLinearAddress(optimum.LinearAddress);

                var endMemory = GC.GetTotalMemory(false);
                sw.Stop();
                Console.WriteLine($"Elapsed: {sw.ElapsedMilliseconds}");
                Console.WriteLine($"Memory: {endMemory - startMemory}");
                Console.WriteLine($"Optimum: {optParams[0].Current} - {optParams[1].Current} - {optParams[2].Current}");
            }
        }
예제 #2
0
        public async Task CouldFindMaximum()
        {
            var sw          = new Stopwatch();
            var startMemory = GC.GetTotalMemory(true);

            sw.Restart();
            var par0 = new Parameter("par0", 0, 100, 1);
            var par1 = new Parameter("par1", 0, 100, 1);
            var par2 = new Parameter("par2", 0, 100, 1);

            var pars = new Parameters(new[] { par0, par1, par2 });

            var total = pars.TotalInterations;

            Console.WriteLine($"Total iterations: {total}");

            Func <Parameters, ValueTask <double> > targetFunc = (args) =>
            {
                //return Task.Run(() => {
                //    //await Task.Delay(0);
                //    var result = -(Math.Pow(200 - args[0].Current, 2) + Math.Pow(10 - args[1].Current, 2) +
                //          Math.Pow(70 - args[2].Current, 2));
                //    return result;
                //});

                var result = -(Math.Pow(20 - args[0].Current, 2) + Math.Pow(10 - args[1].Current, 2) +
                               Math.Pow(70 - args[2].Current, 2));
                return(new ValueTask <double>(result));
            };

            var maximizer = new GridOptimizer <double>(pars, targetFunc);

            EvalFolderFunc <double, EvalAddress> folder = FolderFunc;

            // NB Func<> cannot have byref params
            //Func<EvalAddress, GridOptimizer.EvalParametersResult, EvalAddress> folder = (state, item) => {
            //    if (item.Value > state.Value) {
            //        return new EvalAddress() { Value = item.Value, LinearAddress = item.Parameters.LinearAddress() };
            //    }
            //    return state;
            //};

            var optimum = await maximizer.FoldGrid(EvalAddress.Worst, folder);

            var optParams = pars.SetPositionsFromLinearAddress(optimum.LinearAddress);

            var endMemory = GC.GetTotalMemory(false);

            sw.Stop();
            Console.WriteLine($"Elapsed: {sw.ElapsedMilliseconds}");
            Console.WriteLine($"Memory: {endMemory - startMemory}");
            Console.WriteLine($"Optimum: {optParams[0].Current} - {optParams[1].Current} - {optParams[2].Current}");
        }
예제 #3
0
        /// <summary>
        /// Iterate over grid, evaluate target function and fold its results.
        /// </summary>
        public async Task <TState> FoldGrid <TState>(TState seed, EvalFolderFunc <TEval, TState> evalFolder, Parameters parameters = null)
        {
            parameters = parameters ?? _parameters.Clone().Reset();

            var accumulator = seed;

            var depth = 0;

            while (true)
            {
                if (depth < _parameters.Count)
                {
                    if (parameters.List[depth].MoveNext())
                    {
                        depth++;
                        // when all moved, the first `if` above is false
                    }
                    else
                    {
                        parameters.List[depth].Reset();
                        depth--;
                    }
                }
                else
                {
                    try
                    {
                        var position = _tail % _concurrencyLimit;
                        if (_activeTasks.Count < _concurrencyLimit)
                        {
                            var   point   = parameters.Clone();
                            var   address = point.LinearAddress();
                            TEval tmp;
                            var   t = (_memoize && _results.TryGetValue(address, out tmp)) ? new ValueTask <TEval>(tmp) : _targetFunc(point);
                            _activeTasks.Add(new EvalResultTask {
                                Parameters = point, Value = t
                            });
                        }
                        else
                        {
                            // now the active tasks buffer is full
                            // await on the task at the position, process the result and replace the task at the position
                            // if current task is slow and other tasks already completed, we will just replace them very quickly
                            // later, but while we are waiting for the tail task concurrency could drop,
                            // so here is 'amortized' concurrency.

                            var currentTask = _activeTasks[position];
                            await currentTask.Value;

                            var evalResult = new EvalParametersResult <TEval>()
                            {
                                Value      = currentTask.Value.Result,
                                Parameters = currentTask.Parameters
                            };
                            var   address = currentTask.Parameters.LinearAddress();
                            TEval tmp;
                            if (_memoize)
                            {
                                if (!_results.TryGetValue(address, out tmp))
                                {
                                    _results[address] = currentTask.Value.Result;
                                }
                            }

                            // NB this is single-threaded application of evalFolder and evalResult.Parameters could be modified
                            // later since they are reused. Folder should copy parameters or store linear address
                            accumulator = evalFolder(accumulator, ref evalResult);

                            for (int i = 0; i < parameters.Count; i++)
                            {
                                currentTask.Parameters.List[i] = parameters.List[i];
                            }
                            address = currentTask.Parameters.LinearAddress();
                            var t = (_memoize && _results.TryGetValue(address, out tmp)) ? new ValueTask <TEval>(tmp) : _targetFunc(currentTask.Parameters);

                            currentTask.Value      = t;
                            _activeTasks[position] = currentTask;
                            _tail++;
                        }
                    }
                    finally
                    {
                        depth--;
                    }
                }
                if (depth == -1)
                {
                    break;
                }
            }

            // NB All items in _activeTask are active

            foreach (var currentTask in _activeTasks)
            {
                await currentTask.Value;
                var evalResult = new EvalParametersResult <TEval>
                {
                    Value      = currentTask.Value.Result,
                    Parameters = currentTask.Parameters
                };
                accumulator = evalFolder(accumulator, ref evalResult);
            }

            return(accumulator);
        }