ICPC国内予選2017参加記
過去のblogから移動しました 元公開日時 2017-07-19 17:07:17
こんにちは。3回生のwassです。
ICPCに参加したのでそのログを残しておきます。
僕は競プロから1年以上退いて,
活動としては部内のプロコンに月に1回程度参加するぐらいでした。
そのため実装はチームメイトに任せることにしました。
A: やってもらった。
B: やってもらった。焦って誤読しあってしまったのは良くなかった。みんなで同じ問題読む大事さを忘れていた。
C: やるだけ。やってもらった。
D: 困った。全探索解法部分はわかるが, bitDP部分でつまずく。半嘘解法を思いつき実装しているチームメイトを眺めた。オーダーがnだけ余計にかかる解法のため実行に時間がかかっていたらしい。
E: Dを実行しながらEを僕が実装することになった。構文木の全列挙で間に合うことがわかる。構文木のデータ構造を作らずに探索する方法は気づかなかった。構文木を素直に全列挙し, 恒等式判定をする実装をした。実行がコンテスト終了に間に合わなかった。あとで確認すると実装は合ってたっぽい。Dではついてた-O3
を忘れていたのは事故。
G: 右手法で探索をすれば行けるやろという気分ではいた。だけ。フローは賢いなあ。。
Dは奇跡的に間に合ったので結果は4完。4完内ではビリ近くの55位。くやしい。
競プロ楽しいですね。活動を再燃させる。
悪いものを食べて判断力が鈍っているときに,
楽しそうな提案をすると乗ってくれることがわかるブログです→
http://kyp.hatenadiary.com/entry/2017/07/19/024104
部室に温度センサーとかつけて監視する
(過去のblogから移動しました 元公開日時 2016-12-22 05:45:44)
こんにちは, KMC2回生のwass80です。
この記事はKMC Advent Calendar 2016 21日目の記事です.
昨日の記事はtronくんの「Neutron 買ってみたのは いいけれど……」でした。記事タイトルが575ですね。
明日の記事はbase64くんの「いい感じのメドレーを自動生成したい」です。自分がもやりたかったことやられたので, 後でいい感じコミットぜったいしたる。
今回はRaspberryPi3 ModelBを買ったので, 使って部室の監視をしたいと思います。
概略図
Raspberryにつながった温度センサーの値をfluentdでinfluxDBに送りつける。
grafanaでグラフを表示。
用意するもの
- Amazon
- 秋月
- 部室に落ちていたもの
- ブレッドボード
- オス-オスジャンプワイヤー
- microUSBケーブル
- 買い忘れたもの
- オス-メスのジャンプワイヤー
RasberryPi3はArduinoと違って, オス-メスのジャンプワイヤーが必要になるので注意しましょう。買い忘れました。
RasberryPi3
センサーをつなげて値を読み取りましょう。
セットアップ
Raspberry Pi 3を買ってMacを使ってWiFi接続とSSHの接続するまで
SDカードにRaspbianを焼いてRasberryPi3に差し込みます。
USBで電源を供給すれば起動します。HDMIで画面を見ます。
初期パスワードはuser:pi/pass:raspberryです。速やかに変更しましょう。
sshがデフォルトで無効になっているので有効化する必要があります。
Wifiでつながると便利なのでその設定もします。
温度センサー
第39回「ラズベリーパイで温度・湿度・気圧をまとめて取得!AE-BME280でIC2通信」
このセンサーにははんだ付けが必要です。
I²C方式シリアル通信をします。
上の記事通りに接続したら, I²Cを有効化します。
Github: SWITCHSCIENCE/BME280のコードを借りて(少し改変して)データを表示してみます。
t, p, h = readData()
print("気温:%f\t大気圧:%f\t湿度:%f" % (t, p, h))
pi@raspberrypi:~ $ python bme280/bme280.py
気温:19.729584 大気圧:1005.779496 湿度:56.260745
動いてそうです。
このデータを10秒おきに次のfluentdに送りつけましょう。
from fluent import sender
import time
logger = sender.FluentSender('raspi', host='sharp')
if __name__ == '__main__':
while True:
t, p, h = readData()
print("気温:%f\t大気圧:%f\t湿度:%f" % (t, p, h))
logger.emit('climate', {'temperature': t, 'pressure': p, 'humidity': h})
time.sleep(10)
systemd用のunitファイルを書きましょう。
#/etc/systemd/system/bme280.service
[Unit]
Description = bme280 climate sensor
[Service]
ExecStart = /home/pi/bme280/bme280.py
Restart = always
Type = simple
[Install]
WantedBy = multi-user.targe
$ sudo systemctl enable bme280
$ sudo systemctl start bme280
fluentd
ログの受け渡しをするサービス。
fluentdは Input → Filter → Output の経路でJSONのログ(event)を流します。
例えば, 以下のことができます。
- あるログファイルの書き込みを感知して(Input)
- それがErrorのログならば(Filter)
- Slackへ通知する(Output)
今回は以下の構成になります。
- TCPでログを受け取る(Input)
- そのすべてを(Filterなし)
- influxDBに送りつける(Output)
InputとFilterとOutputを結びつけるのは, ログに紐づくタグです。
Inputでログにタグを付け, 対応するFilter, Outputが動きます。
fluentdはすでに部室で動いていたので間借りします。
fluentdはデフォルトでTCPで受け取る以下のForward Inputが動いています。
#不要なコード
<source>
type forward
port 24224
bind 0.0.0.0
</source>
RaspberryPIからraspi.climate
タグをつけてfluentdに送っています。
#前述抜粋
logger = sender.FluentSender('raspi', host='sharp') #sharpはfluentdのあるサーバ名
logger.emit('climate', {'temperature': t, 'pressure': p, 'humidity': h})
なので以下の設定を追加します。
<match raspi.climate> #このタグであれば
@type copy #次のOutputそれぞれに受け渡す
<store> #ファイルに保存
@type file
path /var/log/td-agent/raspi/climate.log
</store>
<store> #influxdbに送りつける
@type influxdb
host 192.168.220.31
port 8086
dbname climate
user root
password root
use_ssl false
time_precision s
</store>
</match>
# matchは上からマッチし, マッチしたものがあればそれ以上マッチしない。
<match raspi.**> #上にマッチしなければ, 別のファイルに保存。
@type file
path /var/log/td-agent/raspi/raspi.log
</match>
今回はinfluxDBに送るついでにファイルにも保存していますが, DBを真面目に運用するなら必要ないでしょう。
influxDB
field/tagキーに値を時系列で突っ込んで行くデータベース。
「性別(∋男,女)」のように値の種類(=カーディナリティ)が少ないものはtagキー。
「気温=実数」のようにカーディナリティが高いものはfieldキーに指定します。
influxDBの準備にはdocker-composeを用いました。
参考: nicolargo/docker-influxdb-grafana
# docker-compose.yml
version: '2'
services:
influxdb:
image: influxdb:latest
ports:
- "8083:8083"
- "8086:8086"
env_file:
- 'env.influxdb'
volumes:
- influxdb-storage:/var/lib/influxdb
grafana:
image: grafana/grafana:latest
ports:
- "13000:3000"
links:
- influxdb
volumes:
- grafana-storage:/var/lib/grafana
environment:
- GF_SERVER_ROOT_URL=%(protocol)s://example.jp/~wass80/app/grafana
- GF_AUTH_ANONYMOUS_ENABLED=true
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
volumes:
influxdb-storage:
driver: local
grafana-storage:
driver: local
起動する。
$ docker-compose up -d
InfluxDB と fluentd を組み合わせを試してみた
データベースを作ればデータを受け取る準備が完了します。
influxDBのWebインターフェースはdeprecatedのようなので, 今回はCLIを用いました。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
791734f2cf3a grafana/grafana:latest "/run.sh" 8 hours ago Up 8 hours 0.0.0.0:13000->3000/tcp dockerinfluxdbgrafana_grafana_1
d39bac4136e8 influxdb:latest "/entrypoint.sh influ" 8 hours ago Up 8 hours 0.0.0.0:8083->8083/tcp, 0.0.0.0:8086->8086/tcp dockerinfluxdbgrafana_influxdb_1
$ docker exec -it d39 influx
Visit https://enterprise.influxdata.com to register for updates, InfluxDB server management, and monitoring.
Connected to http://localhost:8086 version 1.1.1
InfluxDB shell version: 1.1.1
> CREATE DATABASE climate
> SHOW databases
name: databases
name
----
_internal
climate
#fluentdの設定 前述抜粋
<store> #influxdbに送りつける
@type influxdb
host 192.168.220.31 # influxDBの動くサーバ
port 8086
dbname climate #データベース名
user root
password root
use_ssl false
time_precision s
</store>
これで{'temperature': t, 'pressure': p, 'humidity': h}
というfleid:値がinfluxdbに流れます。
Grafana
influxDBの内容をめっちゃかっこよく表示してくれるいい子。
先程のdocker-composeで一緒に起動していました。
今回はBasic認証がすでにかかっているところで動かすため, Grafanaの認証を無効化しています。
リバースプロキシ用の設定を環境変数に追加しています。
# docker-compose.yml (前述抜粋)
grafana:
image: grafana/grafana:latest
ports:
- "13000:3000"
links:
- influxdb
volumes:
- grafana-storage:/var/lib/grafana
environment:
- GF_SERVER_ROOT_URL=%(protocol)s://example.jp/~wass80/app/grafana
- GF_AUTH_ANONYMOUS_ENABLED=true
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
influxDBを登録しましょう。
GUIで設定できます。
あとはめっちゃいい感じGUIでグラフの設定をします。
いいですね。
できました。
凡例の色付き横線を押すと色の変更と軸の左右の変更ができます。
他にも色々センサーを買いましたが, RaspberryPIがアナログ入出力が出来ないことを知りませんでした。A-D変換を買ってきます。
明日の記事をお楽しみに。
ISUCON6本戦を復習して勉強する
(過去のblogから移動しました 元公開日時 2016-10-24 13:08:12)
ISUCON6お疲れ様でした。とても楽しかったです。
:innocent:チームは順位表で😇と表示されていました。 これは運営の方がわざわざ実装をしてくださったらしいです。 絵文字のチームが増えると 🍣と🍺問題 http://blog.kamipo.net/entry/2015/03/23/093052 が起こりうるのでやめましょう。 競技中のポータルサイトの右上に現れる"Hello, 😇"は面白かったです。 ぜひこの絵文字を結果発表で前に大きく出したかった。
:innocent:チームは与えられた実装よりスコアを下げてしまいました。 全くもって付け焼き刃が通らないという様子で作問者の思惑通りに手のひらの上で転がされた感じになりました。チームの3人の知識を合わせて0.01人の量に満たないことがわかったので, これから勉強していきたいと思います。
docker上で実行されているrackアプリにrack-lineprofileを仕込むという戦略を最初に予定していたのですが, 実行したところ一切のログが残らず混乱をしてしまいました。プロファイルを取る方法を失い, nodeでのボトルネック具合もよくわからないので, 問題点を追求できなかったです。 その場合でもCPU時間を参考にすればよかったです。
今回はチーム内での分担も行うことが出来ず, 問題に取り組む効率が最悪だったと思います。 全体の構成図を最初に書いておけば方針の決定に役立ったと思いました。 本番中はreactやらSSEやらSSLやらでかなり打ちのめされていました‥。
やることがたくさんあるとてもいい問題だったので, KMC内で本戦に出ていないチームともう一度解き直す会を行いたいです。
チームメイトutgwの様子 http://utgwkk.hateblo.jp/entry/2016/10/23/233114
ISUCON6予選学生枠通過しました
(過去のblogから移動しました 元公開日時2016-09-18 14:23:20)
びっくりしました。
:innocent:チームのチームメイトはKMCの同期の @utgwkk https://twitter.com/utgwkk くんと先輩の @yu3mars https://twitter.com/yu3mars さんでした。お疲れ様でした。
やったことは,
GET /が遅くてSCOREが0
とりあえずhtmlifyの無駄を関数をくくりだして呼び出しを減らす。
すべてのカラムを使っていないSelect *を削減。
POST /starが遅くてSCOREが0
データベースを直接問い合わせる。疎結合なにそれおいしいの。
静的ファイルのキャッシュ
utgwくんが調べてやってくれた。
GET /keyword/が遅い
難敵。utgwくんのProfileによるとここが他の100倍ぐらいの律速。
原因は動的生成される長大な正規表現gsub。
自分で実装書き換えるのは試したけど厳しかった。
頭が冷えていれば, まずテストケースを作るところからやるべき。
- だけどそんな筋力がない。アホコラは競プロでお願いします。
終了一時間前に
pattern = pattern.select{|pat| contents.include?(pat) }
- みたいなことを書いた以外もとの実装のままで最終SCOREの19610点
- yu3のアイデア。さすが。
僕は初っ端にKのキートップが外れたので, vimが使えませんでした。 そのため, コード読みながらutgwくんに色々言っていました。 今回殆どの準備をutgwくんがやってくれたので彼を祭り上げたい https://www.amazon.co.jp/wishlist/3JZEEE505CI87/ref=cm_sw_r_tw_wlp_HiglL.41T49YJ です。
utgwくんのブログ → ISUCON6 に出て予選で打ちのめされてきた #isucon http://utgwkk.hateblo.jp/entry/2016/09/18/182304
キャッシュの知識がなかったので, 問題点に全力投資ができたことが救いだったらしいです。 本番はせっかくなのでもっと勉強してから挑戦します。 KMCでISUCON勉強会やりましょう。というかKMCONやりましょう。