2020年6月3日水曜日

Visual C++2019での挙動差異

Algorithm4のインスタンスの一部が動きませんでした。
調べたところ、
次の箇所、std::mapの挙動が違いました。
mapがemptyであるとき、0が入ると思っていたのですが、デバッグモードでは、0、最適化を行うと、1が入ってしまいました。

  map[xx]=map.size();
  
言語仕様上、正しい動作は分からないのですが、とりあえず、明示的に次のような対処を行いました。

 int size=map.size();
  map[xx]=size;
  
Runtime自体は、変わっていないようですので、恐らくコンパイラの差異なんでしょう。いつものことですが、コンパイラを変えると何かしら、こうした問題が発生します。

2020年6月2日火曜日

各国祝日の調査

AWS対応は、ほぼCodingが終わりました。
後は、Docker SDK提供とIAM Role/Principal等のインタフェース定義対応が残るのみです。

SC3のデスクトップブリッジ対応は、海外から始めようと思います。

そうなると問題は、

1)英語マニュアル
2)ソフトの各国対応

になります。中でも祝日定義をどこから拾ってくるか問題です。

WindowsでAPIであればよいのですが、UWPでもなく、方法としては、次の二つになるかと思います。

1)https://qiita.com/richmikan@github/items/9090407e3ab9cd3e80b2
2)https://hnw.hatenablog.com/entry/2019/04/13/212054

1)は、オンライン 2)は、オフラインになります。要検討です。デスクトップブリッジは、ネットアクセスを許容すると思うので、1)が第一候補です。

とりあえず、SC3日本語マニュアルを作ります。

2020年6月1日月曜日

SC3のプロモーション動画を作りました

3交代正循環を題材にして動画をSC3での動画を作ってみました。

https://youtu.be/0vuGpXbO2Wc

AVIをそのままアップロードしましたが、文句を言われませんでした。

2020年5月31日日曜日

Dockerの勉強

AWS LambdaをいきなりCALLしてもらうのは、難しいかもしれないので、ローカルでデバッグできる環境を提供しようと思いました。必要なのは、C++lambdaが動かせること、ローカルでDynamodbにlambdaがW/Rできることです。

https://github.com/lambci/docker-lambda
https://aws.amazon.com/jp/serverless/sam/

を理解出来れば、そういったキットを提供できるかもしれません。いずれも、Dockerなる仮想化技術が使われているので、Dockerを勉強する必要があります。

本もいくつか買ってみたのですが、このサイトの記事が私的にはよさそうでした。

https://kirohi.com/docker_study_resources

2020年5月29日金曜日

C++11/C++17へ

AWS用の記述では、C++14 をベースとして、部分的にC++17を使用しています。例えば、WindowsとLinux、スレッド生成一つ取ってもC++11を使えば、共通のstd::thread が使えます。ファイルのアクセスについてもC++17では、filesystemがあり、便利に使えます。ということで、同じ事をやるのに書き換えてWindows/Linux共通で使えるようにした部分が多数あります。

恐らく現リリース最新版129CとAWS開発最新版では、1万行以上記述が変わっています。そのためRegression Testが必要となっています。

このテストが1週間、マニュアル更新に1週間、リリースは、6月中旬を予定しています。



2020年5月28日木曜日

Python Editor の改善

次期リリース予定版(現在開発中のAWS対応版)では、PythonEditor(scintilla)を少し改善しています。Python Editorは、二つのタブになりました。[ソース]と[ソース全体]です。[ソース]は今までのエディタに同じです。


[ソース全体]の方は、ReadOnlyなので書くことはできません。また、最初の状態では、何もありません。
 求解すると、以前の_property.py と現在のソースとが合体したソースを[ソース全体]タブ中に見ることができます。


ここで、故意にエラーを作ってみます。今月:の:を削除して求解してみます。



 当然エラーになります。
● 
行をダブルクリックすると当該行がピンクでハイライトされます。
 
 
 ソース全体は、ソルバーが内蔵しているpython interpreterが認識しているソース全体になります。
従い、今までと違い正しく当該行を表示することが出来ます。
また、pythonソースを記述するのに、外部エディタを参照しながら記述する面倒が少し改善されます。

内部動作として、~property.pyは、以前と同様に出力されています。GUIは、それを拾ってきて、[ソース全体]として表示しています。GUIは、python interpreterの出力する"<string>"をKeywordとして、findしたら、python editorにその後続の(行)を表示されています。

AWS版でも、同様ですが、ファイル出力というインタフェースは利用できません。代わりに
lambda call のresponce payload中にソース全体が返ります。また、求解状況は,ユーザアカウント上の指定する(lambdaがアクセス許可された)テーブル上のStatusに出力されます。Status
は、XXsecに一回更新されます。(streaming modeにしてすると、上記GUI画面の右ペイン相当を得ることが出来ます。) 従い、AWSユーザは、(やろうと思えば)上記GUI動作と同じ処理を行うことが出来ます。

2020年5月27日水曜日

AWS 構成変更

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/gettingstarted-limits.html
によるとpayload sizeの上限は、リクエスト・レスポンスで、6MBになっています。勘違いしていたのですが、往復計で6MBではなく、リクエスト6MB、レスポンス6MBということみたいです。とすれば、レスポンスで、解とpython property fileを返しても問題ないので、そのように設計変更しました。(今までは、dynamodbに出力するようにしていました。)下図が、変更後の構成とシーケンス図になります。


下がレスポンスの結果でpythonチュートリアル1の求回数を2にしたときのログになります。
 
Calling lambda..SC3_Lambda_Engine problem.json  clientConfig.requestTimeoutMs=900000sec
1:{
2: "peak_memory": "527.921875MB",
3: "result": "{\n  \"solution1.txt\":{\n    \"スタッフ名1\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名10\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名11\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名12\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名13\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名14\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名15\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名16\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名17\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名18\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"日勤\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名2\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名3\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名4\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名5\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名6\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名7\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名8\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名9\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"]\n  },\n  \"solution2.txt\":{\n    \"スタッフ名1\":[\"入り\",\"公休\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名10\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名11\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名12\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名13\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名14\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名15\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名16\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名17\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名18\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"日勤\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名2\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名3\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名4\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名5\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名6\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名7\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名8\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名9\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"]\n  }\n}\n",
4: "python": "#staffdef\nstaffdef=['スタッフ名1','スタッフ名2','スタッフ名3','スタッフ名4','スタッフ名5','スタッフ名6','スタッフ名7','スタッフ名8','スタッフ名9','スタッフ名10','スタッフ名11','スタッフ名12','スタッフ名13','スタッフ名14','スタッフ名15','スタッフ名16','スタッフ名17','スタッフ名18']\n#daydef\n制約開始日=5\n制約終了日=35\n表示開始日=0\ndaydef=['2016-07-27','2016-07-28','2016-07-29','2016-07-30','2016-07-31','2016-08-01','2016-08-02','2016-08-03','2016-08-04','2016-08-05','2016-08-06','2016-08-07','2016-08-08','2016-08-09','2016-08-10','2016-08-11','2016-08-12','2016-08-13','2016-08-14','2016-08-15','2016-08-16','2016-08-17','2016-08-18','2016-08-19','2016-08-20','2016-08-21','2016-08-22','2016-08-23','2016-08-24','2016-08-25','2016-08-26','2016-08-27','2016-08-28','2016-08-29','2016-08-30','2016-08-31']\n#staffcollection\n全スタッフ=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]\n入り=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]\n公休=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]\n日勤=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]\n明け=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]\nタスク1=[]\nタスク2=[]\nタスク3=[]\nNoTaskVar=[]\n\n#daycollection\n今月=[5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35]\n日=[4,11,18,25,32]\n月=[5,12,19,26,33]\n火=[6,13,20,27,34]\n水=[0,7,14,21,28,35]\n木=[1,8,15,22,29]\n金=[2,9,16,23,30]\n土=[3,10,17,24,31]\n全日=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35]\n祝=[15]\n振=[]\n平日=[0,1,2,5,6,7,8,9,12,13,14,15,16,19,20,21,22,23,26,27,28,29,30,33,34,35]\n週末=[3,4,10,11,17,18,24,25,31,32]\n休日=[3,4,10,11,15,17,18,24,25,31,32]\n稼働日=[0,1,2,5,6,7,8,9,12,13,14,16,19,20,21,22,23,26,27,28,29,30,33,34,35]\n制約開始日一日前=[4]\n制約開始日二日前=[3]\n制約開始日三日前=[2]\n制約開始日四日前=[1]\n制約開始日五日前=[0]\n制約開始日六日前=[]\n制約開始日七日前=[]\n制約開始日P1=[6]\n制約開始日P2=[7]\n制約開始日P3=[8]\n制約開始日P4=[9]\n制約開始日P5=[10]\n制約開始日P6=[11]\n第一週=[5,6,7,8,9,10,11]\n第二週=[12,13,14,15,16,17,18]\n第三週=[19,20,21,22,23,24,25]\n第四週=[26,27,28,29,30,31,32]\n第五週=[33,34,35]\n第六週=[]\n四週間=[5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32]\n制約開始日1日前から=[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35]\n制約開始日2日前から=[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35]\n制約開始日3日前から=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35]\n制約開始日4日前から=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35]\n制約開始日5日前から=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35]\n制約開始日6日前から=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35]\n制約終了日六日前=[29]\n制約終了日五日前=[30]\n制約終了日四日前=[31]\n制約終了日三日前=[32]\n制約終了日二日前=[33]\n制約終了日一日前=[34]\n金土日=[2,3,4,9,10,11,16,17,18,23,24,25,30,31,32]\n金土日月=[2,3,4,5,9,10,11,12,16,17,18,19,23,24,25,26,30,31,32,33]\n\n#shiftcollection\n\n#classcollection\n全スタッフ属性=[全スタッフ]\n\n#shiftdef\nshiftdef={'入り':入り,'公休':公休,'日勤':日勤,'明け':明け}\n#taskdef\ntaskdef={'タスク1':タスク1,'タスク2':タスク2,'タスク3':タスク3,'NoTaskVar':NoTaskVar}\n#non_auto_tasks\nnon_auto_tasks=[]\n#phase_list\n\n#task collections\n#digited group\n#column_constraints\n週末入り強制=(True,('週末',週末),'',入り,('',''),全スタッフ,2,-1,-1,-1.000000,-1.000000,0,0)\n列制約グループ1={'週末入り強制':週末入り強制}\n列制約グループ2={}\ncolumn_constraints={'列制約グループ1':列制約グループ1,'列制約グループ2':列制約グループ2}\n#shift schedules\nshift_schedules=[[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n]\ntask_schedules=[[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n]\n"
5:}
Elapsed time(C++):4947[ms]
 
