Example #1
0
 private QueueItem NextItem()
 {
     if (EnableResourceScheduling)
     {
         return(ResourceSections
                // 各リソース区間の優先度リスト
                .Select(prs => prs
                        // リソース区間のエントリをリスト化
                        // リストは優先度の高い順になっていることに注意
                        .SelectMany(pr => queue[pr])
                        // リソースキーでまとめる
                        .GroupBy(entry => entry.Key)
                        // リソースキーをコストに変換
                        // アイテムはそのリソースキーで最も優先度の高いアイテム1つだけにする
                        // アイテムは優先度順になっているはずなのでこれでOK
                        .Select(g => new {
             Cost = resourceManager.ResourceCost(ReqResource.FromCanonical(g.Key)),
             Item = g.First().Value.First()
         })
                        // リソースの空き具合で並べ替え
                        .OrderBy(g => g.Cost)
                        // 最もリソースの空きの大きいアイテムを選択
                        // アイテムがない場合nullになることに注意
                        .FirstOrDefault()?.Item)
                // 優先度の高い順になっているので最初のアイテムを返す
                .FirstOrDefault(s => s != null));
     }
     else
     {
         return(queue.Reverse()
                .Select(level => level.FirstOrDefault().Value?.FirstOrDefault())
                .FirstOrDefault(s => s != null));
     }
 }
Example #2
0
        /// <summary>
        /// リソースを確保する
        /// </summary>
        /// <param name="req">次のフェーズで必要なリソース</param>
        /// <param name="cancelToken">キャンセルトークン</param>
        /// <returns>確保されたリソース</returns>
        public async Task <Resource> GetResource(ReqResource req, CancellationToken cancelToken, bool reqEncoderIndex)
        {
            var waiting = new WaitinResource()
            {
                Req = req
            };

            cancelToken.Register((Action)(() =>
            {
                waitingResources.Remove(waiting);
                // キャンセルされたら一旦動かす
                SignalAll();
            }), true);

            waitingResources.Add(waiting);
            RecalculateCosts();

            while (true)
            {
                // リソース確保可能 かつ 最小コスト
                if (waiting.Cost <= 0 && waiting.Cost <= waitingResources[0].Cost)
                {
                    waitingResources.Remove(waiting);
                    var res = ForceGetResource(req, reqEncoderIndex);
                    SignalAll();
                    return(res);
                }
                // リソースに空きがないので待つ
                //Util.AddLog("リソース待ち: " + req.CPU + ":" + req.HDD + ":" + req.GPU);
                await waitTask.Task;
                // キャンセルされてたら例外を投げる
                cancelToken.ThrowIfCancellationRequested();
            }
        }
Example #3
0
        public int ResourceCost(ReqResource req)
        {
            int gpuIndex = MostCapableGPU();
            int nextCPU  = curCPU + req.CPU;
            int nextHDD  = curHDD + req.HDD;
            int nextGPU  = curGPU[gpuIndex] + req.GPU;

            return(Math.Max(Math.Max(nextCPU - MAX, nextHDD - MAX), nextGPU - maxGPU[gpuIndex]));
        }
Example #4
0
        // 上限を無視してリソースを確保
        public Resource ForceGetResource(ReqResource req, bool reqEncoderIndex)
        {
            int gpuIndex = MostCapableGPU();

            curCPU           += req.CPU;
            curHDD           += req.HDD;
            curGPU[gpuIndex] += req.GPU;
            RecalculateCosts();

            return(new Resource()
            {
                Req = req,
                GpuIndex = gpuIndex,
                EncoderIndex = reqEncoderIndex ? AllocateEncoderIndex() : -1
            });
        }
Example #5
0
        public Resource TryGetResource(ReqResource req, bool reqEncoderIndex)
        {
            int cost = ResourceCost(req);

            if (cost > 0)
            {
                // 上限を超えるのでダメ
                return(null);
            }

            if (waitingResources.Count > 0)
            {
                // 待っている人がいる場合は、コストが最小値以下でない場合はダメ
                if (cost > waitingResources[0].Cost)
                {
                    return(null);
                }
            }

            // OK
            return(ForceGetResource(req, reqEncoderIndex));
        }