質問番号: 202203-3
質問名: コンピューティング リソース スケジューラ
制限時間: 1.0 秒
メモリ制限: 512.0MB
トピック リンク: CSP 25th CSP-CCF-202203-3 コンピューティング リソース スケジューラ
問題の説明:
トピックの背景
シシー アイボール島には多数のデータ センターが建設され、クラウド コンピューティング リソース プラットフォームが構築されています。Little C は、Sisi Aifer Cloud の開発を担当するエンジニアです。Sisyever Cloud には多数のコンピューティング ノードがあり、各コンピューティング ノードには一意の番号が付いています。
SISI Cloud は複数のアベイラビリティ ゾーンに分割されており、各コンピューティング ノードは特定のアベイラビリティ ゾーンに配置されます。アベイラビリティ ゾーンには複数のコンピューティング ノードが存在できます。
SISIIF Cloud で実行されるコンピューティング タスクはさまざまなアプリケーションに分割され、各コンピューティング タスクには対応するアプリケーションがあり、1 つのアプリケーションに複数のコンピューティング タスクが含まれる場合があります。
各計算タスクは特定の計算ノードによって実行され、以下、「ある可用性ゾーンで動作する」というときは、「ある可用性ゾーン内の計算ノードで動作する」ことを意味する。
コンピューティング タスクが異なれば、実行中のコンピューティング ノードに対する要件も異なります。
一部のコンピューティング タスクは、指定されたアベイラビリティ ゾーンで実行する必要があり、一部のコンピューティング タスクは、他のアプリケーション コンピューティング タスクと同じアベイラビリティ ゾーンで実行する必要があり、また、一部のコンピューティング タスクは、特定のアプリケーション コンピューティング タスクと同じコンピューティング ノード上で実行したくないものもあります。
コンピューティング タスクの場合、それを実行するコンピューティング ノードが選択されると、そのコンピューティング ノードは変更されません。コンピューティング ノードが選択された後は、新しくスケジュールされたコンピューティング タスクが以前の計算
ノードのタスクの要件に違反することも合法です。
次の図は、アベイラビリティ ゾーン、コンピューティング ノード、コンピューティング タスク間の関係、およびアプリケーションとコンピューティング タスク間の対応を概略的に示しています。
最初、Little C はスプレッドシート プログラムを使用してコンピューティング タスクの分布を数えました。クラウド上のコンピューティング ノードとコンピューティング タスクの数が増加するにつれて、Xiao C はこれらの奇妙な要件に圧倒され、時には間違った手配をしてしまい、顧客に大きな不満を与えていました。
Little C があなたを見つけました。実行するコンピューティング タスクとノードの要件を入力し、Sisiever Cloud の既存のコンピューティング ノードの情報を組み合わせて、どのコンピューティング ノードがコンピューティングを実行するかを計算できるプログラムを彼に提供できることを願っています。タスクは上位でスケジュールする必要があります。
問題の説明:
コンピューティング タスクにはコンピューティング ノードの要件が非常に複雑で、説明するのは簡単ではありません。あなたは Little C に、プログラムを書くのは非常に難しいと言いました。そこで、Little C は調査を実施し、
これらの要件を要約し、次の 3 つの標準要件を作成しました。要件を提示する場合、これら 3 つの標準要件からいくつかのタイプを選択する必要があり、各要件は 1 つだけを持つことができます。複数の要件を選択するということは、すべての要件を同時に満たすことを意味します。
- コンピューティング ノード アフィニティ
コンピューティング タスクは、指定されたアベイラビリティ ゾーンで実行する必要があります。 - コンピューティング タスクのアフィニティ
コンピューティング タスクは、指定されたアプリケーションのコンピューティング タスクと同じアベイラビリティ ゾーンで実行する必要があります。
この要件により、コンピューティング タスクを実行できるアベイラビリティ ゾーンに制限が追加されます。タスク自体に関係なく、可用性ゾーンが指定されたアプリケーションを使用してタスクを実行する場合、そのタスクは要件を満たします。 - 計算タスクの非アフィニティ
計算タスクは、指定されたアプリケーションの計算タスクと同じ計算ノード上で実行できません。
この要件により、計算タスクを実行できる計算ノードに制限が追加されます。タスク自体に関係なく、指定されたアプリケーションでタスクを実行する場合、コンピューティング ノードは要件を満たしません。
実行すべきコンピューティング タスクが多数ある場合、コンピューティング タスクの反アフィニティ要件を満たすことが困難になる場合があります。したがって、計算タスクの反アフィニティ要件を追加する場合、その要件が「必ず満たされなければならない」のか、「満たされるように努める」のかを指定する必要もあります。
Little C では、次の方法に従って計算ノードを割り当てる必要があります。計算タスクの起動シーケンスに従って、要件に応じて各計算タスクの計算ノードを順番に選択します。コンピューティング ノードが選択されると、それは固定され変更されません。
その後の選択では、このコンピューティング タスクの要件は考慮されなくなります。コンピューティング タスクごとに、コンピューティング ノードを選択する方法は次のとおりです。
-
フィルタリング段階
この段階では、コンピューティングタスクの要件に従って、要件を満たすすべてのコンピューティングノードがフィルタリングされます。該当する計算ノードが存在せず、計算タスクの反アフィニティ要件が指定されており、かつ、計算タスクの反アフィニティ要件を可能な限り満たしている場合には、計算タスクの反アフィニティ要件を解除して再度フィルタリングを行う
。存在しない場合は、演算タスクの要件を満たさないとみなされ、演算タスクを割り当てることができない。 -
並べ替えフェーズ
このフェーズでは、フィルタリングされたコンピューティング ノードが次の方法に従って並べ替えられます。- 現時点で実行中のコンピューティング タスクの数が最も少ないコンピューティング ノードを選択します。
- 最小の番号を持つコンピューティング ノードを選択します。
入力フォーマット
出力フォーマット
サンプル入力
10 4
1 1 1 1 1 2 2 2 2 2
6
2 1 4 1 2 1
6 1 1 0 1 1
1 2 2 0 0 0
6 1 2 0 2 1
5 2 2 0 1 0
11 3 0 1 3 0
サンプル出力
0 0
1 2 3 4 5 0
6
7 8 9 10 7 8
6 6 6 6 6
1 2 3 4 5 9 10 7 8 6 1
例の説明
この入力では、10 個のコンピューティング ノードが宣言されており、最初の 5 個はアベイラビリティ ゾーン 1 に配置され、最後の 5 個はアベイラビリティ ゾーン 2 に配置されています。アベイラビリティーゾーン 3 および 4 にはコンピューティング ノードは含まれません。
最初のグループのコンピューティング タスクでは、コンピューティング ノード アフィニティ要件が宣言されていますが、必要なアベイラビリティ ゾーン番号は 4 であり、コンピューティング ノードが含まれていないため、満たすことができません。
2 番目のグループのコンピューティング タスクでは、アプリケーション 1 の 6 つのタスクをアベイラビリティ ゾーン 1 で開始する必要があり、コンピューティング タスクの反アフィニティが必要です。したがって、最初の 5 つのタスクはそれぞれ最初の 5 つのノードでスケジュールされます。6 番目のタスクの場合は、アベイラビリティ ゾーン 1 で実行する必要があるため、スケジュールできる範囲は最初の 5 ノードに制限されます。ただし、必須の計算タスクの非アフィニティも指定しています。アプリケーション 1 に属する計算タスクは最初の 5 つのノードですでに開始されているため、それを実行できるノードはありません。
コンピューティング タスクの 3 番目のグループでは、アベイラビリティーゾーン 2 でアプリケーション 2 のタスクを開始し、それをノード 6 に直接割り当てます。
4 番目のグループのコンピューティング タスクでは、アプリケーション 1 の 6 つのタスクをアベイラビリティ ゾーン 2 で開始する必要があり、コンピューティング タスクの反アフィニティが必要であり、アプリケーション 2 のコンピューティング タスクを同じノードに割り当てることはできません。したがって、ノード 6 を分散に使用することはできず、これら 6 つのタスクはノード 7 ~ 10 にのみ分散できます。質問の意味に応じて、実行中のタスクの数が最も少なく、番号が小さいものを選択しますので、7、8、9、10、7、8 の順に割り当てます。
コンピューティング タスクの 5 番目のグループでは、5 つのアプリケーション 2 タスクをアベイラビリティ ゾーン 2 で開始する必要があり、コンピューティング タスクの反アフィニティが可能な限り必要であり、アプリケーション 1 のコンピューティング タスクを同じアベイラビリティ ゾーン 2 に割り当てることはできません。ノード。現時点では、アベイラビリティ ゾーン 2 のノード 6 にはアプリケーション 1 のコンピューティング タスクがないため、5 つのコンピューティング タスクすべてがこのノードに割り当てられます。
6 番目のグループの計算タスクでは、アプリケーション 3 の 11 個のタスクを開始する必要があり、計算タスクの反アフィニティを可能な限り満たす必要があり、アプリケーションの他の計算タスクと同じノードに割り当てることはできません3 であり、アプリケーション 1 と互換性がある必要があります。コンピューティング タスクは同じアベイラビリティ ゾーンに配置されます。アプリケーション 1 は 2 つのアベイラビリティーゾーンにあるため、10 個のノードすべてを割り当てることができます。最初の 10 個のタスクについては、質問の意味に応じて、実行中のタスクの数が最も少なく、割り当てられるタスクの数が最も少ないノードを選択します。11 番目のタスクでは、すべてのノードがアプリケーション 3 のタスクを実行するため、反アフィニティ要件を満たすノードはありません。また、アンチアフィニティの要件を可能な限り満たしているため、この要件を無視してノード1に配置されます。
サブタスク
ACコード(C++)
Dev-CPP (C++14 標準)
#include<bits/stdc++.h>
using namespace std;
//本地调试时使用
//#define inline
typedef struct node{
int id;//编号
int block;//区
int nums;//当前的任务数
set<int> task; //所运行任务的编号
bool operator <(const node &a)const{
if(this->nums!=a.nums){
return this->nums<a.nums;
}
else {
return this->id<a.id;
}
}
}node;
unordered_map<int,node> Node;
//编号为n的可用区内的计算节点
void fax1(int n,vector<int> &temp){
for(auto it=temp.begin();it!=temp.end();){
if(Node[*it].block!=n){
temp.erase(it);
}
else it++;
}
return;
}
//和编号为n的应用的计算任务在同一个可用区
void fax2(int n,vector<int> &temp){
set<int> qu;
for(auto it=Node.begin();it!=Node.end();it++){
if(it->second.task.count(n)==1){
qu.insert(it->second.block);
}
}
for(auto it=temp.begin();it!=temp.end();){
if(qu.count(Node[*it].block)==0){
temp.erase(it);
}
else it++;
}
return;
}
//表示不能和编号为n的应用的计算任务在同一个计算节点上运行
vector<int> fax3(int n,vector<int> temp){
for(auto it=temp.begin();it!=temp.end();){
if(Node[*it].task.count(n)==1){
temp.erase(it);
}
else it++;
}
return temp;
}
int main(){
#ifdef inline
freopen("stdin.txt","r",stdin);
#endif
ios::sync_with_stdio(false);
int n,m;cin>>n>>m; //n个节点,m个区
int i=1;
vector<int> idsum;
while(i<=n){
int temp;
cin>>temp;
Node.insert(pair<int,node>(i,node{
i,temp,0,set<int>()}));
idsum.push_back(i);
i++;
}
// #ifdef inline
// for(auto &i:Node){
// cout<<i.first<<" "<<i.second.block<<endl;
// }
// cout<<"*************"<<endl;
// #endif
int T;cin>>T;
while(T--){
int a1,a2,a3,a4,a5,a6;
cin>>a1>>a2>>a3>>a4>>a5>>a6;
// #ifdef inline
// for(auto &i:temp){
// cout<<i<<" ";
// }
// cout<<"*************"<<endl;
// #endif
while(a1--){
vector<int> temp=idsum,temp2;
//计算节点亲和性
if(a3!=0) {
fax1(a3,temp);
}
//计算任务亲和性
if(a4!=0) {
fax2(a4,temp);
}
//计算任务反亲和性
if(a5!=0) {
temp2=fax3(a5,temp);
}
//计算任务反亲和性要求是必须满足的且无可用节点 或 不考虑 计算任务反亲和性也无可用节点
if((temp2.empty()&&a6==1)||temp.empty()) {
cout<<0<<" ";
continue;
}
//计算任务反亲和性要求是尽量满足的 且 无可用节点 则 不考虑 计算任务反亲和性
else if(temp2.empty()&&a6==0){
temp2=temp;
}
//排序 按照节点的已有的作业数、序号
sort(temp2.begin(),temp2.end(),[](const auto &a,const auto &b)->bool{
return Node[a]<Node[b];
});
//更新节点信息
Node[temp2[0]].nums++;
Node[temp2[0]].task.insert(a2);
cout<<Node[temp2[0]].id<<" ";
}
cout<<endl;
}
return 0;
}
要約する
アルゴリズムは使用されず、直接シミュレーションのみが行われます。基本的なコーディング能力と stl の使用法をテストする C++stl コンテンツが多数使用されています。分からない事があれば直接コメントして頂ければ、見たら返信させて頂きます。