大変に見にくいのは、ESCAPE シーケンスが挿入されてしまうためだと思われます。解は、peak_memory出力の後、solution1.json, (solution1_task.json),solution2.json,(solution2_task.json)...でJsonフォーマットで出力されます。taskは、フェーズモードでの記述があった場合のみ、出力されます。その後、python記述があれば、python_property.pyが出力されます。
 
レスポンスpayload生成部C++ソースを以下に示します。
 
 
 Aws::Utils::Json::JsonValue jsonPayload;
    string peak_memory=std::to_string(memUsedPeak())+"MB";
      
    jsonPayload.WithString("peak_memory", peak_memory);
    jsonPayload.WithString("result", json_solution);
    jsonPayload.WithString("python",python_property_src);
    string str= jsonPayload.View().WriteReadable();
  
  
    return aws::lambda_runtime::invocation_response::success(str,"application/json");

2020年5月26日火曜日

AWS Lambda-メモリリーク対策C++

設計を大幅に変更しました。行数にして数千行程度、Editしたと思います。

サーバアプリでは、基本的にメモリリークは許されません。が、Lambdaは、毎回HotStartする訳でもないので、目標として、一回のメモリリークは、100KB程度以下としました。(1000回連続HotStartされても100MBの増加に留まる、としました。) 1000回連続で来ることはないという想定です。これが崩れることがあるとするなら、同じLambdaを複数用意すれば事足ります。

<メモリリーク対策の為の設計変更>
次の対策方法を検討しました。

A)shared_ptrの使用
shared_ptrの場合、unionで、ptrを複数定義している部分の回避が面倒。(一応C+11なら書けそうですが..) さらに、performanceの劣化、メモリ増大が懸念されます。さらに、困難なのは変更Edit量が半端ないことです。

B)独自アロケータの使用
shared_ptr使用の場合に比べて、全ての面で優れています。union ptrの変更の必要はありませんし、変更Edit量も最小で済みます。
関連するクラス(ptr参照しているクラス)は、10種以下なので、それら全てを独自アロケータを使って処理します。つまり、delete処理は、最後の一回のみです。ptrを辿ってdeleteしていくことはしません。ですのでクラスのnew ptrは、管理しません。その結果、クラス内のstd::vectorにも細工が必要になります。幸い、std::vectorは、アロケータインタフェースが定義されているので、それらを含めて関連クラスのdelete処理を一気に行う処理が書けます。shared_ptrで、ちまちま参照カウントする方式に比べて速度で10倍くらい違う気がします。(しかし、ここは、ボトルネックではないので、体感では変わりません。)

 


<メモリリーク対策検証>
1)VisualC++内蔵ヒープチェック
メモリリークをEnableします。_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); また、リンカーのDebugを 共有と公開用に最適化されたデバッグ情報の生成 (/DEBUG:FULL)に設定します。(なぜか、デバッグ出力が全くされなかったのでが、VisualStudioの修復 を行ったらデバッグ出力が出るようになりました。)

2)VisualLeakDetectorの活用
1)では、ソース行が殆ど表示されないので分かりずらいです。格段に遅くはなりますが、デバッグ初期は、VisualLeakDetectorを使いました。スタックトレースまで表示されるので、場所の特定は容易です。しかし、ある程度以上の規模になると原因不明のエラーが出ることがありました。そのときは、VisualC++のヒープチェックに頼ることになります。

3)検証
■Windows: VisualC++/Visual Leak Detectorによる検証
■Linux:         g++ -fsanitize=leak による検証
■mainを何回か廻して、取得メモリ量に変化ないことを確認(ptrのリセット処理等検証)

4)メモリリーク箇所
■旧言語制約は、deprecatedで基本使用禁止とします。なので放置です。
■algorithm4 これもAWSではサポートしません。なので放置です。
■python インタフェース: 最新版で少し改善しましたが、僅かに未だ残っているようです。こちらは、改版に期待ということで、放置しています。
■Error 解がなかった場合、原因解析処理でメモリリークします。課題です。
■未検証 TASK周り

5)Tips
 ■Windowsは、OKで、LinuxでNGな箇所がありました。g++ stringstream.str()に要注意です。
 ■new vector<...> を vector<> 形式にして、出来る限りスタック上で自動deleteとするように書き換えました。地道な作業ですが、普段から、明示deleteしなくてもよい書き方を意識して書くべきだったと、反省しています。

<結論>
■従い、Algorithm1で、pythonを使わずに,解があるのであれば、メモリリークはありません。
■pythonを使った場合、記述量に関係なく、constantに1KB以下程度がリークします。1000回呼んで1MB以下です。しかし、解がなかったときの原因解析でリークが発生します。この部分が課題です。
■大幅にいじってしまったので、regression test が必要です。







2020年5月18日月曜日

Zoom オンラインコンサルティングを始めました。

娘が、大学のオンライン授業で使っていて、「知らないの? 遅れているね!」と言われてしまいました。中々良さそうなので、使ってみることにしました。

ついでに、有料でオンラインコンサルティングを始めることにしました。予約制で、単発~1時間5000円です。これまで、ありそうでなかったコンサルティングです。

勤務表の自動勤務表化に関わるコンサルティングです。所属を伏せて顔なしでも可能です。画面共有で、スケジュールナースの操作方法等も直接に指導可能です。勤務の制度設計、工場の変則勤務等、自動勤務化に関わるあらゆるご相談に応じます。 スケジュールナースの使い方レッスンも可能です。




2020年5月17日日曜日

mimallocの評価

こちらで、大変に詳しく解析をされています。
https://qiita.com/methane/items/e88901b7392c10cee2c9
pythonのmalloc置き換え用度では、glibcに比べてよろしくない、という結果のようです。

私のエンジンは、数十バイト規模のメモリを大量に消費しますので、それをシミュレーションする意味で、以下のソースを書きました。(Visual Studio 2019 mimalloc-override-testから書き換えDebugビルド)

ここで、取得しているメモリは、9バイトから始まって、およそ2KBまで、メモリを1バイトづつインクメンタルに取得しています。それを1ブロックとして1000個取得します。理論上の取得メモリは、公差1の等差数列で計算でき、およそ2GBです。(きっちり詰めたときおよそ2GB消費します。)

int main() {

    mi_stats_reset();  // ignore earlier allocations
    mi_heap_t* heap = mi_heap_new(); 
    mi_heap_t* old = mi_heap_set_default(heap);
    for (auto i = 0;i < 1000;i++) {
        for (auto j = 0;j < 2000;j++) {
            char* p = new char[9+j];
        }
        
    }
    
  //  mi_heap_destroy(heap));
    mi_stats_print(NULL);
    return 0;
}
heap stats:     peak      total      freed       unit      count
normal   4:   501.9 kb   501.9 kb       0 b       32 b     16.0 k   not all freed!
normal   6:   752.9 kb   752.9 kb       0 b       48 b     16.0 k   not all freed!
normal   8:  1003.9 kb  1003.9 kb       0 b       64 b     16.0 k   not all freed!
normal   9:     1.2 mb     1.2 mb       0 b       80 b     16.0 k   not all freed!
normal  10:     1.4 mb     1.4 mb       0 b       96 b     16.0 k   not all freed!
normal  11:     1.7 mb     1.7 mb       0 b      112 b     16.0 k   not all freed!
normal  12:     1.9 mb     1.9 mb       0 b      128 b     16.0 k   not all freed!
normal  13:     4.8 mb     4.8 mb       0 b      160 b     32.0 k   not all freed!
normal  14:     5.8 mb     5.8 mb       0 b      192 b     32.0 k   not all freed!
normal  15:     6.8 mb     6.8 mb       0 b      224 b     32.0 k   not all freed!
normal  16:     7.8 mb     7.8 mb       0 b      256 b     32.0 k   not all freed!
normal  17:    19.5 mb    19.5 mb       0 b      320 b     64.0 k   not all freed!
normal  18:    23.4 mb    23.4 mb       0 b      384 b     64.0 k   not all freed!
normal  19:    27.3 mb    27.3 mb       0 b      448 b     64.0 k   not all freed!
normal  20:    31.2 mb    31.2 mb       0 b      512 b     64.0 k   not all freed!
normal  21:    78.1 mb    78.1 mb       0 b      640 b    128.0 k   not all freed!
normal  22:    93.7 mb    93.7 mb       0 b      768 b    128.0 k   not all freed!
normal  23:   109.3 mb   109.3 mb       0 b      896 b    128.0 k   not all freed!
normal  24:   125.0 mb   125.0 mb       0 b      1.0 kb   128.0 k   not all freed!
normal  25:   312.5 mb   312.5 mb       0 b      1.2 kb   256.0 k   not all freed!
normal  26:   375.0 mb   375.0 mb       0 b      1.5 kb   256.0 k   not all freed!
normal  27:   437.5 mb   437.5 mb       0 b      1.7 kb   256.0 k   not all freed!
normal  28:   437.5 mb   437.5 mb       0 b      2.0 kb   224.0 k   not all freed!
normal  30:     3.0 kb     3.0 kb       0 b      3.0 kb       1     not all freed!

heap stats:     peak      total      freed       unit      count
    normal:     2.0 gb     2.0 gb       0 b        1 b              not all freed!
      huge:       0 b        0 b        0 b        1 b              ok
     giant:       0 b        0 b        0 b        1 b              ok
     total:     2.0 gb     2.0 gb       0 b        1 b              not all freed!
malloc requested:          1.8 gb

  reserved:     2.0 gb     2.0 gb       0 b        1 b              not all freed!
 committed:     2.0 gb     2.0 gb       0 b        1 b              not all freed!
     reset:       0 b        0 b        0 b        1 b              ok
   touched:     2.0 gb     2.0 gb       0 b        1 b              not all freed!
  segments:     531        531          0                           not all freed!
-abandoned:       0          0          0                           ok
   -cached:       0          0          0                           ok
     pages:    33.3 k     33.3 k        0                           not all freed!
-abandoned:       0          0          0                           ok
 -extended:   590.2 k
 -noretire:       0
     mmaps:       8
   commits:     577
   threads:       0          0          0                           ok
  searches:     0.9 avg
numa nodes:       1
   elapsed:      16.793 s
   process: user: 15.984 s, system: 0.765 s, faults: 545698, reclaims: 0, rss: 2.0 gb, commit charge: 2.0 gb
 
当然のことながら、個別オブジェクトをdeleteしていないので、freeでないと言ってきます。
次に、コメントアウトしていた、mi_head_destroy(heap)をEnableしてみます。

すると、以下のように、良い感じになりました。9バイトから始めたのは、8バイトだと何故かフリーされなかったからです。(??)  とりあえず、良さそうなので、実装してみようかなと思います。
ドキュメントによれば、Windowsでは、古い実装にAddOnするだけで、new/malloc オーバライドすることが出来るそうです。Linuxへのポートも当然サポートされているので、前に示した要件がクリアされています。しかし、未だ枯れていないので、注意は必要です。(最新のビルドは数日前でした。)
 
int main() heap stats:     peak      total      freed       unit      count
normal   4:   501.9 kb   501.9 kb   501.9 kb      32 b     16.0 k   ok
normal   6:   752.9 kb   752.9 kb   752.9 kb      48 b     16.0 k   ok
normal   8:  1003.9 kb  1003.9 kb  1003.9 kb      64 b     16.0 k   ok
normal   9:     1.2 mb     1.2 mb     1.2 mb      80 b     16.0 k   ok
normal  10:     1.4 mb     1.4 mb     1.4 mb      96 b     16.0 k   ok
normal  11:     1.7 mb     1.7 mb     1.7 mb     112 b     16.0 k   ok
normal  12:     1.9 mb     1.9 mb     1.9 mb     128 b     16.0 k   ok
normal  13:     4.8 mb     4.8 mb     4.8 mb     160 b     32.0 k   ok
normal  14:     5.8 mb     5.8 mb     5.8 mb     192 b     32.0 k   ok
normal  15:     6.8 mb     6.8 mb     6.8 mb     224 b     32.0 k   ok
normal  16:     7.8 mb     7.8 mb     7.8 mb     256 b     32.0 k   ok
normal  17:    19.5 mb    19.5 mb    19.5 mb     320 b     64.0 k   ok
normal  18:    23.4 mb    23.4 mb    23.4 mb     384 b     64.0 k   ok
normal  19:    27.3 mb    27.3 mb    27.3 mb     448 b     64.0 k   ok
normal  20:    31.2 mb    31.2 mb    31.2 mb     512 b     64.0 k   ok
normal  21:    78.1 mb    78.1 mb    78.1 mb     640 b    128.0 k   ok
normal  22:    93.7 mb    93.7 mb    93.7 mb     768 b    128.0 k   ok
normal  23:   109.3 mb   109.3 mb   109.3 mb     896 b    128.0 k   ok
normal  24:   125.0 mb   125.0 mb   125.0 mb     1.0 kb   128.0 k   ok
normal  25:   312.5 mb   312.5 mb   312.5 mb     1.2 kb   256.0 k   ok
normal  26:   375.0 mb   375.0 mb   375.0 mb     1.5 kb   256.0 k   ok
normal  27:   437.5 mb   437.5 mb   437.5 mb     1.7 kb   256.0 k   ok
normal  28:   437.5 mb   437.5 mb   437.5 mb     2.0 kb   224.0 k   ok
normal  30:     3.0 kb     3.0 kb     3.0 kb     3.0 kb       1     ok

heap stats:     peak      total      freed       unit      count
    normal:     2.0 gb     2.0 gb     2.0 gb       1 b              ok
      huge:       0 b        0 b        0 b        1 b              ok
     giant:       0 b        0 b        0 b        1 b              ok
     total:     2.0 gb     2.0 gb     2.0 gb       1 b              ok
malloc requested:          1.8 gb

  reserved:     2.0 gb     2.0 gb       0 b        1 b              not all freed!
 committed:     2.0 gb     2.0 gb   196.5 mb       1 b              not all freed!
     reset:       0 b        0 b        0 b        1 b              ok
   touched:     2.0 gb     2.0 gb     2.0 gb       1 b              ok
  segments:     531        531        531                           ok
-abandoned:       0          0          0                           ok
   -cached:       0          0          0                           ok
     pages:    33.3 k     33.3 k     33.3 k                         not all freed!
-abandoned:       0          0          0                           ok
 -extended:   590.2 k
 -noretire:       1
     mmaps:       8
   commits:     577
   threads:       0          0          0                           ok
  searches:     0.9 avg
numa nodes:       1
   elapsed:      31.050 s
   process: user: 29.953 s, system: 0.765 s, faults: 545700, reclaims: 0, rss: 2.0 gb, commit charge: 2.0 gb

2020年5月16日土曜日

C++メモリリークの対処方法の検討

3案あります。

1)unique_ptr,shared_ptr を使う
2)終了時にまとめてobjectをdeleteする。その際、unordered_set<void*> に記憶させてdouble deleteを防止する。
3)独自のアロケータを使う

1)でunique_ptrで書けるところは、書き直してみました。しかし、shared_ptrを使うとなるとruntime 性能の劣化が気になります。基本的には、C#や、JAVAがやっている参照カウント方式です。書き直しにも膨大な手間が必要でバグなしに書き直すのは至難です。

2)案では、runtime性能の劣化は軽微でしょう。Desktop版では、deleteしなければ、peformanceの劣化は、原理上ありません。しかし、サーバ版では、やはりこまめに、leak箇所を潰していく作業が必要となります。1)案よりは良さそうですが、作業量は未だ多そうです。

3)tcmalloc,jemalloc,nedmalloc,miallocを使う
これらは、小メモリに対しては、threadに対するヒープを備えているはずです。new/delete をオーバライドして、thread 消滅時にそのヒープを開放してやれば、one go で行けるはずです。要件としては、それらのhackが可能であることとLinux/Windows の両方にポート可能であること、さらには、statisticsも出力可能であること、そんなライブラリがあればよいのです。

考えてみれば、サーバアプリケーションでは、メモリの回収機構は、備えていなければなりません。今の時代、C/C++で、サーバアプリというのは、考えられないことかもしれませんが、究極の性能を提供する計算サーバという視点でみるならば、現時点のみならず今後も必要なような気がします。
その意味で、C++の進化は、必要なことであると理解できます。






2020年5月15日金曜日

Lambda のインスタンス寿命

C++ lambdaをColdStart出来ればよいのですが、制御できる方法は見つけられませんでした。

実験してみると、10分程度以内に再アクセスがある場合、インスタンスを再利用するようです。
これをHotStartと呼んでいるようです。インスタンスをプロセスから立ち上げる場合が、ColdStartとなります。これを避けるために、常にHotな状態にする、つまり常にアクセスするなどの対策が取る場合もあるようです。

で、C++の場合の問題なのですが、メモリマネージをちゃんとしないといけないという問題です。
今まで、一回CALLごとにプロセスを立ち上げたので、その必要はなかったのですが、インスタンスを再利用するとなると、メモリリークを潰す必要があります。

仮に、メモリ取得のピークが一瞬でも設定最大の3GBを超えると落ちてしまいます。どんな具合か、とりあえずAWS上で、ピークメモリを取得してみました。メモリ取得ソースは以下です。

インスタンスは、サンプルで添付している正循環8回です。(Windows上での実行時間とほぼ同じ時間70sec程度となっていますので、性能的には、通常PCで行うのと大差ないと思われます。
ちなみに、AWS上の性能は、メモリ設定に比例するらしいので、最大性能でもPC程度と推定されます。AWSの設定は、3GB、タイムアウト15分にしています。




static inline int memReadPeak(void) 
 { 
     char  name[256]; 
     pid_t pid = getpid(); 
 

     sprintf(name, "/proc/%d/status", pid); 
     FILE* in = fopen(name, "rb"); 
     if (in == NULL) return 0; 
 

     // Find the correct line, beginning with "VmPeak:": 
     int peak_kb = 0; 
     while (!feof(in) && fscanf(in, "VmPeak: %d kB", &peak_kb) != 1) 
         while (!feof(in) && fgetc(in) != '\n') 
             ; 
     fclose(in); 
 

     return peak_kb; 
 } 
 

double memUsedPeak() {  
    double peak = memReadPeak() / (double)1024; 
 return peak;
}
インクメンタルにSleep時間を増やして、メモリ取得量の変化をみます。AWS CLIで、Lambdaの起動をかけています。(AWS SC3ユーザでもこの方法はできません) 結果がJsonで返ってきてピークメモリをログしています。

メモリ取得が最初の状態に戻ったときが、インスタンス再起動されたと推測できます。この結果では、700sec後に起動したときに、メモリがほぼ初期値に戻っているので、プロセス再起動(ColdStart)はされた、と考えられます。(別なインスタンスの新規起動かもしれない可能性は残ります。)
 
 
Invoke AWS after sleep(i)
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "455.812500MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):73177[ms]
0sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "633.902344MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):70138[ms]
60sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "766.136719MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):70010[ms]
120sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "898.433594MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):70021[ms]
180sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1030.652344MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):69835[ms]
240sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1153.636719MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):69957[ms]
300sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1276.550781MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):69994[ms]
360sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1399.472656MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):70917[ms]
420sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1531.652344MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):70442[ms]
480sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1663.828125MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):69519[ms]
540sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1796.054688MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):69959[ms]
600sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1919.246094MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):70013[ms]
700sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "489.402344MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):70774[ms]
800sec 
 

2020年5月14日木曜日

動き始めたAWS

ようやくクラウドが動きました。コードのLinux化に続く難所は越えたと思います。

嵌った点は、次の2点でした。

1)SDK使用時、DefaultTimeoutを超えると同期リクエストでもリトライする。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/lambda-function-retry-timeout-sdk/

非同期は、リトライが入るのは理解できますが、同期リクエストでもリトライがDefaultでは入ります。
確かに書いてありますが、C++ については、aws-sdk-docにもそのような記述例はなく、設定方法が不明です。海外を含めてこの点を指摘している記事はないと思います。

Lambdaリソース側では、メモリ3GB、15分のタイムアウトを設定しています。それとは別にCallerがタイムアウトを設定してやらないといけません。そうしないと、C++の場合、defaultでは、10秒くらいで、タイムアウトリトライが発生するようです。リソース側の設定と同じ、15分に設定しました。

Aws::Client::ClientConfiguration clientConfig;
     clientConfig.requestTimeoutMs = 15*60*1000;



2)Pythonライブラリの配置
クラウドにアップするときに、ZIPで固めます。これは、CMAKEがやってくれます。ただし、Pythonについては、コアについてはやってくれますが、Python上のソースについてはやってくれません。この辺、どこに配置されるかが判らず、以下のようなエラーが発生しました。

Could not find platform independent libraries <prefix>
Could not find platform dependent libraries <exec_prefix>
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]

これについては、以下でDirectoryを出力させてどこに配置されるのかを調べました。
  std::system("ls -l ");

で、上で調べたDirectoryを環境変数PYTHONHOMEに設定して事なきを得ました。

2020年5月13日水曜日

WSL2に移行しました。

ubantu20.04 WSL1をWSL2にアップグレードしようとしましが、1日たっても終わらず断念しました。

なので、新しくubantu18.04をインストールし、それをWSL2にアップグレードしました。

AWSのミドルウェア、以下をインストールしました。

■aws CLI
■aws_lambda_cpp
■aws_sdk_cpp
■Docker Desktop WLS2



2020年5月12日火曜日

Excelへの解出力操作方法のビデオ

作成しました。

https://www.nurse-scheduling-software.com/publications/video/formatted_excel_output.AVI

スケジュールナース上の予定です。

Excel上のフォーマット出力です。スタッフ名は、記載順に出力されます。
スケジュールナース管理スタッフでない場合は、無視されます。
上のハードスケジュール予定は、赤で示されます。(これは、手直しをする場合に、手直し禁止の意味があるそうです。ある看護師長さんのご要望を実装しました。)

下は、通常出力になります。
上は勤怠管理用で最終リリース版、下は、解チェック用として利用されたらよいと思います。

2020年5月11日月曜日

WSL2に移行

デプロイしてみたのですが、動きませんでした。原因は色々ありそうですが、先は長そうです。
sleep問題もあるので、開発環境を一新することにしました。

最初からこちらを見ていればよかったのです。

https://qiita.com/mmns/items/eaf42dd3345a2285ff9e

WL2へは、
https://www.kkaneko.jp/tools/wsl/wsl2.html

https://docs.microsoft.com/ja-jp/windows/wsl/wsl2-kernel

を参照しました。開発ツールのインストールにまる一日かかります。

2020年5月10日日曜日

dynamodb get_item (C++) 組み込み

SDKサンプルをいじって、get_itemルーチンを以下のように記述しました。 これを使って、dynamodbをポーリングします。ItemのAttribute Interruptが"On" になっていたら求解を停止します。
■Interrupt   
    On/Off
 


string get_item(string table_name,string item_name,string attribute_name)
  {
        const Aws::String table=table_name;//(argv[1]);
        const Aws::String name=item_name;//(argv[2]);
        const Aws::String projection="";//(argc > 3 ? argv[3] : "");

        // snippet-start:[dynamodb.cpp.get_item.code]
        Aws::Client::ClientConfiguration clientConfig;
        Aws::DynamoDB::DynamoDBClient dynamoClient(clientConfig);
        Aws::DynamoDB::Model::GetItemRequest req;

        // Set up the request
        req.SetTableName(table);
        Aws::DynamoDB::Model::AttributeValue hashKey;
        hashKey.SetS(name);
        req.AddKey("Name", hashKey);
        if (!projection.empty())
            req.SetProjectionExpression(projection);

        // Retrieve the item's fields and values
        const Aws::DynamoDB::Model::GetItemOutcome& result = dynamoClient.GetItem(req);
        if (result.IsSuccess())
        {
            // Reference the retrieved fields/values
            const Aws::Map& item = result.GetResult().GetItem();
            if (item.size() > 0)
            {
                // Output each retrieved field and its value
                for (const auto& i : item){
     if (i.first==trim(attribute_name)){
      return i.second.GetS();
     }
                    std::cout << i.first << ": " << i.second.GetS() << std::endl;
                }    
            }
            else
            {
                std::cout << "No item found with the key " << name << std::endl;
            }

        }
        else
        {
            std::cout << "Failed to get item: " << result.GetError().GetMessage();
        }
        return "";
        // snippet-end:[dynamodb.cpp.get_item.code]
    }

2020年5月9日土曜日

dynamodb update_item (C++)を組み込み

SDKサンプルをいじって、update_itemルーチンを以下のように記述しました。 これを使って、今までファイル出力していた次をdynamodb上にそれぞれのattribute_nameで出力します。

■property.py   
     Python コード
■solution1.txt       
     シフト解
■solution1_task.txt
     タスク解
■Status    
     GUI出力
     
bool update_item(string table_name,string item_name,string attribute_name, string &description)
{
        const Aws::String tableName=table_name;//(argv[1]);
        const Aws::String keyValue=item_name;//(argv[2]);
        const Aws::String attributeNameAndValue=attribute_name;//(argv[3]);

        // snippet-start:[dynamodb.cpp.update_item.code]
        Aws::Client::ClientConfiguration clientConfig;
        Aws::DynamoDB::DynamoDBClient dynamoClient(clientConfig);

        // *** Define UpdateItem request arguments
        // Define TableName argument
        Aws::DynamoDB::Model::UpdateItemRequest request;
        request.SetTableName(tableName);

        // Define KeyName argument
        Aws::DynamoDB::Model::AttributeValue attribValue;
        attribValue.SetS(keyValue);
        request.AddKey("Name", attribValue);

        // Construct the SET update expression argument
        Aws::String update_expression("SET #a = :valueA");
        request.SetUpdateExpression(update_expression);

        // Parse the attribute name and value. Syntax: "name=value"
        //auto parsed = Aws::Utils::StringUtils::Split(attributeNameAndValue, '=');
        // parsed[0] == attribute name, parsed[1] == attribute value
        //if (parsed.size() != 2)
        //{
        //    std::cout << "Invalid argument syntax: " << attributeNameAndValue << USAGE;
        //    return 1;
        //}

        // Construct attribute name argument
        // Note: Setting the ExpressionAttributeNames argument is required only
        // when the name is a reserved word, such as "default". Otherwise, the 
        // name can be included in the update_expression, as in 
        // "SET MyAttributeName = :valueA"
        Aws::Map expressionAttributeNames;
        expressionAttributeNames["#a"] = attribute_name;//parsed[0];
        request.SetExpressionAttributeNames(expressionAttributeNames);

        // Construct attribute value argument
        Aws::DynamoDB::Model::AttributeValue attributeUpdatedValue;
        attributeUpdatedValue.SetS(description);//parsed[1]);
        Aws::Map expressionAttributeValues;
        expressionAttributeValues[":valueA"] = attributeUpdatedValue;
        request.SetExpressionAttributeValues(expressionAttributeValues);

        // Update the item
        const Aws::DynamoDB::Model::UpdateItemOutcome& result = dynamoClient.UpdateItem(request);
        if (!result.IsSuccess())
        {
            std::cout << result.GetError().GetMessage() << std::endl;
            return false;
        }
        std::cout << "Item was updated" << std::endl;
        return true;
        // snippet-end:[dynamodb.cpp.update_item.code]
    }

2020年5月8日金曜日

dynamodbの使い方(C++)

aws-doc-sdk-examplesをコンパイルして、サンプルで使い方を学びました。(ubuntu20.04 WSL上でコンパイル)

コマンドは、delete_table,create_table,put_item,get_item,update_itemになります。注意すべきは、put_itemです。全てのattributeが置き換えられます。部分的なattributeに対する更新は、update_itemを使う、ということが分かりました。

tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ls
CMakeCache.txt  batch_get_item       create_table_composite_key  describe_table  put_item
CMakeFiles      cmake_install.cmake  delete_item                 get_item        update_item
Makefile        create_table         delete_table                list_tables     update_table

tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./list_tables
Your DynamoDB Tables:
HelloTable
mywebsocket_connections
simple-websockets-app-py-connections

tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./delete_table HelloTable
Table "HelloTable deleted!
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./list_tables

Your DynamoDB Tables:
mywebsocket_connections
simple-websockets-app-py-connections

tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./create_table HelloTable us-east-1
Creating table HelloTable with a simple primary key: "Name"
Table "HelloTable created!

tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./list_tables
Your DynamoDB Tables:
HelloTable
mywebsocket_connections
simple-websockets-app-py-connections

tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./put_item HelloTable sugawara Height=172 Weight=85
Done!
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./get_item HelloTable sugawara
Height: 172
Name: sugawara
Weight: 85
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./put_item HelloTable sugawara Height=172
Done!
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./get_item HelloTable sugawara
Height: 172
Name: sugawara

tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./put_item HelloTable sugawara Height=172 Weight=85
Done!
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./get_item HelloTable sugawara
Height: 172
Name: sugawara
Weight: 85
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./update_item HelloTable sugawara Height=173
Item was updated
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./get_item HelloTable sugawara
Height: 173
Name: sugawara
Weight: 85
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$

2020年5月7日木曜日

AWSの構成2

構成を上のように替えました。

1)AWS上のSC3 Userは、菅原システムズアカウントにあるSC3 Lambda FunctionをCALLします。
2)CALL時のPayloadには、problem.jsonを載せます。
3)SC3 Lambda Functionは、求解状況をSC3UserアカウントにあるDynamoDBに書き込みます。
4)SC3 Userは、求解を途中で停止したいときは、DynamoDBに書き込みます。
5)SC3 Lambda Engineは、User Interrupt書き込みをポーリングし、停止要求と判断したら、求解を停止し、それまでのBest解をDynamoDBに書き込み終了します。
6)解が求まったら、解をDyanamoDBに書き込み終了します。

ここで、リソースは、

LambdaFunction:菅原システムズ側
DynamoDB:お客さま側

にあるので、それぞれの側で、アクセス許可が必要となります。AWS内でCloseし、外部からは
アクセスできないので、セキュリティ上も好ましいものとなります。お客さまが、AWS内でアプリを組む場合には、最適な構成ではないかと思います。

2020年5月4日月曜日

Visual C++ からLinuxへの移植

作業を開始しました。移植作業だけで1週間かかります。
以下に作業をまとめます。
項目WindowsLinux対応
ファイル名大文字小文字区別なし区別ありファイル名を統一
ファイル名ShiftJisUtf-8日本語コメントでパースできないのでUTF-8に統一
プロジェクトファイルsln/vscprojファイルCmakelists.txtCmakelists.txt作成
DBL_MAX #include<cfloat> 
#include file pathName\SubNameName/SubName 
関数popcnt/bitscanforward http://herumi.in.coocan.jp/prog/gcc-and-vc.html
Link 順序 Link順序管理必要 

2020年5月3日日曜日

VS2019 へ移行

今まで、VS2017を使ってきたのですが、コードの整理を含めてVS2019に移行中です。

VS2019にコンパイラを替えただけなのに、結構な量のコンパイルエラーが起きます。コンパイラの解釈が変わったことによることが原因です。使い続けて20年位になりますが、今だにそういう状態です。コンパイラのバグFixもありますが、C++の言語仕様が、今だに進化していることが 関わっているようにも思えます。 進化により、主に高級言語化傾向があり、より少ない行数でやりたいことが書けるようになってきています。(今回、C++17にしたかったのですが、default C++14、 部分的にC++17です。)

もう一つの目的は、クロスプラットフォーム化にあります。今までは、Windowsだけを考えればよかったのですが、AWS対応のためには、クロスプラットフォームプロジェクト化は、必須です。ただ、前に述べたように、AWSのエンジンは、かなりいじる必要があり、単純にクロスプラットフォーム化すれば済むという話ではなく、AWS用のコードをかなり書かないといけません。この辺は、AWS-SDKのコードを参考にしながら書くことになります。

2020年5月2日土曜日

AWS 構成を変更

Is it possible to kill/stop a running lambda function?

 1)You cannot kill a running lambda function. Though there is another way by which you can set concurrency limit to 0. This will stop it from starting any more executions.
$ aws lambda put-function-concurrency --function-name my-function --reserved-concurrent-executions 0

これだと、全てのインスタンスで止まってしまいます。緊急停止用途と理解します。

2)That's not what we should use lambda for

Ideally each lambda function should be only one function. A real one function of the programming language. Which not loop or even have state. And it should be able to run in parallel. This is functional paradigm

If you need to have state, use step function to call lambda. Even you just need to loop for pulling task but if it can take times longer than 1 minute you should use step function. All lambda function should be able to let itself die in 1 minute and so you could maintain that it will have only one of it alive in each minute

If you really need to ensure that it must have only one of it in each minute. You could use dynamodb or any other state keeper as a mutex, to let every lambda check that should it end itself when the mutex id was changed. Not that it will always have one lambda but it let old lambda kill itself when it know it not needed

なるほど、lambdaは、Stateレスが前提なのですね。
現状のエンジンをそのままLambda化するのは、難しそうだということが理解できました。

STEP FUNCTIONを使って、API化することは技術的には可能でしょうが、そのための開発負荷が半端ではなくなってしまいます。オーバヘッドも無視できないですし、本筋以外での課金は、避けたいです。

そこで、APIGateWayを通さずに直接に、直接にユーザがLambdaを呼ぶ方法に改めたいと思います。当然のことながら、顧客もAWSアカウントを持つ必要がありますが、元々持っているならば障害にはなりません。

2020年5月1日金曜日

はじめてのAWS LAMBDA CPPサンプル

https://aws.amazon.com/jp/blogs/compute/introducing-the-c-lambda-runtime/
に従ってサンプルを動かしてみました。

■必要となるライブラリのインストール
cmake/g++/libcur..等、次々に文句を言ってきますが、言ってきた時点で、ubuntu用のライブラリインストールの仕方を検索インストールを行いました。

■aws-sdk-cppのmake
失敗しました。同じ関数を2回アクセスしているところ、2回目は、betterAccessKeyを期待しているようですが、goodAccessKeyが却っているようでした。原因は分かりません。とりあえず、コメントアウトして無理やりmakeを通しました。→ubuntu20.04 WSL1にsleepが効かない問題があるようです。色々パッチを充てる必要がありそうです

TEST(InstanceProfileCredentialsProviderTest, TestThatProviderRefreshes)

{

    auto mockClient = Aws::MakeShared(AllocationTag);

    const char* validCredentials = "{ \"AccessKeyId\": \"goodAccessKey\", \"SecretAccessKey\": \"goodSecretKey\", \"Token\": \"goodToken\" }";

    mockClient->SetMockedCredentialsValue(validCredentials);

    InstanceProfileCredentialsProvider provider(Aws::MakeShared(AllocationTag, mockClient), 10);

    ASSERT_EQ("goodAccessKey", provider.GetAWSCredentials().GetAWSAccessKeyId());

    ASSERT_EQ("goodSecretKey", provider.GetAWSCredentials().GetAWSSecretKey());

    const char* nextSetOfCredentials = "{ \"AccessKeyId\": \"betterAccessKey\", \"SecretAccessKey\": \"betterSecretKey\", \"Token\": \"betterToken\" }";

    mockClient->SetMockedCredentialsValue(nextSetOfCredentials);

    std::this_thread::sleep_for(std::chrono::milliseconds(100));

 

    //ASSERT_EQ("betterAccessKey", provider.GetAWSCredentials().GetAWSAccessKeyId());

    //ASSERT_EQ("betterSecretKey", provider.GetAWSCredentials().GetAWSSecretKey());

}

■LAMBDAの登録がタイムアウト
次のコマンドで登録しようとしたのですが、タイムアウトで切断されてしまいました。
10MB以上は、S3経由で、アップロードすることが推奨されているようでしたので、S3で作ったバケットに置いたのですが、CLIでは、上手く呼び出すことができませんでした。なので、WEBコンソールで、関数の作成を行いアップロード、ロールの指定を行いました。

 aws lambda create-function \
--function-name encode-file \
--role <specify the same role arn used in the prior Lambda> \
--runtime provided \
--timeout 15 \
--memory-size 128 \
--handler encoder \
--zip-file fileb://encoder.zip

 ■CLIで起動
$ aws lambda invoke --function-name encode-file --payload '{"s3bucket": "your_bucket_name", "s3key":"your_file_key" }' base64_image.txt
で、base64_image.txtが出来ることを確認しました。中身のテキストをネット上のbase64decoderに通すと、S3バケットに置いたファイルの中身が再現していることを確認しました。

■まとめ
とりあえず、C++でLambdaFunctionをコンソール上から呼び出すことができました。
必要なライブラリ、aws-lambda-cpp,aws-sdk-cppを使いこなすことで、AWS上での操作が出来るようです。


2020年4月30日木曜日

AWSの環境整備

次の事項を行いました。

■Amazon アカウントの取得
■ルートアカウントの2段階認証 (Google Authentification使用)

■WSL Ubuntu20.04 インストール (Microsoft Storeより)
■VisualC++2019 インストール
■aws cli のインストール
■nano editorのインストール
 viは、無理..


Amazon は、当然Linux環境になるので、コンパイラは、g++か、clangになるのですが、最近、VisualC++でも、WSL上で、直接にデバグ出来るようなったようなので、VisualC++2019でやってみようと思いました。

当面、AWS上で、サンプルをいじりながら、理解して行こうと思います。この歳で新しい技術を学ぶことになるとは思っていませんでしたが、鞭打って頑張ってみようと思います。






2020年4月29日水曜日

AWS の構成

上が構成図になります。WebSocketで接続して、スケジューリング問題をJSON形式で受け取り、
求解状況と、最終的な解を送出します。以前、VPSで同じ構成で試したことがありますが、それをサーバレスのクラウド化を行うという、文字通りソルバーのクラウド化です。GUIは、持ちません。エンジンのみです。

AWS化の課題は、色々ありますが、一番は、私はAWSについては、初めてで良く分かっていないことです。加えて、C++のLambdaは、参考になる事例がほとんどなく、WEBSocket構成でできるのかどうかも良く判りません。なので、その辺のFeasiblityStudyを行いつつ、構成を一つ一つ組み上げていくことから始まります。

2020年4月28日火曜日

今後の計画


■SC3正式版リリース 5月End
 Algorithm1のみのサポートとなります。SC3用のマニュアルを作ること、及びビデオチュートリアルの追加を予定しています。SC2は保守扱いとします。また、Algorithm0は、削除する予定です。
 
■Cloud版エンジンの開発設計 6-12月
 AWSによるCloundエンジンの開発を行います。
 
■Microsoft Store版 Desktop 
 優先度としては、一番低くなってしまいますが、適宜開発を進めていきたいと思います。
 

2020年4月27日月曜日

オレゴン州の状況

10年以上顧客で、今も時々メールをくださるジョンさんに教えて頂きました。この後、our president..があるのですが、それは、割愛。

Oregon has a "mild" lock-down" with restaurants, bars, and other social gathering
places closed. Many churches have closed and are doing online services. A lot
of companies are doing mostly "work-from-home" and video conferencing. The
governor is looking at statistics to see when it will be OK to start easing off
restrictions.
As for us, since we live in a suburb that is not very crowded, we go out for walks
and try to enjoy the flowering trees and gardens. We carefully go out shopping
once a week and stores are asking people to stay 2 meters apart.

Stay well!

Instance20の新解が発見されてしまった

既に私が発見していたInstance20の新解が報告されてしまいました。4769は、既報通りで、正しい値です。

ぐずぐずしているからですね。Paperが準備中らしいので、興味深く、楽しみです。残されたインスタンスで未知で、未だ厳密解が報告されていないのは、Instance15/21/22..になってしまいました。Instance15は、報告していない新解を持っていますが、これが唯一となってしまいました。

Instance21/22については、線形ソルバーの高速化が必須で、私のところでも、厳密解に近いところを求めようとすると現状100日位かかってしまいます。

Instance23/24については、規模オーダが一桁違うので、Petter Strandmarkさんの手法か、メタヒューリスティクス等、別なアプローチが要ります。この辺は、数理ソルバーは、勿論、SATでも限界を超えていると思います。INRC2のようなダイナミックスケジューリングが、現実的アプローチになるのではないでしょうか?

2020年4月26日日曜日

SAT2020延期か

今年は、イタリアでの開催予定ですが、リモートにするか延期するか未だ悩んでいるようです。
人口知能学会もリモートの視聴の案内が着ましたし、今年だけなのか、今年からなのか、イベントの開催要項も様変わりするのかもしれません。

2020年4月25日土曜日

129Aをリリースしました

エンジンを少しいじりました。大規模インスタンスに対して動作を少し変えていて、ソフトレベルが多くなっても大丈夫だと思います。他に、本来エラーを出すべきところが漏れていたところがあったので、修正しています。

前回報告したように、Algorithm4は,学術ベンチマークについては、StateOfArt数理ソルバーを凌駕し、無類の強さを発揮しますが、実務インスタンスでは、コンパイルすら通らないのが多いのは変わっていません。この原因については、追って説明したいと思います。

2020年4月24日金曜日

特許化検討

ソフトウェア特許の場合、特に何らかの解法に関する特許関し、他者がそれをライセンスを受けずに実施していることを発見するのは、難しいと思います。表示に関するものでしたら侵害の発見は容易ですが、計算方法の類では、まず難しいと思います。 それ故に、内部に留めたほうが良いこともあります。ですが、私の場合、アプリの販売もありますが、ソルバーとして使って頂いているお客さまもあり、製品性能がトップであることをアピールする重要なツールでもあります。特許権の維持には、コストがかかるのですが、それに見合うだけの価値がある、と勝手に判断した場合には、特許化することにしています。

特許化の最も大きな障害は、審査官とのやり取りです。ほぼ100%拒絶通知が来ます。その拒絶理由について、一つ一つ反論をしないといけないのですが、これがとてつもなく面倒です。およそ現代の特許で、ある技術とある技術の組み合わせではない特許はほぼないと言っても過言ではないと思いますが、審査官は、そこを突いてきます。で、よくあるのが、クレームの一つの文言だけが一致する、先願または、引用文献を示してきます。一つ一つは、全く関係のない技術なのですが、必殺の「...してみれば、引用文献を用いて、本願発明とすることは、当事業者が容易になしえた事項である。」で、片付けられてしまいます。内容を理解もされずに、進歩性云々の要件で却下されることが多いと思います。

これを防ぐ手段を考えてました。有効なのは、コンペティション優勝、または世界記録を更新した、ということです。もし、容易になしえる技術ならば、優勝は自分ではなく、世界記録は、既に誰かが更新しているでしょう。本願を用いて世界記録を更新した、ということであれば、「容易になしえる技術」に、明確に反論することが出来るでしょう。

ベンチマークの目的関数値の更新に固執している理由は、こんな背景もあります。

2020年4月23日木曜日

ログ整形スクリプト

NEOS-ServerのGurobiデータとSC3のデータを拾うスクリプトを書きました。
下がGurobi用です。
import re
import csv
f = open('120w4gurobi.txt', 'r')
line = f.readline()
mode=0
map={ }
read_enable=False
constant=1480 #Constant objective value
while line:
 #print(line.strip())
 if 'Gap' in line:
  read_enable=True
 if 'ERROR' in line:
  read_enable=False
 if read_enable:
  print(line)
  l = line.split()
  count=0;
  second=''
  for s in reversed(l):
  
   if count==0 and 's' in s:
    second=s.replace('s','')
    print(second)
   if count==4:
    print(s)
    if second !='':
     map[int(second)]=float(s)+constant
   count+=1
 line = f.readline()
f.close()
#print(map)
map=sorted(map.items())
print(map)
f = open('result.csv', 'w')

for s in map:
 print(s[0])
 s1=str(s[0])+','+str(s[1])
 s1+='\n'
 f.write(s1) 
f.close()
 
SC3用が下です。
import re
import csv
f = open('result.txt', 'r')
line = f.readline()
mode=0
map={ }
read_enable=False
constant_time=213.809 #Algorithm1 Solving Process Started time
once=False
while line:
 #print(line.strip())
 if 'Algorithm 1 Solving Process Started.' in line and once==False:
  read_enable=True
  once=True
 if '*********UB=' in line:
  read_enable=False
 if read_enable:
  #print(line)
  l = line.split()
  count=0;
  second=''
  for s in reversed(l):
  
   if count==0 and '(sec)' in s:
    second=s.replace('(sec)','')
    print(second)
   if count==1:
    print(s)
    if second !='':
     sec=float(second)+constant_time
     map[sec]=float(s)
   count+=1
 line = f.readline()
f.close()
#print(map)
map=sorted(map.items())
print(map)
f = open('result.csv', 'w')

for s in map:
 print(s[0])
 s1=str(s[0])+','+str(s[1])
 s1+='\n'
 f.write(s1) 
f.close()
 
で、グラフが下です。
これだと、良く判らないので、横(時間)、縦(目的関数値)で拡大してみます。
さらに縦を拡大します。
グラフから、■Algorithm1は、計測直後から実行可能解が出力されます。遅れて、Algorithm4は、200秒、Gurobiは、767sec後から実行可能解が出力されます。
■Algorithm4は、330secで打ち切っていますが、それでも8時間後のGurobiよりも良い目的関数値になっています。

ナーススケジューリング解の設計目標として、良い解を出来る限り早く出力すること、がありますが、どちらかというと学術分野では、速さよりも時間をかけたときの目的関数値の優劣を競う面があります。その意味で、Algorithm4が、最終的な目的関数値が最小ですので優秀なのですが、実務的には、

■数分内に実用的な目的関数値を出力する

ことの方がより重要です。仮に8時間後に厳密解が判ったとしても、その差が数%内ならば、数分内に出力される方を選ぶでしょう。なぜならナーススケジューリングは、一回で解を得ておしまいではなく、何回もの試行を経て決定されることが一般的だからです。その意味で、解の有無が直ぐに判るAlgorithm1が最も実務的です。

が、ソフトエラーが多数に渡る場合、GAP(下界と上界の差)が、今回のように50%程度になることもあります。そのAlgorith1のこうした弱点を補うことが今回のAlgorithm4の目的でした。狙い通り、
INRCⅡの殆ど全てのインスタンス及びSchedulingBenchmarkのBestKnown値の更新、いくつかの成果はありました。残念ながら、実用的には、今だ道が遠いのですが、作業予定時間を大幅に超過してしまいました。これまでの成果をまとめて一区切りとしたいと思います。

■厳密解が確定
その後、テストを続けた結果厳密解が確定しました。16000sec後にAlgorithm4が確定(2050)させました。120W4というのは、スタッフ120人のWeeksが4です。確定できたのは、僅か数インスタンスしかないのですが、必ずしもインスタンス的に小さいものでないことが興味深いです。




2020年4月22日水曜日

NEOS SERVER LOG

下は、CPLEXのログになりますが、Elapsed Timeが表示されるまで、時間の経緯が判りません。
これでは、時間ー目的関数値 の推移グラフが書けません。


        Nodes                                         Cuts/
   Node  Left     Objective  IInf  Best Integer    Best Bound    ItCnt     Gap
*     0+    0                       359195.0000     -370.0000           100.10%
      0     0      -64.2187  3315   359195.0000      -64.2187       19  100.02%
*     0+    0                        43470.0000      -64.2187           100.15%
      0     0       53.7500  2331    43470.0000     Cuts: 279    18717   99.88%
      0     0      110.7778  2628    43470.0000     Cuts: 759    27889   99.75%
      0     0      148.0682  2551    43470.0000     Cuts: 703    38963   99.66%
*     0+    0                        29975.0000      148.0682            99.51%
*     0+    0                        29915.0000      148.0682            99.51%
*     0+    0                        29905.0000      148.0682            99.50%
*     0+    0                        29705.0000      148.0682            99.50%
*     0+    0                        28675.0000      148.0682            99.48%
      0     0      178.1077  2688    28675.0000     Cuts: 729    48298   99.38%
      0     0      216.1885  2671    28675.0000     Cuts: 677    64088   99.25%
      0     0      242.7695  2696    28675.0000     Cuts: 647    72639   99.15%
      0     0      253.8045  2680    28675.0000     Cuts: 623    81504   99.11%
      0     0      270.4266  2508    28675.0000     Cuts: 662    90893   99.06%
      0     0      277.8454  2682    28675.0000     Cuts: 569   101580   99.03%
      0     0      288.5256  2773    28675.0000     Cuts: 570   112909   98.99%
      0     0      294.7174  2735    28675.0000     Cuts: 654   125075   98.97%
      0     0      307.0973  2715    28675.0000     Cuts: 574   134680   98.93%
      0     0      313.8889  2563    28675.0000     Cuts: 569   144764   98.91%
      0     0      318.3333  2735    28675.0000     Cuts: 501   154305   98.89%
      0     0      320.6537  2686    28675.0000     Cuts: 428   165201   98.88%
      0     0      324.8424  2511    28675.0000     Cuts: 479   176102   98.87%
      0     0      328.7166  2701    28675.0000     Cuts: 486   186932   98.85%
      0     0      331.1991  2640    28675.0000     Cuts: 467   196434   98.84%
      0     0      333.7144  2667    28675.0000     Cuts: 511   206362   98.84%
      0     0      335.4018  2422    28675.0000     Cuts: 452   214946   98.83%
*     0+    0                        13650.0000      335.4018            97.54%
      0     0      337.7659  2424    13650.0000     Cuts: 446   224872   97.53%
*     0+    0                         4360.0000      337.7659            92.25%
*     0+    0                         4210.0000      337.7659            91.98%
*     0+    0                         4180.0000      337.7659            91.92%
*     0+    0                         4130.0000      337.7659            91.82%
*     0+    0                         4120.0000      337.7659            91.80%
*     0+    0                         4105.0000      337.7659            91.77%
*     0+    0                         4095.0000      337.7659            91.75%
*     0+    0                         4080.0000      337.7659            91.72%
*     0+    0                         4065.0000      337.7659            91.69%
*     0+    0                         2315.0000      337.7659            85.41%
*     0+    0                         2100.0000      337.7659            83.92%
*     0+    0                         2085.0000      337.7659            83.80%
*     0+    0                         2075.0000      337.7659            83.72%
*     0+    0                         2065.0000      337.7659            83.64%
*     0+    0                         2055.0000      337.7659            83.56%
*     0+    0                         1985.0000      337.7659            82.98%
      0     0      338.7064  2534     1985.0000     Cuts: 341   233655   82.94%
      0     0      338.9290  2501     1985.0000     Cuts: 449   243012   82.93%
      0     0      340.3071  2604     1985.0000     Cuts: 400   252547   82.86%
      0     0      342.6351  2680     1985.0000     Cuts: 479   262409   82.74%
      0     0      345.2399  2705     1985.0000     Cuts: 468   271762   82.61%
      0     0      346.5593  2594     1985.0000     Cuts: 392   281214   82.54%
      0     0      348.2926  2696     1985.0000     Cuts: 424   291728   82.45%
      0     0      348.6862  2780     1985.0000     Cuts: 400   301858   82.43%
      0     0      352.1631  2469     1985.0000     Cuts: 466   311631   82.26%
      0     0      353.1727  2388     1985.0000     Cuts: 518   322374   82.21%
      0     0      354.3967  2365     1985.0000     Cuts: 402   333125   82.15%
      0     0      356.1600  2490     1985.0000     Cuts: 409   344215   82.06%
*     0+    0                         1785.0000      356.1600            80.05%
      0     0      356.3396  2468     1785.0000     Cuts: 458   354575   80.04%
      0     0      358.8643  2531     1785.0000     Cuts: 340   365518   79.90%
      0     0      359.0449  2455     1785.0000     Cuts: 499   380153   79.89%
      0     0      359.3243  2318     1785.0000     Cuts: 395   410059   79.87%
      0     0      360.6046  2354     1785.0000     Cuts: 463   424344   79.80%
      0     0      361.3983  2513     1785.0000     Cuts: 445   438669   79.75%
      0     0      363.0090  2273     1785.0000     Cuts: 429   450682   79.66%
      0     0      364.2676  2379     1785.0000     Cuts: 453   460801   79.59%
      0     0      364.5254  2297     1785.0000     Cuts: 453   473808   79.58%
      0     0      366.6675  2711     1785.0000     Cuts: 363   487309   79.46%
      0     0      369.5115  2678     1785.0000     Cuts: 440   501845   79.30%
      0     0      369.6678  2527     1785.0000     Cuts: 447   515283   79.29%
      0     0      370.5862  2485     1785.0000     Cuts: 409   526362   79.24%
      0     0      372.0121  2644     1785.0000     Cuts: 441   537949   79.16%
      0     0      372.7673  2541     1785.0000     Cuts: 417   561352   79.12%
*     0+    0                         1775.0000      372.7673            79.00%
      0     0      373.3979  2573     1775.0000     Cuts: 443   571316   78.96%
*     0+    0                         1665.0000      373.3979            77.57%
      0     0      374.5699  2491     1665.0000     Cuts: 411   593582   77.50%
      0     0      375.9199  2535     1665.0000     Cuts: 411   606301   77.42%
      0     0      376.9399  2510     1665.0000     Cuts: 427   618234   77.36%
      0     0      377.4003  2617     1665.0000     Cuts: 426   628252   77.33%
      0     0      378.4336  2562     1665.0000     Cuts: 413   641045   77.27%
      0     0      379.1902  2433     1665.0000     Cuts: 404   651619   77.23%
      0     0      381.9274  2640     1665.0000     Cuts: 443   663832   77.06%
      0     0      382.7832  2655     1665.0000     Cuts: 449   688911   77.01%
      0     0      383.8327  2516     1665.0000     Cuts: 478   700613   76.95%
      0     0      384.2792  2581     1665.0000     Cuts: 434   719632   76.92%
      0     0      385.4148  2659     1665.0000     Cuts: 305   731989   76.85%
      0     0      387.5154  2595     1665.0000     Cuts: 457   741474   76.73%
      0     0      390.1512  2554     1665.0000     Cuts: 461   750275   76.57%
      0     0      391.2088  2629     1665.0000     Cuts: 366   759972   76.50%
      0     0      393.4489  2724     1665.0000     Cuts: 597   768781   76.37%
      0     0      394.2833  2650     1665.0000     Cuts: 465   781215   76.32%
      0     0      394.7189  2601     1665.0000     Cuts: 404   790527   76.29%
      0     0      396.0850  2609     1665.0000     Cuts: 483   802531   76.21%
      0     0      396.9782  2520     1665.0000     Cuts: 402   817779   76.16%
      0     0      399.2371  2635     1665.0000     Cuts: 443   829483   76.02%
      0     0      399.7541  2654     1665.0000     Cuts: 401   838973   75.99%
      0     0      400.5069  2506     1665.0000     Cuts: 475   860150   75.95%
      0     0      401.0033  2533     1665.0000     Cuts: 541   870828   75.92%
      0     0      401.1352  2633     1665.0000     Cuts: 441   880720   75.91%
      0     0      401.3362  2377     1665.0000     Cuts: 141   891428   75.90%
      0     0      401.6659  2670     1665.0000     Cuts: 610   903345   75.88%
      0     0      402.2398  2599     1665.0000     Cuts: 353   915823   75.84%
      0     0      402.3160  2585     1665.0000     Cuts: 481   929191   75.84%
Heuristic still looking.
Heuristic still looking.
*     0+    0                         1630.0000      402.3160            75.32%
      0     2      402.3160  2585     1630.0000      402.3160   929191   75.32%
Elapsed time = 10455.15 sec. (1830372.98 ticks, tree = 0.02 MB, solutions = 28)
      1     3      402.3160  2569     1630.0000      402.3160   930957   75.32%
      2     4      402.4682  2570     1630.0000      402.3160   933742   75.32%
      3     5      403.9569  2529     1630.0000      402.3160   936012   75.32%
*     4+    3                         1480.0000      402.3160            72.82%
*     4+    3

一方、GUROBIは、最初にリニアオプティマイザをPrimal・Dual Simplexにして、Simplexを廻した後、最初の整数解が出るまでに、767secかかっていることがわかります。逐次時間のとともに目的関数値が減少していく様子が判るので、グラフ化できます。同じインスタンスについて、SC3 Algorithm1・Algorithm4 と比較すれば、性能比較の可視化を行うことができます。

それにしても、Feasibleな解がでるまでに10分もかかっていたのでは、使い物になりません。

RAMP講演でも、「CPLEXで解が出なかったインスタンスがある」 と報告して、「おかしいんじゃないか?」という指摘を受けたことがありました。その理由は、NEOS SERVERのShort Priority(直ぐにやってくれるが5分でタイムアウト)での実行による結果でした。正しくは、「5分で実行可能解が出てこないインスタンスがある。」に訂正します。手持ちお客さまのインスタンスで説明しましたが、
決して特殊な例ではありません。(5分も何も言ってこないのは、解がない というのが私の感覚でした。)

この例のインスタンスは、INRCⅡの120W4というインスタンスで、規模的には、大きいインスタンスになりますが、超大規模というものではありません。数理的ソルバーの優位性は、厳密解を出せることにありますが、一般のナーススケジューリング問題においては、厳密解を出せるインスタンスというのは、むしろ少ないです。従い実務におけるナーススケジューリング問題では、数理的ソルバーの出番は少なく、主にメタヒューリスティクスによる解法が主になります。決してソルバーのコストによるものではなく、求められる精度と速度が、向いていない、ということに尽きます。





Deterministic concurrent LP optimizer: primal and dual simplex
Showing first log only...

Root simplex log...
Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0    2.3065000e+04   1.830000e+02   6.010239e+08     17s
   24989    5.9105058e+04   0.000000e+00   5.427999e+06     20s
   39027    1.4139465e+04   0.000000e+00   1.530505e+06     25s
   48531    8.4548149e+03   0.000000e+00   8.561291e+05     30s
   54075    4.6553869e+03   0.000000e+00   6.203191e+05     35s
   57243    4.0333315e+03   0.000000e+00   1.884978e+06     40s
   59619    3.2945051e+03   0.000000e+00   2.485297e+07     45s
   61995    2.8932136e+03   0.000000e+00   1.937645e+06     50s
   63843    2.6364303e+03   0.000000e+00   1.824680e+06     56s
   65955    2.4071407e+03   0.000000e+00   1.529677e+06     60s
   67803    2.1433875e+03   0.000000e+00   3.572679e+06     66s
   69387    2.0198157e+03   0.000000e+00   1.500083e+06     70s
   70957    1.8682992e+03   0.000000e+00   5.175105e+06     75s
   72527    1.7109733e+03   0.000000e+00   1.534901e+06     80s
   74371    1.6059518e+03   0.000000e+00   7.316991e+05     86s
   75691    1.4715193e+03   0.000000e+00   8.885731e+05     90s
   77275    1.2998909e+03   0.000000e+00   2.408987e+06     96s
   79123    1.2171491e+03   0.000000e+00   1.039386e+06    100s
   80707    1.1319239e+03   0.000000e+00   7.554920e+06    105s
   82555    1.0430034e+03   0.000000e+00   2.797781e+06    111s
   83875    9.5441597e+02   0.000000e+00   4.827466e+06    115s
   85459    8.9434760e+02   0.000000e+00   2.612262e+05    121s
   86779    8.2570058e+02   0.000000e+00   1.466299e+06    125s
   88363    6.7444245e+02   0.000000e+00   1.998739e+06    131s
   89683    5.7750613e+02   0.000000e+00   1.569387e+06    136s
   90999    5.1294778e+02   0.000000e+00   8.648063e+05    141s
   92031    4.6633167e+02   0.000000e+00   1.271406e+07    145s
   93329    4.1456737e+02   0.000000e+00   4.761322e+06    151s
   94349    3.7612396e+02   0.000000e+00   1.849774e+06    155s
   95599    3.2109644e+02   0.000000e+00   3.595911e+05    161s
   96629    2.6097565e+02   0.000000e+00   5.134349e+05    165s
   97893    2.2486428e+02   0.000000e+00   4.157836e+05    171s
   98907    1.7423268e+02   0.000000e+00   1.301501e+06    176s
  100199    1.2653451e+02   0.000000e+00   1.601937e+06    181s
  101199    8.5595718e+01   0.000000e+00   5.010955e+05    186s
  102247    4.7167686e+01   0.000000e+00   1.260490e+06    190s
  103487    1.2204544e+01   0.000000e+00   4.461667e+05    196s
  104407   -1.6047682e+01   0.000000e+00   1.948257e+05    200s
  105607   -4.7594571e+01   0.000000e+00   2.135647e+05    206s
  106527   -6.6654211e+01   0.000000e+00   1.916288e+05    211s
  107407   -8.9912197e+01   0.000000e+00   4.649965e+05    215s
  108547   -1.1011925e+02   0.000000e+00   2.579404e+06    221s
  109477   -1.2357405e+02   0.000000e+00   1.109971e+05    226s
  110437   -1.4304921e+02   0.000000e+00   4.081576e+06    231s
  111387   -1.5994959e+02   0.000000e+00   3.459370e+05    235s
  112567   -1.7748868e+02   0.000000e+00   4.569213e+05    241s
Concurrent spin time: 0.00s
Solved with dual simplex
Root relaxation: objective -6.890137e+02, 85445 iterations, 227.18 seconds
Total elapsed time = 401.32s
Total elapsed time = 476.00s
Total elapsed time = 579.92s
Total elapsed time = 672.39s
    Nodes    |    Current Node    |     Objective Bounds      |     Work
 Expl Unexpl |  Obj  Depth IntInf | Incumbent    BestBd   Gap | It/Node Time
     0     0 -689.01374    0 3777 1429275.00 -689.01374   100%     -  767s
H    0     0                    31485.000000 -689.01374   102%     -  768s
H    0     0                    27825.000000 -689.01374   102%     -  768s
H    0     0                    8355.0000000 -689.01374   108%     -  769s
     0     0 -578.43551    0 5449 8355.00000 -578.43551   107%     -  886s
H    0     0                    6115.0000000 -578.43551   109%     -  888s
     0     0 -574.51017    0 5343 6115.00000 -574.51017   109%     -  910s
     0     0 -574.34337    0 5278 6115.00000 -574.34337   109%     -  913s
     0     0 -574.34337